This is explained in many locations in more detail such as here on Wikipedia, but briefly, the min to max range on servo (typically 90 degrees total) by producing a pulse at around 50 Hz (20ms) whose width varies from 1000us to 2000us.
- Rate of pulses affects speed of motor response. My maximum was with an interval of 8-10 ms.
- The exact time for min and max and actual angle of rotation vary for different motors, and usually need trimming to offset the exact pulse durations and a measurment to find angles.
- Motor rotation rates vary a lot and are specified in time per 60deg turn.
- 0.15 - 0.25 is typical; less than 0.1 is actually "fast," although lots of parts are referred to as fast are 0.18 - 0.2/60deg. 0.06 is the very fastest I've seen on more expensive, fast servos, at their highest input voltage. Price jumps hugely from $15 to $200 for ones I've found so far for a seemingly small speed increase. (ex: Futaba $$$)
Programming
Directly coding using time will work. Here is the code I used to try out control; it sweeps the value up and down to spin motor from ~min to ~max position, with a little margin near edges.To control more than one motor, use one of the RC Servo libraries (such as the one supplied with Arduino examples).
Higher resolution control with library: https://www.pjrc.com/teensy/td_libs_PulsePosition.html
// Control an RC servo by directly setting times // filename: ds_servo_motion_direct_timer #include <FlexiTimer2.h> int t_on = 1500; // ms int led_pin = LED_BUILTIN; int pulseInterval = 10; // this is the interval between variable pulses. 8 is near minimum time on my tests. nominal is 5 - 25ms https://en.wikipedia.org/wiki/Servo_control void setup() { pinMode(led_pin, OUTPUT); FlexiTimer2::set(pulseInterval, 1.0 / 1000, pulse); // call every n 1ms "ticks" FlexiTimer2::start(); } void loop() { ; } // ISR void pulse() { float rate_factor = 0.10; // adjust this to change servo rotation rate static float t = 0; float t_step = 500.0 / 1000; // ms float f = 1.0; // Hz int i = 0; // ideal range: 1500 +/- ~500 t_on = 1500 + 50 + int( 400 * sin(rate_factor * t)); // fraction controls time; interacts with pulse interval above if (i++ % 4 == 0) { Serial.print(t_on); Serial.print(" "); Serial.println(90.0 * (t_on - 1000) / 1000); // print as degrees. print less often if fast output } //make high and low pulse durations (constant total time) 1000us min; 2000us max digitalWriteFast(led_pin, 1); delayMicroseconds(t_on); digitalWriteFast(led_pin, 0); delayMicroseconds(2000 - t_on); t += t_step; }
No comments:
Post a Comment