
So I was working on trying to get wheels on the pan/tilt webcam and realized I should post how I did the first part of it before I post the second. Youtube of it in action here.
The parts you need are:
two mounts to hold two servos
some kind of heavy base to attach to the servos to prevent it from shaking and tipping over
arduino , wiring and a joystick
python 2.6 , pyserial, and pygame module.
BIG BIG thanks to the folks over at principal labs for posting great tutorials and the code. They did 90% of the work and I slightly altered the python script to make it work for two servos moving in different directions.
So the setup is pretty simple, a joystick > computer running python script > send data serially to arduino > servos
first hook up the two servos to pins 2,3 ground and +5V on the arduino.
I used a script that principal labs made to send data serially. Make sure you find out what com port your arduino is connected to and replace that part of the code.
#!/usr/bin/env python
################################################
# Module: servo.py
# Created: 2 April 2008
# Author: Brian D. Wendt
# http://principialabs.com/
# Version: 0.2
# License: GPLv3
# http://www.fsf.org/licensing/
'''
Provides a serial connection abstraction layer
for use with Arduino "MultipleServos" sketch.
'''
################################################
import serial
usbport = 'COM9'
ser = serial.Serial(usbport, 9600, timeout=1)
#print ser
def move(servo, angle):
'''Moves the specified servo to the supplied angle.
Arguments:
servo
the servo number to command, an integer from 1-4
angle
the desired servo angle, an integer from 0 to 180
(e.g.) >>> servo.move(2, 90)
... # "move servo #2 to 90 degrees"'''
if (0 <= angle <= 180):
ser.write(chr(255))
ser.write(chr(servo))
ser.write(chr(angle))
print servo
print angle
else:
print "Servo angle must be an integer between 0 and 180.\n"Now the python script uses the previous one to interpret the joystick data.
#!/usr/bin/env python
import servo
import pygame
# allow multiple joysticks
joy = []
# handle joystick event
def handleJoyEvent(e):
if e.type == pygame.JOYAXISMOTION:
axis = "unknown"
if (e.dict['axis'] == 0):
axis = "X"
if (e.dict['axis'] == 1):
axis = "Y"
if (e.dict['axis'] == 2):
axis = "Throttle"
if (e.dict['axis'] == 3):
axis = "Z"
if (axis != "unknown"):
str = "Axis: %s; Value: %f" % (axis, e.dict['value'])
# uncomment to debug
output(str, e.dict['joy'])
# Arduino joystick-servo hack
if (axis == "X"):
pos = e.dict['value']
# convert joystick position to servo increment, 0-180
move = round(pos * 90, 0)
if (move < 0):
serv = int(90 - abs(move))
else:
serv = int(move + 90)
# convert position to ASCII character
servoPosition = serv
# and send to Arduino over serial connection
servo.move(1, servoPosition)
# Arduino joystick-servo hack
if (axis == "Y"):
pos = e.dict['value']
# convert joystick position to servo increment, 0-180
move = round(pos * 90, 0)
if (move < 0):
serv = int(90 - abs(move))
else:
serv = int(move + 90)
# convert position to ASCII character
servoPosition = serv
# and send to Arduino over serial connection
servo.move(2, servoPosition)
elif e.type == pygame.JOYBUTTONDOWN:
str = "Button: %d" % (e.dict['button'])
# uncomment to debug
output(str, e.dict['joy'])
# Button 0 (trigger) to quit
if (e.dict['button'] == 0):
print "Pew Pew You're DEAD!!\n"
if (e.dict['button'] == 8):
print "Bye!\n"
quit()
else:
pass
# print the joystick position
def output(line, stick):
print "Joystick: %d; %s" % (stick, line)
# wait for joystick input
def joystickControl():
while True:
e = pygame.event.wait()
if (e.type == pygame.JOYAXISMOTION or e.type == pygame.JOYBUTTONDOWN):
handleJoyEvent(e)
# main method
def main():
# initialize pygame
pygame.joystick.init()
pygame.display.init()
if not pygame.joystick.get_count():
print "\nPlease connect a joystick and run again.\n"
quit()
print "\n%d joystick(s) detected." % pygame.joystick.get_count()
for i in range(pygame.joystick.get_count()):
myjoy = pygame.joystick.Joystick(i)
myjoy.init()
joy.append(myjoy)
print "Joystick %d: " % (i) + joy[i].get_name()
print "Depress trigger (button 0) to quit.\n"
# run joystick listener loop
joystickControl()
# allow use as a module or standalone script
if __name__ == "__main__":
main()
And the final part is the micro controller sketch:
#!/usr/bin/env python
/*
* MultipleServos
* --------------
* Arduino servo control from a PC
*
* Created: 2 April 2008
* Author: Brian D. Wendt
* http://principialabs.com/
* License: GPLv3, copyleft 2008
* http://www.fsf.org/licensing/
*
* Adapted from code by Tom Igoe
* http://itp.nyu.edu/physcomp/Labs/Servo
*/
/** Adjust these values for your servo and setup, if necessary **/
int pinArray[4] = {2, 3, 4, 5}; // digital pins for the servos
int minPulse = 600; // minimum servo position
int maxPulse = 2400; // maximum servo position
int refreshTime = 20; // time (ms) between pulses (50Hz)
/** The Arduino will calculate these values for you **/
int i; // iterator
int servoPin; // control pin for current servo
int userInput[3]; // raw input from serial buffer, 3 bytes
int pulseWidth; // servo pulse width
int servoPosition; // commanded servo position, 0-180 degrees
int pulseRange; // maxPulse - minPulse
int centerServo; // servo starting point
long lastPulse = 0; // recorded time (ms) of the last pulse
int servo; // which servo to pulse? 1-4
int servo1[2]; // servo #1 array{pin, pulsewidth}
int servo2[2]; // servo #2 array{pin, pulsewidth}
int servo3[2]; // servo #3 array{pin, pulsewidth}
int servo4[2]; // servo #4 array{pin, pulsewidth}
int pin; // digital pin for pulse() function
int puls; // pulsewidth for pulse() function
int startbyte; // start byte, begin reading input
void setup() {
// loop through all 4 servo pins
// and set them as OUTPUT
for (i=0;i<4;i++) {
pinMode(pinArray[i], OUTPUT);
}
// servo starting point (center)
pulseRange = maxPulse - minPulse;
centerServo = maxPulse - ((pulseRange)/2);
pulseWidth = centerServo;
// map pins to servos
servo1[0] = pinArray[0]; // servo #1 is pin 2
servo2[0] = pinArray[1]; // servo #2 is pin 3
servo3[0] = pinArray[2]; // servo #3 is pin 4
servo4[0] = pinArray[3]; // servo #4 is pin 5
// center all servos
servo1[1] = pulseWidth;
servo2[1] = pulseWidth;
servo3[1] = pulseWidth;
servo4[1] = pulseWidth;
// open serial connection
Serial.begin(9600);
}
void loop() {
// wait for serial input (min 3 bytes in buffer)
if (Serial.available() > 2) {
//read the first byte
startbyte = Serial.read();
// if it's really the startbyte (255)
if (startbyte == 255) {
// then get the next two bytes
for (i=0;i<2;i++) {
userInput[i] = Serial.read();
}
// first byte = servo to move?
servo = userInput[0];
// second byte = which position?
servoPosition = userInput[1];
// packet check
if (servoPosition == 255) { servo = 255; }
// compute pulseWidth from servoPosition
pulseWidth = minPulse + (servoPosition * (pulseRange/180));
// stop servo pulse at min and max
if (pulseWidth > maxPulse) { pulseWidth = maxPulse; }
if (pulseWidth < minPulse) { pulseWidth = minPulse; }
// assign new pulsewidth to appropriate servo
switch (servo) {
case 1:
servo1[1] = pulseWidth;
break;
case 2:
servo2[1] = pulseWidth;
break;
case 3:
servo3[1] = pulseWidth;
break;
case 4:
servo4[1] = pulseWidth;
break;
}
}
}
// pulse each servo
if (millis() - lastPulse >= refreshTime) {
pulse(servo1[0], servo1[1]);
pulse(servo2[0], servo2[1]);
pulse(servo3[0], servo3[1]);
pulse(servo4[0], servo4[1]);
// save the time of the last pulse
lastPulse = millis();
}
}
void pulse(int pin, int puls) {
digitalWrite(pin, HIGH); // start the pulse
delayMicroseconds(puls); // pulse width
digitalWrite(pin, LOW); // stop the pulse
}


Hi, just wondering about the Arduino sketch – I know it’s perfectly valid to do it your way, but why not just use the standard servo library? (You’d achieve the same thing with far fewer lines of code.) http://arduino.cc/en/Reference/Servo
Greeting
Have you ever seen these error?
pygame.joystick.init()
AttributeError: ‘module’ object has no attribute ‘joystick’
I tried looking it up, but not one can explained it in the “Noobie” language I understand.
Valuable info. Lucky me I found your site by accident, I bookmarked it.
hello,
i am trying to build this project but am stuck as i do not know how to find what com port my arduino is connected to!
i have a mac.
if anyone can shed some light on this i would appreciate it!
tanks