A Servo is a small device that has an output shaft. This shaft can be positioned to specific angular positions by sending the servo a coded signal. As long as the coded signal exists on the input line, the servo will maintain the angular position of the shaft. As the coded signal changes, the angular position of the shaft changes. In practice, servos are used in radio controlled airplanes to position control surfaces like the elevators and rudders. They are also used in radio controlled cars, puppets, and of course, robots.
What's inside:
The servo motor has some control circuits and a potentiometer (a variable resistor) that is connected to the output shaft. This pot allows the control circuitry to monitor the current angle of the servo motor. If the shaft is at the correct angle, then the motor shuts off. If the circuit finds that the angle is not correct, it will turn the motor the correct direction until the angle is correct. The output shaft of the servo is capable of traveling somewhere around 180 degrees. Usually, its somewhere in the 210 degree range, but it varies by manufacturer. A normal servo is used to control an angular motion of between 0 and 180 degrees. A normal servo is mechanically not capable of turning any farther due to a mechanical stop built on to the main output gear.
The amount of power applied to the motor is proportional to the distance it needs to travel. So, if the shaft needs to turn a large distance, the motor will run at full speed. If it needs to turn only a small amount, the motor will run at a slower speed. This is called proportional control.
Angles of Rotation: What they're good for
Roboticists, movie effects people, and
puppeteers use them extensively
Any time you need controlled, repeatable
motion
Can turn rotation into linear movement
with clever mechanical levers
Where you find them The underpinnings of one of the five transforming dresses featured in Hussein Chalayan's latest runway show. Wires within the tubes connect to motors at the bottom of the dress. The motors reel in wires attached to the outer layer of the garment, altering its shape.
When using the servo, it is helpful to mark the servo horn. This allows you to follow the rotation:
Connect the servo to the Microcontroller like this:
This program allows you to control the movement of the servo through the keyboard and the serial monitor:
/*
* Servo Control Serial
* modified for TUI October 2007
* Servo Serial Better
* -------------------
*
* Created 18 October 2006
* copyleft 2006 Tod E. Kurt <tod@todbot.com>
* http://todbot.com/
*
* adapted from "http://itp.nyu.edu/physcomp/Labs/Servo"
*/
int servoPin = 7; // Control pin for servo motor
int pulseWidth = 0; // Amount to pulse the servo
long lastPulse = 0; // the time in millisecs of the last pulse
int refreshTime = 20; // the time in millisecs needed in between pulses
int val; // variable used to store data from serial port
int minPulse = 500; // minimum pulse width
int maxPulse = 2250; // maximum pulse width
void setup() {
pinMode(servoPin, OUTPUT); // Set servo pin as an output pin
pulseWidth = minPulse; // Set the motor position to the minimum
Serial.begin(9600); // connect to the serial port
Serial.println("Servo control program ready");
}
void loop() {
val = Serial.read(); // read the serial port
if (val >= '1' && val <= '9' ) {
val = val - '0'; // convert val from character variable to number variable
val = val - 1; // make val go from 0-8
pulseWidth = (val * (maxPulse-minPulse) / 8) + minPulse; // convert val to microseconds
Serial.print("Moving servo to position ");
Serial.println(pulseWidth,DEC);
}
updateServo(); // update servo position
}
// called every loop().
// uses global variables servoPi, pulsewidth, lastPulse, & refreshTime
void updateServo() {
// pulse the servo again if rhe refresh time (20 ms) have passed:
if (millis() - lastPulse >= refreshTime) {
digitalWrite(servoPin, HIGH); // Turn the motor on
delayMicroseconds(pulseWidth); // Length of the pulse sets the motor position
digitalWrite(servoPin, LOW); // Turn the motor off
lastPulse = millis(); // save the time of the last pulse
}
}
Exercise 1
Wire up the Servo and a potentimeter:
You are going to drive the servo with a potentiomer.
/*
* Servo with Potentiometer control
* Theory and Practice of Tangible User Interfaces
* October 11 2007
*/
int servoPin = 7; // Control pin for servo motor
int potPin = 0; // select the input pin for the potentiometer
int pulseWidth = 0; // Amount to pulse the servo
long lastPulse = 0; // the time in millisecs of the last pulse
int refreshTime = 20; // the time in millisecs needed in between pulses
int val; // variable used to store data from potentiometer
int minPulse = 500; // minimum pulse width
void setup() {
pinMode(servoPin, OUTPUT); // Set servo pin as an output pin
pulseWidth = minPulse; // Set the motor position to the minimum
Serial.begin(9600); // connect to the serial port
Serial.println("servo_serial_better ready");
}
void loop() {
val = analogRead(potPin); // read the value from the sensor, between 0 - 1024
if (val > 0 && val <= 999 ) {
pulseWidth = val*2 + minPulse; // convert angle to microseconds
Serial.print("moving servo to ");
Serial.println(pulseWidth,DEC);
}
updateServo(); // update servo position
}
// called every loop().
void updateServo() {
// pulse the servo again if rhe refresh time (20 ms) have passed:
if (millis() - lastPulse >= refreshTime) {
digitalWrite(servoPin, HIGH); // Turn the motor on
delayMicroseconds(pulseWidth); // Length of the pulse sets the motor position
digitalWrite(servoPin, LOW); // Turn the motor off
lastPulse = millis(); // save the time of the last pulse
}
}
What's going on in the loop?
In converting the range of an analog input to an analog output, it's necessary to know the maxmum and minimum values of each range so that a ranging function can be made up.
Ultimately your analog inputs will return an idiosyncratic range of numbers.
The range will vary depending on many factors, such as the
brand of transducer, the values of the resistors and capacitors in your circuit,
the quality of your microcontroller and the time of day. To use these numbers you
will have to know the range your output device needs and convert the input range into that range.
The code below was written for a potentiometer.
It assumes you're going to get values from 0 to 1023 from the sensor.
If you don't, the servo won't move through its whole range. Determine
the range of numbers the sensor is giving you and adjust the servo formula to fit.
Here's a a scaling formula that will make the adjustment:
(pulseWidth - minPulse) / pulseRange
OR
(sensorValue - minSensorValue) /sensorRange
Multiply both sides by pulseRange, and you get:
(pulseWidth - minPulse)
OR
(sensorValue - minSensorValue * pulseRange /sensorRange
That's the full ranging formula. However, because there are no floating-point variables
(i.e. fractions) in the Arduino language (and in most microcontroller languages),
you have to fudge the formula a bit. For example, if you have a sensor range from 0 to 512,
and a servo range from 500 to 2500 (i.e. a 2000-point range), you know that you can just
multiply the servo by 4 and add 500. You'll lose a little detail, but not enough to make
a difference to the end user.
When you're making approximations like this, you have to test the approximation at the
extremes of both the sensor and the output to make sure it does the job.
/*Servo control from an analog input
The minimum (minPulse) and maxiumum (maxPuluse) values
will be different depending on your specific servo motor.
Ideally, it should be between 1 and 2 milliseconds, but in practice,
0.5 - 2.5 milliseconds works well for me.
Try different values to see what numbers are best for you.
This program uses the millis() function to keep track of when the servo was
last pulsed. millis() produces an overflow error (i.e. generates a number
that's too big to fit in a long variable) after about 5 days. if you're
making a program that has to run for more than 5 days, you may need to
account for this.
by Tom Igoe
additions by Carlyn Maw
Created 28 Jan. 2006
Updated 7 Jun. 2006
*/
int servoPin = __; // Control pin for servo motor
int minPulse = 500; // Minimum servo position
int maxPulse = 2500; // Maximum servo position
int pulse = 0; // Amount to pulse the servo
long lastPulse = 0; // the time in milliseconds of the last pulse
int refreshTime = 20; // the time needed in between pulses
int analogValue = 0; // the value returned from the analog sensor
int analogPin = ___; // the analog pin that the sensor's on
void setup() {
pinMode(________, OUTPUT); // Set servo pin as an output pin
pulse = minPulse; // Set the motor position value to the minimum
Serial.begin(9600);
}
void loop() {
analogValue = analogRead(analogPin); // read the analog input
pulse = (analogValue * 19) / 10 + minPulse; // convert the analog value
// to a range between minPulse
// and maxPulse.
// pulse the servo again if rhe refresh time (20 ms) have passed:
if (millis() - lastPulse >= refreshTime) {
digitalWrite(________, HIGH); // Turn the motor on
delayMicroseconds(pulse); // Length of the pulse sets the motor position
digitalWrite(________, LOW); // Turn the motor off
lastPulse = millis(); // save the time of the last pulse
}
}
/*
* Servo Serial Better
* -------------------
*
*
* Created 18 October 2006
* copyleft 2006 Tod E. Kurt <tod@todbot.com>
* http://todbot.com/
*
* adapted from "http://itp.nyu.edu/physcomp/Labs/Servo"
*/
int servoPin = 7; // Control pin for servo motor
int pulseWidth = 0; // Amount to pulse the servo
long lastPulse = 0; // the time in millisecs of the last pulse
int refreshTime = 20; // the time in millisecs needed in between pulses
int val; // variable used to store data from serial port
int minPulse = 700; // minimum pulse width
void setup() {
pinMode(servoPin, OUTPUT); // Set servo pin as an output pin
pulseWidth = minPulse; // Set the motor position to the minimum
Serial.begin(19200); // connect to the serial port
Serial.println("Servo Serial Better ready");
}
void loop() {
analogValue = analogRead(analogPin); // read the analog input
pulse = (analogValue * 19) / 10 + minPulse; // convert the analog value
// to a range between minPulse
// and maxPulse.
updateServo(); // update servo position
}
// called every loop().
// uses global variables servoPin, pulsewidth, lastPulse, & refreshTime
void updateServo() {
// pulse the servo again if rhe refresh time (20 ms) have passed:
if (millis() - lastPulse >= refreshTime) {
digitalWrite(servoPin, HIGH); // Turn the motor on
delayMicroseconds(pulseWidth); // Length of the pulse sets the motor position
digitalWrite(servoPin, LOW); // Turn the motor off
lastPulse = millis(); // save the time of the last pulse
}
}
Doesn't Arduino have PWM?
Arduino has built-in PWM on pins 9,10,11.
It uses analogWrite(pin,value). It operates at a high, fixed frequency and isn't usable for servos, but great for LEDs and motors. The PWM speed used for analogWrite() is set to 450Hz or 30 kHz currently. It's
not something changeable without understanding more about how AVRs work.
So when programming AVRs in C outside of Arduino, PWM speed can be set to just about any value.
Critter
Build your own critter by transforming the movement of the servo into linear motion by attaching objects to your servo:
Program your critter so that a pot controls the crawler's speed or use random(min,max) to make a crazy critter/cat toy!
Servo Library
Standard Methods attach(int)
Turn a pin into a servo driver. Calls pinMode. Returns 0 on failure. detach()
Release a pin from servo driving. write(int)
Set the angle of the servo in degrees, 0 to 180. read()
return that value set with the last write(). attached()
return 1 if the servo is currently attached.
Extra Methods setMinimumPulse(uint16_t)
set the duration of the 0 degree pulse in microseconds. (default minimum value is 544 microseconds) setMaximumPulse(uint16_t)
set the duration of the 180 degree pulse in microseconds. (default maximum pluse value is 2400 microsconds)
Safety Quirk
Even though you attach a servo, it won't receive any control signals until you send its first position with the write() method to keep it from jumping to some odd arbitrary value.
Size
The library takes about 850 bytes of flash and 6+(8*servos) bytes of SRAM.
The Code
You can find the code in http://www.arduino.cc/playground/uploads/ComponentLib/servo.zip. Unpack that into your lib/targets/libraries folder to add the library.
Limitations
This library does not stop your interrupts, so millis() will still work and you won't lose incoming serial data, but a pulse end can be extended by the maximum length of your interrupt handles which can cause a small glitch in the servo position. If you have a large number of servos there will be a slight (1-3 degrees) position distortion in the ones with the lowest angular values.
Examples
The following code Sweeps the shaft of a servo motor back and forth from 0 to 180
// Sweep
// by BARRAGAN <http://barraganstudio.com>
#include <Servo.h>
Servo myservo; // create servo object to control a servo
int pos = 0; // variable to store the servo position
void setup()
{
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}
void loop() {
for(pos = 0; pos < 180; pos += 1) // goes from 0 degrees to 180 degrees
{ // in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
for(pos = 180; pos>=1; pos-=1) // goes from 180 degrees to 0 degrees
{
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
}
The following code lets you control Servo on pin2 by potentiometer on analog 0
#include
Servo myservo; // create servo object to control a servo
int potpin = 0; // analog pin used to connect the potentiometer
int val; // variable to read the value from the analog pin
void setup()
{
myservo.attach(9); // attaches the servo on pin 2 to the servo object
}
void loop()
{
val = analogRead(potpin); // reads the value of the potentiometer (value between 0 and 1023)
val = map(val, 0, 1023, 0, 179); // scale it to use it with the servo (value between 0 and 180)
myservo.write(val); // sets the servo position according to the scaled value
delay(15); // waits for the servo to get there
}
The following code lets you send strings like "90s" and "80w" to position servos on pin 14 and 15 (analog in 0 and 1) to 90 degrees and 80 degrees. You can also use "d" to detach the servo on pin 15 and "a" to reattach it. Ok, it is a silly program but it works for testing.
#include <Servo.h>
Servo servo1;
Servo servo2;
void setup(){
//which pin
servo1.attach(___);
servo1.setMaximumPulse(2200);
//which pin
servo2.attach(__);
Serial.begin(19200);
Serial.print("Ready");
}
void loop(){
static int v = 0;
if ( Serial.available()) {
char ch = Serial.read();
switch(ch) {
case '0'...'9':
v = v * 10 + ch - '0';
break;
case 's':
servo1.write(v);
v = 0;
break;
case 'w':
servo2.write(v);
v = 0;
break;
case 'd':
servo2.detach();
break;
case 'a':
//which pin
servo2.attach(__);
break;
}
}
}
Here's a little robot
#include <Servo.h>
#define LEFTSERVOPIN 10
#define RIGHTSERVOPIN 9
Servo leftServo;
Servo rightServo;
int speed = 100; //sets the speed of the robot (both servos)
//a percentage between 0 and 100
// END OF ARDUINO CONTROLLED SERVO ROBOT (SERB) PREAMBLE
//--------------------------------------------------------------------------
/*
* sets pins to appropriate states and attaches servos. Then pauses
* for 1 second before the program starts
*/
void setup(){
serbSetup(); //sets the state of all neccesary
//pins and adds servos to your sketch
randomSeed(analogRead(0)); //sets the random number seed with
//something mildly random
delay(1000);
}
/*
* turns the robot either left or right (randomly) for a period between
* 0.1 and 1 second. Before going forward for a random time period
* between 1 and 4 seconds. Before pausing for two seconds then starting
* again.
*/
void loop(){
turnRandom(100,1000); //Turns randomly left or right for a
//randomtime period between .1 second
//and one second
goForwardRandom(1000,2000); //Goes forward for a random time period
//between
//1 and 2 seconds
goStop(); //Stops the robot
delay(2000); //pauses for 2 seconds (whilst stopped)
}
/*
* turns the robot randomly left or right for a random time period between
* minTime (milliseconds) and maxTime (milliseconds)
*/
void turnRandom(int minTime, int maxTime){
int choice = random(2); //Random number to decide
//between left (1) and right (0)
int turnTime = random(minTime,maxTime); //Random number for the pause
//time
if(choice == 1){ goLeft();} //If random number = 1 then turn
//left
else {goRight();} //If random number = 0 then turn
//right
delay(turnTime); //delay for random time
}
/*
* goes forward for a random time period between minTime (milliseconds)
* and maxTime (milliseconds)
*/
void goForwardRandom(int minTime, int maxTime){
int forwardTime = random(minTime,maxTime); //determine a random time to
//go forward
goForward(); //sets the SERB forward
delay(forwardTime); //delays for random time period
}
//------------------------------------------------------------------------
//START OF ARDUINO CONTROLLED SERVO ROBOT (SERB) ROUTINES
/*
* sets up your arduino to address your SERB using the included routines
*/
void serbSetup(){
setSpeed(speed);
pinMode(LEFTSERVOPIN, OUTPUT); //sets the left servo signal pin
//to output
pinMode(RIGHTSERVOPIN, OUTPUT); //sets the right servo signal pin
//to output
leftServo.attach(LEFTSERVOPIN); //attaches left servo
rightServo.attach(RIGHTSERVOPIN); //attaches right servo
goStop();
}
/*
* sets the speed of the robot between 0-(stopped) and 100-(full speed)
* NOTE: speed will not change the current speed you must change speed
* then call one of the go methods before changes occur.
*/
void setSpeed(int newSpeed){
if(newSpeed >= 100) {newSpeed = 100;} //if speed is greater than 100
//make it 100
if(newSpeed <= 0) {newSpeed = 0;} //if speed is less than 0 make
//it 0
speed = newSpeed * 0.9; //scales the speed to be
//between 0 and 90
}
/*
* sends the robot forwards
*/
void goForward(){
leftServo.write(90 + speed);
rightServo.write(90 - speed);
}
/*
* sends the robot backwards
*/
void goBackward(){
leftServo.write(90 - speed);
rightServo.write(90 + speed);
}
/*
* sends the robot right
*/
void goRight(){
leftServo.write(90 + speed);
rightServo.write(90 + speed);
}
/*
* sends the robot left
*/
void goLeft(){
leftServo.write(90 - speed);
rightServo.write(90 - speed);
}
/*
* stops the robot
*/
void goStop(){
leftServo.write(90);
rightServo.write(90);
}
Controlled Robot
(Instructables from Make a Web Connected Robot (for about $500) (using an Arduino and Netbook) http://www.instructables.com/id/How_to_Make_a_Web_Connected_Robot_for_about_500/)
/*
* Arduino Controlled Web Connected Robot (WEBB) - Serial Host
* For more details visit: http://www.oomlout.com/serb
*
* Behaviour: The Arduino listens to its Serial port for a command
* in format 254, 88, 88, (COMMAND), (TIME)
* Supported Commands - 'F' - 70 - Forward
* 'B' - 66 - Backward
* 'L' - 76 - Left
* 'R' - 82 - Right
* 'S' - 83 - Speed
* 'X' - 88 - SetSpeedLeft
* 'Y' - 89 - SetSpeedRight
* 'C' - 67 - Stop
* Supported Times - 0 - 255 (0 to 25.5 Seconds) value * 100 milliseconds
*sp
* Wiring: Right Servo Signal - pin 9
* Left Servo Signal - pin 10
*
* License: This work is licenced under the Creative Commons
* Attribution-Share Alike 3.0 Unported License. To
* view a copy of this licence, visit
* http://creativecommons.org/licenses/by-sa/3.0/
* or send a letter to Creative Commons, 171 Second
* Street, Suite 300, San Francisco, California 94105,
* USA.
*
*/
//-------------------------------------------------------------------------
//START OF ARDUINO SERIAL SERVER PREAMBLE
//Defining constants corresponding to each command (also the ascii code number)
#define FORWARD 70 //F
#define BACKWARD 66 //B
#define LEFT 76 //L
#define RIGHT 82 //R
#define SETSPEED 83 //S
#define STOP 67 //C
#define SETSPEEDLEFT 88 //X
#define SETSPEEDRIGHT 89 //Y
/*The three check bytes (used to keep the robot from responding to random serial
*data) currently "AAA"
*/
#define checkByte1 65 // "A"
#define checkByte2 65 // "A"
#define checkByte3 65 // "A"
//--------------------------------------------------------------------------
// START OF ARDUINO CONTROLLED SERVO ROBOT (SERB) PREAMBLE
#include <Servo.h>
#define LEFTSERVOPIN 10 //The pin the left servo is connected to
#define RIGHTSERVOPIN 9 //The pin the right servo is connected to
Servo leftServo;
Servo rightServo;
int leftSpeed = 50; //holds the speed of the robots leftServo
//a percentage between 0 and 100
int rightSpeed = 100; //holds the speed of the robots rightServo
//a percentage between 0 and 100
// END OF ARDUINO CONTROLLED SERVO ROBOT (SERB) PREAMBLE
//--------------------------------------------------------------------------
//Gets everything up and running
void setup(){
Serial.begin(9600); //Starts the serial port
serbSetup(); //sets the state of all neccesary
//pins and adds servos to your sketch
}
//The main program loop
void loop(){
serbPollSerialPort(); //continuously looks to the serial port
//if there is data it processes it
}
//-----------------------------------------------------------------------
//START OF ARDUINO SERIAL SERVER ROUTINES
/*
* Processes commands delivered to the arduino's serial port
*/
void serbPollSerialPort(){
int dta; //variable to hold the serial byte
if ( Serial.available() >= 5) { //if 5 bytes are in the buffer (length pf a full request)
dta = Serial.read();
if ( dta = checkByte1){ //Checks for first check byte
dta = Serial.read();
if ( dta = checkByte2){ //Checks for second check byte
dta = Serial.read();
if ( dta = checkByte3){ //Checks for third check byte
int command = Serial.read(); //Fourth byte is the command
int param1 = Serial.read(); //Fifth byte is param1
interpretCommand(command, param1); //sends the parsed request to it's handler
}
}
}
}
}
/*
* Takes the command and parameter and passes it to the robot
*/
void interpretCommand(int command, int param1){
if (command == FORWARD){
goForward(); delay(param1 * 100); goStop();
} //if forward
else if(command == BACKWARD){
goBackward(); delay(param1 * 100); goStop();
} //if backwards
else if(command == LEFT){
goLeft(); delay(param1 * 100); goStop();
} //if left
else if(command == RIGHT){
goRight(); delay(param1 * 100); goStop();
} //if right
else if(command == SETSPEED){
setSpeed(param1);
} //if setting speed
else if(command == STOP){
goStop();
} //if stop
else if(command == SETSPEEDLEFT){
setSpeedLeft(param1);
} //if setting left speed
else if(command == SETSPEEDRIGHT){
setSpeedRight(param1);
} //if setting right speed
else{ //if unrecognized command do a little shimmey
goLeft();
delay(150);
goRight();
delay(150);
goStop();
}
}
//------------------------------------------------------------------------
//START OF ARDUINO CONTROLLED SERVO ROBOT (SERB) ROUTINES
/*
* sets up your arduino to address your SERB using the included routines
*/
void serbSetup(){
setSpeed(leftSpeed);
pinMode(LEFTSERVOPIN, OUTPUT); //sets the left servo signal pin
//to output
pinMode(RIGHTSERVOPIN, OUTPUT); //sets the right servo signal pin
//to output
leftServo.attach(LEFTSERVOPIN); //attaches left servo
rightServo.attach(RIGHTSERVOPIN); //attaches right servo
goStop();
}
/*
* sets the speed of the robot between 0-(stopped) and 100-(full speed)
* NOTE: speed will not change the current speed you must change speed
* then call one of the go methods before changes occur.
*/
void setSpeed(int newSpeed){
setSpeedLeft(newSpeed); //sets left speed
setSpeedRight(newSpeed); //sets right speed
}
/*
* Sets the speed of the left wheel
*/
void setSpeedLeft(int newSpeed){
if(newSpeed >= 100) {newSpeed = 100;} //if speed is greater than 100
//make it 100
if(newSpeed <= 0) {newSpeed = 0;} //if speed is less than 0 make
//it 0
leftSpeed = newSpeed * 0.9; //between 0 and 90
}
/*
* Sets the speed of the right wheel
*/
void setSpeedRight(int newSpeed){
if(newSpeed >= 100) {newSpeed = 100;} //if speed is greater than 100
//make it 100
if(newSpeed <= 0) {newSpeed = 0;} //if speed is less than 0 make
//it 0
rightSpeed = newSpeed * 0.9; //scales the speed to be
}
/*
* sends the robot forwards
*/
void goForward(){
leftServo.write(90 + leftSpeed);
rightServo.write(90 - rightSpeed);
}
/*
* sends the robot backwards
*/
void goBackward(){
leftServo.write(90 - leftSpeed);
rightServo.write(90 + rightSpeed);
}
/*
* sends the robot right
*/
void goRight(){
leftServo.write(90 + leftSpeed);
rightServo.write(90 + rightSpeed);
}
/*
* sends the robot left
*/
void goLeft(){
leftServo.write(90 - leftSpeed);
rightServo.write(90 - rightSpeed);
}
/*
* stops the robot
*/
void goStop(){
leftServo.write(90);
rightServo.write(90);
}
//END OF ARDUINO CONTROLLED SERVO ROBOT (SERB) ROUTINES
//----------------------------------------------------------
,/div>
Toy
When the toy detects the user (using sensor), it would turn its head and stay at that position until it detects the user again and turns its head.
#include <Servo.h>
Servo myservo; //create servo object to control a servo
int sensor = 0;// analog pin used to connect the sensor
int motorPin=11;
int val; // variable to read the value from the analog pin
boolean status=0; //status of detecting
int counter=0;
void setup(){
myservo.attach(11);
myservo.setMaximumPulse(2200);
Serial.begin(9600); // set up Serial library at 9600 bps
pinMode(sensor, INPUT);
pinMode(motorPin, OUTPUT);
myservo.setMaximumPulse(2000);
myservo.setMinimumPulse(700);
Serial.print("Ready\n");
}//end of setup
int getSensor() {
val = analogRead(sensor); // reads the value of the potentiometer (value between 0 and 1023)
val = map(val, 0, 1023, 0, 179); // scale it to use it with the servo (value between 0 and 180)
val=max(val,5);
val=min(val,180);
return val;
} //end of getSensor
void myRefresh(int delayTime){
for(int i=0; i < delayTime/20; i++){ //delay is the total ms delay we want, 20 is the delay per iteration of the loop
Servo::refresh();
delay(20);
}
}
int move0(){
Serial.print("servo position 0\n");
myservo.write(0);
myRefresh(100);
}//end of move0
int move90(){
Serial.print("servo position 90\n");
myservo.write(90);
myRefresh(100);
}//end of move90
int move180(){
Serial.print("servo position 180\n");
myservo.write(180);
myRefresh(100);
}//end of move180
void loop(){
val=getSensor();
Serial.println(val);
if (val>20){
if(status==0){
move180();
myRefresh(1000); // waits for the servo to get there
counter++;
}
else if(status==1){
move0();
myRefresh(1000);
counter++;
}//end of else
}//end of if
if(counter%2!=0){
status=1;
}else{
status=0;
}
//myservo.write(getSensor());
//Serial.println(getSensor());
//delay(15);
Servo::refresh();
}
/*
* Two servos with two potentiometer control
* Theory and Practice of Tangible User Interfaces
* October 11 2007
*
*/
int servoPin1 = 7; // Control pin for servo motor 1
int servoPin2 = 8; // Control pin for servo motor 2
int potPin1 = 0; // select the input pin for the potentiometer 1
int potPin2 = 1; // select the input pin for the potentiometer 2
int pulseWidth1 = 0; // Amount to pulse the servo 1
int pulseWidth2 = 0; // Amount to pulse the servo 2
long lastPulse1 = 0; // the time in millisecs of the last pulse of servo 1
long lastPulse2 = 0; // the time in millisecs of the last pulse of servo 2
int val_1; // variable used to store data from potentiometer 1
int val_2; // variable used to store data from potentiometer 2
int refreshTime = 20; // the time in millisecs needed in between pulses
int minPulse = 500; // minimum pulse width
void setup() {
pinMode(servoPin1, OUTPUT); // Set servo pin 1 as an output pin
pinMode(servoPin2, OUTPUT); // Set servo pin 2 as an output pin
pulseWidth1 = minPulse; // Set the motor position to the minimum
pulseWidth2 = minPulse; // Set the motor position to the minimum
Serial.begin(9600); // connect to the serial port
Serial.println("Two servos with two potentiometers ready");
}
void loop() {
val_1 = analogRead(potPin1); // read the value from the sensor 1, between 0 - 1024
val_2 = analogRead(potPin2); // read the value from the sensor 2, between 0 - 1024
if (val_1 > 0 && val_1 <= 999 ) {
pulseWidth1 = val_1*2 + minPulse; // convert angle to microseconds
}
updateServo1(); // update servo 1 position
if (val_2 > 0 && val_2 <= 999 ) {
pulseWidth2 = val_2*2 + minPulse; // convert angle to microseconds
}
updateServo2(); // update servo 2 position
}
void updateServo1() {
if (millis() - lastPulse1 >= refreshTime) {
digitalWrite(servoPin1, HIGH);
delayMicroseconds(pulseWidth1);
digitalWrite(servoPin1, LOW);
lastPulse1 = millis();
}
}
void updateServo2() {
if (millis() - lastPulse2 >= refreshTime) {
digitalWrite(servoPin2, HIGH);
delayMicroseconds(pulseWidth2);
digitalWrite(servoPin2, LOW);
lastPulse2 = millis();
}
}