In Control
We show how to wirelessly control pan/tilt servos with an Arduino Yún and a Raspberry Pi.
Lead Image © Phil Wohlrab, 123RF.com
We show how to wirelessly control pan/tilt servos with an Arduino Yún and a Raspberry Pi.
A while back, I gave a talk at Fossetcon about wirelessly controlling pan/tilt servos running on an Arduino Yún [1]. The on-screen sliders worked on a Linux notebook with code written using the Processing language [2]. So, I asked myself, "Could a Raspberry Pi replace the notebook for this job?"
It turns out that moving the Processing code over to a Pi is fairly straightforward. However, there are plenty of moving parts, even for a simple multidevice "system" like this one, and making the pieces all work right together can be a challenge.
The major components of this project include the Arduino Yún, its servos, and the Arduino code needed to interpret the data sent from the Raspberry Pi. There's also the Raspberry Pi hardware and its Processing code used to display and manage the sliders, the local area network (LAN) needed to connect the two parts together, and, finally, the Linux notebook used to program the Yún, which I'll explain in a minute.
I'll start with the Arduino Yún, then talk about what's needed with the Raspberry Pi, and finish up with some challenges and enhancements you can make to your own project.
The Yún is a unique beast in the Arduino world. It has two processors. The AR 9331 chip runs an ultra-small version of Linux handling the WiFi connection and a few other tasks. The ATmega 32u4 chip takes care of the traditional super-fast, microcontroller input/output and functions similar to an Arduino Leonardo. They are tied together by the "bridge library" that allows the two processors to interact with each other. The bridge library connects the servos to the network.
I chose to keep the programming of the Yún on the Linux laptop for this project instead of doing everything on the Pi. The default Arduino IDE for my version of Raspbian Linux (on the Pi) is stuck at 1.0.1. You need at least version 1.5.4 to be able to upload firmware with the Yún's WiFi capability. Working it this way makes it easy to troubleshoot the Arduino code and upload it over the air, right into the Yún.
Although it might be interesting to program the Yún from the Pi, getting a project working quickly is important for your motivation and "fun factor." Get a minimum viable project going, then expand the complexity as you see fit. Remember, parts left out cost nothing and cause few maintenance problems.
On the notebook, I started the Arduino IDE with the following, from a terminal.
rob-notebook% cd arduino-1.5.7 rob-notebook% ./arduino
The IDE then loads, and you can copy the code from Listing 1.
Listing 1
Arduino Yún Servo Control Code
01 // Arduino servo control code // 02 #include <Bridge.h> 03 #include <YunServer.h> 04 #include <YunClient.h> 05 #include <Console.h> 06 #include <Servo.h> 07 #define PORT 6666 08 Servo servo1; 09 Servo servo2; 10 YunServer server(PORT); 11 YunClient client; 12 13 void setup() { 14 Bridge.begin(); 15 servo1.attach(9); //pwm pin 9 16 servo2.attach(11); //pwm pin 11 17 server.noListenOnLocalhost(); 18 server.begin(); 19 Console.begin(); 20 Console.println("Console Connected"); 21 } 22 23 void loop() { 24 static int v = 0; 25 char ch; 26 client = server.accept(); 27 if(client.connected()){ 28 Console.println("Client Connected"); 29 while(client.connected()){ 30 if(client.available()){ 31 ch = client.read(); 32 33 switch(ch) { 34 case '0'...'9': 35 v = v * 10 + ch - '0'; 36 break; 37 case 'a': 38 // send 'a' to control pan servo1 39 servo1.write(v); 40 Console.print(v); 41 Console.println("a"); 42 v = 0; 43 break; 44 case 'b': 45 // send 'b' to control tilt servo2 46 servo2.write(v); 47 Console.print(v); 48 Console.println("b"); 49 v = 0; 50 break; 51 } 52 } 53 } 54 client.stop(); 55 } 56 }
Make sure the following libraries are present; otherwise, you won't be able to compile the code:
Bridge.h
YunServer.h
YunClient.h
Console.h
Servo.h
The code consists of the usual variable definitions and initializations, a setup section, and the main loop. I've included some "Console" lines to help with debugging and to let you see the data coming in from the Processing/Raspberry Pi code.
The logic of the Yún code is pretty straightforward. A client instance is opened, and while it's connected to the Raspberry Pi client code, it reads in characters and interprets the results.
If the character is a digit from 0 to 9, it stores the number. When either an a or b comes along, it directs the servo to the desired location. Because this is a basic "minimum viable" project, there's no error or range checking, failover, or security code baked into the program.
The program then just sits in a loop until the next set of characters come through. Be sure to upload the Yún code using the Arrow button, in the IDE. Check that you have the Yún board selected under the Tools | Board tab, if you have troubles uploading. You might also need to check the Tools | Port tab and make sure it's pointing to the IP address of the Yún and not the USB port.
A couple of things might trip you up in the code. To avoid trouble, make sure the IP address and PORT
number in the code matches whatever you use in the Processing code on the Raspberry Pi. Also, make sure that your servo data connections go to the right connections on the Yún.
As far as the actual Yún hardware goes, I powered the servos from the 5V header on the board itself. Keep in mind that I was using tiny little nano-RC servos, so the current draw was pretty modest. Going with larger servos will require having their own dedicated power supply. The Yún won't be able to supply the current needed and will be unstable because of noise created by servo operation. They are electric motors, after all.
I used a breadboard to hook the servos to the Yún. Figure 1 shows the Yún/servo test rig I modded from a previous Steampunk Eye project (Figure 2), which ran an Arduino Duemilanove. The breadboard is easily eliminated with a little creative wiring harness design of your own.
Other than that, wiring the servos is pretty basic. Take a look at Figure 3 for the layout.
I already had the slider code (Listing 2) working on my Linux notebook, so most of the work porting it over involved installing Processing on the Pi. The controlP5 [3] library, which is used to display the sliders, also has to be installed. Finally, the slider code has to be moved over from the notebook.
Listing 2
Slider Control Processing Code
01 // Slider control Processing code // 02 /** 03 * ControlP5 Slider 04 * by andreas schlegel, 2010 05 * www.sojamo.de/libraries/controlp5 06 **/ 07 import processing.net.*; 08 import controlP5.*; 09 Client c; 10 ControlP5 cp5; 11 int pan = 10; 12 int tilt = 10; 13 int ptmp = pan; 14 int ttmp = tilt; 15 16 void setup() { 17 size(500,500); 18 noStroke(); 19 c = new Client(this, "192.168.1.111", 6666); 20 21 cp5 = new ControlP5(this); 22 23 // add a horizontal slider for pan 24 cp5.addSlider("pan") 25 .setPosition(50,70) 26 .setSize(300, 30) 27 .setRange(0,180) 28 .setValue(58) 29 ; 30 31 // add a vertical slider for tilt 32 cp5.addSlider("tilt") 33 .setPosition(150,130) 34 .setSize(30, 300) 35 .setRange(180, 0) 36 .setValue(58) 37 ; 38 } 39 40 void draw() { 41 //Output the servo position (from 0 to 180) 42 // "a" corresponds to servo1 43 // "b" corresponds to servo2 44 if (pan != ptmp){ 45 c.write(pan + "a"); 46 // println(pan); 47 ptmp = pan; 48 } 49 if (tilt != ttmp){ 50 c.write(tilt + "b"); 51 // println(tilt); 52 ttmp = tilt; 53 } 54 }
Installing the Processing language on the Raspberry Pi only takes a few commands. My Pi is running Raspbian Linux version 2.2.1. From a terminal, type:
rob-pi% cd ~ rob-pi% sudo apt-get install processing
Next, apt-get
will do its thing and after a few minutes, you can bring up the Processing IDE. While still in the terminal, check that Processing runs correctly by typing the following:
rob-pi% cd processing-2.2.1 rob-pi% ./processing
Because I developed the code on the Linux notebook, the easiest way to move the code was with rcp
[4]. Just find the directory that houses your code and send it over to the Raspberry Pi. Here's the command line I used:
rob-pi% rcp servo4_processing2.pde \ pi@192.168.1.109:/home/pi/\ sketchbook/servo4_processing1\ servo4_processing2.pde
Enter your Rasp Pi's password, if needed. You might have to make adjustments if you stored the Processing code in a different directory. Also, you'll need to know the IP address of the Raspberry Pi. In a terminal on the Pi, use the ifconfig
command:
rob-pi% ifconfig
An IP address will appear on the inet addr:
line in the eth0 section if the Rasp Pi is connected properly. If your Pi is connected via WiFi, the IP address will show up in the wlan0 section.
To be able to use the slider program on the Pi, the controlP5 contributed library must also be installed. Download it [3]; then, in a terminal, type the following:
rob-pi% mv controlP5-2.0.4.zip \ sketchbook/libraries rob-pi% cd sketchbook/libraries rob-pi% unzip controlP5-2.0.4.zip
Make sure to change the IP address in the Processing code to match your Yún's setup. In my case, the Yún had an IP of 192.168.1.111 and the Pi had 192.168.1.109. My Linux notebook was set to 192.168.1.80. Also, note that I used 6666 for the port number, which deviates from the standard port used in the ControlP5 examples.
Pages: 6
Price $15.99
(incl. VAT)