A Tiny Servo Motor Controller

If you’re building a moving thing with a microcontroller, you’ll probably want to throw a servo controller in the mix. Driving a servo or two with a microcontroller takes away valuable cycles that just babysit the servo, making sure all the PWM signals are in sync. The thing is, most servo controllers are a massive overkill, and you don’t need that much to control a few servos over a UART. The proof of this is an attiny13 servo controller over on hackaday.io.

[arief] developed his tiny servo controller around one of the tiniest microcontrollers – the ATtiny13. This chip has just 1kB of Flash and 64 Bytes of RAM, but that’s enough to keep a few servos going and listen in to a UART for commands to drive the servo.

The construction of this servo controller board is simple enough – just a single sided board, microcontroller, and a few headers, caps, and resistors. Commands are sent to the ATtiny through a half duplex UART we covered before, with servos responding to simple serial commands.

If you’re building a robot army, this is the board to make. You’re going to need a high-powered controller to take over the world, but there’s no need to bog down that controller by babysitting a few servos.

33 thoughts on “A Tiny Servo Motor Controller

      1. Or use a packet based async serial protocol that kind of works like I2C
        – listen in on the broadcast address byte and ionly do something when that’s matching the address.
        – ignore the rest of the packet if the address doesn’t match
        There is a 9th bit on the UART that can be used for marking special sideband commands/address like this.

        1. Or, send a burst of bytes, followed by a pause. First servo listens to first byte, second servo listens to second byte, etc.

          What I don’t like about these solutions is that they require the hassle of programming all the MCUs and figuring out a way to assign them ID numbers.

          Instead, I would rather hook up the servos to a bunch of GPIO pins, and use a single high priority timer interrupt to control them. For limited number of servos you can turn off one, and turn on the next one, and set new timeout value. That would only take a few cycles.

        2. It does hardly seem worth an article on HAD. If I need to power a servo I use a PIC and assembler, that is about 20 lines of code if that, if I need to talk to it more than up and down then I use I2C routines that I wrote some time in the 1980s

    1. If the other side of the link is willing to play along, (i.e. has appropriate software UART code running) you can do half-duplex with no extra hardware and one pin.

      The circuit you’re referring to (http://hackaday.com/2014/01/13/software-half-duplex-uart-for-avrs/) is only really necessary to bridge a 1-pin UART to a 2-pin, normal UART.

      But yeah, at the moment he’s just got RX working on the board, probably b/c that’s all he’s really needed.

      1. I mis-wrote. I took a look at an old RGBW LED micro intelligent light project collecting dust on my workbench. I should mention there is a TLC5940 driving the ULN2803. The TLC drives the PWM cycles. The ULN is for amplification.

        That makes more sense, I think.

        :-D

        1. Why do you need to amplify the PWM signals? A servo doesn’t require high-current on the control signal and, in the case of LEDs, you have 120mA to work with before any amplification is added. Driving some big RGBW LEDs?

    1. My original post should have read “I use a TLC5940 to handle my servo or PWM housekeeping to keep my Arduino free for other things.” The ULN2803 drives a 1-watt RGBW LED in one of my projects. That’s what I get for glancing at the proto board this early in the morning. :-D

  1. A bit error rate that high may necessitate the use of a crystal oscillator to drive the micro. Probably in the datasheet.

    I2c would be better

    A protocol that embeds the timing in it, like Manchester Encoding is an even better option and can be done with your 1 bit hardware.

    I2C is just so much easier in this case though.

    1. Tiny13 does not have external clock input.
      And the PWM is done in software as 5 servos are driven.
      And even if there was hardware for all five outputs, you need to either accept poor resolution or tweak OSCAL registers to get proper frequency out of 8-bit timer (I’ve done PWM for servo with the timer on tiny13 and software i2c master, but that was on another project).

  2. Nice use of a resource constrained processor. :) I like seeing projects that take something so small and makes it hit well above it’s weight. I don’t care for people questioning it’s usefulness, that it has been done is enough for me. Great job! :)

  3. I’ve had my soft UART running error-free at 115,200 on an ATtiny13a. I find the internal oscillator on the t13 is often a long way from 9.6Mhz, with some as low as 9.2 and others as high as 9.8. Either use a programmer that does OSCCAL tuning, or change F_CPU for the particular AVR you are programming.
    To measure the frequency, run a small program that toggles a pin at a known internval, and then measure the output with a scope or even a multimeter that has a frequency setting. A simple 4-line asm program could work:
    ldi r15, 0x01
    out DDRB, r15 ; output mode
    out PINB, r15 ; toggle pin
    rjmp -2 ; repeat

    PB0 will toggle every 3 cycles, or 1.6Mhz if the t13 oscillator is running at 9.6Mhz. If you get 1.55Mhz at PB0, you know the oscillator is running at 9.3Mhz, and can adjust F_CPU accordingly.

    I also have improved the original soft UART code so that there is no jitter on the Tx timing (original version had a 1 cycle difference between a 1 and a 0 bit).
    https://github.com/nerdralph/nerdralph/tree/master/avr/libs/bbuart

      1. I’ve done exactly this and it works well on the ATtiny series. At least the ones I worked on. I wish I could take credit for it but I borrowed the code from TinySafeBoot for those I didn’t want a bootloader on. IIRC, the code can be trimmed to remove the undesired protocols.

    1. Entirely true, but you’re not fanning your I/O. Except for RST, I’ve had very satisfactory performance on the “less than full strength” pins* in a 1 to 1 IC configuration. That’s all the servo really needs, a signal. Not like you’re trying to drive the motor itself using the ATtiny pins.

      * I never tried to disable RST on any AVR.

  4. would like to see an i2c version. it would eat up a pin though and you would only get 4 channels. though im sure one of my projects would make good use of the serial version. i dont really use a whole lot of serial devices and so i always end up using the uart lines for other things..

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.