Manual Control of a Servo on the Arduino for the Zipwhip TextSpresso Machine
March 28, 2012 19 Comments
Control a servo without using the Arduino servo library.
The Arduino has a great servo library, but we found while making our TextSpresso machine that the servo library wouldn’t play nice with our stepper motors. We happily connected our stepper motors up to pins 2 through 9 because we were using a stepper motor shield. Then we connected the servos to much higher pin numbers like 26 and 27. To our dismay whenever we sent commands to the steppers, it would cause massive gyrations on the servos.
This had us investigate what was going on and to do that we had to dig under the covers of the servo library. Not many newbies know about the timer capabilities of the Arduino. The servo library hides us from the gory details. Well, it turns out that the servo library relies on a timer callback to get the precision control of the servos. This callback means the Arduino can’t be processing any other code at the exact moment the callback occurs. If the Arduino is busy, then all hell breaks lose on the exact timing of pulses being sent to the servo.
Servos expect a 20 millisecond (ms) pulse. To set the servo at 0 degrees, you send it a high voltage for the 1st ms of the 20 ms pulse. To set the servo at 180 degrees, you send it a high voltage for the 1st 2 ms of the 20 ms pulse. Pretty easy actually. Anywhere in between 1.0 ms and and 2.0 ms gives you different degrees between 0 and 180.
We wrote the sample code below to help you manually control your servo. It just takes a millisecond value and sends it to the servo and then pauses for the remainder of the pulse. I’m actually not sure why the Arduino IDE doesn’t give a manual example like this because it’s so easy to do. We couldn’t find any sample code on the Internet either for “manual servo control on the Arduino”. We hope you find this helpful.
// Manual servo control // Copyright 2012 by Zipwhip. // You are free to use and modify this code in your own software. #define SERVO_PIN 39 // Any pin on the Arduino or Mega will work. void setup() { pinMode(SERVO_PIN, OUTPUT); } int lenMicroSecondsOfPeriod = 20 * 1000; // 20 milliseconds (ms) int lenMicroSecondsOfPulse = 1.8 * 1000; // 1.0 ms is 0 degrees void loop() { // Servos work by sending a 20 ms pulse. // 1.0 ms at the start of the pulse will turn the servo to the 0 degree position // 1.5 ms at the start of the pulse will turn the servo to the 90 degree position // 2.0 ms at the start of the pulse will turn the servo to the 180 degree position // Turn voltage high to start the period and pulse digitalWrite(SERVO_PIN, HIGH); // Delay for the length of the pulse delayMicroseconds(lenMicroSecondsOfPulse); // Turn the voltage low for the remainder of the pulse digitalWrite(SERVO_PIN, LOW); // Delay this loop for the remainder of the period so we don't // send the next signal too soon or too late delayMicroseconds(lenMicroSecondsOfPeriod - lenMicroSecondsOfPulse); }
Manually Sweeping the Servo from 0 to 180 Degrees
Taking the example above further and trying to mimic the Arduino sample sweep code for a servo we produced the test code below. This let us fully test our manual control of the servo. We found that for our HiTec HS-422 servo that the 0 degree position was at about a 0.5 ms pulse and that the full 180 degrees was around a 2.2 ms pulse. You may find something different for your servo but you can adjust the control variables in the code below until you’re happy.
We also found that a pulse length of about 25 ms worked better for our servo. The standard is 20 ms so I’m not surprised we found something a bit longer than the expected pulse worked better. When we went shorter on the pulse like 18 ms we found the servo acted really weird. That’s probably because the voltage was getting applied prior to the servo finishing it’s measurements and that would throw off pulse lengths overall.
// Manually Sweeping the Servo from 0 to 180 Degrees
// Copyright 2012 by Zipwhip.
// You are free to use and modify this code in your own software.
#define SERVO_PIN 39 // 26 or 39. Any pin on the Arduino or Mega will work.
int lenMicroSecondsOfPeriod = 25 * 1000; // 25 milliseconds (ms). found much better smoothness at 25, not 20 ms.
int lenMicroSecondsOfPulse = 0; // used in the while loop below
int lenMicroSecondsOfPulseStart = 0.5 * 1000; // 0 degrees
int lenMicroSecondsOfPulseEnd = 2.2 * 1000; // 180 degrees
int lenMicroSecondsOfPulseStep = 0.01 * 1000; // .1 millisecond. That's 200 increments b/w 1.0 and 2.0
void setup()
{
pinMode(SERVO_PIN, OUTPUT);
// Setup our start point for our main loop
lenMicroSecondsOfPulse = lenMicroSecondsOfPulseStart + lenMicroSecondsOfPulseStep;
}
void loop()
{
// Servos work by sending a 20 ms pulse.
// 1.0 ms at the start of the pulse will turn the servo to the 0 degree position
// 1.5 ms at the start of the pulse will turn the servo to the 90 degree position
// 2.0 ms at the start of the pulse will turn the servo to the 180 degree position
// Do a while loop starting at our start pulse and incrementing each time thru the loop
// Stop when we reach our final end point
while (lenMicroSecondsOfPulse = lenMicroSecondsOfPulseStart)
{
// Turn voltage high to start the period and pulse
digitalWrite(SERVO_PIN, HIGH);
// Delay for the length of the pulse
delayMicroseconds(lenMicroSecondsOfPulse);
// Turn the voltage low for the remainder of the pulse
digitalWrite(SERVO_PIN, LOW);
// Delay this loop for the remainder of the period so we don't
// send the next signal too soon or too late
delayMicroseconds(lenMicroSecondsOfPeriod - lenMicroSecondsOfPulse);
// Increment our pulse
lenMicroSecondsOfPulse += lenMicroSecondsOfPulseStep;
}
// Now reverse the step so we go in the opposite direction
lenMicroSecondsOfPulseStep = lenMicroSecondsOfPulseStep * -1;
lenMicroSecondsOfPulse += lenMicroSecondsOfPulseStep;
// delay for a few seconds and do it all again
delay(2 * 1000);
}

Does this remove that spastic movement when the servo first gets power and swings one direction at full speed? If so, I’ll definitely dig into this!
Pingback: Espresso machine can print text messages on coffee foam with edible ink | Jason Penna
Pingback: ‘Textspresso’ machine prints texts on your espresso foam | Cheap Samsung Phones 2012
Pingback: ‘Textspresso’ device prints texts on your coffee foam | Best HTC Phones 2012
Pingback: ‘Textspresso’ machine prints texts on your coffee foam | hptouchpadbestbuy99
Pingback: ‘Textspresso’ machine prints texts on your coffee foam | buytasergun
Pingback: ‘Textspresso’ machine prints texts on your coffee foam | directbuy
Pingback: ‘Textspresso’ machine prints texts on your coffee foam | buycar
Pingback: ‘Textspresso’ machine prints texts on your coffee foam | buyjessicasimpsonhairextensions
Pingback: ‘Textspresso’ machine prints texts on your coffee foam
Pingback: ‘Textspresso’ machine prints texts on your coffee foam : Pillalu.com
Pingback: Zipwhip’s Textpresso can print texts and numbers on espresso foam
Pingback: 'Textspresso' machine prints texts on your coffee foam
Pingback: New video for Textspresso coffee machine | Coffee Machine Reviews
Pingback: 'Textspresso' machine prints texts on your coffee foam
Pingback: The world’s first coffee machine that takes orders by text – Simply Zesty - Simply Zesty
Pingback: The world’s first coffee machine that takes orders by text « sifabie
Pingback: Café Coqueto
Thanks for this, I was looking for something like this as arduino Servo library wasn’t cutting it.
Not all servos are built alike.