hubbabubba
Posts: 5
Joined: Sat Jul 30, 2016 2:09 pm

Raspberry Pi as I2C slave?

Sat Jul 30, 2016 2:20 pm

Hi! I have been building an Arduino robot. I'm going to add my Raspberry Pi to it and it will run a simple OpenCV computer vision program to spot a ball in a camera feed. I have the program written but I hit a bit of a snag. My Arduino obviously controls the motors, as well as a Bluetooth module and an Ultra Sonic Range Finder module. My Raspberry Pi just needs to communicate to the Arduino where the ball is in the camera frame and I will code a simple logic for the robot to move toward it. The bluetooth module uses I2C and I figured I'd stick the Raspberry Pi onto the I2C bus as well and just have the Arduino periodically request information from the Pi. Now, with my soldering done and all, as I like to do things a bit backwards, I shockingly discover that it may not be so easy to run the Pi as an I2C slave!!

Is there a solution for this? Or must I revert to serial communication between the Arduino and the Pi? This might be a problem, since the bluetooth module on my robot uses the hardware serial pins on the Arduino and I have been having problems with the SoftwareSerial library interfering with servos on my robot (I believe the library temporarily prevents interrupts so that they don't interfere with the serial I/O and this messes up the timing for PWM signal to my robot's servos which go haywire).

So is there a way to run the Pi as slave? Any other neat solutions besides serial communication? I guess I could just run the Raspberry Pi as master and the Arduino as slave? If I understand correctly, the master provides the clock on SLC but the slaves can talk to each other as well as to the slave? This might be complicated for the Arduino bluetooth module and range finder module though, as well as for my Adafruit Motor Shield as I believe it uses I2C too.. Their libraries may be written for the Arduino running as master, so I'd have to check how they configure the I2C connection, right?

baantonia
Posts: 63
Joined: Fri Feb 06, 2015 2:19 pm

Re: Raspberry Pi as I2C slave?

Sun Jul 31, 2016 6:29 pm

I'm planning to use a Pi Zero as a slave, communicating over SPI using GPIOs 18, 19, 20 and 21 (pins 12, 35, 38 and 40). However the same pins can be used as an I2C slave according to the documentation set to function select ALT3.

hubbabubba
Posts: 5
Joined: Sat Jul 30, 2016 2:09 pm

Re: Raspberry Pi as I2C slave?

Wed Aug 03, 2016 5:59 pm

After a bit more reading up on I2C, it seems I was mistaken. I thought you could only have one master on the bus, but you can in fact have multiple masters. So it seems that there should be no problem with running the Arduino as master for communication with my range finder module and motor shield and having the Raspberry Pi act as master for communicating to the Arduino which way the robot should go. Interesting stuff...

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

Re: Raspberry Pi as I2C slave?

Wed Aug 03, 2016 6:58 pm

hubbabubba wrote:After a bit more reading up on I2C, it seems I was mistaken. I thought you could only have one master on the bus, but you can in fact have multiple masters. So it seems that there should be no problem with running the Arduino as master for communication with my range finder module and motor shield and having the Raspberry Pi act as master for communicating to the Arduino which way the robot should go. Interesting stuff...
That's news to me. I didn't think the Pi supported I2C multi-master mode.

hubbabubba
Posts: 5
Joined: Sat Jul 30, 2016 2:09 pm

Re: Raspberry Pi as I2C slave?

Wed Aug 03, 2016 7:31 pm

Oh... Well that might be a new problem. See, originally I thought with I2C you could only have one master, then I learned thats not the case and thought there would be no problem. It didnt occur to me that the Pi wouldnt support this either. After some quick googling, it seems that indeed it doesnt. Sigh! Back to the drawing board i guess! Thanks for pointing that out!

I guess there is no easy hack to make this work? It wouldn't matter for my purposes if the messages from any of the devices on the bus occationally didnt get through. Someone suggested somewhere to make the Pi win the arbitration between masters (even though its not in multimaster) by keeping SLC low for a while before transmitting. I'm not sure if this would work?

photomankc
Posts: 80
Joined: Fri Aug 24, 2012 12:58 pm

Re: Raspberry Pi as I2C slave?

Fri Aug 05, 2016 2:22 pm

Sometimes you have to look for new cat-skinning processes. Many libraries are deficient in support for I2C multi-master operation. Even if one device supports it, the other may not. How much GPIO do you have open on the two? Could use 5 lines to create a 4 bit bus. The 5th line acting a little like I2C where one device pulls the line low to signal to the other that it wants or has data. As long as you follow a protocol they could exchange data that way but you'd be writing the libraries to do it. Given you can move 4 bits at a time you can get data across quickly that way.

I was working on something like this for a while till I came up with another way. My idea was the master device requested data by pulling line 5 (/D-REQ) low then releasing it. If the other device had data then it would present that on the bus and /D-REQ would return to high via a pull-up resistor. If there was no data to send then D-REQ was held low by the slave device for a few microsecs and the master then knew there was nothing to read.

My idea was implemented via micro-controllers though so it may be a challenge to get Linux to respond quickly enough to D-REQ signals to keep things moving fast. The addition of a 6th line could have allowed for the slave to send an interrupt when data was available so the master didn't need to poll for it. The Pi could then EXPECT the Arduino to have responded and read that data and then setup the next nibble. In fact that could be the only communication in this case. Pi sends interrupt, Arduino reads a nibble ASAP. Pi waits at least 30us and sets up the next nibble and sends the next interrupt.

Trick will be to remember that the Arduino needs to be the one that gets things done with tight timing. Depending on the Pi to respond to fleeting signals within small time windows is probably not going to work out, and you don't want the Arduino ever getting into a busy-loop reading the data. It needs to grab whats available as quick as possible and go on with what it was doing. Assemble the message in the background.


hubbabubba
Posts: 5
Joined: Sat Jul 30, 2016 2:09 pm

Re: Raspberry Pi as I2C slave?

Sat Aug 06, 2016 7:04 am

Thanks a lot for the suggestions! Yeah, I'll probably have to give up on using I2C. Its just that it would have been elegant to have multiple devices communicate via I2C. But its pretty clearly a no-go. I'll have look at those other ideas you suggested. Thanks again!

aBUGSworstnightmare
Posts: 2303
Joined: Tue Jun 30, 2015 1:35 pm

Re: Raspberry Pi as I2C slave?

Sat Aug 06, 2016 7:21 am

hubbabubba wrote:Thanks a lot for the suggestions! Yeah, I'll probably have to give up on using I2C. Its just that it would have been elegant to have multiple devices communicate via I2C. But its pretty clearly a no-go. I'll have look at those other ideas you suggested. Thanks again!
Why not simply use a microcontroller (i.e. with more than one I2C bus) and connect it via USB to your Pi (Virtual COM port for keeping things simple on both ends)?

hubbabubba
Posts: 5
Joined: Sat Jul 30, 2016 2:09 pm

Re: Raspberry Pi as I2C slave?

Mon Aug 08, 2016 5:42 pm

aBUGSworstnightmare wrote: Why not simply use a microcontroller (i.e. with more than one I2C bus) and connect it via USB to your Pi (Virtual COM port for keeping things simple on both ends)?
Well I already have my Uno so I will have to make do with it. I'm going to have a look at the different options for communication between my Pi and my Arduino. I'll forget about doing it with I2C.

photomankc
Posts: 80
Joined: Fri Aug 24, 2012 12:58 pm

Re: Raspberry Pi as I2C slave?

Mon Aug 15, 2016 2:18 am

So as a simple example of something possible. Here is my C++ GPIO_Group wrapper object using wiringPi functions to drive outputs as a 4 bit bus with a data clock when all bits have a valid state. Its sending 128 4-bit counts. That's 64 bytes. It takes 320us to send that. The period of the clock works out to about 2.36 microseconds. This works out to about 1.6Mbps or around 200KBps. You can see where the OS steals some time from us on the OE signal a couple of times. That's probably faster than an UNO could respond so you would be able to go as fast as the UNO could manage to respond to the clock in an interrupt and grab the nibble on the wires. Of course bi-directional comms get more complicated but this is really pretty good for software-based communication.
BusSpeed.jpg
BusSpeed.jpg (52.01 KiB) Viewed 7073 times
Ignore those little spikes in the channels. I used a crappy spot to connect the ground lead on a breadboard so it was picking up noise.

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