Firmata und I2C/Wire

Firmata

Firmata is a protocol for communicating with microcontrollers from software on a host computer. So you can control an Arduino with a Raspberry Pi using Firmata.

There is a tutorial for Firmata and Raspberry Pi in The MagPi Issue 7 and here is also a small guide.

Prepare RPi-ShieldBridge

  • Sketch upload with USB FTDI adapter

    • Download and install the Arduino IDE on your computer or Raspberry Pi.
    • Close the JVCC Jumper next to the FTDI connector to power the RPi-ShieldBridge from the FTDI adapter or put it on a Raspberry Pi for powering.
    • Connect the RPi-ShieldBridge with a FTDI adapter (5V) to the computer or Raspberry Pi.
    • Start the Arduino IDE.
    • Select Arduino Uno under Tools->Board.
    • Choose the serial port from the FTDI adapter under Tools->Serial Port.
    • Open the Firmata Sketch under File->Examples->Firmata->StandardFirmata.
    • Start build and upload: File->Upload. If there are upload problems then add a pull-down resistor (10k-47k Ohm) between GPIO18 or Jumper JBL and GND.
    • Now exit the Arduino IDE.
  • Sketch upload via hardware serial port of the Raspberry Pi

    • Close the Jumpers: JTX, JRX and JBL on the RPi-ShieldBridge.
    • Install the Arduino IDE on the Raspberry Pi.
    • Run the Arduino IDE.
    • Select Arduino Uno under Tools->Board.
    • Select the hardware serial port /dev/ttyAMA0 under Tools->Serial Port.
    • Open the Firmata Sketch under File->Examples->Firmata->StandardFirmata.
    • Upload the Sketch.
    • Now exit the Arduino IDE.

Prepare Raspberry Pi

The RPi-ShieldBridge can be connected via USB or UART:

  • USB connection (FTDI adapter)

    • Put the RPi-ShieldBridge on the Raspberry Pi.
    • Connect a FTDI adapter (5V) to the USB port of the Raspberry Pi and FTDI connector on the RPi-ShieldBridge.
    • Device name: /dev/ttyUSB0 or /dev/ttyACM0
  • UART connection (hardware serial port)

    • Close the Jumpers JTX and JRX on the RPi-ShieldBridge.
    • Put the RPi-ShieldBridge on the Raspberry Pi.
    • Run $ sudo raspi-config and select Advanced > Interfacing Options > Serial > Disable shell > Enable serial port hardware
    • Device name: Pi 3 /dev/ttyS0, all other Pi models /dev/ttyAMA0

Controlling with Python

  • Install pySerial and pyFirmata using pip:

    $ sudo apt-get update
    $ sudo apt-get install python-serial
    $ sudo pip install pyfirmata
    
  • Create a test script named Firmata.py:

    $ nano Firmata.py
    
    import time
    import RPi.GPIO as GPIO
    import pyfirmata
    
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(12, GPIO.OUT)   # GPIO18 output
    GPIO.output(12, GPIO.LOW)  # GPIO18 low -> Arduino reset off
    
    # start connection to Arduino
    #  USB: /dev/ttyUSB0 or /dev/ttyACM0
    #  UART: /dev/ttyS0 or /dev/ttyAMA0
    board = pyfirmata.Arduino('/dev/ttyAMA0')
    
    board.digital[13].write(1) # switch on LED
    time.sleep(3)              # 3s delay
    board.digital[13].write(0) # switch off LED
    time.sleep(3)              # 3s delay
    board.exit()
    
  • Run the script:

    $ python Firmata.py
    

Controlling with Node.js (JavaScript)

  • Install Node, Firmata library and rpio library:

    $ sudo apt-get install node
    $ sudo npm install -g firmata
    $ sudo npm install -g rpio
    

    If the node package is not found then add Adafruit to the package repository: $ curl -sLS https://apt.adafruit.com/add | sudo bash

  • Create a test script named Firmata.js:

    $ nano Firmata.js
    
    var rpio = require('rpio');
    var firmata = require('firmata');
    
    // GPIO18 low -> Arduino reset off
    rpio.setOutput(12);
    rpio.write(12, rpio.LOW);
    
    // start connection to Arduino
    //  USB: /dev/ttyUSB0 or /dev/ttyACM0
    //  UART: /dev/ttyS0 or /dev/ttyAMA0
    var board = new firmata.Board('/dev/ttyAMA0', function(err)
    {
      if(err)
      {
        console.log(err);
        return;
      }
      console.log('connected');
      board.pinMode(13, board.MODES.OUTPUT);
      // switch on LED
      board.digitalWrite(13, board.HIGH);
      // switch off LED after 3s
      setTimeout(function()
      {
        board.digitalWrite(13, board.LOW);
        process.exit(0);
      }, 3000);
    });
    
  • Run the script:

    $ sudo node Firmata.js
    

I2C/Wire

A small guide to show the communication via I2C between the RPi-ShieldBridge and Raspberry Pi.

The I2C pins of the Raspberry Pi are connected to the AVR and the Shield connectors (SDA+SCL) on the RPi-ShieldBridge.

Prepare RPi-ShieldBridge

Upload the following Sketch:

#include <Wire.h> 

#define ADDRESS 0x30

void setup() 
{
  pinMode(13, OUTPUT);     // set pin 13 as output (LED connected)
  digitalWrite(13, LOW);   // set pin 13 to low (0V)

  Wire.begin(ADDRESS);     // join I2C bus with respective address
  Wire.onReceive(receive); // receive data function
  Wire.onRequest(request); // send data function
} 

void loop() 
{
  // do nothing
} 

void receive(int numBytes) // function that runs when data is received
{
  unsigned char c;

  while(Wire.available())
  { 
    c = Wire.read();
    if(c == 0x00)      // LED off, if byte equals 0
    {
      digitalWrite(13, LOW);
    }
    else if(c == 0x01) // LED on, if byte equals 1
    {
      digitalWrite(13, HIGH);
    }
  }
}

void request() // function that runs when data is requested
{
  Wire.write(0xAA); // send 0xAA
}

Prepare Raspberry Pi

  • Activate I2C:

    $ sudo modprobe i2c_bcm2708 baudrate=100000
    $ sudo modprobe i2c-dev
    

    Note: For a Device Tree Kernel add to /boot/config.txt the following line: dtparam=i2c1=on (before any dtoverlay statement).

  • Install i2c-tools and python-smbus:

    $ sudo apt-get install i2c-tools
    $ sudo apt-get install python-smbus
    
  • Test I2C bus:

    $ sudo i2cdetect -y 1
    

    The Raspberry Pi hardware revision 1 boards connect I2C bus 0 (GPIO 0 + 1) and revision 2 boards connect I2C bus 1 (GPIO 2 + 3) to the GPIO connector.

  • Note: As default the reset pin of the AVR is connected to GPIO18 (Pin 12) of the Raspberry Pi (GPIO18 high = reset on, GPIO18 low = reset off). To disable the reset:

    $ sudo -i
    $ echo 18 > /sys/class/gpio/export
    $ echo out > /sys/class/gpio/gpio18/direction
    $ echo 0 > /sys/class/gpio/gpio18/value
    $ exit
    

    Or if you have installed WiringPi:

    $ gpio -g mode 18 out
    $ gpio -g write 18 0
    

Shell

  • Switch on LED:

    $ sudo i2cset -y 1 0x30 0x01
    
  • Switch off LED:

    $ sudo i2cset -y 1 0x30 0x00
    

Python

  • Create a test script named I2CTest.py:

    $ nano I2CTest.py
    
    import time
    import smbus
    bus = smbus.SMBus(1)
    addr = 0x30
    
    while True:
        bus.write_byte(addr, 0x01)
        print "on"
        time.sleep(1)
        bus.write_byte(addr, 0x00)
        print "off"
        time.sleep(1)
    
  • Run the script:

    $ sudo python I2CTest.py