Raspberry PI I2C

Once again playing with erlang ale, and last time I played with the gpio module and to change it up I decided I would give a go at the I2C module. I’m very interested in using it coupled with something like this board from adafruit to drive servos.


I happen to have a teensyduino v2.0 board (have v3.1 in the mail) laying around and decided to turn it into an i2c slave device and use erlang_ale to talk to it. This was a fairly simple to do actually. I started with the example sketch here for i2c on the arduino, and modified it to suit my needs; I only used the slave_receiver example and my code turned out like

#include <Wire.h>

const int iPin = 11;
const int dPin = 13;

void setup() {
    Wire.begin(4);
    Wire.onReceive(receiveEvent);
    pinMode(iPin, OUTPUT);
    pinMode(dPin, OUTPUT);
    debugLed(2, 500);
    Serial.begin(9600);
}

void debugLed(int times, int d) {
    digitalWrite(dPin, LOW);
    delay(100); 
    while (times-- > 0) {
        digitalWrite(dPin, HIGH);
        delay(d); 
        digitalWrite(dPin, LOW);
        delay(d); 
    }
    digitalWrite(dPin, LOW);
}

void loop() {
    delay(100);
}

void receiveEvent(int howMany) {
    while (0 < Wire.available()) {
        Serial.print("found: ");
        Serial.println(Wire.available());
        int c = Wire.read();
        if (c == 0x01) {
            digitalWrite(iPin, HIGH);
            digitalWrite(dPin, LOW);
        }
        else if (c == 0xff) {
            digitalWrite(iPin, LOW);
            digitalWrite(dPin, HIGH);
        }
        Serial.println(c);
    }
}

It Simply flips between two leds depending on the byte sent and only handles 0x01, and 0xff. Not particular reason I chose those values, just did.


On the Raspberry side I fired up an erlang shell via make shell in the root of the erlang ale directory and ended up typing:

%% running make shell in the erlang_Ale 
%% root brings up a shell start the i2c supervisor
i2c_sup:start_link([{i2c1, "/dev/i2c-1"}]).

%% using a named fun to create an infinite loop 
%% effectively bouncing between the two leds.
D = fun Blink(on) ->
    i2c:write(i2c1, 16#04, { 1 }),
    timer:sleep(500),
    Blink(off);
Blink(off) ->
    i2c:write(i2c1, 16#04, { 255 }),
    timer:sleep(500),
    Blink(on)
end.

%% set it in motion
D(on).

This creates a named fun that calls itself over and over swapping the leds that are on. Not much to it, but still pretty cool to do something that simple to just talk to the teensyduino.


Interestingly I didn’t quite understand on the erlang side if I was sending one byte or multiple bytes and on the arduino side I was assuming a single byte: I wasn’t able to switch the leds when sending 0xff though – which led me down some rabbit holes.

First thing to note, which you can see in the github gist is that on the erlang side all you have to do is send

i2c:write(..., ..., { 1 }). %% or

%% if it makes you feel better you could express 
%% this as 16#ff instead of 255 or 16#01 instead of 1
i2c:write(..., ..., { 255 }). 

and it will just send a single byte – furthermore if you happen to want to send multiple bytes you send them by adding more elements to the tuple. So { 16#ff, 16#01, 16#ff } would actually send three bytes (which i verified in the serial output) and if for example you send { 16#ffff } it would get truncated to a single byte. However, that led me to play with erlangs bit syntax, thinking I needed to explicitly send a byte and that maybe I was sending more than one byte etc… and turns out that that was not the case at all which is how I found all this out.

The issue actually ended up being this line but instead of int c, it was char c. So { 1 } would work but { 255 } would not work. That is still odd to me. I’m almost thinking that I did something brilliant like

if (c = 0x01) ...
// instead of 
if (c == 0xff) ...

I’m not sure that the fact that it was char vs integer would have mattered, though char would be signed though, so barring that I didn’t actually make an error in comparing, then perhaps it was me not catching the char being signed (I know it is signed, but wasn’t thinking about it…)

For those curious as far as hooking them up this helped on the pi side, and this for the teensydunio side. Match up the scl and sda pins, and I chose to power the teensyduino from the pi, so I also used the +5v and ground pins on the pi which get hooked up to the VCC and ground pin on the teensyduino.

here is another extremely exciting video of two leds blinking! Enjoy. It’s still pretty damn cool type a few lines into the erlang shell and suddenly this spings to life and here is the gist with the code

 

Advertisements
This entry was posted in Embedded, Erlang. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s