I2C LCD Screen, Arduino Freezing after 12-32 hours

Hello all!

I have a Arduino UNO with a program that does some basic temperature and light control. The program worked great until I swapped from a standard 16x2 LCD screen to a 20x4 I2C LCD screen. Now the Arduino will run great for a while, usually 12-32 hours, but then it will display crazy data on the screen and totally stop responding.

I heard that there was a problem with the Wire.h Library that can cause this, something about noise on the line causing the screen not to respond, and sending the Arduino into an endless loop. There are new libraries that are supposed to address this issue, however some of my other libraries like LiquidCrystal_I2C.h reference the Wire.h library directly (by using wire.xxx commands) so I can't switch to the updated, fixed library like WCWire.h.

What can I do?

Thank you for your help!
Whiskey

How is your wiring between the Arduino and the display ?

Quite good in fact. I have a connector soldered to a shield which plugs into the Arduino. A 5 foot wire plugs into that connector, and this goes out to a plug which connects to the screen. The screen is mounted, and the arduino is inside a plastic project case, the wireing is behind an aquarium stand so it is not touched.

Whiskey

5 ft = 1.52 meters

That is long for I2C. It means that the SDA and SCL might cause noise to each other, and perhaps also from the power wires to SDA and SCL.
You need to select the wires in cable for SDA and SCL that has the least influence on each other.

A single wire (not in a cable) for SDA and a single wire for SCL free in the air would be very ugly, but that would work.

As far as I know, the Arduino Wire library has some timeouts, but it is not full proof against I2C bus errors. I have seen a number of propositions to improve it, but none of those are implemented in the library yet.
The I2C is designed to be used within a pcb board, it was never designed to extend it into a cable.

Peter_n:
5 ft = 1.52 meters

That is long for I2C. It means that the SDA and SCL might cause noise to each other, and perhaps also from the power wires to SDA and SCL.
You need to select the wires in cable for SDA and SCL that has the least influence on each other.

A single wire (not in a cable) for SDA and a single wire for SCL free in the air would be very ugly, but that would work.

As far as I know, the Arduino Wire library has some timeouts, but it is not full proof against I2C bus errors. I have seen a number of propositions to improve it, but none of those are implemented in the library yet.
The I2C is designed to be used within a pcb board, it was never designed to extend it into a cable.

Oh :frowning: Well, that explains why I didn't have problems during testing, and why I never have problems with my RTC. It's good to have a definite answer that this can't work though, that way I don't waste time trying to figure out what might be wrong.
Unfortunately with this aquarium controller I need that wire to be that length, and I also need this to be reliable, because if it ever freezes in the "Heater on" position my fish are in trouble.

Do I have any other options? Other serial interfaces maybe? Going from the parallel interface to the serial freed up so many data pins on my somewhat limited UNO, I'd have to remove some nice functionality if I needed to go back.

Thank you!
Whiskey

Slower I2C, or lower pullup resistor, or an other cable.
What do you use now for pullup resistors for SDA and SCL ?

Peter_n:
Slower I2C, or lower pullup resistor, or an other cable.
What do you use now for pullup resistors for SDA and SCL ?

I do not currently use pull up resistors on SDA and SCL, my understanding was that the wire library used built in ones.
My RTC may also have some,.. but I didn't purposely use any.

What should I be using?
Thank you,
Whiskey

The internal pullup resistors are 50k or 60k or something like that, that is useless with those wires.

Every module with I2C could have pullup resistors. Try to find the schematics and calculate the total parallel pullup resistor value. A normal value would be 4k7, but you can try 2k2 (for the total parallel value).

Peter_n:
The internal pullup resistors are 50k or 60k or something like that, that is useless with those wires.

Every module with I2C could have pullup resistors. Try to find the schematics and calculate the total parallel pullup resistor value. A normal value would be 4k7, but you can try 2k2 (for the total parallel value).

Okay,.. It LOOKS like neither of my I2C devices include pull UP resistors, I only have a schematic for one though, and rumors on the other.

So,.. that means to end up with about 4.7K Ohm I need a resistor around 5K ohm, or for 2.2K I need about 2.3K Ohm.

And this needs to be a Pull UP resistor, right? That sounds odd to me so I just wanted to Verify. Do I pull it up to 5V?

Should I place these Resistors at the Screen on the end of the long wire? Or should I place them at the Arduino side?

Thank you,
Whiskey

I looked up the microchip spec and answered some of my own questions (should have done that a while ago) :blush:

I placed a 3.9K ohm resistor between the +5 rail and the SDA and another one between the +5 rail and SCL. The circuit still works! That's a good sign. I'll now monitor for a few days and see if it freezes again.

Do you think the best place for this is at the Arduino? Or do you think the end of the wire is better? I'll solder them in if this works for me.

If it works for a few days, do you think I could depend on it long term? Or is this always going to be an "Iffy" connection because of the long wires? I don't care if I have to clear the LCD every once and a while because of bad data, but I can't have the thing locking up.

Thank you for all your help!!!! You guys are awesome :slight_smile:
Whiskey

Using no pullups (just the internal) and 3k9 is a big difference. But I can not guarantee it will work.
If you give links to your modules, I can try to see if there are pullup resistors. Most modules have them.
Can you try other values, like 10k ? or 22k ? If that already makes it work, then 3k9 will be good.

The pullup resistors should be placed at the Arduino side. There is no science behind that, it is common use that the I2C Master has the pullup resistors.

When all your modules are 5V modules, and they have a 5V I2C bus, you can connect the pullup to 5V.
When one of the modules is a 3.3V module, you might fry it when the SDA and SCL are pulled to 5V. In that case you need to pullup to 3.3V. But if you have 5V I2C mixed with 3.3V I2C and longer wires, you better use a level shifter to get it right.

You don't have to calculate the exact pullup resistor. You could have used 2k2 or 4k7. Some I2C devices allow a pullup of 1k (the total parallel pullup resistor), while other devices start grumbling with 2k2. So the rule of thumb is to use 4k7. The maximum value is about 10k, higher values makes the I2C bus vulnerable for electric noise, even if the I2C stays on a pcb board.

Peter_n:
Using no pullups (just the internal) and 3k9 is a big difference. But I can not guarantee it will work.
If you give links to your modules, I can try to see if there are pullup resistors. Most modules have them.
Can you try other values, like 10k ? or 22k ? If that already makes it work, then 3k9 will be good.

The pullup resistors should be placed at the Arduino side. There is no science behind that, it is common use that the I2C Master has the pullup resistors.

When all your modules are 5V modules, and they have a 5V I2C bus, you can connect the pullup to 5V.
When one of the modules is a 3.3V module, you might fry it when the SDA and SCL are pulled to 5V. In that case you need to pullup to 3.3V. But if you have 5V I2C mixed with 3.3V I2C and longer wires, you better use a level shifter to get it right.

You don't have to calculate the exact pullup resistor. You could have used 2k2 or 4k7. Some I2C devices allow a pullup of 1k (the total parallel pullup resistor), while other devices start grumbling with 2k2. So the rule of thumb is to use 4k7. The maximum value is about 10k, higher values makes the I2C bus vulnerable for electric noise, even if the I2C stays on a pcb board.

Here are links to my 2 I2C modules:

RTC from SparkFun, they provide a schematic and I don't see any pull up resistors. Looking at the physical board I also don't see any pull up resistors:
Device: SparkFun Real Time Clock Module - BOB-12708 - SparkFun Electronics
Schematic: http://dlnmh9ip6v2uc.cloudfront.net/datasheets/BreakoutBoards/RTC-Module-v13.pdf

This one is a little more of a guess, StainSmart LCD with I2C interface:
Where I bought it: http://www.amazon.com/gp/product/B0080DYTZQ/ref=oh_details_o07_s00_i02?ie=UTF8&psc=1
Stain Smart's Page: http://www.sainsmart.com/sainsmart-iic-i2c-twi-serial-2004-20x4-lcd-module-shield-for-arduino-uno-mega-r3.html
They do have a download there that has specs on it, as well as a PDF of the traces on the I2C Board, I don't see any resistors, and the board itself I can only look at one side because it's soldered to the display but I don't see resistors there either. I'm not impressed with the level of information provided, or the fact that the wrong I2C address was provided but if I can get it to work this will save me from having to redesign everything to go to a Mega.

Both Modules take 5V power BTW, and so far the circuit is working great!

Thank you so much for all your help Peter!
Whiskey

I didn't see any pullup resistor either.
Perhaps you had a lot of luck that it was working with the other display and the wires and only the internal pullup resistors..

You can keep the 3k9 as pullup resistors. If needed, you can use a little lower value.

Meanwhile we are still waiting for the Wire library to have timeouts on every operation....

Before, with the other display, I was using a parallel interface not I2C. The only thing running I2C was the RTC modal, and it's wires were less than 1/4 inch long. The RTC is mounted directly to the Shield.

It makes sense that when I added another I2C device and long wires it would shine a spotlight on my existing resistor issue.

Thank you for all your help!! So far the Arduino has not locked up. If it lasts a week I think I will trust it :slight_smile:

Whiskey

The pullup resistors should be placed at the Arduino side. There is no science behind that, it is common use that the I2C Master has the pullup resistors.

There is science behind it!

I2C is a simple low frequency transmission line. Long transmittion lines need to be terminated at each end in order to avoid reflection of the pulses carried on the line. A 1.5m I2C is very short, so the pull-up can be anywhere on the line with 4k7 should be enough.

I once ran a 116m I2C line over CAT5 cable out doors. I used twisted pairs for SDA and SDL where one of the twisted pair is grounded at the Arduino end. This effectively shields the SDA and SDL. I used 2k2 at each end of both SDA and SDL lines. This configuration was at the limit of the Arduino to pull the signal lines low enough and to overcome the transmission line capacitance. An oscilloscope can show when the correct pull-up is selected.

If you suspect noise is causing the problem, ensure the ground wire between Arduino and the LCD is good. You could also use pairs as described to provide shielding.

Thank you for jumping in George! The fact that you were able to make a 100M run work reliably gives me lots of hope!!!!

Good news! So far it is working great, no lockups. This is the longest it's worked so far, it seems like the lack of resistors was the issue.

Whiskey

We are still going strong!!!!

I'm going to go ahead and trust it. This forum is great!! Thank you.

James