Is it possible that freeMemory() is wrong in some cases ?

Hello,

I usually always find a solution on this forum (or wherever). But this problem is giving me hard time… So I decided to activate my account, and ask :slight_smile: … so sorry for the long topic to come…

The context : I’m using Tinkercad to work on a small project of “framework”. It’s quite easy to learn and try with this. I ended up with finally a really basic electrical scheme (diodes and buttons), because the interesting part is inside the card. I know that it will never work on UNO (it will be on MEGA), but as a playground, I try every features with just less functions…

I’m using a lot the SRAM monitoring to detect when I’m running out, or when I’ve a leak, and it works pretty well.

But since I’ve implemented my last class, I’m facing to a weird problem… I’m almost sure I’m running out of memory, but I can’t prove it, and it is really annoying…

Here is what happen: the card is rebooting itself with some continuous " ? ? ? " characters. If I comment the line that make it fall from OK to KO, the program works again, it can be on any line, but most of the time, it happen on a Serial.print(F(“Blablah”)). As it is a playground, I let it commented, and I continue. But soon or later, I face again to this strange situation on another line… and it’s always when I free up some memory (reduce array for example) that system works again.

However, Sram monitoring can sometime indicate 900bytes available and issue happen ! …
I thought a time, that it was FLASH memory that was full, but not… when I copy/past my program in the Arduino IDE I even don’t overtake 60%…

When I execute step by step it can happen on the very first lines of setup…

Is there something I missed in terms of memory usage ? is it possible that SRAM usage is not the exact reality ? (Until now when I see that I reach 0; I can see UNO flickering…) .
Or is it possible that Flash memory is full, and the IDE indication is wrong ?

Any experience to share with me would be very nice !

I’m not using Strings, I use PROGMEM every time I can. I only used 2 times a Calloc (but there are only called one time in constructor). All class I use are global.

Below, you’ll find the setup function. In the current situation, system reboot continuously between Serial.begin and the first Serial.println(F("–MAIN : Don’t forge

this happen because I added at the end “Serial.print(F(”–ERRORS_HANDLER : Errors storage capacity…
If I comment this line, It continues to work like before… whereas Sram is about 900bytes at this time of the execution…

void setup(){
  Serial.begin(NETWORK_SERIAL_SPEED);
   while (!Serial) {
           ; // wait for serial port to connect. Needed for native USB port only
         }
  
  Serial.println(F("--MAIN : Don't forget to remove serial.begin when releasing.."));

  // Pin configuration
  //BOF:BUTTONS
  pinMode(PUSH_BUTTON_1, INPUT);  
  pinMode(PUSH_BUTTON_2, INPUT);  
  pinMode(PUSH_BUTTON_3, INPUT);  
  pinMode(PUSH_BUTTON_4, INPUT);  
  pinMode(PUSH_BUTTON_5, INPUT); 
  //EOF:BUTTONS
  
  //BOF:EEPROM
  pinMode(EEPROM_PINOUT_ACCESS_MODE, INPUT);  
  //EOF:EEPROM

  //BOF:LIGHT
  pinMode(LIGHT_PINOUT_LED_1, OUTPUT);
  pinMode(LIGHT_PINOUT_LED_2, OUTPUT);
  pinMode(LIGHT_PINOUT_LED_3, OUTPUT);
  pinMode(LIGHT_PINOUT_LED_4, OUTPUT);
  //EOF:LIGHT
  
  //BOF:7 SEGMENTS DISPLAY
  pinMode(PINOUT_BCD_2_1, OUTPUT);  //0001
  pinMode(PINOUT_BCD_2_2, OUTPUT);  //0010
  pinMode(PINOUT_BCD_2_3, OUTPUT);  //0100
  pinMode(PINOUT_BCD_2_4, OUTPUT);  //1000
  //EOF:7 SEGMENTS DISPLAY
  
  //BOF:EEPROM
  uint16_t analogEepromAccessMode = analogRead(EEPROM_PINOUT_ACCESS_MODE);  // read the input pin
  _eepromAccessMode = EEPROM_ACCESS_MODE_DISABLE;
  if(analogEepromAccessMode >= (uint16_t)(ARDUINO_ANALOG_READ_RESOLUTION * (0.25)) ) _eepromAccessMode = EEPROM_ACCESS_MODE_READ;
  if(analogEepromAccessMode >= (uint16_t)(ARDUINO_ANALOG_READ_RESOLUTION * (0.75)) ) _eepromAccessMode = EEPROM_ACCESS_MODE_WRITE;
  //EOF:EEPROM
  
  //BOF:CLASSES INITIALIZATION
  uint16_t startAddress = EEPROM_FIRST_CLASS_USABLE_ADDRESS;
  
  //framework classes
  _tools = new Tools();
  _tools->monitorMinFreeRam();
  
  _handler = new ErrorsHandler("mainEH"); 
  _eeprom = new Eeprom("mainEE",1, startAddress, MAIN_COUNT, sizeof(*_variables));

  for(uint8_t position = 0; position < MAIN_COUNT; position++) {
    _eeprom->load(&_variables[position], position);
  }
  startAddress += _eeprom->getSize();
  _network = new Network("mainNET");

  //pointer recopy for cross relations
  _handler->setEeprom(startAddress);
  startAddress += _handler->getPersistentSize();
  _handler->setNetwork(_network);
  
  //device classes  
  _l1 = new Light("L1", startAddress, LIGHT_PINOUT_LED_1);
  startAddress += _l1->getPersistentSize();
  _l2 = new Light("L2", startAddress, LIGHT_PINOUT_LED_2);
  startAddress += _l2->getPersistentSize();
  _l3 = new Light("L3", startAddress, LIGHT_PINOUT_LED_3);
  startAddress += _l3->getPersistentSize();
  _l4 = new Light("L4", startAddress, LIGHT_PINOUT_LED_4);
  startAddress += _l4->getPersistentSize();
  //EOF:CLASS INITIALIZATION
  
  // WELCOME SCREEN
  Serial.println(F("--################### ARDUINO DEMO BOARD ######################"));
  Serial.println(F("--#  Framework testing : Error Handler object         05/2020 #"));
  Serial.println(F("--#############################################################"));
  
  //debug
  Serial.print(F("--FRAME : Size of Frame object is: "));
  Serial.println(sizeof(_inbound));
  Serial.print(F("--EEPROM : Access mode set to: "));
  Serial.println(_eepromAccessMode);  
  Serial.print(F("--ERRORS_HANDLER : Errors storage capacity: "));
  Serial.println(_handler->getMaxStoredErrors(false));  

  
  //BOF:NETWORK
  _network->clearFrame(&_inbound);			// inbound frame initialization : ready to receive
  _network->clearFrame(&_outbound);			// outbnound frame initialization : ready to send
  //EOF:NETWORK
  
}

Annotation 2020-05-12 235801.png

which freeMemory?

There is one which showed 2500 bytes free on Uno with stack full

Would you mind Sending your whole Code? I think, you have too big progmem writings and you override your System files. You might need to use correct sections.

Send your Code first, then we will see.

Juraj:
which freeMemory?

There is one which showed 2500 bytes free on Uno with stack full

You're giving me hope, I'm using the one we can find on forums, I just replaced size_t by int32_t to have negative values (I know it's weird but this way, I still got the alarm when I go to far.. otherwise negative gave positive high value with no alarm) :

int32_t getFreeRam ()  {
  int value = 0;
  int result = 0;
  extern int *__brkval;
  extern int __heap_start;
  result = (int)&value - ((int)__brkval == 0 ? (int)&__heap_start : (int)__brkval);
  return result;
}

dr-o:
Would you mind Sending your whole Code? I think, you have too big progmem writings and you override your System files. You might need to use correct sections.

Send your Code first, then we will see.

I can, but it's about 1800 lines.. which is better for reading, to copy/paste between code tags or to add a link to the complete code ? Let me know

Thanks a lot for your help !

djfox007:
I can, but it's about 1800 lines.. which is better for reading, to copy/paste between code tags or to add a link to the complete code ? Let me know

Thanks a lot for your help !

Here is the link to the whole sketch.

My little framework is simple, it :

  • Sends status over the serial
  • Get information from the serial
  • Has a tool class with usefull functions (like display the min Sram reached during the execution)
  • Has an eeprom class at disposal of others class for storing settings
  • Has an error handler to be able to warn and eventually store trouble codes.
  • As it's a playground I created a Led class with no real usage except to validate it works like I have in my mind.

Hope this helps to understand.