UUGear Solution: Raspberry Pi + Arduino
What are Raspberry Pi and Arduino?
Raspberry Pi is a credit-card-sized single-board computer, while Arduino is a single-board microcontroller, and they are so famous today for electronic hobbyists.
Why put them together?
Raspberry Pi is a mini, fully functional computer. It runs Linux and there are many ready-to-use resource for it. It is very easy to connect Raspberry Pi to the internet and make it a real server. Many USB devices are compatible with Raspberry Pi and can work without installing the driver. Raspberry Pi provides up to 17 GPIO pins for programming, however that’s usually not enough if you plan to build a serious project: making a simple digital clock could use up all of the GPIO pins. What’s more, Raspberry Pi could not accept analog input via the GPIO pins, and has only one pin that could output PWM with hardware, these factors limit the utility of Raspberry Pi in many scenarios.
Arduino is microcontroller, which will run the predefined program to process input/output on its GPIO pins. Better than Raspberry Pi, Arduino has some GPIO pins that could accept analog input, and has several (usually 6) GPIO pins that could generate PWM output with hardware. There are many well designed shields for Arduino, which could extend Arduino to do specific job. Usually Arduino doesn’t have network connection, and could not work as USB host.
The main idea of this project is to use Arduino as the extension of Raspberry Pi, and make the best of both worlds. We can easily access the GPIO pins on connected Arduino, just like they are on Raspberry Pi; accept analog input and generate accurate PWM output via the GPIO pins on Arduino. It is also possible to make use of the shields for Arduino, indirectly on Raspberry Pi.
What can the solution do?
The solution includes a sketch project on Arduino side and a programing library on Raspberry Pi Side. After uploading the sketch, the Arduino becomes a UUGear device and could be found by its unique id. The library provides APIs in C and Python languages, and allows your application to find the UUGear device (Arduino) and access its digital/analog pins, or interact with other modules connect to the Arduino.
How it works?
Some Arduinos have USB port on board, and could connect to Raspberry Pi via USB cable. After the connection, Raspberry Pi can talk to the Arduino, as a serial device. Your application can open the serial device as a file, and read/write data from/to it, as long as you know its serial device name, and the correct baud rate for communication. However the serial device name may change every time you connect Arduino to Raspberry Pi, and your application could not adapt that change automatically. Also your Arduino will need to run a sketch as protocol stack to make sure it understand the commands sent from your application.
The idea of this project is to provide an abstracted model of Arduino device, and allows your application to access the Arduino device via a unique and constant id. This project designs a protocol for the communication between Raspberry Pi and Arduino, and develop a set of friendly APIs to support programming the GPIO pins on Arduino. In order to make the APIs thread-safe, there will be a daemon process that manages all Arduino devices via the corresponding serial ports, which works just like a server. The client application, which will be developed by you, will communicate with the daemon process via message queue. Don’t worry, all these details are transparent for you, you don’t really need to know daemon process or message queue.
It is possible to control multiple Arduino devices at a time, from one or more client applications. As you may already know, Raspberry Pi only has one or two USB ports (depending it’s model A or B). If you wish to connect more Arduino devices to Raspberry Pi, you may need a powered USB hub. UUGear designed and developed a 7-port USB hub for Raspberry Pi, which could make perfect integration:
After connecting Arduino to Raspberry Pi, you can see it as a serial device. Just type the command below in Raspberry Pi console:
ls /dev/tty*
All serial devices that has name started with “tty” will be listed. Usually Arduino device has name with prefix “ttyUSB”, so you may see something like figure below, if you have two Arduino devices connected:
/dev/tty /dev/tty19 /dev/tty3 /dev/tty40 /dev/tty51 /dev/tty62
/dev/tty0 /dev/tty2 /dev/tty30 /dev/tty41 /dev/tty52 /dev/tty63
/dev/tty1 /dev/tty20 /dev/tty31 /dev/tty42 /dev/tty53 /dev/tty7
/dev/tty10 /dev/tty21 /dev/tty32 /dev/tty43 /dev/tty54 /dev/tty8
/dev/tty11 /dev/tty22 /dev/tty33 /dev/tty44 /dev/tty55 /dev/tty9
/dev/tty12 /dev/tty23 /dev/tty34 /dev/tty45 /dev/tty56 /dev/ttyAMA0
/dev/tty13 /dev/tty24 /dev/tty35 /dev/tty46 /dev/tty57 /dev/ttyprintk
/dev/tty14 /dev/tty25 /dev/tty36 /dev/tty47 /dev/tty58 /dev/ttyUSB0
/dev/tty15 /dev/tty26 /dev/tty37 /dev/tty48 /dev/tty59 /dev/ttyUSB1
/dev/tty16 /dev/tty27 /dev/tty38 /dev/tty49 /dev/tty6
/dev/tty17 /dev/tty28 /dev/tty39 /dev/tty5 /dev/tty60
/dev/tty18 /dev/tty29 /dev/tty4 /dev/tty50 /dev/tty61
However, these names may vary every time you connect the Arduino device to Raspberry Pi. If an Arduino device is named “ttyUSB0”, you unplug it and then plug it back after a few seconds, its name might (not always) be changed to “ttyUSB1”. As a mater of fact, those names could not be used to identify an Arduino device. If the name of device is changing, how could the client application find the device?
We need a way to identify the Arduino device without human intervention, thus the client application could find the device and talk to it via APIs. Arduino device has EEPROM on board, which is a perfect place to store the device id. We need to upload a sketch to Arduino device, thus it could generate and save its id in its EEPROM, if it has not been done yet. The sketch needs to listen to serial port and intercept the incoming command, execute the command and send back the response via serial port.
After uploading this sketch, the Arduino device becomes a UUGear device and its EEPROM stores its unique id, which will not change after rebooting, or even re-uploading the sketch (unless you force it to erase EEPROM in new sketch).
There is a very useful tool named “lsuu” in this project, which could list all UUGear devices connected to the Raspberry Pi. Say you connect two UUGear devices (Arduino with UUGear sketch) to Raspberry Pi, and run the command below:
./lsuu
You will see the result printed on the screen, like this:
--------------------------------------------------
UUGear-Arduino-7853-2668 (/dev/ttyUSB1)
UUGear-Arduino-5448-5069 (/dev/ttyUSB0)
--------------------------------------------------
2 device(s) found.
See? Each UUGear device has its unique id, which will never change (while the serial device name in the parentheses may change). You can copy the device id, and keep it for future usage in client application.
In order to control the GPIO pins on the UUGear device, the client application should establish the connection to UUGear device first. The device id will be used to find the correct Arduino.
After establishing the connection, the client application could talk to the UUGear device via UUGear Daemon.
By wrapping the details with friendly APIs, the client application doesn’t need to know how to find the device and manipulate it. The APIs are available in C and Python languages.
What APIs are Provided?
So far UUGear solution provides APIs for C, Python and PHP language.
The Python APIs are actually wrapping C APIs with ctypes.
The PHP APIs are communicating with the UUGear daemon via UNIX domain socket. So the SocketBroker must be running when using the PHP APIs.
Source Code and Examples
This project is hosted in GitHub: https://github.com/shawnu/UUGear
Here is an example written in C. It will blink the LED on pin 13 of Arduino board and then read the status of pin 9:
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <mqueue.h> #include <unistd.h> #include "../../src/UUGear.h" int main(int argc, char **argv) { setupUUGear(); setShowLogs(1); UUGearDevice dev = attachUUGearDevice ("UUGear-Arduino-7853-2668"); if (dev.fd != -1) { setPinModeAsOutput (&dev, 13); int i = 0; for (i = 0; i < 5; i ++) { setPinHigh (&dev, 13); usleep(200000); setPinLow (&dev, 13); usleep(200000); } setPinModeAsInput (&dev, 9); printf("Pin 9 status=%d\n", getPinStatus(&dev, 9)); sleep(1); detachUUGearDevice (&dev); } else { printf("Can not open UUGear device.\n"); } cleanupUUGear(); return 0; }
Below is the same example written in Python (make sure libUUGear.so and UUGear.py files are in the same directory):
from time import sleep from UUGear import * device = UUGearDevice('UUGear-Arduino-7853-2668') if device.isValid(): device.setPinModeAsOutput(13) for i in range(5): device.setPinHigh(13) sleep(0.2) device.setPinLow(13) sleep(0.2) device.setPinModeAsInput(9) print 'Pin 9 status=', device.getPinStatus(9) device.detach() device.stopDaemon() else: print 'UUGear device is not correctly initialized.'
More Examples
Raspberry Pi Measures 0~5V Voltage via Arduino
Raspberrry Pi reads DHT11 via Arduino