Changes

Driving Hobby Servos

3,057 bytes added, 00:46, 23 July 2016
Added Hobby RC Servo modules
Hobby RC Servo modules like this can be controlled from KFLOP.


[[File:HobbyServo.png|none|link=]]


Most Servo Modules require a 1-2ms pulse at 50Hz to command their position.  


[[File:HobbyServoPulse.png|none|link=]]


This is somewhat difficult to generate with normal PWM generators as high Time resolution is required at a slow rate.  KFLOP Hardware PWM generators have a minimum frequency of 254Hz.


A KFLOP User C Program can be used to enable and disable a PWM generator in a way that one pulse is output only every N PWM cycles.  PWM gernerator #1 is sacrificed to generate a fixed long PWM pulse that the C Program can monitor to count cycles as well as determine when the next PWM cycle for all the PWM generators will begin.

<pre class="brush:c">#include "KMotionDef.h"

void ServiceHobbyPWM(void);

int ncycles, v1, v2;

main()
{
int LowClocks, scaler=150;
float PWMPeriod, BaseFreq=16.6667e6, PulseGap=20e-3, SafetyTime=200e-6;
// Set base PWM to be high for entire time less 200us

LowClocks = SafetyTime * BaseFreq / scaler;
PWMPeriod = 256.0*scaler/BaseFreq;
ncycles = PulseGap/PWMPeriod;
printf("PWM Period = %fus\n", PWMPeriod*1e6);
printf("Low Clocks = %d\n", LowClocks);
printf("Skip Cycles = %d\n", ncycles);

SetBitDirection(26,1); // define bit as an output
ClearBit(26);
SetBitDirection(27,1); // define bit as an output
ClearBit(27);
SetBitDirection(28,1); // define bit as an output
ClearBit(28);

FPGA(IO_PWMS_PRESCALE) = scaler; // divide clock by 256 (250Hz)
FPGA(IO_PWMS) = 255-LowClocks; // Mostly high pulse
FPGA(IO_PWMS+1) = 1; // Enable
ClearBit(26);

v1 = 800e-6 * BaseFreq / scaler; // set Pulse time
v2 = 1700e-6 * BaseFreq / scaler; // set Pulse time

printf("PWM settings v1 = %d v2 = %d\n", v1,v2);

for (;;)
{
ServiceHobbyPWM();
}
}


void ServiceHobbyPWM(void)
{
static int i=0;
static WaitLevel=0;

if (!WaitLevel) // waiting for low?
{
if (!ReadBit(26)) // yes is it low?
{
WaitLevel=1; // yes, change state
if (++i == ncycles) // count mostly high pulses, special cycle?
{
FPGA(IO_PWMS+2) = v1; // Pulse size
FPGA(IO_PWMS+3) = 1; // Enable
FPGA(IO_PWMS+4) = v2; // Pulse size
FPGA(IO_PWMS+5) = 1; // Enable
i=0;
}
else
{
FPGA(IO_PWMS+3) = 0; // Disable
FPGA(IO_PWMS+5) = 0; // Disable
}
}
}
else
{
if (ReadBit(26)) // no, waiting for high, is it high?
{
WaitLevel=0; // yes, change state
}
}
}</pre>

The code above prints this:


PWM Period = 2303.995425us<br />Low Clocks = 22<br />Skip Cycles = 8<br />PWM settings v1 = 88 v2 = 188


It generates the timing shown below.  Note the yellow trace is the reference PWM used by the C Program to count the cycles.  Two PWM pulses are emitted every 8 cycles.  The cyan trace shows a pulse width of 780us (specified in the program to be 800us) with a period of 18.5ms.  The magenta trace shows a pulse width of 1.7ms (specified in the program to be 1700us) with a period of 18.5ms.


[[File:HobbyServoTwoPulses.png|none|link=]]
Bureaucrat, administrator
469
edits