Tuesday, October 11, 2011

The miniProp Contest Begins

miniProp. Win one.
It's time. Head on over to the Bot Thoughts facebook page and enter to win a miniProp, a Parallax Propeller on a DIP form factor with built in regulator, eeprom and crystal. Free IDE from Parallax, lots of community support, 8 cores (cogs), deterministic timing, easy to learn assembly, and more.

Next Tuesday I'll pick the winner at random out of the list of folks who comment on or like the contest post. Good luck!

Friday, October 7, 2011

Win A Propeller Board!

Aww... so cute!
It's small, it's standalone, it's purple, and it's a Parallax Propeller, aka an experimenters dream. I designed this breakout board and I'm giving away a fully populated board to a lucky reader! I call it the miniProp board.

The Propeller has 8 cores (cogs) that operate together in perfect lockstep. The chip has perfectly deterministic timing and really simple assembly language. Writing device drivers on the Propeller is truly a piece of cake. And when you're done you have several cogs left to do lots of interesting things besides.

Friday, September 30, 2011

I2C: mbed reading from Arduino

Quite some time ago, I covered how to get two AVRs talking to each other using the I2C protocol.

Here's how to get an mbed and AVR talking with I2C, with the mbed acting as Master and the AVR acting as Slave.

Let's say you want the mbed to query the Arduino to respond with 4 bytes of data.

The mbed will write an address byte with the read bit set, using the Arduino's address, and then it'll request to read four bytes.  The protocol exchange looks like this:

1. Send a start sequence
2. Send 0xC1 ( I2C address of the slave with the R/W bit high (odd address)
3. Read data bytes from slave
4. Send the stop sequence.

(source: I2C Tutorial)

On the Arduino, call Wire.begin(7), where 7 is the Arduino's I2C address. That tells the Arduino I2C peripheral what messages to listen for. Then call Wire.onRequest() specifying a handler function that is called when the master requests data.

void handleI2CReceive(int numBytes)
{
  char command = Wire.receive(); // pretty much just ignore the command

  return;
}

void handleI2CRequest()
{
  byte data[4];

  // the code below just sends
  // data from the global variable
  // box, a struct with 4 char members
  //
  data[0] = box.x1;
  data[1] = box.y1;
  data[2] = box.x2;
  data[3] = box.y2;
  
  Wire.send(data, 4);
  
  return;
}

void setup() {
  Wire.begin(I2C_ADDRESS);

  box.x1 = box.x2 = box.y1 = box.y2 = 0;

  Wire.onRequest(handleI2CRequest);
  Wire.onReceive(handleI2CReceive);
}
On the mbed, use the "raw" I2C library's start(), write(), read(), stop() methods and manually set the address. Take the I2C slave address, left shift once, and set bit 0 high to indicate a read operation. Then read four bytes. Like this:

        cam.start();
        data[0] = (0x7<<1 | 0x01); // send address + !write = 1
        cam.write(data[0]);       // send address
        data[0] = cam.read(1);
        data[1] = cam.read(1);
        data[2] = cam.read(1);
        data[3] = cam.read(0);    // don't ack the last byte
        cam.stop();

This only works when the slave has one "register". Suppose you have an Arduino that can respond with one of several ADC readings. The protocol exchange would first include the master writing the desired register number to the slave, sending another start, then reading the data. The Arduino would have to accept the register number and store that until the next read request, responding with the correct register's value.