Raspberry pi controls Arduino using Python (RAP)
The Raspberry Pi is sometimes seen as competition to micro controllers like the Arduino. However the Raspberry Pi has a different sweet spot and can easily be combined with an Arduino to accomplish a wider range of tasks than otherwise possible. For example the missing Analog inputs.
Setting up your Arduino for Firmata
Firmata control of the Arduino requires loading an Arduino with the special Firmata sketch. You can download the Arduino software from the Arduino website. After opening the Arduino IDE, follow these steps to install Firmata on your Arduino:
1. Click File->Examples->Firmata->StandardFirmata
2. From the Tools->Board menu, select the type of Arduino you are using.
3. From the Tools->Serial Port menu, choose the USB port to which your Arduino is connected.
4. Click the upload button (it looks like a right arrow, just next to the checkmark) and wait for your sketch to upload. A message in the bottom black window will indicate success or failure
5. Once the Firmata sketch is loaded on your Arduino, you can test it out with the Firmata Test Program. (http://www.firmata.org/wiki/Main_Page)
Controlling your Arduino from Python
Next, your Raspberry Pi must be setup with the python firmata libraries. Run the following commands:
sudo apt-get install python-pip python-serial sudo pip install pyfirmata
Use a USB cable to connect the Arduino with the Raspberry Pi (remember to use the big USB Standard A connector and not the smaller Micro B power connector). You can now find the USB name of the Arduino by running ‘ls -lrt /dev/tty*’. On my Raspberry Pi, it was listed as /dev/ttyUSB0. Remember this value for later.
Connecting to an Arduino
To control an Arduino from a Python script on your Raspberry Pi, you must first import the Arduino and util classes from the pyfirmata module. Then, create an object using the USB address you found in the previous step
>>> from pyfirmata import Arduino, util >>> board = Arduino('/dev/ttyUSB0')
Controlling Arduino GPIO
The Arduino’s digital input and output ports can be controlled using the board.digital[] list. Calling write() can set the pin values high or low (1 and 0 respectively). The read() method returns the current value of the pin.
>>> board.digital[2].write(1) >>> print board.digital[2].read()
If you’d like to use a pin repeatedly, its cumbersome to keep referring to it as board.digital[2]. Instead, you can get a reference to a pin with the board.get_pin() function. To this function, you pass a string of the format “[a|d]:[pin#]:[i:o:p:s]”. It is split by colons into three sections. The first section determines if the pin will be used in analog or digital mode. The second section is the number of the pin you would like to use. The third section selects the pin mode between input, output, pwm, and servo. The returned pin can be assigned to a variable and then later used to call read() and write() methods.
>>> pin2 = board.getpin('d:2:o') >>> pin2.write(1)
Controlling Analog Pins
To read the value on an analog pin, you have to first turn on the analog value reporting on that pin. However, this continuously sends the analog value from the Arduino to the Raspberry Pi. If not continuously read, this will clog up the serial connection and prevent the rest of your script from running properly. To read the values, it is helpful to use an iterator thread.
>>> it = util.Iterator(board) >>> it.start() >>> board.analog[0].enable_reporting() >>> board.analog[0].read() >>> it.start()
To turn off the reporting of analog values, call disable_reporting() on the pin object
Sample code
Read LM35 temperature from AI0 pin and store in CSV
# Python27 import csv import pyfirmata import time from time import sleep port = '/dev/cu.usbmodemfa1331' #'COM3' for Windows board = pyfirmata.Arduino(port) #pin =[0] it = pyfirmata.util.Iterator(board) it.start() a0 = board.get_pin('a:0:i') #a0.enable_reporting() with open('SensorDataStore.csv', 'w') as f: w = csv.writer(f) w.writerow(["Number","Temperature"]) i = 0 while i < 25: Temperature = a0.read() if (Temperature != None): Temperature = Temperature*100 # to read value in decimal sleep(1) i += 1 row = [i, Temperature] w.writerow(row) print (Temperature) print ("Done. CSV file is ready!") board.exit()
Very helpful. I’m working on an autonomous quadcopter but the Pi’s PWM isn’t stable enough with everything else going on so I was thinking of using a Nano to handle the ESC’s. This should make the comms a lot easier.
LikeLike
Yes Wronbow, It is wise to use the AI, PWM etc from Arduino to avoid the real time issues.
LikeLike