Raspberry Pi I2C comms

Firstly i am no expert. I have been playing around with a Raspberry Pi zero and Arduino using I2C as communication between the two. On the Raspberry Pi I was using Python 3 and SmBUS. On the face of it the communication using I2C worked. Every so often though the communication would fault. I believe this to be something to do with a bug with the Raspberry Pi I2C where it doesn't fully follow the communication protocol. It fails to implement clock stretching (If the slave is busy the slave can hold up the communication [clock stretching] then release the communication when the slave has completed the task). The Arduino uses clock stretching.
My question to you before I look to buy a motor controller is do your motor control boards implement clock stretching? If your motor boards don't then I don't think there is a problem.

thank you in advance. Richard

piborg's picture

We actually found the same issue when we were developing our boards. It caused a lot of confusion at the time :)

Our boards are not using clock stretching and have been tested extensively with various models of Raspberry Pi to ensure they communicate without issues.

Thank you for that information. Informative and reassuring.

My own solution with my Arduino was to use serial communication unfortunately.

Hallo there.
I am very new to this Forum and a proud owner of some PiBorgs (KS2, KS1).
I itend using those for controlling 7 DC Motors, with one RaspberryPI3B+.
Also, I would like to use the same I2C connection on the Raspberry (pins 3, 5)
for one more sensor(Temperature, Humidity, Pressure sensor) with Address 0x77.
The other pins 27, 27 (SDA.0, SCL.0) do not work

When i use RaspberryPI only with the KS2 PiBorg, Motor cotrol, Infrared
and Analog inputs work perfect (Address of PiBorg default 0x40)
I use the GUI zbGui.py which comes with the examples from PiBorg and
shows 4 sliders for controlling the motors, IR reception and two analog readouts.

When i connect the second sensor for some seconds everything is fine.
Afterwards, On PiBorg works only the Motor Control (not infrared and analog inputs)
The second sensor continues working perfect (bme280).
i2cdetect -y 1 shows both Addresses (0x40, 0x77) correct.

Is there anything i should take care of?

Thank you very much in advance

MSid

piborg's picture

I have had a quick look at the bme280 datasheet and as far as I can tell it should be able to share the I2C bus with the ZeroBorg without problems.

The first thing to check is if you are using the old or new version of the ZeroBorg.py library as we fixed some I2C related issues a while ago. You can check this by opening the file in an editor and look for the section labelled "Import the libraries we need".

The old version looks like this:

# Import the libraries we need
import smbus
import types
import time

The new version looks like this:

# Import the libraries we need
import io
import fcntl
import types
import time

If you have the old version I would suggest trying the new version instead and see if the same fixes solve your problem as well. You can update the examples using these commands:

cd ~
mv zeroborg zeroborg-old
bash <(curl https://www.piborg.org/installer/install-zeroborg.txt)

Thank you very much for your prompt answer.

I have checked and i have the new library.

Running ./zbGui.py in zeroborg directory i get the following.
Immediately after start:

Loading ZeroBorg on bus 1, address 40
Found ZeroBorg at 40
ZeroBorg loaded on bus 1
Failed reading IR message!
Failed reading new IR message received flag!

For the next 5 to 10 seconds everything is fine.
and then comes:

Failed reading analog level #2!
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1545, in __call__
return self.func(*args)
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 595, in callit
func(*args)
File "./zbGui.py", line 103, in Poll
self.lblAnalog2['text'] = '%01.2f V' % (analog2)
TypeError: float argument required, not NoneType

after that:
Window with analog readouts and IR freezes.
Motor control works properly
bme280 keeps working also properly.

i2cdetect gives the following:

0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- 77

which was expected.

Once more thank you very much for your answer

MSid

piborg's picture

It sounds like the reads are failing occasionally, but working most of the time. The GUI gets stuck because it does not handle the error properly, which can be easily fixed :)

Look for the Poll function in zbGui.py:

    # Polling function
    def Poll(self):
        if ZB.HasNewIrMessage():
            self.lastIR = ZB.GetIrMessage()
            if buttonMap.has_key(self.lastIR):
                self.lastButton = buttonMap[self.lastIR]
            else:
                self.lastButton = self.lastIR
            self.lblIR['text'] = 'IR: %s\nCode: %s' % (self.lastButton, self.lastIR)
        else:
            self.lblIR['text'] = 'No IR\nLast: %s' % (self.lastButton)
        analog1 = ZB.GetAnalog1()
        analog2 = ZB.GetAnalog2()
        self.lblAnalog1['text'] = '%01.2f V' % (analog1)
        self.lblAnalog2['text'] = '%01.2f V' % (analog2)

        # Re-run the poll after 100 ms
        self.after(100, self.Poll

What you want to do is change the analog reading lines so they check the value first like this:

    def Poll(self):
        if ZB.HasNewIrMessage():
            self.lastIR = ZB.GetIrMessage()
            if buttonMap.has_key(self.lastIR):
                self.lastButton = buttonMap[self.lastIR]
            else:
                self.lastButton = self.lastIR
            self.lblIR['text'] = 'IR: %s\nCode: %s' % (self.lastButton, self.lastIR)
        else:
            self.lblIR['text'] = 'No IR\nLast: %s' % (self.lastButton)
        analog1 = ZB.GetAnalog1()
        analog2 = ZB.GetAnalog2()
        if analog1 is None:
            self.lblAnalog1['text'] = '?.?? V'
        else:
            self.lblAnalog1['text'] = '%01.2f V' % (analog1)
        if analog2 is None:
            self.lblAnalog2['text'] = '?.?? V'
        else:
            self.lblAnalog2['text'] = '%01.2f V' % (analog2)

        # Re-run the poll after 100 ms
        self.after(100, self.Poll

This will not fix the underlying problem, but the GUI will no longer get stuck when it fails to read a number from the ZeroBorg.

Dear PiBorg.
Than you very much for your answer and suggestion. I tried that and it works fine.
Now i have another problem.
I try to get one step motor (see attached file) working with the piborg.
I am not sure about the connections. I tried using the schema like in your examples for the connections.
black green (my motor) like blue yellow(your example), and red blue like orange pink.
Motor vibrates but dont turn.
I power the whole thing with the power suply from the raspberry (3 Ampers).
I tried also with a lot 9 Volts Batteries, but raspberry could not even boot.
Any suggstion?
Thank you very much in advance.

MSid

Attachments: 
piborg's picture

The first thing to try is adjusting the speed at which the ZeroBorg tries to step.

Open zbStepper.py and look for this line:

stepDelay = 0.002                       # Delay between steps

I would start by using a very large delay, say 0.1 seconds, to prove that the stepper works correctly. If that works you can keep reducing the value until you find the smallest delay that still moves properly.

Subscribe to Comments for &quot;Raspberry Pi I2C comms&quot;