Let's Make Robots!

ATtiny servo control


After a brief discussion with fellow LMR member Maxhirez, about his Hedwig robot,
it seems as though there isn't much support for servos in the ATtiny family of
microcontrollers. After fighting with the 8-bit servo library I found HERE that was
supposed to make it as easy as a standard Arduino to add servos to an ATTiny project,
I decided to start from scratch and create something that was user friendly and Arduino
IDE compatable. Eventually I hope to turn this code into a fully functional open source
library, but until then I wanted to share the code I used to sweep a 9g servo on an
ATtiny84. Here's some code I came up with last night to get a servo to sweep somewhat
accurately that should work out-of-the-box. Future updates should eliminate the delay()
function and support multiple servos. Comments and suggestions are welcome.

              // **** ATtiny Servo Sweep Example **** // const byte servo = 0; // Servo pin on ATtiny int tPulse = 4000; // Total pulse length on 1 Mhz clock int hPulse = 60; // High pulse time (60=0deg -> 280=180deg) bool Dir          =    1;         // Servo direction void setup() {   pinMode(servo, OUTPUT); } void loop() {   digitalWrite(servo, HIGH); // Set pin high to start pulse   delayMicroseconds(hPulse); // High pulse angle data   digitalWrite(servo,LOW); // Set low for the rest of pulse   delayMicroseconds(tPulse-hPulse);      if (hPulse < 280 && Dir == 1) hPulse+=10; // Rotate servo to 180 degrees   else if (hPulse >= 280 && Dir == 1){ // Servo hit upper limit     hPulse = 280;                           // Keep servo angle in bounds     Dir=!Dir;                               // Switch direction   }   if (hPulse > 60 && Dir == 0) hPulse-=10; // Rotate servo to 0 degrees   else if (hPulse <= 60 && Dir == 0){ // Servo hit lower limit     hPulse = 60;                            // Keep servo angle in bounds     Dir=!Dir;                               // switch direction   }   delayMicroseconds(500); // Give servo some time to move before giving it a new position }

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

If you do make it a library then make sure you can set minimum and maximum range settings. Although the original servo standard is from 1000 - 2000μS many of the servos available today will work from as much as 600 - 2400μS. This is handy because it equates to 1μS=0.1°

I agree that flexibility of calibrating the software to the servo is a good idea. I think, to make the library as easy to use as possible, I will include all of the same commands as the standard servo library:

attach(pin) OR attach(pin, min, max), write(angle), writeMicroseconds(544->2400 OR min->max), read(), readMicroseconds, attached(), and detach().

I will, however, have open ears for any suggestions for additional features.

I'm glad to see there is some interest in this. If I can get it to support at least 4 servos, I would consider it a success, as a robot running an ATtiny would be able to run two continuous rotation drive servos with a pan-tilt head and still have a free pin. Or a three- servo hexapod with 2 spare pins, and that is just with the smallest 8-pin chips of the family.

Work is busy at the moment, but I do have most of a large chunk of the framework written in C++. Still many hours of pouring through datasheets of the whole group of chips for compatabilities sake. Stay tuned :)

It takes quite a bit of gumption to make a brand new library.  I considered doing exactly the same thing but the difference is that I am too lazy to.) There's just one little "but..."

I experienced about the same level of success that you had here with the ATTiny 45/85 cores (never tried 44/84 or 2313, even though I have them in the Planos...) which is to say some-generally with the pulsing method you can get a servo to go to a fairly predictable position and hold it.  The only problem is that when I tried to incorporate other timing into the sketches, everything goes all to hell.

Functionally, all I tried to do was to get a servo to go from position a to position b for 500μs and back again, wait 1 second, repeat the move and then wait 5 seconds before looping.  The sketch worked perfectly ad infinitum on the Unos, but when I moved it over to the ATTiny, It worked once or twice but then it would get caught in the middle, hang up, or ignore the programmed timing all together. I got the same results using delay and millis timing methods, whether using the built-in 1Mhz or 8Mhz clock core.


Try incorporating an incremental delay between 5 predetermined positions (ie, position 1, delay 1 sec, position 2, delay 2 secs, position 3...) and see if things don't go all wonky.  If it does work and has some integrity timing-wise then you may have figured out the solution that eluded me.

If not, what that means is that it might be useful to use a Tiny if all you want to do is to open a door or a valve in response to a sensor-it might work well for you, but if you want to have that servo open only for a perdetermined interval then you might want to look at another option.  Forget about a walking gait for a small bot.  


This whole thing is all your fault :P Seriously though, Your recent posts have been rather inspiring, and I've already learned a lot. I did find out the IDE can set the clock "divide by 8" fuse. If you get a new chip that is set to 1 MHz, just load up the 8 MHz board from "boards.txt" in the IDE and click "Burn Bootloader" It doesn't put an actual bootloader on the chip, but it will set all the fuses that are specified in the .txt file. I got a long ways to go yet, but in the end it should open the door for some new ways to make tiny robots (no pun intended).

Nice work, but I don't think the ATTinies support 2 way serial communication, And I'm not sure your method supports a slower clock rate. I could have gotten a bit more range, but dialed it back so it didn't strip anyones servo. Collected for future reference though ;)

See my article Servo Math and my programs to get full range out of your servos.