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.
In most projects, UART ports are scarcer than CPU cycles.
Multiplex the TX lines!
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.
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.
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
Good to know there is always a besserwisser at hand.
Do you want to share your approach on Hackaday.io?
this is why I love my Arduino Megas!!!
Original and SeedStudio, 4 UARTs FTW!!!!
This looks like a great way to add servo control to a Raspberry Pi.
It’s actually not that half-duplex UART. If you look at the board, you will see there are no transistors there. It’s just half of an UART, with only RX pin. No TX at all.
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.
I use a ULN2803 to handle my servo or PWM housekeeping to keep my Arduino free for other things.
How do Darlington drivers do that??!?
Second that question!
Michael – say more. Do you have any projects documented somewhere that you could share? Thanks.
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
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?
You may be right. I’m using the ULN for the 1-watt LED’s. Not the servos.
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
Ahem…
RS485 / 422 or I2C solves this (1 Transmitter, Multiple down receivers)
That requires two wires, and he wants all the pins he can have for the servos.
“Because of hit rate UART less than 70% there is good for you to repeat the command 3-5 times” WTF? You just lost all your savings real-or-imagined right there.
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.
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).
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! :)
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
Why not use the data on the serial line as timing reference? With the servos being addressed with ‘A’ … ‘E’, there is always a low to high transition after the 6th data bit.
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.
One thing to note about the t13 when driving external loads is that only PB0 & PB1 have full drive strength. PB2-5 are less, and as will all attinies, drive strength on PB5 (with RST disabled) sucks.
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.
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..
I tend to think a can bus would be a good way to control a lot of servo’s. Would love to see it used more in projects.
Anyone wanting to control a servo with some serious precision should take a look at this:
SuperModified v3.0 Zero One Mechatronics
SKU: ENC5V15BS / DRV24V005AV03 / MCU24V328V03
http://www.01mechatronics.com/products
https://www.youtube.com/watch?v=qhIxHj_V1_g