I2C (SSD1311 Oled) and EMI interference in car

Hello,

I have an Arduino Nano connected to a CAN-BUS module and communicating with the car ECU..

For the power supply I use a buck converter which converts the 12-14v of the car to 9v and I then connect that to the Vin pin of the Nano.

I also use this OLED display WideHK which states that it uses SSD1311 controller.

I have not used a library because they were all setting delays and that caused the CAN-BUS to not work properly as it didn't have enough time to read the messages and clear its buffer.

What happens so far:

The display (16x2) is generally working properly but it messes the text up randomly when the engine is running. When I am with the key ON it reads and displays flawlessly. When I start the car, after a while (which could be from 5 seconds to anything) it does the following:

Suppose the text to display is:
"HELLO ARDUINO!!!" 1st line
"HELLO WORLD TEST" 2nd line.

The display shows the following:
"LD TESTRDUINO!!!" 1st line
"HELLO WORLD TEST" 2nd line

And then it displays correctly. It is happening for a fraction of a second each time.

The above is the most frequent problem in different variants of the length of the 2nd line text.

Or it could show:
"#HHELLO ARDUIN"
"HELLO WORLD TEST" (# is for a dotted symbol for empty character).

I have to mention that in the past the above problems where causing the arduino to freeze as well but I tweaked the twi.c file to include a timeout and reset the I2C interface by using code lying around on the net. I am also at TWBR 12=400Khz and I can't lower that because it will cause malfunction of the CAN-BUS (even if it has its own interrupt)..

Now, when I had a 40cm header cable the problem seemed to happen only for the first 5-10seconds and then the display was working properly.

Now I replaced that cable with a 3meter cable in order to place the display in the dash and it is doing that all the time and messes up the display instantly, then goes back to normal.

I used an RJ11 connector with a 4wire telephone cable which probably is not appropriate and works like an antenna for EMI?? But even with the 40cm header cable it was doing that in the beginning.

I also tried a ferrite and wrapped the cable around it on the display end AND the arduino end with no luck..

The code for sending commands and text is the following:

void sendCommand(unsigned char command)
{    
    Wire.beginTransmission(OLED_Address);    // **** Start I2C 
    Wire.write(OLED_Command_Mode);         // **** Set OLED Command mode
    Wire.write(command);
    Wire.endTransmission();                    // **** End I2C 
}
void sendData(uint8_t *pbytes, uint8_t len)
{
    Wire.beginTransmission(OLED_Address);
    Wire.write(OLED_Data_Mode);
    Wire.write(pbytes,len);
    Wire.endTransmission();                   // **** End I2C 
}

Also, regarding the Pull-up resistors, the display has 4.7K resistors on it already and I measure 4.6KOhms between SDA and VCC and 4.2kOhms between SCL and VCC on the Arduino side but 3.8K on both SDA-SCL and VCC on the display side. I guess I am not reading 4.7 because of the arduino internal resistors? Arduinos alone read around 6.5KOhms between A4 and VCC and A5 and VCC..

Any suggestions? Had been struggling with that in the past with no luck! The only progress is the I2C not freezing and reset..

Thank you

I was doing some testing on the bench and is impossible to make the problem appear but then I rememberd some other’s member post stating:

“Jumpering the SDA-SCL pins will cause the I2C to freeze”… So I tried it and guess what!

I am getting very similar results like when the engine is on!! Of course mine is restarting and not freezing but it seems that it is definately an EMI problem…!

Waiting for your thoughts!

Having a 3m cable with a 400kHz you're a lucky guy that you get even that through the cable. The maximum bus length for a 100kHz bus is 0.5-1m. You might get it running reliably with the same length (up to 1m) with 400kHz if you're using a good cable but for more than 1m you should use I2C expander chips as p.e. the PCF8575 on both ends of the long line.

If ever possible I would move the Arduino near the display and make the CAN bus cable longer. The CAN bus is designed to have these lengths, in contrary to the I2C bus.

True.. But I have read threads about even 100m cables (not even closer my case) and trust me, with the engine off or on the bench it is working flawlessly for hours and hours of testing time..

For 400Khz I just used the correct pullup resistors..

Check out this EXCELLENT link!

So any other ideas dear fellow arduiners? I would like to remind that it does it even with short cables.. What is the best cable to use in that case?

For example where is the best place to add the pullup resistor, near the arduino or on the display? I currently have the 4.7KOhms installed by the manufacturer on the display and I have added on Arduino (A4->5V,A5->5V) 2.2kohms each in order to have a total of around 1.5KOhms.. Is this ok or should all the resistors be on one side and which one may that be?

Thank you

True.. But I have read threads about even 100m cables (not even closer my case) and trust me, with the engine off or on the bench it is working flawlessly for hours and hours of testing time..

100m I2C bus (standard speed) without expander hardware is something I believe when I see it.

If your bench is working flawlessly what's your problem then? I thought you have display problems?

For 400Khz I just used the correct pullup resistors..

but

I currently have the 4.7KOhms installed by the manufacturer on the display and I have added on Arduino (A4->5V,A5->5V) 2.2kohms each in order to have a total of around 1.5KOhms.

That's for your definition of correct: Most I2C devices have a maximal sink current of 3mA, your bus has a higher value. I didn't find the maximum sinking current of the display, for the ATmega328p it's 3mA.

Is this ok or should all the resistors be on one side and which one may that be?

The pullup resistors should be installed only once on the bus. Take the side that has the hardware allowing more sink current.

I would like to remind that it does it even with short cables.

0.4m is not a short cable in an EMI intensive area!

Try putting your Arduino together with the display inside a metal case and shorten the I2C bus as much as possible and you probably get better results.

If that's not enough, stablilize the power supply.

The working environment is the car where there is the problem, especially near the rev limiter.. On the bench it is perfect but useless.. :stuck_out_tongue:

Arduino and the rest of the PCB is inside an aluminum project box.. The display is on the dash, just above the instrument cluster.. I don't know about the sink of the display but I can tell you this:

The arduino and the rest of the components on the PCB draw 0.04A.. When the display is connected the total current draw is 0.11A so the display draws 0.07A but I don't know if you can make any sense of what I just wrote..

I don't get the impression that you understood what I wrote. The current your devices draw is not relevant for the transmission. I wrote that the resistors you have currently installed are a bit to small for your devices although they probably survive that.

From what you write I believe to understand that you are either not willing or not able to make the I2C bus shorter. This means you have to insert the bus expanders. And use a shielded cable for the bus but don't connect the shield to Arduino GND but to the chassis of your car (both are connected at some point but it makes a difference in many cases).

Happy new year!!

So I performed some tests:

Changed the Wire library with the I2C library by Wayne Truchsess. It ALMOST doesn’t do it. So this verifies my first imperssion that the Wire library is not working well.

Changed the cable with a CAT5e grounded at the 12V Raw Ground of my power supply (so basically this is a car ground).

It didn’t do it at a 20 minute drive near the rev limiter (poor car!)…

So I believe that the best solution is a shielded cable like you pylon said and thank you about that!

Also, please note that the RJ45 cable is 2m long and the Cat5e cable I used is 3M long! It works!

I don’t yet consider the problem solved, I have to make more tests and I will come back. I also ordered a CAT7 flat cable (to be flexible) from ebay and I will do all the testing with that as well and report back.

Thank you again! Any thoughts?