Chapter 5. Arduino and the Pi

As you’ll see in the next few chapters, you can use the GPIO pins on the Raspberry Pi to connect to sensors or things like blinking LEDs and motors. And if you have experience using the Arduino microcontroller development platform, you can also use that alongside the Raspberry Pi.

When the Raspberry Pi was first announced, a lot of people asked if it was an Arduino killer. For about the same price, the Pi provides much more processing power: why use Arduino when you have a Pi? It turns out the two platforms are actually complementary, and the Raspberry Pi makes a great host for the Arduino. There are quite a few situations where you might want to put the Arduino and Pi together:

  • To use the large number of libraries and sharable examples for the Arduino.

  • To supplement an Arduino project with more processing power. For example, maybe you have a MIDI controller that was hooked up to a synthesizer, but now you want to upgrade to synthesizing the sound directly on the Pi.

  • When you’re dealing with 5V logic levels. The Pi operates at 3.3V, and its pins are not tolerant of 5V. The Arduino can act as a “translator” between the two.

  • To prototype something a little out of your comfort zone, in which you may make some chip-damaging mistakes. For example, we’ve seen students try to drive motors directly from a pin on the Arduino (don’t try it); it was easy to pry the damaged microcontroller chip out of its socket and replace it (less than $10 usually). Not so with the Raspberry Pi.

  • When you have a problem that requires exact control in real time, such as a controller for a 3D printer. As we saw in Chapter 4, Raspbian is not a real-time operating system, and programs can’t necessarily depend on the same “instruction per clock cycles” rigor of a microcontroller.

The examples in this section assume that you know at least the basics of using the Arduino development board and integrated development environment (IDE). If you don’t have a good grasp of the fundamentals, Getting Started with Arduino by Massimo Banzi is a great place to start. The official Arduino tutorials are quite good as well, and provide a lot of opportunities to cut and paste good working code.

gsrp 0701
Figure 5-1. Arduino and the Raspberry Pi are BFFs

Installing Arduino in Raspbian

To program an Arduino development board, you need to hook it up to a computer with a USB cable, then compile and flash a program to the board using the Arduino IDE. You can do this with any computer, or you can use your Raspberry Pi as a host to program the Arduino.

Using the Raspberry Pi to program the Arduino will be quicker to debug, but compiling will be a little slower on the Pi than on a modern laptop or desktop computer. It’s not too bad though, and you’ll find that compiling will take less time after the very first compile, as Arduino only compiles code that has changed since the last compilation.

To install the Arduino IDE on the Raspberry Pi, type the following into a terminal:

sudo apt-get update 1
sudo apt-get install arduino 2
1

Make sure you have the latest package list.

2

Download the Arduino package.

This command will install Java plus a lot of other dependencies. The Arduino environment will appear under the Electronics section of the program menu (don’t launch it just yet though).

You can just plug the Arduino into one of the open USB ports. The USB connection will be able to provide enough power for the Arduino, but you might want to power the Arduino separately, depending on your application (if you’re running motors or heaters for instance).

Warning

Note that you’ll need to plug the Arduino USB cable in after the Raspberry Pi has booted up. If you leave it plugged in at boot time, the Raspberry Pi may hang as it tries to figure out all the devices on the USB bus.

When you launch the Arduino IDE, it polls all the USB devices and builds a list that is shown in the Tools→Serial Port menu. Click Tools→Serial Port and select the serial port (most likely /dev/ttyACM0), then click Tools→Board, and select the type of Arduino Board you have (e.g., Uno). Click File→Examples→01.Basics→Blink to load a basic example sketch. Click the Upload button in the toolbar or choose File→Upload to upload the sketch, and after the sketch loads, the Arduino’s onboard LED will start blinking.

Warning

In order to access the serial port on versions of Raspbian older than Jessie, you’ll need to make sure that the pi user has permission to do so. You don’t have to do this step on Jessie. You can do that by adding the pi user to the tty and dialout groups. You’ll need to do this before running the Arduino IDE:

sudo usermod1 -a -G2 tty pi  
sudo usermod -a -G dialout pi
1

usermod is a Linux program to manage users.

2

-a -G puts the user (pi) in the specified group (tty, then dialout).

Finding the Serial Port

If, for some reason, /dev/ttyACM0 doesn’t work, you’ll need to do a little detective work. To find the USB serial port that the Arduino is plugged into without looking at the menu, try the following from the command line. Without the Arduino connected, type:

ls /dev/tty*

Plug in Arduino, then try the same command again and see what changed. On my Raspberry Pi, at first I had /dev/ttyAMA0 listed (which is the onboard USB hub). When I plugged in the Arduino, /dev/ttyACM0 popped up in the listing.

Talking in Serial

To communicate between the Raspberry Pi and the Arduino over a serial connection, you’ll use the built-in Serial library on the Arduino side, and the Python pySerial module on the Raspberry Pi side. It comes pre-installed on Jessie, but if you ever need to install it, the package names are:

sudo apt-get install python-serial python3-serial

Open the Arduino IDE and upload this code to the Arduino:

void setup() {
  Serial.begin(9600);
}

void loop() {
  for (byte n = 0; n < 255; n++) {
   Serial.write(n);
   delay(50);
  }
}

This counts upward and sends each number over the serial connection.

Note

Note that in Arduino, Serial.write() sends the actual number, which will get translated on the other side as an ASCII character code. If you want to send the string “123” instead of the number 123, use the Serial.print() command.

Next, you’ll need to know which USB serial port the Arduino is connected to (see “Finding the Serial Port”). Here’s the Python script; if the port isn’t /dev/ttyACM0, change the value of port. (See Chapter 4 for more on Python). Save it as SerialEcho.py and run it with python SerialEcho.py:

import serial

port = "/dev/ttyACM0"
serialFromArduino = serial.Serial(port,9600) 1
serialFromArduino.flushInput() 2
while True:
   if (serialFromArduino.inWaiting() > 0):
       input = serialFromArduino.read(1) 3
       print(ord(input)) 4
1

Open the serial port connected to the Arduino.

2

Clear out the input buffer.

3

Read one byte from the serial buffer.

4

Change the incoming byte into an actual number with ord().

Note

You won’t be able to upload to Arduino when Python has the serial port open, so make sure you kill the Python program with Ctrl-C before you upload the sketch again. You will be able to upload to an Arduino Leonardo or Arduino Micro, but doing so will break the connection with the Python script, so you’ll need to restart it anyhow.

The Arduino is sending a number to the Python script, which interprets that number as a string. The input variable will contain whatever character maps to that number in the ASCII table. To get a better idea, try replacing the last line of the Python script with this:

print(str(ord(input)) + " = the ASCII character " + input + ".")

The first simple example just sent a single byte; this could be fine if you are only sending a series of event codes from the Arduino. For example, if the left button is pushed, send a 1; if the right, send 2. That’s only good for 255 discrete events, though; more often you’ll want to send arbitrarily large numbers or strings. If you’re reading analog sensors with the Arduino, for example, you’ll want to send numbers in the range 0 to 1,023.

Parsing arbitrary numbers that come in one byte at a time can be trickier than you might think in many languages. The way Python and pySerial handle strings makes it almost trivial, however. As a simple example, update your Arduino with the following code that counts from 0 to 1,024:

void setup() {
 Serial.begin(9600);
}

void loop() {
 for (int n = 0; n < 1024; n++)
   Serial.println(n, DEC);
   delay(50);
  }
}

The key difference is in the println() command. In the previous example, the Serial.write() function was used to write the raw number to the serial port. With println(), the Arduino formats the number as a decimal string and sends the ASCII codes for the string. So instead of sending a byte with the value 254, it sends the string 254 . The represents a carriage return, and the represents a newline (these are concepts that carried over from the typewriter into computing: carriage return moves to the start of the line; newline starts a new line of text).

On the Python side, you can use readline() instead of read(), which will read all of the characters up until (and including) the carriage return and newline. Python has a flexible set of functions for converting between the various data types and strings. It turns out you can just use the int() function to change the formatted string into an integer:

import serial

port = "/dev/ttyACM0"
serialFromArduino = serial.Serial(port,9600)
serialFromArduino.flushInput()
while True:
    input = serialFromArduino.readline() 
    inputAsInteger = int(input) 
    print(inputAsInteger * 10) 

Note that it is simple to adapt this example so that it will read an analog input and send the result; just change the loop to:

void setup() {
 Serial.begin(9600);
}

void loop() {
  int n = analogRead(A0);
  Serial.println(n, DEC);
  delay(100);
}

Assuming you change the Python script to just print inputAsInteger instead of inputAsInteger * 10, you should get some floating values in the 200 range if nothing is connected to analog pin 0. With some jumper wire, connect pin 0 to GND and the value should be 0. Connect it to the 3V3 pin and you’ll see a value around 715, and 1,023 when connected to the 5V pin.

Using Firmata

As you go deeper, many projects will look the same as far as the code for basic communication goes. As with any form of communication, things get tricky once you get past “Hello, world”; you’ll need to create protocols (or find an existing protocol and implement it) so that each side understands the other.

One good solution that comes bundled with Arduino is Hans-Christoph Steiner’s Firmata, an all-purpose serial protocol that is simple and human readable. It may not be perfect for all applications, but it is a good place to start. Here’s a quick example:

  1. Select File→Examples→Firmata→StandardFirmata in Arduino; this will open the sample Firmata code that will allow you to send and receive messages to the Arduino and get information about all of the pins.

  2. Upload that code to the Arduino the same way you did in previous examples.

  3. You’ll need a bit of Python code on the Pi to send commands to the Arduino to query or change its state. The easiest way is to use the pyFirmata module. Install it using Pip (see “Easy Module Installs with Pip”):

    sudo pip install pyfirmata
  4. Because Firmata is a serial protocol, you talk to the Arduino from Python in the same way as in previous examples, but using pyFirmata instead of pySerial. Use the write() method to make a digital pin high or low on the Arduino:

    from pyfirmata import Arduino
    from time import sleep
    board = Arduino('/dev/ttyACM0')
    while (1):
        board.digital[13].write(1)
        print("on")
        sleep(1)
        board.digital[13].write(0)
        print("off")
        sleep(1)

    This code should blink the LED on the Arduino Uno board that is connected to pin 13. The full module is documented on the pyFirmata GitHub page.

Going Further

The nitty-gritty of serial protocols is beyond the scope of this book, but there are a lot of interesting examples of how other people have solved problems in the “Interfacing with Software” section of the Arduino Playground. In addition, you may want to try:

MIDI

If your project is musical, consider using MIDI commands as your serial protocol. MIDI is (basically) just serial, so it should just work.

Arduino-compatible Raspberry Pi shields

There are a few daughterboards (or shields) on the market that connect the GPIO pins on the Raspberry Pi with an Arduino-compatible microcontroller. WyoLum’s AlaMode shield is a good solution and offers a few other accessories, including a real-time clock.

Talk over a network

Finally, you can ditch the serial connection altogether and talk to the Arduino over a network. A lot of really interesting projects are using the WebSocket protocol along with the Node.js JavaScript platform.

Using the serial pins on the Raspberry Pi header

The header on the Raspberry Pi pulls out a number of input and output pins, including two that can be used to send and receive serial data bypassing the USB port. To do that, you’ll first need to cover the material in Chapter 7, and make sure that you have a level shifter to protect the Raspberry Pi 3.3V pins from the Arduino’s 5V pins.

If you’re looking to get deeper into making physical devices communicate, a good starting point is Making Things Talk, 2nd Edition, by Tom Igoe.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset