LCD Producing Garbage After Time

So I have an Arduino Mega 2560 rev3 that I am using to control the lights and heater of my snakes enclosure. I am using an HD44780 20X4 LCD screen to display the time, number of times the loop has run, humidity readings, and temperature readings.

The problem that I am having, is that after a seemingly random period of time garbage text starts to appear, usually starting in the whitespace, then, if left alone, the garbage starts overwriting the text.

I am attaching my code, and I will post pictures of the LCD screen.

Any help would be greatly appreciated.

main4.txt (18.3 KB)

These are what the screen should look like:

These are of it starting to display garbage:

Lastly, these are of it displaying its garbage:

Could be caused by spikes on the lines when things are switching. Outside of that, it might be violating timing specs or your program might be smashing data. Do you use dynamic memory allocation (malloc())? Do you have an oscilloscope? Does your program continue to function correctly after the display is corrupted?

afremont:
Do you use dynamic memory allocation (malloc())? Do you have an oscilloscope? Does your program continue to function correctly after the display is corrupted?

I'm not familiar with malloc(), though I am using F() macros for my constant strings.
Unfortunately I don't have an o-scope.
The program does continue to function.

If the program continues to function correctly, then I would lean towards noise causing the corruption. Try adding some bypass capacitance on the power pin of the LCD (something like a .1uF and perhaps a 10uF) and see if that helps any. If you are switching relays, make sure you have the diode clamps across the coils.

afremont:
If the program continues to function correctly, then I would lean towards noise causing the corruption. Try adding some bypass capacitance on the power pin of the LCD (something like a .1uF and perhaps a 10uF) and see if that helps any. If you are switching relays, make sure you have the diode clamps across the coils.

Thanks, I'll pick some caps up this afternoon. As for the relays, I have 16 channel relay module. I assume that it includes diode clamps...

I don't see anything dangerous in your code and can't see any simple explanation for the corruption.

If the problem is reproducible, I suggest you create a copy of your sketch and remove everything except the LCD I/O, and replace all those calculated values with the equivalent constant numeric values. Do you still see the problem? If so, there's probably something wrong in the way you're driving the display; if not, the rest of the code is having unexpected side effects and you can start reinstating it to find out which part triggers the problem.

Your code doesn't look as if it would use much RAM but just to eliminate the possibility that you're running out of RAM I suggest you add some code to display the free memory.

PeterH:
I don't see anything dangerous in your code and can't see any simple explanation for the corruption.

If the problem is reproducible, I suggest you create a copy of your sketch and remove everything except the LCD I/O, and replace all those calculated values with the equivalent constant numeric values. Do you still see the problem? If so, there's probably something wrong in the way you're driving the display; if not, the rest of the code is having unexpected side effects and you can start reinstating it to find out which part triggers the problem.

Your code doesn't look as if it would use much RAM but just to eliminate the possibility that you're running out of RAM I suggest you add some code to display the free memory.

Thank you, these are really good ideas. Let the troubleshooting begin!

So I found an old 0.01uF cap laying around and put it across power to the LCD and, after an hour or so it started glitching again. So I am now running only the code that talks to the LCD (replaced variables with constants). Now comes the wait...

The cap is still connected, and will stay so...noise filtration is a good thing.

When you get some caps, get a bunch of the .1uF caps, they make good bypass caps. You're right, filtering is a good thing. You aren't switching any brushed DC motors are you? Depending upon your wiring and the stuff around it, any of the wires running to the LCD could be carrying noise in. Are you using any of the pins for other purposes, or anything where you might be accidentally leaving on in the wrong state (input vs. output). I don't know if you have any ISRs, but it could be that one is running and expecting some pin to bin in a specific state, but main level code occasionally changes it right before the interrupt fires. Just food for thought.

A simple thing to try that has helped me in the past. Before you do a block of updates to the LCD, use lcd.noDisplay() and then turn it on again at the end with lcd.display(). Thgis stops the display updating immediately but changes the memory buffer of the display. It makes no difference to the perception of updates on the display but fixed my (occasional) odd character apprearing on the screen.

marco_c:
A simple thing to try that has helped me in the past. Before you do a block of updates to the LCD, use lcd.noDisplay() and then turn it on again at the end with lcd.display(). Thgis stops the display updating immediately but changes the memory buffer of the display. It makes no difference to the perception of updates on the display but fixed my (occasional) odd character apprearing on the screen.

Thanks, I'll throw that in JIC. Just to be clear, you turn off the LCD, write to it, then turn it back on?

afremont:
When you get some caps, get a bunch of the .1uF caps, they make good bypass caps. You're right, filtering is a good thing. You aren't switching any brushed DC motors are you? Depending upon your wiring and the stuff around it, any of the wires running to the LCD could be carrying noise in. Are you using any of the pins for other purposes, or anything where you might be accidentally leaving on in the wrong state (input vs. output). I don't know if you have any ISRs, but it could be that one is running and expecting some pin to bin in a specific state, but main level code occasionally changes it right before the interrupt fires. Just food for thought.

Thanks, I will. The 0.01uF that I'm using will work though, right?
I'm not using any motors; random emi from the wires is quite possible, I need to borrow my buddy's picoScope and check them. All of my pins are single purpose, and to my knowledge, no ISRs are running.

Technically you turn off the updates and then turn them back on. The power to the lcd stays on and the display stays powered on. You should not have any delay()s in the on/off bracket of code or it will be noticeable.

Update

So I have added the noDisplay and display, and it doesn't fix the problem, but it seems to allow the program to fix the display after garbage starts appearing. After seeing this, I decided to see what would happen if I cleared the display (insert spaces for every character) after the noDisplay before writing my values to it on each loop. This seems to have fixed the issue, though more time is needed to make sure. I am going to replace the "clearing" code with lcd.clear...it should provide essentially the same function, right?