Arduino Dock 2 I2C Example



  • I finally got the arduino dock 2 working under O2+ 0.1.9 b149 and I built up a commented example for using the I2C interface between the Omega and the dock. For the example ideally you would have an external LED w/ resistor attached between ground and digital pin 12 of the arduino headers. But if you don't have that you can simply change the code right at the beginning to use digital pin 13 which is effectively the blue led on the dock:

    #include <Wire.h> // for i2c communications
    
    int EXTLED = 12; // use any arduino digital pin between 2 and 12, or 13 if no external led
    int REGISTER[8]; // can range in size from 1 to 255
    int INDEX = 0; // current index into the register
    int STATE = 0; // current state
    
    void setup() {
      pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LOW); // blue led on the arduino dock 2
      pinMode(EXTLED, OUTPUT); digitalWrite(EXTLED, LOW); // my selected external led
      Wire.begin(0x08); // 0x08 is the arduino dock 2 i2c port
      Wire.onReceive(i2c_on_receive_handler);
      Wire.onRequest(i2c_on_request_handler);
      Serial.begin(9600); // serial output to /dev/ttyS1 on the omega2
    }
    
    void loop() {
      // the first byte of the register controls blinking for the external led
      // to start the blinking: i2cset -y 0 0x08 0x02 0x00 0x01 i # the third byte sets index 0
      // to stop the blinking: i2cset -y 0 0x08 0x02 0x00 0x00 i # the last byte is the value
      if (REGISTER[0] != 0) {
        digitalWrite(EXTLED, HIGH);
        delay(1000);
        digitalWrite(EXTLED, LOW);
        delay(1000);
      }
    }
    
    // called when a transmission is received via the i2c port
    void i2c_on_receive_handler(int bytes_received) {
      int cmd = Wire.read();
      int v = 0;
      Serial.print("received command/data, value: "); Serial.print(cmd, HEX); Serial.print("\n");
      switch (cmd) {
        case 0: // toggle the blue led once - ex: i2cset -y 0 0x08 0x00
          digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
          Serial.print("toggled led\n");
          STATE = 0;
          break;
        case 1: // turn the blue led on or off - ex: i2cset -y 0 0x08 0x01 0x01 i # for on, last byte 0x00 for off
          v = Wire.read();
          digitalWrite(LED_BUILTIN, v ? HIGH : LOW);
          Serial.print("led value set to: "); Serial.print(v); Serial.print("\n");
          STATE = 0;
          break;
        case 2: // write value to the register at index - ex: i2cset -y 0 0x08 0x02 0x00 0x01 i # 3rd byte is the index, 4th byte is the value
          INDEX = Wire.read(); v = Wire.read(); // note: should check valid range for INDEX, in our case 0-7
          REGISTER[INDEX] = v;
          STATE = 0;
          Serial.print("wrote value: "); Serial.print(v, HEX); Serial.print(" to register at index: "); Serial.print(INDEX, HEX); Serial.print("\n");
          break;
        case 3: // prepare to read a value from the register at index - ex: i2cset -y 0 0x08 0x03 0x00 i # 3rd byte is the index
          INDEX = Wire.read();
          STATE = 3; // register value at index can now be read - ex: i2cget -y 0 0x08
          Serial.print("set register index to: "); Serial.print(INDEX); Serial.print(", and state to 3\n");
          break;
        default:
          Serial.print("error, unexpected command value!\n");
      }
    }
    
    // called when data is requested via the i2c port
    void i2c_on_request_handler() {
      byte v = 0;
      switch (STATE) {
        case 0: // default - reads and returns the current state of the blue led - ex: i2cget -y 0 0x08
          v = digitalRead(LED_BUILTIN);
          break;
        case 3: // read and return register value at index - must be set up for read using command 0x03 from above
          v = REGISTER[INDEX];
          STATE = 0;
          break;
        default:
          ;
      }
      // note: any attempt to print causes the Wire.write() to fail - don't know why
      // Serial.print("received request, returned: "); Serial.print(v, HEX); Serial.print("\n");
      Wire.write(v);
    }
    

    Basically you use i2cset and i2cget to send commands and data to the arduino and possibly retrieve data back. For example to simply toggle the blue LED:
    i2cset -y 0 0x08 0x00

    This sends a command byte of 0x00 to the arduino via I2C port 0x08. The blue LED will toggle on or off. These use command byte 0x01 with some data to explicitly turn the blue LED on or off (vs toggling):
    i2cset -y 0 0x08 0x01 0x01 i # turns blue led on
    i2cset -y 0 0x08 0x01 0x00 i # turns blue led off

    Notice the addition of the 'i' at the end of the command line because now we are sending an array of bytes vs a single byte. The example also has a data register that can be used to store values or to control something. In the example I am using the first byte of the register to control whether the external LED is blinking or not. Command byte 0x02 is used to write to the register at a specified index:
    i2cset -y 0 0x08 0x02 0x00 0x01 i # writes value 0x01 at index 0x00 of the register - external LED blinks
    i2cset -y 0 0x08 0x02 0x00 0x00 i # writes 0x00 to the register stopping the external LED blinking

    It's possible to request data from the arduino also. This reads the current state of the blue LED:
    i2cget -y 0 0x08 # that's it - no other bytes - will return 0x00 or 0x01

    To request data from the register you first have to tell the arduino where to read from. First we'll write some data to the register at index 0x07:
    i2cset -y 0 0x08 0x02 0x07 0x99 i # write 0x99 to register at index 0x07

    And now request the data back but first you have to say from where using command byte 0x03:
    i2cset -y 0 0x08 0x03 0x07 i # pre-set index to 0x07 for subsequent request
    i2cget -y 0 0x08 # should return 0x99

    These sequences can be packaged into scripts also to make life simple. For example, to continuously blink the blue LED, this script could be called i2c-blink:
    while true
    do
    i2cset -y 0 0x08 0x00
    sleep 1
    done

    You can define an alias when you start getting tired of typing (or forgetting) the -y 0 all the time:
    alias i2cset='i2cset -y 0'
    Then use a simpler:
    i2cset 0x08 0x00 # toggles the blue led

    So anyway, that's my slightly non-trivial I2C example for the arduino dock 2. Hopefully there are no typos in my sample commands above. Enjoy!


Log in to reply
 

Looks like your connection to Onion Community was lost, please wait while we try to reconnect.