can low memory cause the uno to hault

hi guys when i compile my code on arduino uno i get the following warning

"Sketch uses 28,582 bytes (88%) of program storage space. Maximum is 32,256 bytes.
Global variables use 1,624 bytes (79%) of dynamic memory, leaving 424 bytes for local variables. Maximum is 2,048 bytes.
Low memory available, stability problems may occur"

the code gets uploaded ok , works ok

the problem happens after some time (sometimes minutes sometimes a day) , the arduino halts it doesnt restart or do anything it just halts . if i reset it it works again then it halts after time

can this be due to memory low warning or its some other problem.

the code is attached and i can explain it if you think that there is any conflict.

with_files.ino (8.39 KB)

Be aware that you only have 32,768 bytes of flash if you upload via SPI (USBasp or using another arduino), otherwise you have to worry about the bootloader taking up flash as well.

Also,even though you use 1,624 bytes of ram, doesn't mean that there are not variables and buffers and arrays using the ram behind the scenes.
I bet Ethernet.h, SD.h, SPI.h, and Serial are using buffers.

You did not include TimerOne.h or Debounce.h, so I cant help you there. But it is possible that if you are allocation memory then you are growing the heap and even when you deallocate it, the heap doesn't grow smaller, it just creates a fragmented heap. This seems to be the case in your saving() function (which you will need to account for in ram usage).

Another problem I see is this

Timer1.initialize(2000000); // set a timer 2 seconds

which should be

Timer1.initialize(2000000L); // set a timer 2 seconds

because most arduino's default set data types to 16 bit, thus this is an overflow, you must force it to be a long

Also, you should use progmem for your strings, for example

Serial.println(F("Card failed, or not present")); //this will save the string to flash, so you save ram, 28 bytes of it

You've got a few String type variables in there. These are going to fragment your memory so you're probably running out of memory. Try to use char arrays instead.

first of all thaaaaaaaanks :smiley: i was starting to loose hope

now i will trun all my println to save on flash

what will be the gain of turning the string variables to array of characters arent they the same? and please suggest how to do it as im not that good in C :sweat_smile:

what else can i do to lower my memory usage

the Timer one overflow is not a matter to me because i dont care about the actual time all i need is periodic call to repeats function , does it have any other bad effects?

attached are the Timerone and the debounce library

libs.zip (78.4 KB)

abdullahshawky:
what will be the gain of turning the string variables to array of characters arent they the same? and please suggest how to do it as im not that good in C :sweat_smile:

NO! They're not the same. The String type is a class with all kinds of dross built in. Although it's helpful dross for newbies, it comes at a cost.

Checking out your variable dataString, I notice that this is only ever used in one function. ( saving() ) So there's no reason this should be a global variable at all. Instead simply delete it from the top of your file.

Here's a rewrite of your saving() function using a local char array instead.

void saving()
{
char dataString[40];
sprintf(dataString, "%02d/%02d/%04d %02d:%02d:%02d Production=%l",
      clock.dayOfMonth, clock.month, clock.year, 
      clock.hour, clock.minute, clock.second, total
      );

      dataFile = SD.open("datalog.txt", FILE_WRITE);
      if (dataFile) 
      {
        dataFile.println(dataString);
        dataFile.close();
      }
}

i will try the adjustment tomorrow on the lab and come to you again

but i need to know is it a problem to me to fill the flash memory too , i use normal arduino IDE to upload my sketches

thanks

abdullahshawky:
i will try the adjustment tomorrow on the lab and come to you again

but i need to know is it a problem to me to fill the flash memory too , i use normal arduino IDE to upload my sketches

thanks

If your sketch fits, it fits. If it uploads without error then it's unlikely to be a problem.

If you ever run out of space, you may get a little more flash by uploading via SPI or another arduino, this will grant you another ~2k of flash. If you are still pushing for more flash, then under worst case scenarios you can always upgrade to an ATmega1284P with will have more flash then you know what to do with (although I am not sure if your timer functions will work or not).

Another thing you may want to try is removing all occurances of digitalWrite, digitalRead, and pinMode and replacing them with "True C" equivalents. It saves not only time, but some flash.

Extra: http://forum.arduino.cc/index.php?topic=91079.0

// --- PIN MODE: OUTPUT  --- 

  DDRD |= _BV (0); // pinMode (0, OUTPUT);
  DDRD |= _BV (1); // pinMode (1, OUTPUT);
  DDRD |= _BV (2); // pinMode (2, OUTPUT);
  DDRD |= _BV (3); // pinMode (3, OUTPUT);
  DDRD |= _BV (4); // pinMode (4, OUTPUT);
  DDRD |= _BV (5); // pinMode (5, OUTPUT);
  DDRD |= _BV (6); // pinMode (6, OUTPUT);
  DDRD |= _BV (7); // pinMode (7, OUTPUT);
  DDRB |= _BV (0); // pinMode (8, OUTPUT);
  DDRB |= _BV (1); // pinMode (9, OUTPUT);
  DDRB |= _BV (2); // pinMode (10, OUTPUT);
  DDRB |= _BV (3); // pinMode (11, OUTPUT);
  DDRB |= _BV (4); // pinMode (12, OUTPUT);
  DDRB |= _BV (5); // pinMode (13, OUTPUT);
  DDRC |= _BV (0); // pinMode (A0, OUTPUT);
  DDRC |= _BV (1); // pinMode (A1, OUTPUT);
  DDRC |= _BV (2); // pinMode (A2, OUTPUT);
  DDRC |= _BV (3); // pinMode (A3, OUTPUT);
  DDRC |= _BV (4); // pinMode (A4, OUTPUT);
  DDRC |= _BV (5); // pinMode (A5, OUTPUT);

// --- PIN MODE: INPUT  --- 

  DDRD &= ~_BV (0); // pinMode (0, INPUT);
  DDRD &= ~_BV (1); // pinMode (1, INPUT);
  DDRD &= ~_BV (2); // pinMode (2, INPUT);
  DDRD &= ~_BV (3); // pinMode (3, INPUT);
  DDRD &= ~_BV (4); // pinMode (4, INPUT);
  DDRD &= ~_BV (5); // pinMode (5, INPUT);
  DDRD &= ~_BV (6); // pinMode (6, INPUT);
  DDRD &= ~_BV (7); // pinMode (7, INPUT);
  DDRB &= ~_BV (0); // pinMode (8, INPUT);
  DDRB &= ~_BV (1); // pinMode (9, INPUT);
  DDRB &= ~_BV (2); // pinMode (10, INPUT);
  DDRB &= ~_BV (3); // pinMode (11, INPUT);
  DDRB &= ~_BV (4); // pinMode (12, INPUT);
  DDRB &= ~_BV (5); // pinMode (13, INPUT);
  DDRC &= ~_BV (0); // pinMode (A0, INPUT);
  DDRC &= ~_BV (1); // pinMode (A1, INPUT);
  DDRC &= ~_BV (2); // pinMode (A2, INPUT);
  DDRC &= ~_BV (3); // pinMode (A3, INPUT);
  DDRC &= ~_BV (4); // pinMode (A4, INPUT);
  DDRC &= ~_BV (5); // pinMode (A5, INPUT);

// --- DIGITAL WRITE: HIGH  --- 

  PORTD |= _BV (0); // digitalWrite (0, HIGH);
  PORTD |= _BV (1); // digitalWrite (1, HIGH);
  PORTD |= _BV (2); // digitalWrite (2, HIGH);
  PORTD |= _BV (3); // digitalWrite (3, HIGH);
  PORTD |= _BV (4); // digitalWrite (4, HIGH);
  PORTD |= _BV (5); // digitalWrite (5, HIGH);
  PORTD |= _BV (6); // digitalWrite (6, HIGH);
  PORTD |= _BV (7); // digitalWrite (7, HIGH);
  PORTB |= _BV (0); // digitalWrite (8, HIGH);
  PORTB |= _BV (1); // digitalWrite (9, HIGH);
  PORTB |= _BV (2); // digitalWrite (10, HIGH);
  PORTB |= _BV (3); // digitalWrite (11, HIGH);
  PORTB |= _BV (4); // digitalWrite (12, HIGH);
  PORTB |= _BV (5); // digitalWrite (13, HIGH);
  PORTC |= _BV (0); // digitalWrite (A0, HIGH);
  PORTC |= _BV (1); // digitalWrite (A1, HIGH);
  PORTC |= _BV (2); // digitalWrite (A2, HIGH);
  PORTC |= _BV (3); // digitalWrite (A3, HIGH);
  PORTC |= _BV (4); // digitalWrite (A4, HIGH);
  PORTC |= _BV (5); // digitalWrite (A5, HIGH);

// --- DIGITAL WRITE: LOW  --- 

  PORTD &= ~_BV (0); // digitalWrite (0, LOW);
  PORTD &= ~_BV (1); // digitalWrite (1, LOW);
  PORTD &= ~_BV (2); // digitalWrite (2, LOW);
  PORTD &= ~_BV (3); // digitalWrite (3, LOW);
  PORTD &= ~_BV (4); // digitalWrite (4, LOW);
  PORTD &= ~_BV (5); // digitalWrite (5, LOW);
  PORTD &= ~_BV (6); // digitalWrite (6, LOW);
  PORTD &= ~_BV (7); // digitalWrite (7, LOW);
  PORTB &= ~_BV (0); // digitalWrite (8, LOW);
  PORTB &= ~_BV (1); // digitalWrite (9, LOW);
  PORTB &= ~_BV (2); // digitalWrite (10, LOW);
  PORTB &= ~_BV (3); // digitalWrite (11, LOW);
  PORTB &= ~_BV (4); // digitalWrite (12, LOW);
  PORTB &= ~_BV (5); // digitalWrite (13, LOW);
  PORTC &= ~_BV (0); // digitalWrite (A0, LOW);
  PORTC &= ~_BV (1); // digitalWrite (A1, LOW);
  PORTC &= ~_BV (2); // digitalWrite (A2, LOW);
  PORTC &= ~_BV (3); // digitalWrite (A3, LOW);
  PORTC &= ~_BV (4); // digitalWrite (A4, LOW);
  PORTC &= ~_BV (5); // digitalWrite (A5, LOW);

// --- DIGITAL READ  --- 

  x = (PIND & _BV (0)) == 0; // digitalRead (0);
  x = (PIND & _BV (1)) == 0; // digitalRead (1);
  x = (PIND & _BV (2)) == 0; // digitalRead (2);
  x = (PIND & _BV (3)) == 0; // digitalRead (3);
  x = (PIND & _BV (4)) == 0; // digitalRead (4);
  x = (PIND & _BV (5)) == 0; // digitalRead (5);
  x = (PIND & _BV (6)) == 0; // digitalRead (6);
  x = (PIND & _BV (7)) == 0; // digitalRead (7);
  x = (PINB & _BV (0)) == 0; // digitalRead (8);
  x = (PINB & _BV (1)) == 0; // digitalRead (9);
  x = (PINB & _BV (2)) == 0; // digitalRead (10);
  x = (PINB & _BV (3)) == 0; // digitalRead (11);
  x = (PINB & _BV (4)) == 0; // digitalRead (12);
  x = (PINB & _BV (5)) == 0; // digitalRead (13);
  x = (PINC & _BV (0)) == 0; // digitalRead (A0);
  x = (PINC & _BV (1)) == 0; // digitalRead (A1);
  x = (PINC & _BV (2)) == 0; // digitalRead (A2);
  x = (PINC & _BV (3)) == 0; // digitalRead (A3);
  x = (PINC & _BV (4)) == 0; // digitalRead (A4);
  x = (PINC & _BV (5)) == 0; // digitalRead (A5);

KenF:
If your sketch fits, it fits. If it uploads without error then it's unlikely to be a problem.

I don't think that's right at all. much more to the point is what is clearly advised:...

"Sketch uses 28,582 bytes (88%) of program storage space. Maximum is 32,256 bytes.
Global variables use 1,624 bytes (79%) of dynamic memory, leaving 424 bytes for local variables. Maximum is 2,048 bytes.
Low memory available, stability problems may occur"

Where the programme indeed fits and uploads without error but there is no guarantee it will run properly.

While I wouldn't use strings like that at all, I think the operative number is 28,582, which spells likely doom, even before the programme starts running. The programme looks fairly innocuous, so I assume it is in the libraries where the real action is taking place and they are what are hogging the memory. I can't tell what it is supposed to do, but it is likely that you will want to expand upon it in the future. Expanding in the near future tends to be what Arduinos are all about.

So take it from somebody who has been there - it's time to get a Mega. I submit the Uno is not up to doing what you want to do. If that isn't absolutely true now, it will be by next month, so there is no point in banging your head against a brick wall for the rest of this month.

 Timer1.attachInterrupt( Repeats ); // attach the service routine here
...
void Repeats()
{
   sendether(); 
   saving();
   Serial.println(total);
   writetotal();
}

Don't do serial prints inside an ISR.

String dataString = ""; //COLLECTION STRING FOR SD SAVING
String dataString2 = ""; //COLLECTION STRING FOR SD SAVING
String dataString1 = "";

Using String can cause memory fragmentation which will eventually cause the program to crash.

Getting a larger microcontroller merely delays this happening.

Nick_Pyner:

KenF:
If your sketch fits, it fits. If it uploads without error then it's unlikely to be a problem.

I don't think that's right at all. much more to the point is what is clearly advised:...

Could you perhaps educate me as to what is going to use up the remaining progmem AFTER the sketch has been uploaded?

abdullahshawky:
but i need to know is it a problem to me to fill the flash memory too , i use normal arduino IDE to upload my sketches

I agree with KenF. Either the sketch fits or it doesn't. I wouldn't care if there were zero bytes free (excepting if I wanted to add improvements in the future).

As for RAM, I've read about sketches that run for days with only 4 bytes of stack free.

the problem happens after some time

Likely to be stack fragmentation then. Or possibly some problem communicating with the Ethernet client that has not been handled correctly.

KenF:
Could you perhaps educate me as to what is going to use up the remaining progmem AFTER the sketch has been uploaded?

No, I can't, but the message of dire warning, given at the point of uploading, not running, is plain for anybody who can read and comprehend the meaning of "stability problems", and I assume who ever wrote it knows the reason why. For myself, I can only go by the deafening voice of experience - experience which is more or less what the OP is experiencing now, although I don't recall getting the warnings.

In short, I'm the guy who spent a couple of weeks banging his head against the wall, and I managed to do it without any string stuff whatsoever. The bottom line is that - if your programme is hanging around 29 -30k, you are straying into the danger zone. Further, shaving off a couple of dozen k here and there is a futile exercise which merely puts off the inevitable.

It's not for me to doubt a superguru like Nick Gammon, but the warning is there, and running programmes with 4 bytes of stack is probably not for everybody.

Nick_Pyner:
It's not for me to doubt a superguru like Nick Gammon, but the warning is there, and running programmes with 4 bytes of stack is probably not for everybody.

It needs to be done with care, for sure, because a function call would use 2 bytes, at least.

approach is wrong.

Nick_Pyner:
No, I can't, but the message of dire warning, given at the point of uploading, not running, is plain for anybody who can read and comprehend the meaning of "stability problems", and I assume who ever wrote it knows the reason why.

If you're attempting to solve issues with a sketch that is failing by simply reducing it's size, then your approach is wrong. You may get lucky and eliminate the real problem by your modifications but that's what it is, LUCK. Hence the head banging experience.

Instead you should be focusing your efforts on memory leaks, areas that can cause closed loops, or anything that causes the stack or heap to overflow.

The String class (especially as global variables) causes memory fragmentation and so is one of the first things to be eliminated. (hence being one of my first suggestions).

The over use of global variables, is another issue. If something is being used by just one function then having it occupy memory when it's not being used is another waste of memory.

Use of variables when constants would suffice is another area that can make all the difference.

Use of PROGMEM and the F macro is another great memory saving method.

Simply reducing the space you're sketch is occupying is NOT going to solve anything.

I agree, and also you need to consider that if your program crashes after running for a day because "it ran out of RAM" them doubling the amount of RAM just means it will crash after two days, hardly a great outcome.

In addition, if the "crash" is due to other things (eg. an interrupt occurring at an unexpected moment) then you won't even have bought yourself two days, by increasing RAM.

KenF:
approach is wrong. If you're attempting to solve issues with a sketch that is failing by simply reducing it's size, then your approach is wrong.

I don't think you bothered to read what I said. I'm not advocating reducing the size of the sketch. Quite the opposite, I submit it is a futile exercise. What I am advocating is getting the boy off the man's job. While the programme size was much the same, 29k, in my case the difference was between more or less instant failure and running unattended for six months or so.

Seriously guys :grin: :grin: :grin: thannnnnnnks

i have learned alot , and starting to eliminate my fatal mistakes now , see you in 5 hours after i try it :fearful:

Nick Gammon

Can you please tell me why not to use Serial.println inside an interrupt because i use it to debug my counting when the machine has errors , i also call functions inside the interrupt is that ok and can i print serial inside a function called by an interrupt

also what happens if i declare a variable and use it in the interrupt that is not a volatile?

thanks in advance , happy to see you in my post :slight_smile: