This ATTiny10 contains a 16 bit counter/timer unit that is capable of generating precise RC timing signals using its Fast PWM mode. This article shows how to create a dual channel RC servo controller based on the ATTiny10 that receives asynchronous serial command bytes sent at 9600 baud and uses these commands to program and create a pulse stream that can control one, or two RC servos. A command to set a servo to a particular position only needs to be sent once and the controller will then continue to generate a pulse stream with that setting until a new command is received that changes it. Separate command codes are provided for individually programming each of the two channels, which operate independently of each other. This is an all software implementation, so nothing more than an ATTiny10 (or ATTiny9) is needed, just connect the controller into your system, like this:
Two bytes must be sent to change the setting of one of the servo channels. Each byte sends 6 bits of a 12 bit value that defines the width of the servo pulse created by the ATTiny10. The first byte sends the least significant six bits and the 2nd sends the most significant six bits. The bytes must be sent in this order because the reception of the 2nd byte triggers the change to the servo setting. In addition, the upper two bits of each byte is used as an address to indicate which byte (MS, or LS) is being sent and which servo channel (A, or B) to change. The command bytes are coded like this:
After a RESET, the code it set to output a 1.5 ms pulse at a 60 Hz repetition rate on both channels. This corresponds to the middle, or neutral position of most servos. However, if you want to change this, the code that controls this is:
The "6000" value set in both
value = (pulse width in milliseconds) * 4000
Using the Controller
To better understand how to use the controller, here's a simple Arduino sketch that uses SoftwareSerial to send commands to channel A that slowly ramps a servo connected to that channel back and forth between two positions near the extreme range of that most servos can handle. Note: you can increase the values of LOW_LIMIT, and/or decrease HIGH_LIMIT to limit the servo's travel to a smaller range. You can also increase STEP_SIZE to make the servo move faster.
When you send a position value to either channel, the internal code multiplies the 12 bit value it receives by 2 and then adds 2000 to it before using this value to program the
width (ms) = (value * 2 + 2000) / 4000
If You Want to Make One
The code to needed to program an ATTiny10 as a dual channel servo controller is available at the bottom of the page and you can use my ATTiny10 Assembly IDE and Device Programmer to program a blank ATTiny10 with this code. However, there are a few details you need to know in order to reproduce my results. First, the code uses the ATTiny10's internal clock to drive the timing. Since the serial reception is done with software emulation using timing loops, it's important that the master clock that drives the timing be as accurate as possible. ATMEL does some calibration of the internal clock oscillator, but it's only guaranteed to an accuracy of +/- 10%, which may not be good enough to reliably receive serial data at 9600 baud. However, it's possible to tweak the clock in software and, in fact, the code attached below has done this for the particular ATTiny9 chip I used. The code that does this is, as follows:
In effect, this code writes a "tweak" value to a special register that adjust the internal clock frequency up, or down, depending on the value written to it. I recommend that, at first, you should comment out this code and tryi using the factory calibration, as it may work fine for you. If it does, that's great. If not, you'll need to figure out a proper calibration value for your ATTiny and use it in place of the
Note: the latest version of the IDE and Programmer software adds a way to automatically get the 8 MHz calibration value for your chip.