|
|
View previous topic :: View next topic |
Author |
Message |
noyz
Joined: 31 Jan 2009 Posts: 59
|
PPM to PWM for RC receivers |
Posted: Sun May 31, 2009 11:23 am |
|
|
I have a receiver with 6 channels, a remote control with 4 channels so I will only use the first 4 channels from the receiver.
I want to build a code where I'm using only one pic to decode the PPM from every channel from the receiver and send PWM to another pin to control a motor. |
|
|
noyz
Joined: 31 Jan 2009 Posts: 59
|
|
Posted: Sun May 31, 2009 2:40 pm |
|
|
nobody can help me with some code ? |
|
|
bungee-
Joined: 27 Jun 2007 Posts: 206
|
|
Posted: Sun May 31, 2009 4:05 pm |
|
|
First of all you would need the PIC with 4 PWM channels. Then everything else is simple
You will be monitoring four inputs and you will count the time interval for each channel. When pulse is 1ms long then you have 0% PWM duty and when the pulse is 2ms long you'll have 100% PWM duty.
This is what you need to program. But if you want somebody else to code it for you, then you are looking at the wrong place. |
|
|
noyz
Joined: 31 Jan 2009 Posts: 59
|
|
Posted: Mon Jun 01, 2009 11:30 am |
|
|
Easy to say. Hard to put in code. Could you give me an example of ppm to PWM only for one channel for pic16f88 or 628 ?
The signal is already splitted to channels so I don't have to count if this is the first signal / channel.
The only thing to do is measure the high duty cycle and put an pwm output.
I'm quite a noobie and I didn't work before with pwm, and for ppm do I need a comparator or what ?
Take a look here
http://www.fmx.dk/projects/mc_pic16/rc_speedcontroller.html
The ppm signal is explained, and the pwm, it has a hex code for 16f84 but didn't work.
And I would like to have some C code to understand what's happening there. |
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1933 Location: Norman, OK
|
|
|
noyz
Joined: 31 Jan 2009 Posts: 59
|
|
Posted: Wed Feb 19, 2020 4:57 am |
|
|
Me answering to myself few years later )
PIC 16F648 - INT OSC 4 MHZ
PWM FREQ 1 KHZ
PPM signal 1000 - 1500 - 2000 ms (Full Back,Neutral, Full FWD)
I have an N Mosfet and a relay for changing the Direction of the motor.
Code: |
#include <16F648A.h>
#FUSES NOWDT //Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOMCLR //do not reset when mclr is floating
//#use delay(int=8000000,RESTART_WDT)
#use delay(int=4000000,RESTART_WDT)
//#use FIXED_IO( B_outputs=PIN_B3,PIN_B2,PIN_B5 )
//#use rs232(baud=9600,parity=N,xmit=PIN_B2,rcv=PIN_B1,bits=9,stream=PORT1,restart_wdt)
#include <float.h>
int1 ppm_signal=0;
int16 timer_1_OverFlows=-1;
int16 ppm_length = 0;
#int_RB
void RB_isr(void) {
int1 currentSignal = input(PIN_B4);
if (currentSignal == 0 && ppm_signal==1){
timer_1_OverFlows = 0;
set_timer1(0);
ppm_signal = currentSignal;
} else if(currentSignal == 1 && ppm_signal==0){
ppm_length = get_timer1();
ppm_signal = currentSignal;
}
}
#int_TIMER1
void TIMER1_isr(void) {
timer_1_OverFlows++;
if(timer_1_OverFlows > 3){ // 3x 65 ms , then we need to reset pwm output
ppm_length = 0;
}
}
//4Mhz
//(249+1) * 4 = 1000
//inverted PWM
// int16 PWM_MAX_DUTY = (int16) 0;
// int16 PWM_MIN_DUTY = (int16) 1000;
//NORMAL_PWM
int16 PWM_MAX_DUTY = (int16) 624;
int16 PWM_MIN_DUTY = (int16) 0;
int16 PPM_BACK = (int16)1080;
int16 PPM_MIDDLE = (int16)1550;
int16 PPM_FWD = (int16)2000;
int16 PPM_THRESHOLD = (int16) 90;
void pwm_test(int16 ms){
int16 duty = PWM_MIN_DUTY;
if (PWM_MIN_DUTY < PWM_MAX_DUTY){
while (true){
output_low(PIN_B5);
restart_wdt();
set_pwm1_duty((int16)duty);
// printf("pwm=%Lu \r\n",duty);
delay_ms(ms);
duty++;
if (duty >= PWM_MAX_DUTY) {
while (true){
output_high(PIN_B5);
restart_wdt();
set_pwm1_duty((int16)duty);
// printf("pwm_=%Lu \r\n",duty);
delay_ms(ms);
duty--;
if (duty <= PWM_MIN_DUTY) break;
}
}
}
} else {
while (true){
output_high(PIN_B5);
restart_wdt();
set_pwm1_duty((int16)duty);
//printf("pwmB=%Lu \r\n",duty);
delay_ms(ms);
duty--;
if (duty <= PWM_MAX_DUTY) {
while (true){
output_low(PIN_B5);
restart_wdt();
set_pwm1_duty((int16)duty);
// printf("pwmB_=%Lu \r\n",duty);
delay_ms(ms);
duty++;
if (duty >= PWM_MIN_DUTY) break;
}
}
}
}
}
int16 computeDutyCyclePWM(int16 x,int16 x1, int16 x2,int16 y1, int16 y2){
//y = (y2-y1)*(x-x1)/(x2-x1) + y1;
float32 ppm_diff = (float32) y2 - y1;
float32 pd = (float32)x - x1;
float32 pwm_diff = (float32)x2 - x1;
//return ((float32) ppm_diff * (float32) pd / (float32) pwm_diff) + (float32) y1;
return ((float32) pd / (float32) pwm_diff) * (float32) ppm_diff + (float32)y1;
}
void ppm_to_pwm(){
int16 duty = PWM_MIN_DUTY;
int relay = PIN_B5;
while(TRUE){
restart_wdt();
int16 ppm = ppm_length;
int16 ovf= timer_1_OverFlows;
//printf(" =%Ld= ow=%Ld \r\n",ppm,ovf);
if (ppm < PPM_BACK - PPM_THRESHOLD
|| (ppm > PPM_MIDDLE - PPM_THRESHOLD && ppm < PPM_MIDDLE + PPM_THRESHOLD) ){
duty = PWM_MIN_DUTY;
restart_wdt();
//printf("u duty=%Lu \r\n", PWM_MIN_DUTY);
} else if (ppm > PPM_BACK - PPM_THRESHOLD && ppm < PPM_MIDDLE - PPM_THRESHOLD){
output_high(relay);
if (ppm < PPM_BACK + PPM_THRESHOLD){
duty = PWM_MAX_DUTY;
//printf("bl duty=%Lu \r\n",PWM_MAX_DUTY);
} else {
duty = computeDutyCyclePWM(ppm,PPM_BACK,PPM_MIDDLE,PWM_MAX_DUTY,PWM_MIN_DUTY);
//printf("b duty=%Ld \r\n", duty);
}
restart_wdt();
} else if (ppm > PPM_MIDDLE + PPM_THRESHOLD && ppm < PPM_FWD + PPM_THRESHOLD){
output_low(relay);
if (ppm > PPM_FWD - PPM_THRESHOLD){
duty = PWM_MAX_DUTY;
// printf("fl duty=%Lu \r\n", PWM_MAX_DUTY);
} else{
duty = computeDutyCyclePWM(ppm,PPM_MIDDLE,PPM_FWD,PWM_MIN_DUTY,PWM_MAX_DUTY);
// printf("f duty=%Lu \r\n", duty);
}
restart_wdt();
}
//printf ("duty= %Ld\r\n",duty);
set_pwm1_duty(duty);
}
}
void main()
{
//port_B_pullups(0xFF);
//4Mhz
//setup_wdt(WDT_36MS); // 36 ms reset;
//4Mhz
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); //65.5 ms overflow /1ms resolution
// Crystal Frequency
//PWM Freq = -----------------------------------------
// (PR2 + 1) * (Timer2 Prescaler) * 4
//The Timer2 prescaler can have values of 1, 4, or 16.
//PR2 can have a value from 0 to 255.
//4Mhz
//setup_timer_2(T2_DIV_BY_4,249,1); //1.0 ms overflow, 1.0 ms interrupt pwm = 1khz / duty_max=1000
//setup_timer_2(T2_DIV_BY_16,124,1); //pwm = 500hz / duty_max=500
setup_timer_2(T2_DIV_BY_16,155,1); //pwm = 400hz / duty_max=624
//setup_timer_2(T2_DIV_BY_16,207,1); //pwm = 300hz / duty_max=832
//Max Duty cycle formula / 10 bit pwm
// max_duty = (PR2 +1 ) * 4 ???
setup_comparator(NC_NC_NC_NC);
setup_ccp1(CCP_PWM);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
output_low(PIN_B5);
set_pwm1_duty(PWM_MIN_DUTY);
//pwm_test(50);
enable_interrupts(INT_RB);
ppm_to_pwm();
}
|
|
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|