Connect NGW100 Linux (AVR32) to Arduino with I2C

For a Linux embedded training, I need to find something fun to plug on an AVR32 board. The board used for the training is a NGW100 board. I decided to try to use the I2C bus. I have several I2C stuff on the desk, but nothing really fun and I don’t want to solder a lot of stuff, and spend a lot of time on this. I decided to use a Arduino board as a I2C slave device and plug this to the NGW100 board.

First step: Simply use the Arduino IDE and the Wire lib. I use an Seeeduino because I need an Arduino that works at 3.3v level. Here the code :

#include <Wire.h>
void setup()
{
  Wire.begin(4);                // join i2c bus with address #4
  Wire.onReceive(receiveEvent); // register event
  Wire.onRequest(requestEvent); // register event
  Serial.begin(38400);           // start serial for output
  Serial.println("Boot Ok");
}

void loop()
{ delay(100); }

void receiveEvent(int howMany)
{
  char c = NULL;
  while(Wire.available()) // loop through all
  {
    c = Wire.receive(); // receive byte as a character
    Serial.print(c);         // print the character
  }
  Serial.println();
  Serial.println("===");
}

void requestEvent()
{
  Serial.println("read");
  Wire.send("Hello world from Arduino");
}

To test the Arduino I used a Bus Pirate, this is quite simple and fun, here a little snipset of my initial test with the BP (note the string are different). The I2C slave is at the 0×4 address (check the setup()).

Searching I2C address space. Found devices at:
0x08(0x04 W) 0x09(0x04 R) 

Read content from the device, 'ABCD'
I2C>[0x09 rrrrrr]
I2C START BIT
WRITE: 0x09 ACK
READ: 0x41
READ:  ACK 0x42
READ:  ACK 0x43
READ:  ACK 0x44
READ:  ACK 0xFF
READ:  ACK 0xFF
NACK
I2C STOP BIT
I2C>

send content to the device 'ABC'
I2C>[0x08 0x41 0x42 0x43]
I2C START BIT
WRITE: 0x08 ACK
WRITE: 0x41 ACK
WRITE: 0x42 ACK
WRITE: 0x43 ACK
I2C STOP BIT

Second step: Plug the Arduino to the NGW100. I used the wrapping technique. Simply connect SDA, SCL, and GND. (NGW100 pinouts : SDA=>9, SCL=>10, GND=>2)

On Linux, load the I2C-GPIO kernel module. On OpenWRT (used on the NGW100), simply load the kmod-i2c-gpio package.

Final step: If everything is Ok, we can now test the communication. I used a small piece of C code to deal with I2C on Linux.

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include <fcntl.h>

void i2c_run(void) {
    int file;
    char filename[40];
    int addr = 0x4;
    char buf[32] = {0};
    int i;

    sprintf(filename,"/dev/i2c-0");
    if ((file = open(filename,O_RDWR)) < 0) {
        printf("Failed to open the bus.");
        exit(1);
    }

    if (ioctl(file,I2C_SLAVE,addr) < 0) {
        printf("Failed to acquire bus access and/or talk to slave.\n");
        exit(1);
    }

    i = 24;
    // read I2C
    if (read(file,buf,i) != i) {
      printf("Failed to read from the i2c bus.\n");
    } else {
      printf("Read %d bytes from I2C: [%s]\n",i,buf);
    }

    sprintf(buf,"IC2 from Linux to Arduino");
    i = strlen(buf);
    if (write(file,buf,i) != i) {
        printf("Failed to write to the i2c bus.\n");
    } else {
      printf("Sent %d bytes to I2C: [%s]\n",i,buf);
    }
}

int main()
{
  i2c_run();
  return 0;
}

As you can see this code is a bit rude, but works really well : Read the I2C bus, and send a sample string, a proof ? :)

Of course, I used string values but in real life a small protocol shoud be used. Another important thing: I used a NGW100 but you can use the same idea on all Linux embedded board like the Fonera, or anything else.

Update: Of course you can use the i2c-tools on Linux to detect your own device. To do that : Grab the i2c-tools source, and cross compile it for the AVR32. (You only have to change the CC path in the Makefile).

/Enjoy small Linux



Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>