I'm a little confused. I read that servos are controlled via PPM, but I thought that standard servos are controlled via PWM. Does PPM control only apply to R/C servos?
I'm working on a project to create a PWM expander using the tlc5940 to control standard servo motors. But now I'm confused as to if this will work or not. So far, using the tlc5940 library, I've had only a few bugs controlling my servo motors (10k potentiometers need to be calibrated because the servos are a little glitchy when moved by the pots). Can somebody clear up this PPM vs PWM thing please?
From one of the gurus:
The manufacturers of hobby radio control equipment refer to the modulation used to encode servo information to be sent from transmitter to receiver as PPM.
There have been a number of threads discussing this terminology in the past and I don't want to turn this into another one, but PWM involves modulation of the duty cycle, servo position is independent of duty cycle (it's determined solely by pulse duration). The current Arduino servo library does not use PWM to produce servo pulses and the duty cycle can change even if a servos pulse width (and therefore position) does not change.
Using the term PWM to refer to the control of servos in the Arduino environment can be confusing because PWM is what analogWrite produces (there is some discussion in the developers mailing list about changing the name of the current analgWrite functionality to pwmWrite and leaving analgWrite free to be used when arduino supports true digital to analog conversion – not sure if this will happen, but I like the idea)
Anyway, people have tried to drive servos using analogWrite (heck the Arduino analogWrite reference says it produces PWM and if servos use PWM then it should work, right?). This can damage servos and is not to be encouraged.
So far, using the tlc5940 library, I've had only a few bugs controlling my servo motors
This one comes up with astonishing regularity.
Yes, your servos may well appear to work with high(er) frequency PWM, but they will almost certainly be consuming far more current than they would if operated correctly, consequently running hotter than they would normally, wasting power and reducing device life.
So, should I consider building/using a servo shield instead of the tlc5940?
If you can get your PWM frequency down to 50Hz, and get adequate resolution to accurately control your servos on a duty cycle of about 5 to 10% (1ms to 2ms), then yes, carry on using your LED driver.
I just checked the PWM frequency (with analogWrite(), is that the same? I don't see any explicit PWM library) with a CRO and get a 2mS period which is 10x 50Hz. Is there a way to adjust the frequency?
Yes, but you have to abandon analogWrite() and get your hands dirty with the internals, as described on the ATmega328 datasheet. Read the timer section of the datasheet and the source code for analogWrite() to get a handle on how it works.
Naturally, portability suffers; the existing analogWrite code deals with the problem with a mess of conditional compilation.
Even if you hack analogWrite to output at 50Hz, you're still stuck with 8 bit resolution, so you get only about 12 or 13 discrete servo positions.
If you've got an LED driver with 10 or 12 bit PWM, this gets you 50 (10 bit) or 200 (12 bit) positions.
It is posible, I think, to get LED drivers with 14 bit resolution.
Cool. Thanks for the responses! I just have one more question. When I tried using the tlc5940 with my servos again I noticed something - I could only move the servo position between 0 and 90 degrees. I should be able to move between 0 and 180 degrees. I'm pretty sure I have the frequency set around 50 Hz so I don't know what this could be the result of?
I'm pretty sure I have the frequency set around 50 Hz
The frequency is not really the issue, it's the pulse width / duty cycle / mark:space ratio.
Or it may simply be that the servo is incapable of greater travel - how does it perform with the standard servo library?
A scope is useful at times like these.
On the standard library, I can move the servo position between 0 and 180 degrees without a problem. I'm not sure if there's a bug in the tlc5940 library, but I'm guessing I might have to write my own functions to interface with the tlc5940 to drive the servos?
You aren't stuck with 8 bit resolution, at least not on all of the PWM pins. If you're hacking up analogWrite() to turn down the frequency, it's not that big a stretch to further hack it to use the full capability of the 16 bit timers. You can't get that on every PWM pin, but you can have it on some.
Alum, what values are you writing to the tlc5940 for your testing?
vinceherman, I'm using the tlc5940 library:
The PWM values being written are coming from pins 3, 9, 10, and 11. These should be outputting a correct pulse width to drive the servos. The function tlc_initServos() drops the PWM frequency to 50 Hz.
And on the page you linked to, it says:
* 3993, 0xf99: 500 microseconds
* 3584, 0xe00: 1500 microseconds
* 3168, 0xc60: 2500 microsecond
I was just wondering what values you were writing to get the servo movement you describe.