Servo PWM using 8 Bit timer

Mee_n_Mac:

FightCube:
I wrote a 2 channel radio receiver emulator program on one Arduino tonight, controlled by two potentiometers… and then wrote the servo reverser program on another Arduino… hooked them together and it works perfectly with zero noticeable lag!

Code sent to your email :wink:

In general terms, what was your solution ?

Hi Mee_n_Mac!

So I basically started creating the RxEmulator as a way to quickly debug the ServoReverser. I created a two channel system that would generate the 1.0 to 2.0ms pulse, and also be able to completely shut off the pulse so that I could test the ServoReverser for a lost signal.

The RxEmulator was pretty easy. A main loop reads two ADC inputs and main loop calculates onTime values for the servo output based on the percentage of ADC value vs. the max value. Once these values are known, both servo outputs are set HIGH and a while loop is started that counts down 20ms worth of time. Within that loop the onTime for each output is monitored and terminated (i.e. set LOW) at the correct time. If the ADC value is 0 the outputs are never set HIGH but the 20ms loop runs anyway.

The ServoReverser is pretty cool. I used the attachInterrupt() function in the Arduino which is capable of interrupting on a pin change. Fortunately there are two of these available in the Arduino library because I needed two. The Mega supports an additional 4 more. Obviously there are more available for the ATmega328 but they are not all implemented in the default libraries, so it’s not a limitation really if you need more… you just have to figure it out yourself… not too hard. Anyhoo, using the attachInterrupt() function, it was easy to set up ISR’s that were called for every change on the inputs, one for each Rx channel. I decided to just interrupt on both rising and falling states, and do a simple test to see which pulse width value I wanted to store. This is easy to do because the period is 20ms, and the pulses I care about are always less than 3ms :wink:

I used the micros() function to keep track of a few different counters for measuring pulse widths of the two Rx channels, and to generate the output pulse with the same type of while loop used in the RxEmulator. Reversing the pulse width was dead simple, so I added another couple neat features to make things a bit more interesting. Jason had the idea to use the other channel to do something for the system, so I worked that in. Also, I decided if any signal was lost for more than 100ms, the reversed output would return to the default center position of 1.5ms. As of right now it works as designed. All of this was done in basically one evening, and the ServoReverser code is only 1.8K. The output is obviously delayed due to measurement and calculation, but it’s absolutely transparent to the user operating the servos. In fact, if you look at the channels of a multi-channel receiver on a scope, you’ll see they are all done the same way and are not sync’d on the leading edge. At least they are on my Spektrum DX7 7 channel system.

If I were you, I would take a look at the Arduino. It’s a fantastic rapid prototyping development tool that I use all of the time. With so many variations that plug right into a breadboard, all of the shields available with just about every sensor you can think of, and super simple compiling and programming they are a snap to use. The power of the system is really only as good as the operator though… so if you don’t know C code and don’t have room in your brain for some more code library knowledge, it won’t be for you. However, they even have Arduino compatible boards that use the PIC32 as the main uC now, and they are still compatible with the Arduino IDE as well. They work for me and that’s what counts when I need to get something done quickly. I can be out in the lab running some new test or testing some new sensors while the rest of the engineering staff are still sitting around trying to configure the files for a PIC uC.

-Brett (FightCube.com)