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-UNO-HAT

  • Sketch upload via hardware serial port of the Raspberry Pi

    • The jumpers TX, RX and RES have to be closed, which is also the default state of these jumpers.
    • Install the Arduino IDE on the Raspberry Pi.
    • Start the Arduino IDE.
    • Select Arduino Uno under Tools->Board.
    • Choose the hardware serial port /dev/ttyS0 or /dev/ttyAMA0 under Tools->Serial Port.
    • Open the Firmata Sketch under File->Examples->Firmata->StandardFirmata.
    • Start build and upload: File->Upload.
    • Now exit the Arduino IDE.
  • Sketch upload with USB FTDI adapter

    • Download and install the Arduino IDE on your computer or Raspberry Pi.
    • Close the VCC Jumper next to the FTDI connector to power the RPi-UNO-HAT from the FTDI adapter or put it on a Raspberry Pi for powering.
    • Connect the RPi-UNO-HAT 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.
    • Now exit the Arduino IDE.

Prepare Raspberry Pi

The RPi-UNO-HAT can be connected via USB or UART:

  • USB connection (FTDI adapter)

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

    • Put the RPi-UNO-HAT 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 pyfirmata
    
    # 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 and Firmata library:

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

    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 firmata = require('firmata');
    
    // 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 Arduino (RPi-UNO-HAT) and Raspberry Pi.

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

Prepare RPi-UNO-HAT

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
    

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