Jump to content
  • 0

Chipkit Max32: Floating Point Problem


EigenFunctions

Question

I have an ultra simple program that doesn't seem to work.

// Show problem(?) with floating point
// 01-06-2015


void setup() {
  Serial.begin(115200);
  Serial.println("setup() ");
  }
  
void loop() {
  float x;
  
  x = x + 1.01;
  Serial.println(x);
  delay(1000);
  
  }

The println statement shows the same value "1.01" without changing. I've tried a variety of changes:

  • I tried x += 1.01; with the same result
  • I tried float x = 0.0; with the same result
  • As I ran out of idea's I tried setting the delay() to different values - same result
  • I have a Basic I/O board connected and I sent the result to the LCD - same result

The only way I can make it work is if I move the float statement to make "x" a global variable. It then works. Why does it have to be a global variable? I assume I must be doing something wrong, but I don't know what.

 

Can anyone help?

 

Thanks,

  EigenFunctions

 

  BTW- I'm running with Win7 using the ChipKit Max32 USB cable directly;

      Mpide 0023-windows-20140821

 

Link to comment
Share on other sites

7 answers to this question

Recommended Posts

Hi EigenFunctions,

 

The issue that you're running into here, and the reason x needs to be a global variable, is that each time you are going through your loop you are essentially "re-declaring" your float value. This makes your "x" a value of 0.0 (or whatever you may have declared the initial value to be), so you will always end up adding 1.01 to 0.0.

 

With a global variable, you will only declare/initiate your float value once, so you won't run into this resetting back to zero issue.

 

Let me know if you have any more questions.

 

Thanks,

JColvin

Link to comment
Share on other sites

I thought of that but then, why does it work with integers? Change float to int and change 1.0 to 1 and it works as expected (as it should). My next question then becomes what are the implications of making every variable global? For one, I believe it will run slower as a result of making everything global. I don't know the implications to memory space.

 

I'm beginning to believe the Mpide is a quick and dirty tool. So I guess I should go the route of the Microchip IDE.

 

Thanks,

  EigenFunctions

Link to comment
Share on other sites

That's interesting. When I run the int version, my answer remains as a 1. This was also with a Max32 and the Mpide 0023-windows-20140821 version.

 

I am not a C++ expert (what MPIDE code is based on) by any means, but I will try explain my understanding of what I am seeing.

 

When you declare a variable inside your loop() function, that variable is a local variable. By nature of local variables, once you have reached the end of the scope that your local variable is in, which in this case is at the end of the loop() function, that local variable is "destroyed" and is no longer accessible to other parts of your code outside of that scope. Because the int or float is destroyed at the end of the loop, when you go back to the beginning of the loop it would create a new local variable.  

 

However, if we had a for loop or while loop inside our main MPIDE loop that did the x = x + 1 for some set amount of times, then the x variable would increase as expected. Truthfully, I have no idea how/why your main loop was increasing your local x variable. From my understanding (and testing) that should not be occurring. Could you copy and paste the code that you were using to get your x increasing?

 

As for making variables global, my understanding is that global variables would be stored in the flash memory (there is 512K bytes worth on the Max32) and local variables would be stored in RAM (128K bytes worth of SRAM on the Max32), but the compiler takes care of this for you.

 

I believe you are right that global variables do take a little more time to access, but (this is just my guess) because the Max32 runs at a set clock rate, both a local and global variable would be accessed by the PIC32 processor before the clock signal for the next instruction execution occurs.

 

Let me know if you have any more questions.

 

Thanks,

JColvin

Link to comment
Share on other sites

Hi EigenFunctions,

 

I am a bit of a C/C++ expert, and easiest solution to your problem is to add the 'static' keyword in front of the variable declaration.

 

void loop() {
  static float x;
  
  x = x + 1.01;
  Serial.println(x);
  delay(1000);
  
  }

This will cause the compiler to allocate storage in memory that holds global data, rather than on the stack, so it can hold its value between calls.

 

It only works by fluke with the integer variables - if you had a bit more code in the program it is likely that the same area of stack would be reused giving you very unpredictable results. If you turn compiler warnings on "pedantic" level (not sure how you do that in MPIDE...) it will warn that you are using a variable that isn't initialized. 

 

There isn't any difference in speed - anything that can be changed must be held in RAM. As part of the start-up process the initialization values are copied from the FLASH to RAM. This is why every time you apply power your global variables are set back to their initial values.

 

In the Arduino world you have 'PROGMEM' attributes that can be attached to global variables, causing them to only be stored in ROM. This saves on the limited RAM in the AVR CPU.

 

Mike

Link to comment
Share on other sites

Mike,

 

First, thanks for your response, I appreciate the insight and support.

 

I finally got a chance to try the static attribute and it works. I've used the 8-bit PIC uC very often in the past and where you locate variables in memory, on the 8-bit uC, does matter. However, it seems the PIC32 uC's, being MIPS based, are different. This project is first time I've had a chance to use PIC32's.

 

The exact program source that worked with integers was never saved (I just continued to amend it to add features). So when I wrote a simple program to try and show that integers would preserve the results, it failed. So your analysis seems plausible, that the value was on the stack and preserved, by chance, through multiple calls to loop().

 

Thanks again for the help.

  EigenFunctions

Link to comment
Share on other sites

Mike,

 

At first I thought that Sketches were not a good approach and that using C would be a better way to go. However, the simple sketch I cobbled together to test the features of the Basic I/O Shield (i.e., buttons, switches, analog input, LCD, etc.) took very little time. I then installed mpLab X and XC32 and tried to write a simple C program to toggle the User LED on the Max32. I had to first solve the issue of two different bootloaders.  mpIDE does so much behind the scenes to get the code up and running. All that initialization and configuration needs to be done by hand when writing in C (unless I missed something). My experience with PIC8 told me that there would be some configuration, but the PIC32 is more complex and requires more. Also, I could not find any simple example programs that would help (unlike the 8-bit world where there are thousands). I finally got the C program to flash the LED, but it took about a days worth of work and I know the configuration is not complete.

 

I may be missing something, but I found it difficult to find information and useful examples for PIC32 on the Max32. It would be nice if some of the libraries used with the mpIDE were available for mpLab X based development. It may be available, but I don't know where to look for libraries or documentation.

 

Ideally, having a GUI that you could enter the ChipKit board (e.g., Max32, UNO, etc.), the shield (e.g., Basic I/O, Network, etc) and it would generate a header file and basic configuration code that could be inserted in your main(). It would be a difficult project, but one can always dream.

 

Thanks,

  EigenFunctions

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...