View previous topic :: View next topic |
Author |
Message |
StealthMicro
Joined: 10 Apr 2007 Posts: 17
|
Multiple R/C Servo PPM signal. |
Posted: Thu Apr 30, 2009 11:33 am |
|
|
I have built a Flight Simulator like a helicopter seat that I need to interface with the R/C Transmitters. Right now I have to hack each transmitter and tap in to the pots to access the controls. It is a bit of a pain as I have to use a 24V power supply and voltage dividers to get the voltage ranges I need as the controls on the flight simulator do not have the same range of motion as the R/C transmitter does.
What I would like to do instead is send the signal out to the Buddy Box port on the transmitter and do it that way. I can use the A/D ports to convert the voltage to the PPM stream needed to control the servos using the buddy box port.
What I need is a way to generate the PPM signal. It basically is a signal that stretches 22.5 MS in length with a series of high lows between that signify the position of each servo.
Does anyone have a good way to generate this PPM stream? I know the PWM ports will not work here right as they are designed to give a repetitive stream not one that needs to be changed constantly correct?
Any ideas here would be greatly appreciated. |
|
|
bungee-
Joined: 27 Jun 2007 Posts: 206
|
|
Posted: Thu Apr 30, 2009 12:11 pm |
|
|
You can do that with a code in a timer ISR |
|
|
StealthMicro
Joined: 10 Apr 2007 Posts: 17
|
|
Posted: Thu Apr 30, 2009 12:16 pm |
|
|
bungee- wrote: | You can do that with a code in a timer ISR |
Give me a little example and you will be a hero!
I plan to use a 18F4550 so that I can utilize the USB port for some other stuff I need to do as well.
I would greatly appreciate a little code snippet if someone has the time to do it. |
|
|
bungee-
Joined: 27 Jun 2007 Posts: 206
|
|
Posted: Thu Apr 30, 2009 2:25 pm |
|
|
Here is the code for driving 8 servos from the same PIC. You can rewrite the ISR for your need. Basically you will need to turn my parallel code to serial one ;)
Code: | #include <18F4550.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES HSPLL //High Speed Crystal/Resonator with PLL enabled
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES BORV20 //Brownout reset at 2.0V
#FUSES PUT //Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES NOPBADEN //PORTB pins are configured as digital I/O on RESET
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOCPB //No Boot Block code protection
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOLPT1OSC //Timer1 configured for higher power operation
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PLL12 //Divide By 12(48MHz oscillator input)
#FUSES CPUDIV1 //No System Clock Postscaler
#FUSES USBDIV //USB clock source comes from PLL divide by 2
#FUSES VREGEN //USB voltage regulator enabled
#FUSES ICPRT //ICPRT enabled
#use delay(clock=48000000)
// The code is written for servos to be on portB !!!
#use fast_io(B) // We will take care of port direction
int8 servo[8]; // Value where the servo should be
int1 pause=1; // Is this pause cycle
int8 pause_cycle,servo_cycle=0;
#int_TIMER2
void TIMER2_isr(void)
{
int8 _i;
if (!pause) //Are we in servo cycle
{
if (servo_cycle<=64) // First part of signal is allways 1ms long
{
Output_b(0xff);
servo_cycle++;
}
else
{
for (_i=0;_i<=8;_i++) //set the actual delay of servos
{
if ((servo[_i]+64)<=servo_cycle) output_bit(pin_b1+_i,0);
}
if (servo_cycle>=64) //End of servo cycle
{
servo_cycle=0;
pause=1;
}
}
servo_cycle++;
}
if (pause) //Are we in pause cycle
{
pause_cycle++;
if (pause_cycle==0) pause=0;
}
}
void setup()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DIV_BY_1,16,11);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
set_tris_b(0); //PortB is output
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
}
void main()
{
setup();
while (1)
{
delay_cycles(1);
}
} |
|
|
|
bungee-
Joined: 27 Jun 2007 Posts: 206
|
|
Posted: Thu Apr 30, 2009 2:33 pm |
|
|
I forgot to point out that there are only 64 positions per servo if you use this code. |
|
|
ricard0g0mes
Joined: 19 May 2009 Posts: 6
|
|
Posted: Tue Jul 07, 2009 6:52 am |
|
|
delay_cycles() is where? |
|
|
Ttelmah Guest
|
|
Posted: Tue Jul 07, 2009 8:13 am |
|
|
Standard compiler function.
It isn't actually dong anything. It just puts a single 'NOP' instruction. The work is all done in the ISR.
Best Wishes |
|
|
mbradley
Joined: 11 Jul 2009 Posts: 118 Location: California, USA
|
|
Posted: Sat Jul 11, 2009 11:26 pm |
|
|
I have done this many times, to make simple multi servo cyclers and setup tools so people don't have to disconnect their receivers.
Super simple, if this is all your pic is going to do:
This is not complete code, but give you a starting point.
Code: | #define pinPPM PIN_C2 |
Each servo[i] should be from 1100 to 1900,
extended would be 1000 to 2000.
1500 would be servo center, or 1520 for JR servos.
Code: | output_high(pinPPM);
while(true)
{
delay_ms(5);
for (i=0; i<10; i++)
{
output_low(pinPPM);
delay_us(servo[i]);
output_high(pinPPM);
delay_us(100);
}
} |
|
|
|
|