MarkDH102
Posts: 354
Joined: Fri Feb 13, 2015 3:18 pm

High rate of i2c failure when connecting to Arduino UNO

Tue Jan 10, 2017 12:57 pm

All

Sorry for the lengthy post...

The Pi is an I2C MASTER, the UNO is a SLAVE.
The Pi has fixed on board pull-ups (3.3K) on the SDA and SCL pins.
The Arduino code is enabling its weak (20K – 50K according to the datasheet) internal pull ups on the SDA and SCL lines.
The ATMEGA 328 datasheet says the SDA and SCL lines need a minimum of 0.7*VCC (5V) as a logic high. The Pi only supplies 3.3V.
I guess the weak pull ups are helping the Arduino as the code is working – most of the time.
The cable between the two units is about 10cm long. I’m running at 100kbps.

I am getting an approximate 10% failure rate in the communications. It looks like the transfer from the slave just stops at random points in the buffer (32 bytes).
I think this may be due to clock stretching on the Arduino which the driver on the Pi can’t cope with. Can someone confirm this?
I've modified the Arduino TWI interface code to timeout and give me a timeout reason, but it isn't timing out anywhere.
I check the data for consistency so it isn’t really a problem. And my acquisition rate is quite low.

I know I should use level converters but as the I2C protocol is open drain and the Pi is the MASTER, I assume I can get away with this?

Here's my code :

Pi - Python

Code: Select all

import smbus
import time

bus = smbus.SMBus(1)

address = 0x04
responses = ["", "Z", "12.10,22.10,25.50,9.30,", "5.610,4.950,5.200,4.900,", "1,2,3,4,", "67.40,56.60,", "5,6,7,8,", "0,14,"]
types = ["", "ID", "Temp", "Volt", "CRC", "Humidity", "Count", "Misc"]

count = 0
bad = 0

while (count < 1000) :
    print("Count = {} Bad = {}".format(count, bad))

    # Send a set of 7 commands to the Arduino
    for cmd in range(1, 8) :
        data = bus.read_i2c_block_data(address, cmd)
        str = ""
        for e in data :
            if e != 0 :
                str = str + chr(e)

        if str != responses[cmd] :
            print("Bad {} {}".format(types[cmd], str))
            print(data)
            bad += 1
            # Interrogate Arduino for potential reason why transfer failed
            bus.write_byte(address, 8)
            reason = bus.read_byte(address)
            print(reason)

    count += 1
    time.sleep(2.0)
And my Arduino code :

Code: Select all

#include <PString.h>
#include <Wire.h>

#define MAX_BUF_LEN 32

#define I2C_IDENTIFIER 0x5A
#define I2C_ADDRESS    4
#define I2C_CMD_ID     1
#define I2C_CMD_TEMP   2
#define I2C_CMD_VOLT   3
#define I2C_CMD_CRC    4
#define I2C_CMD_HUM    5
#define I2C_CMD_CNT    6
#define I2C_CMD_MISC   7
#define I2C_CMD_REASON 8

char       mi2cCommand = 0;
byte       mbufConcat[MAX_BUF_LEN];

const byte mV[] = "5.610,4.950,5.200,4.900,\x00\x00\x00\x00\x00\x00\x00\x00";
const byte mT[] = "12.10,22.10,25.50,9.30,\x00\x00\x00\x00\x00\x00\x00\x00\x00";
const byte mH[] = "67.40,56.60,\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
const byte mC[] = "5,6,7,8,\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
const byte mB[] = "1,2,3,4,\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
const byte mM[] = "0,14,\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";

void setup()
{  
  mi2cCommand = 0;

  Wire.begin(I2C_ADDRESS);
  Wire.onReceive(i2cReceiveEvent);
  Wire.onRequest(i2cRequestEvent);
}

void loop()
{
}

void clearConcatBuffer(void)
{
  for (byte bytI = 0; bytI < MAX_BUF_LEN; bytI++)
      mbufConcat[bytI] = 0;
}        

void i2cReceiveEvent(int bytesReceived)
{
  mi2cCommand = Wire.read();
}

void i2cRequestEvent(void)
{
  switch(mi2cCommand)
  {
    case I2C_CMD_ID:
      clearConcatBuffer();
      mbufConcat[0] = I2C_IDENTIFIER;
      Wire.write(mbufConcat, 32);
    break; 
    case I2C_CMD_VOLT:
      sendVoltages();
    break; 
    case I2C_CMD_TEMP:
      sendTemperatures();
    break; 
    case I2C_CMD_HUM:
      sendHumidities();
    break; 
    case I2C_CMD_CRC:
      sendBadMessageCounts();
    break; 
    case I2C_CMD_CNT:
      sendMessageCounts();
    break; 
    case I2C_CMD_MISC:
      sendMiscellaneous();
    break; 
    case I2C_CMD_REASON:
      Wire.write((byte) Wire.reason());
    break; 
  }
}

void sendTemperatures(void)
{    
  Wire.write(mT, 32);    
}

void sendHumidities(void)
{
  Wire.write(mH, 32);    
}

void sendMessageCounts(void)
{
  Wire.write(mC, 32);    
}

void sendBadMessageCounts(void)
{
  Wire.write(mB, 32);    
}

void sendVoltages(void)
{    
  Wire.write(mV, 32);    
}

void sendMiscellaneous(void)
{   
  Wire.write(mM, 32);
}


And finally, a couple of data error pics.
Fault.png
Fault.png (33.73 KiB) Viewed 5790 times
Attachments
Fault1.png
Fault1.png (22.83 KiB) Viewed 5790 times

NicoVanDerDussen
Posts: 74
Joined: Sat Aug 24, 2013 2:41 pm

Re: High rate of i2c failure when connecting to Arduino UNO

Tue Jan 10, 2017 1:12 pm

I solved similar problems by using a proper 5V to 3.3V adapter

I found the voltage fluctuation just too much for the narrow margin available.

Another solution is to use a 3.3V Arduino like board - I have a few just for this purpose.

Or use an ESP8266 board such as Wemos or NodeMCU which has 3.3V I2C
Last edited by NicoVanDerDussen on Tue Jan 10, 2017 1:22 pm, edited 1 time in total.
Setting up your Raspberry Pi to work with a 3G dongle http://nvdd.info/11gKrsZ

6by9
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 7425
Joined: Wed Dec 04, 2013 11:27 am
Location: ZZ9 Plural Z Alpha, aka just outside Cambridge.

Re: High rate of i2c failure when connecting to Arduino UNO

Tue Jan 10, 2017 1:19 pm

Use level shifters.
Voltages > 3.3V on Pi GPIO pins will cause odd behaviour, or may damage the SoC.

The I2C pullups on the Pi are 1k8, not 3k3 that you quote.

Doing the simple potential divider maths on

Code: Select all

5V-+
   |
  20k
   |
   +---SDA/SCL
   |
  1k8
   |
   +- 3V3
SDA/SCL will be floating at 3.3 + (1.8 / (1.8+20)) * (5 - 3.3) = 3.44V, which is < 5 * 0.7 = 3.5V.
So your Arduino will only sometimes be detecting a 1 state correctly, therefore expect errors.
Software Engineer at Raspberry Pi Trading. Views expressed are still personal views.
I'm not interested in doing contracts for bespoke functionality - please don't ask.

MarkDH102
Posts: 354
Joined: Fri Feb 13, 2015 3:18 pm

Re: High rate of i2c failure when connecting to Arduino UNO

Tue Jan 10, 2017 1:51 pm

Ok both. Thanks for the replies. I will invest in a level shifter.

User avatar
mwilliams03
Posts: 123
Joined: Mon Oct 29, 2012 2:56 pm
Contact: Website

Re: High rate of i2c failure when connecting to Arduino UNO

Wed Jan 11, 2017 5:08 am

Mark -- OzzMaker.com -- Creator of;
+ BerryIMU
+ Berry GPS-IMU
+BerryGPS-GSM
+ PiScreen - A 3.5" TFT for the Rasspberry Pi

NicoVanDerDussen
Posts: 74
Joined: Sat Aug 24, 2013 2:41 pm

Re: High rate of i2c failure when connecting to Arduino UNO

Wed Jan 11, 2017 6:13 am

I would first eliminate the voltage issue before investigating things like bugs etc.

As I said, I had the same issues and a voltage level shifter sorted it all.
Setting up your Raspberry Pi to work with a 3G dongle http://nvdd.info/11gKrsZ

MarkDH102
Posts: 354
Joined: Fri Feb 13, 2015 3:18 pm

Re: High rate of i2c failure when connecting to Arduino UNO

Wed Jan 11, 2017 8:13 am

To mwilliams03, I did wonder about the clock stretching in my original post.
I've been running PiScope and can't see any evidence.
I have some bi-directional level shifters arriving today, they were only £2 for a set of 5 PCB's (4 I/O on each).
I will get back if this doesn't solve the problem.

To NicoVanDerDussen, I have an Arduino DUE (3.3V), but I don't want to tie that up in this application as it has far more processing power than I need. What are the Arduino-like 3.3V boards you mention? Are they Arduino IDE compatible and as cheap (I get my UNO's for £7!).

User avatar
joan
Posts: 14371
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: High rate of i2c failure when connecting to Arduino UNO

Wed Jan 11, 2017 8:54 am

To be reasonably frank the Arduino I2C implementation is not the most robust. I have managed to kill it by doing fairly straightforward operations (please don't ask what as it was several years ago and I don't remember).

User avatar
DougieLawson
Posts: 36322
Joined: Sun Jun 16, 2013 11:19 pm
Location: Basingstoke, UK
Contact: Website Twitter

Re: High rate of i2c failure when connecting to Arduino UNO

Wed Jan 11, 2017 8:59 am

MarkDH102 wrote:Ok both. Thanks for the replies. I will invest in a level shifter.
Why not run the uno on a 3V3 power supply rather than 5V0?
Note: Having anything humorous in your signature is completely banned on this forum. Wear a tin-foil hat and you'll get a ban.

Any DMs sent on Twitter will be answered next month.

This is a doctor free zone.

MarkDH102
Posts: 354
Joined: Fri Feb 13, 2015 3:18 pm

Re: High rate of i2c failure when connecting to Arduino UNO

Wed Jan 11, 2017 10:42 am

To DougieLawson

Can the Pi supply enough current (I think a bare UNO takes about 40mA) on its 3.3V GPIO pin? If so, I can try it out.
However, I have a lot of 5V sensors and digio plugged into the UNO so in the long term it's not a good solution.

NicoVanDerDussen
Posts: 74
Joined: Sat Aug 24, 2013 2:41 pm

Re: High rate of i2c failure when connecting to Arduino UNO

Wed Jan 11, 2017 10:53 am

My advice: Use a dedicated 5V power supply for your Uno.

500mA would be ample

Most of the "ghosts" I had on projects were due to power supply issues.

Once I started using quality power supplies and dedicated units for 'Pi and Arduino my problems vanished
Setting up your Raspberry Pi to work with a 3G dongle http://nvdd.info/11gKrsZ

MarkDH102
Posts: 354
Joined: Fri Feb 13, 2015 3:18 pm

Re: High rate of i2c failure when connecting to Arduino UNO

Wed Jan 11, 2017 11:07 am

I've just piped the Pi 3.3V into the UNO and can see I'm drawing 27mA.
Where the 3.3V enters the UNO it is 3.3V. Where it gets to the VCC pin on the processor it is reading 2.69V.
I've just looked at the Arduino schematic but not fully understanding hardware, I can only assume there are some voltage drops on the comparator (I didn't think there should be).
I'll just wait for my level shifters to arrive... :)

NicoVanDerDussen
Posts: 74
Joined: Sat Aug 24, 2013 2:41 pm

Re: High rate of i2c failure when connecting to Arduino UNO

Wed Jan 11, 2017 11:15 am

MarkDH102 wrote:
To NicoVanDerDussen, I have an Arduino DUE (3.3V), but I don't want to tie that up in this application as it has far more processing power than I need. What are the Arduino-like 3.3V boards you mention? Are they Arduino IDE compatible and as cheap (I get my UNO's for £7!).
See https://www.arduino.cc/en/Main/arduinoBoardProMini You will need a USB to serial converter.

Easier: Use a NodeMCU or Wemos ESP8266 based unit. Cheap, powerful, has Wifi and 3.3V pins. https://www.wemos.cc/

All of these can be programmed with the Arduino IDE - see https://github.com/esp8266/Arduino on how to configure the Arduino IDE for ESP8266

BTW: I'm using my ESP8266 based units to broadcast MQTT messages via Wifi to Mosquitto on a Raspberry Pi - WiFi is much easier that I2C and the unit does not need to be close to the Raspi :D
Setting up your Raspberry Pi to work with a 3G dongle http://nvdd.info/11gKrsZ

MarkDH102
Posts: 354
Joined: Fri Feb 13, 2015 3:18 pm

Re: High rate of i2c failure when connecting to Arduino UNO

Wed Jan 11, 2017 11:30 am

See https://www.arduino.cc/en/Main/arduinoBoardProMini You will need a USB to serial converter.

Easier: Use a NodeMCU or Wemos ESP8266 based unit. Cheap, powerful, has Wifi and 3.3V pins. https://www.wemos.cc/
I like the look of the Wemos but it only has the one Analogue IN. Will be worth using for other projects I have in mind.
The ProMini also looks good and I may get one to play around with.

Cheers.

MarkDH102
Posts: 354
Joined: Fri Feb 13, 2015 3:18 pm

Re: High rate of i2c failure when connecting to Arduino UNO

Wed Jan 11, 2017 8:08 pm

Update. I've installed a bi-directional level converter. Still got exactly the same problem.
I think I must agree with an earlier entry by joan saying that the Arduino i2c is not implemented very well.
It's a real shame as I wanted to replace a B+ with a Zero and need the USB port on the Zero for WiFi.
I already have a small touchscreen connected to the serial port and a device connected to the SPI.

MarkDH102
Posts: 354
Joined: Fri Feb 13, 2015 3:18 pm

Re: High rate of i2c failure when connecting to Arduino UNO

Thu Jan 12, 2017 2:01 pm

Frustration isn't the word.
I've now tried with the pigpio library using the non smbus calls and get the same issues.
Does anyone know a definitive way (Pi3 and Jessie Pixel) to decrease the clock speed of i2c bus 1.
I foolishly tried this in boot/config.txt

dtparam=i2c_arm_baudrate=32000

and managed to trash my SD card. Luckily I have good backups so I just reflashed it.
I assume this speed is used by both i2c ports.

6by9
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 7425
Joined: Wed Dec 04, 2013 11:27 am
Location: ZZ9 Plural Z Alpha, aka just outside Cambridge.

Re: High rate of i2c failure when connecting to Arduino UNO

Thu Jan 12, 2017 2:21 pm

MarkDH102 wrote:I assume this speed is used by both i2c ports.
Nope. i2c_vc_baudrate is the rate for i2c-0, but do NOT try to use i2c-0 from Linux on a Pi3. It's used on the GPU side to talk to a GPIO expander, and using it from multiple processors simultaneously is going to lead to odd behaviour.

i2c_arm_baudrate is the correct setting for i2c-1. https://github.com/raspberrypi/linux/bl ... b.dts#L191
Oh, and dmesg should log:

Code: Select all

BSCx Controller at <addr> (irq N) (baudrate <baudrate>)
when the driver is loaded, so that should allow you to confirm your value is taken.
Software Engineer at Raspberry Pi Trading. Views expressed are still personal views.
I'm not interested in doing contracts for bespoke functionality - please don't ask.

MarkDH102
Posts: 354
Joined: Fri Feb 13, 2015 3:18 pm

Re: High rate of i2c failure when connecting to Arduino UNO

Thu Jan 12, 2017 3:01 pm

Ok, thank you for that.
Can I just confirm that setting it to 32000 will not cause any issues to the Pi other than slow the external I2C interface down...

MarkDH102
Posts: 354
Joined: Fri Feb 13, 2015 3:18 pm

Re: High rate of i2c failure when connecting to Arduino UNO

Thu Jan 12, 2017 4:49 pm

BINGO! AT LAST!

I've set a clock rate of 32000 and have run 700,000 transactions without fault.
Brilliant.
I tried a rate of 64000 but ended up with problems again.
I hope that the Zero will work at this rate too...

MarkDH102
Posts: 354
Joined: Fri Feb 13, 2015 3:18 pm

Re: High rate of i2c failure when connecting to Arduino UNO

Fri Jan 13, 2017 10:37 am

UN BINGO...

Just transferred the whole setup to a Pi Zero.
Back to the same issue. Loads of dropped transactions.
Same Arduino, same level shifter, same code on Arduino, same code on Pi. Both Pi3 and Zero up to date OS. Same I2C clock rate in /boot/config.txt.

Only difference is that the Arduino was connected to the USB on the Pi3 and is now powered through a PC USB port. I have a common ground between Arduino and Zero. I have also tried powering the Arduino directly from the 5V/0V on the Pi GPIO pins.

Any theories?
Cheers.

fivdi
Posts: 208
Joined: Sun Sep 23, 2012 8:09 pm
Contact: Website

Re: High rate of i2c failure when connecting to Arduino UNO

Fri Jan 13, 2017 9:57 pm

Drop the baudrate even further to see if that works. Maybe to 10,000.

I managed to get an ATmega328P running at 8MHz and 3.3V to communicate with a Pi 2 at 100,000 baud using https://github.com/fivdi/avr-io. The I2C interrupt routine does the bare minimum to avoid clock stretching issues and there is only one interrupt routine.

User avatar
Gavinmc42
Posts: 3918
Joined: Wed Aug 28, 2013 3:31 am

Re: High rate of i2c failure when connecting to Arduino UNO

Sat Jan 14, 2017 12:52 am

I have done lots of i2c stuff, 5+ years on Pi's.

If I have trouble with some chips I use a Cypress PSoC1 micro to interface to the other i2c chips.
The PSoC acts as a buffer and reads fine most of the time, works fine from the Pi 3v3 supply.
PSoC have an advantage over Arduino's in that they use the i2c port for programing.
Plus I have been using them since they first came out so coding for them is not difficult for me.
5V chips talking to 3V3 Pi is not a good idea, level converters and even isolators make it safer.

Fast repetitive reads using Linux OS does seem to cause i2c issues.
Most of my code was for detecting missing data and handling errors.
Went as low as 10KHz i2c clock rates, which helped.

In the end I went for Ultibo on the Pi, less OS meant very reliable i2c reads.
As in no errors in more than a week of testing, compared to an error about every 10-60 secs with Linux.
Without any actual errors I have no idea how many orders of magnitude Ultibo is better :P
I'm dancing on Rainbows.
Raspberries are not Apples or Oranges

MarkDH102
Posts: 354
Joined: Fri Feb 13, 2015 3:18 pm

Re: High rate of i2c failure when connecting to Arduino UNO

Sat Jan 14, 2017 11:02 am

To fivdi :
Thanks for that link. I've downloaded the code and I was going to do the same thing by cutting down the TWI library ISR and not going via the Wire library.
BUT:
I have managed to write my own very simplistic 2 wire interface based on the Arduino PinChangeInterrupt and FastDigitalWrite.
It has more than enough speed for my needs. And as a bonus I don't ever get any duff transactions. Plus it is very specific to my needs so it is as fast as it can possibly be. I have the spare I/O so using the extra 2 wires isn't a problem.
Also, I will have other devices on the I2C bus and I got the impression that your routine would not work correctly with multiple devices or global addressing.

fivdi
Posts: 208
Joined: Sun Sep 23, 2012 8:09 pm
Contact: Website

Re: High rate of i2c failure when connecting to Arduino UNO

Sat Jan 14, 2017 1:18 pm

@MarkDH102: good to hear that you found a solution.

The code linked to above will work with other devices on the bus. This has been tested :). General call recognition isn't enabled in code as it wasn't needed. A device isn't required to do anything with a general call if it doesn't need it. See http://www.i2c-bus.org/addressing/general-call-address/

Return to “Interfacing (DSI, CSI, I2C, etc.)”