View previous topic :: View next topic |
Author |
Message |
gjs_rsdi
Joined: 06 Feb 2006 Posts: 468 Location: Bali
|
Model aircraft servo pulses |
Posted: Sun Jun 26, 2016 5:03 pm |
|
|
Code: |
///////////////////////////////////////////////////////////////////
//GENERATING 9 MODEL AIRCRAFT SERVO PULSES
//HITEC servo pulse 1520+/-500us
//setting the pulses to 1514+/-500us gives 250ns max pulse error
//on 1520+/-500us pulse output
//adding 62us to the pulses sum gives 313ns error to the 20ms period
//pulse9 is dummy time kept at 1020us
//generating 10 pulses is possible with the commented out line in case 10
//gives max error of 205us to the 20ms period
///////////////////////////////////////////////////////////////////
#include <18F26K22.h>
#device ADC=10
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES PUT //Power Up Timer
#FUSES NOPBADEN //PORTB pins are configured as digital I/O on RESET
#FUSES NOHFOFST //High Frequency INTRC waits until stable before clocking CPU
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#use delay(internal=64MHz)
#define flashled PIN_A4
#define servo0 PIN_B0
#define servo1 PIN_B1
#define servo2 PIN_B2
#define servo3 PIN_B3
#define servo4 PIN_B4
#define servo5 PIN_B5
#define servo6 PIN_C3
#define servo7 PIN_C4
#define servo8 PIN_C5
int flashledcnt=0;
int pulses=0;
long pulse0=1514;
long pulse1=1514;
long pulse2=1514;
long pulse3=1514;
long pulse4=1514;
long pulse5=1514;
long pulse6=1514;
long pulse7=1514;
long pulse8=1514;
long pulse9=1014;//dummy pulse
long pulsestime=0;
#int_TIMER0
void TIMER0_isr(void)
{
switch(pulses)
{
case 0:
{
output_high(servo0);
set_timer0(65536-pulse0);//first pulse time
pulsestime=pulse0;
pulses++;
}
break;
case 1:
{
output_high(servo1);
output_low(servo0);
set_timer0(65536-pulse1);
pulsestime=pulsestime+pulse1;
pulses++;
}
break;
case 2:
{
output_high(servo2);
output_low(servo1);
set_timer0(65536-pulse2);
pulsestime=pulsestime+pulse2;
pulses++;
}
break;
case 3:
{
output_high(servo3);
output_low(servo2);
set_timer0(65536-pulse3);
pulsestime=pulsestime+pulse3;
pulses++;
}
break;
case 4:
{
output_high(servo4);
output_low(servo3);
set_timer0(65536-pulse4);
pulsestime=pulsestime+pulse4;
pulses++;
}
break;
case 5:
{
output_high(servo5);
output_low(servo4);
set_timer0(65536-pulse5);
pulsestime=pulsestime+pulse5;
pulses++;
}
break;
case 6:
{
output_high(servo6);
output_low(servo5);
set_timer0(65536-pulse6);
pulsestime=pulsestime+pulse6;
pulses++;
}
break;
case 7:
{
output_high(servo7);
output_low(servo6);
set_timer0(65536-pulse7);
pulsestime=pulsestime+pulse7;
pulses++;
}
break;
case 8:
{
output_high(servo8);
output_low(servo7);
set_timer0(65536-pulse8);
pulsestime=pulsestime+pulse8;
pulses++;
}
break;
case 9:
{
output_low(servo8);
set_timer0(65536-pulse9);//1000us dummy pulse
pulsestime=pulsestime+pulse9;
pulses++;
}
break;
case 10:
{
set_timer0(45536+pulsestime+62);//to complement the period to 20ms
// set_timer0(45536+pulsestime-141);//to complement the period to 20ms
pulses=0;//to start the next sequence
flashledcnt++;
}
break;
}
}
void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16);//65.5 ms overflow
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
while(TRUE)
{
if(flashledcnt>=25)
{
flashledcnt=0;
output_toggle(flashled);
}
}
}
|
|
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Thu Aug 11, 2016 3:32 pm |
|
|
this submission is surprisingly indeterminate in it's execution.
As soon as any of the pulse'n' values change -to alter servo position
- the cycling time between interrupt servicing becomes indeterminate.
if a lot of fast position changes are needed - the delay before the new position command is sent- is variable too.
this is use at your own peril code -IMHO |
|
|
gjs_rsdi
Joined: 06 Feb 2006 Posts: 468 Location: Bali
|
|
Posted: Thu Aug 11, 2016 4:01 pm |
|
|
asmboy
Did you test the program in MPLAB and or with real hardware?
I am using the posted program for 10 years already on a few aircrafs, had never any problem.
16F876 and 18F252 at 16MHz clock
18F2520 and 18F25K20 at 32Mhz clock
18F26K22 at 64MHz on the last aircraft
But if you think the program should not be here, I will delete it
Best wishes
Joe |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Thu Aug 11, 2016 4:44 pm |
|
|
tried with actual hardware and noticed variable delay as to when the new position command takes. Probably OK for model airplane but not for scientific optical instrument i am working on. very fast response to command stream needed in my app. working n another way t make it synchronous for all channels.... |
|
|
gjs_rsdi
Joined: 06 Feb 2006 Posts: 468 Location: Bali
|
|
Posted: Thu Aug 11, 2016 5:06 pm |
|
|
My previous software was in assembler so the glitch was 2 PC
Now can be up to 1 us. 1 us, from 1000 us is 0.1% . If the elevator range for example is +/- 22.5 degree if will result in 0.045 degree that is really nothing for a model aircraft.
This is the reason the program title is:
GENERATING 9 MODEL AIRCRAFT SERVO PULSES
I should mention also that the delay between the stick movement to servo movement should be 75 ms maximum not to see by eye delay between the command and the movement. The minimum for real time is defined 125 ms, but most model aircraft pilots will tell you that have delay at 125 ms, some at even 80 ms.
Best wishes
Joe |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Fri Aug 12, 2016 1:17 pm |
|
|
let me better explain the weakness to you.
if pulses=1
AND you change the value of pulse0 desiring an immediate start to a new position command EDGE to be set, the leading edge of the new servo command for channel 0 will not begin to change until all the other pulses duration have been walked through. can you understand what i am telling you ?
This is too slow and unresponsive in my app - and leads to my first complaint.
" indeterminate in it's execution. "
in the time domain - because it is.
in reality - your code is serial -multitasking.
i am doing it in a wholly different (parallel) way that allows the new "move-to" leading edge to be set from the foreground IMMEDIATELY and uses a countdown int16 array[8] that gets decremented for ALL actively being moved servo channels on each time tick interrupt. This method makes periodic refresh raise ALL active leading edges in parallel too. |
|
|
gjs_rsdi
Joined: 06 Feb 2006 Posts: 468 Location: Bali
|
|
Posted: Fri Aug 12, 2016 7:27 pm |
|
|
Quote: | ...the leading edge of the new servo command for channel 0 will not begin to change until all the other pulses duration have been walked through. can you understand what i am telling you ?
|
Yes I can. As I explained in my previous post, is not important for my application
Best wishes
Joe |
|
|
|