CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

PPM to PWM for RC receivers

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
noyz



Joined: 31 Jan 2009
Posts: 59

View user's profile Send private message

PPM to PWM for RC receivers
PostPosted: Sun May 31, 2009 11:23 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sun May 31, 2009 2:40 pm     Reply with quote

nobody can help me with some code ?
bungee-



Joined: 27 Jun 2007
Posts: 206

View user's profile Send private message

PostPosted: Sun May 31, 2009 4:05 pm     Reply with quote

First of all you would need the PIC with 4 PWM channels. Then everything else is simple Smile

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

View user's profile Send private message

PostPosted: Mon Jun 01, 2009 11:30 am     Reply with quote

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: 1934
Location: Norman, OK

View user's profile Send private message

PostPosted: Mon Jun 01, 2009 11:50 am     Reply with quote

A search of this forum using the word PWM turns up the following links:

http://www.ccsinfo.com/forum/viewtopic.php?t=37206
http://www.ccsinfo.com/forum/viewtopic.php?t=35191

The first link shows simple, well commented PWM code using an 18F4431 PIC and the second shows PWM with the the 16F88. Use the referenced info in the thread to find lots of info on PWM and PPM

Also see here:
http://www.embeddedrelated.com/usenet/embedded/show/57698-1.php

____________________________
Google and Forum Search are Your Friends!!
noyz



Joined: 31 Jan 2009
Posts: 59

View user's profile Send private message

PostPosted: Wed Feb 19, 2020 4:57 am     Reply with quote

Me answering to myself few years later Smile)


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();
   
}


Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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