A little background: I have been trying to get my Arduino Uno or Mega2650 to reliably read 8 rc reciever channels with pulseIn(), massage/normalize data, and output to 8+ servos/motors. After learning that the pulseIn() function and the standard servo library use of interrupts interfere with each other. Next, I began to use RCArduinoFastLib with my Uno and was able to get basic read/write function but wasn't able to get achieve a serial connection for debugging. This library can only be used with the Uno so being able to read 8 channels and have 8+ outputs isn't going to work. If you want more info on using that library you can follow the link below to view the forum thread.
After seeing the 16ch servo driver in the store, I thought it would be extremely handy for my project. Would using the servo driver interfere with the pulseIn() function? Or give poor performance for rc control?
Also, I'm unsure how to use the setPWM() function? I see that there is a 12-bit window(0-4096) to turn the signal on and then off. How to i make the distinction between these values and servo position? Or at least to pulse length required be the servo? Does this factor in the 1ms minimum required pulse for 0 degrees?
16-Channel Servo Driver
http://www.adafruit.com/products/815
setPWM
http://learn.adafruit.com/16-channel-pw ... nel-on-off
FlySky TH-9x Transmitter & R8b Receiver
http://www.hobbypartz.com/79p-th9x-r9b- ... radio.html
Arduino Forum Thread
http://arduino.cc/forum/index.php/topic,153475.0.html
RCArduinoFastLib
http://rcarduino.blogspot.com/2012/11/h ... stlib.html
Servo Fundamentals PDF Download from Princeton University
https://www.google.com/url?sa=t&rct=j&q ... 1H21IxRWjg
16-Channel Servo Driver For RC Project
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- adafruit_support_bill
- Posts: 88154
- Joined: Sat Feb 07, 2009 10:11 am
Re: 16-Channel Servo Driver For RC Project
The 16 channel servo driver communicates via the hardware i2c on the Uno (pins A4 and A5) and does not interfere with timers or serial communication.
There is a servo example program in the library download that shows appropriate PWM settings for servo control.
There is a servo example program in the library download that shows appropriate PWM settings for servo control.
-
- Posts: 466
- Joined: Thu Aug 30, 2012 1:34 am
Re: 16-Channel Servo Driver For RC Project
here's the way i understand it...
your basic analog hobby servo wants a pulse of between 1 and 2 ms. these values represent the extremes of the servo position, with a 1.5ms pulse giving a neutral position. the pwm frequency is usually 50Hz. higher frequencies will provide more torque, but frquencies that are too high will lead to motor overheating or jitter.
the chip on the servo controller supports frequencies between 40Hz and 1000Hz. higher frequencies will allow finer granularity in control of the pulse width. at 50Hz, the maximum pulse width is 20ms. only 1/10 of that is useful for servo control. the pulse width is set with a 12 bit value in the range 0-4095. so a 1 ms pulse with a 50Hz pwm frequency would be 4096 / 20, or about 205. the maximum pulse width would be 410, giving you about 7.5 bits of resolution. a little better than 1 bit per degree, assuming about 180 degree range of motion on the servo.
so, at 50Hz, your on time will be 0 and your off time will be 205 + degrees * (180 / 205). or thereabouts. please don't do these calculations using integers.
i should note that i'm just making this up as i peruse the datasheet. as always, my math and logic are somewhat suspect. if i can get this thing working with my raspberry pi this afternoon, i'll post again.
your basic analog hobby servo wants a pulse of between 1 and 2 ms. these values represent the extremes of the servo position, with a 1.5ms pulse giving a neutral position. the pwm frequency is usually 50Hz. higher frequencies will provide more torque, but frquencies that are too high will lead to motor overheating or jitter.
the chip on the servo controller supports frequencies between 40Hz and 1000Hz. higher frequencies will allow finer granularity in control of the pulse width. at 50Hz, the maximum pulse width is 20ms. only 1/10 of that is useful for servo control. the pulse width is set with a 12 bit value in the range 0-4095. so a 1 ms pulse with a 50Hz pwm frequency would be 4096 / 20, or about 205. the maximum pulse width would be 410, giving you about 7.5 bits of resolution. a little better than 1 bit per degree, assuming about 180 degree range of motion on the servo.
so, at 50Hz, your on time will be 0 and your off time will be 205 + degrees * (180 / 205). or thereabouts. please don't do these calculations using integers.
i should note that i'm just making this up as i peruse the datasheet. as always, my math and logic are somewhat suspect. if i can get this thing working with my raspberry pi this afternoon, i'll post again.
-
- Posts: 466
- Joined: Thu Aug 30, 2012 1:34 am
Re: 16-Channel Servo Driver For RC Project
better make that 205+ degrees * (205/180).
-
- Posts: 466
- Joined: Thu Aug 30, 2012 1:34 am
Re: 16-Channel Servo Driver For RC Project
so, on reflection, i was thinking that fixed point math would be your best bet here. hmm, but there is no fixed point math on the arduino. it's easy enough to fake it though.
assuming that my assertions above are correct, we need to calculate degrees * (205/180). 205/180 is 1.13888889. multiply that by 256 to get 292, which will be the fixed point, 8 bit integer + 8 bit fractional, representation of 1.13888889.
so multiply the position you want in degrees by 292, add 128 to round the result, and shift the whole thing right 8 bits to get just the integer part, then add 205 and you've got the off time for the servo.
why? you may ask. because floating point arithmetic on the arduino is god awful slow.
i think i've demonstrated already, that my work should be checked.
assuming that my assertions above are correct, we need to calculate degrees * (205/180). 205/180 is 1.13888889. multiply that by 256 to get 292, which will be the fixed point, 8 bit integer + 8 bit fractional, representation of 1.13888889.
so multiply the position you want in degrees by 292, add 128 to round the result, and shift the whole thing right 8 bits to get just the integer part, then add 205 and you've got the off time for the servo.
Code: Select all
setPWM (channel, 0, ((degress * 292 + 128) >> 8) + 205);
i think i've demonstrated already, that my work should be checked.
-
- Posts: 3
- Joined: Sat Mar 30, 2013 3:37 pm
Re: 16-Channel Servo Driver For RC Project
Thanks for the reply tldr, for the most part am following you, 205 is the 1ms minimum pulse and (degrees*292+128)>>8 is storing the value as an 8 bit integer? I also have a total range 205 and integer math should work since the resolution of input to output values is 1.1389, above 1. Granted, the resulting movement might not be as precise as possible but it can't be any worse than the cheap servos I'm using. If you are testing on your pi I would like to see if there is a huge difference between your forced floating logic and integer math.tldr wrote:Code: Select all
setPWM (channel, 0, ((degress * 292 + 128) >> 8) + 205);
Also, does the map function on the Arduino only work with integer math?
- adafruit_support_bill
- Posts: 88154
- Joined: Sat Feb 07, 2009 10:11 am
Re: 16-Channel Servo Driver For RC Project
The Arduino map function is integer-only. But even with premium quality analog servos, the positional accuracy is going to be +/- a degree or so - regardless of the precision of your math.
-
- Posts: 3
- Joined: Sat Mar 30, 2013 3:37 pm
Re: 16-Channel Servo Driver For RC Project
Awesome, This product has saved my bacon and all my RC projects to come.adafruit_support wrote:The Arduino map function is integer-only. But even with premium quality analog servos, the positional accuracy is going to be +/- a degree or so - regardless of the precision of your math.
-
- Posts: 466
- Joined: Thu Aug 30, 2012 1:34 am
Re: 16-Channel Servo Driver For RC Project
there, you see? i ought to spend more time reading arduino sources like i used to.
you could save a few cycles by dropping this function directly into your code with constants for the minima and maxima, so all that has to happen at runtime is the multiply and divide. even 32 bit additions and subtractions take a while on an 8 bit machine. not to mention pushing and popping 16 bytes worth of arguments. i reckon decoding the incoming pulses will be pretty cpu intensive.
Code: Select all
long map(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
Please be positive and constructive with your questions and comments.