AbstractBeliefs

Untitled

Jul 28th, 2011
128
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.48 KB | None | 0 0
  1. ///////////////////////////////////////
  2. //
  3. // A17 = Input PPM, PWM Out on D2-D7
  4. //
  5. ///////////////////////////////////////
  6.  
  7. #include <avr/io.h>
  8. #include <avr/interrupt.h>
  9. #include <util/delay.h>
  10.  
  11. #define width_500 ((F_CPU * 5) / 10000) //  calculates ticks for 0.5ms
  12. #define width_01 width_500 / 5          //  calculates ticks for 0.1ms
  13.  
  14. // pin and port renaming
  15.  
  16. #define LED_PIN 13
  17. #define in_port PORTK
  18. #define in_pinin PINK
  19. #define in_ddr DDRK
  20. #define in_pin 6
  21.  
  22. // global variables
  23.  
  24. bool PWM_ENABLE = false;
  25. byte pwm_values[8];
  26. static volatile unsigned long ovf_cnt; // overflow counter
  27. static volatile unsigned char chan_cnt; // channel counter
  28. static volatile unsigned char mask_cnt; // used to determin next pin
  29. static volatile unsigned int chan_width[8]; // stores pulse width in clock ticks
  30. static volatile unsigned int chan_width_temp[8];
  31. static volatile unsigned int last_capt; // time of last capture, used to find difference
  32. static volatile unsigned char data_ready; // 1 if data is good, 0 if transmitter is off
  33. static volatile unsigned char next_mask; // next port mask to apply
  34.  
  35. // input capture interrupt vector
  36. ISR(TIMER1_CAPT_vect)
  37. {
  38.     mask_cnt++; // next pin
  39.  
  40.     unsigned long t_ovf = ovf_cnt; // store overflow counter in case another overflow occurs during interrupt
  41.     ovf_cnt = 0;
  42.  
  43.     unsigned long t_icr = ICR1; // convert to unsigned long
  44.  
  45.     // calculate total time using overflows and time difference
  46.     unsigned long t = ((t_icr | 0x10000) - last_capt) & 0xFFFF;
  47.     if(t_icr < last_capt)
  48.     {
  49.         t_ovf--;
  50.     }
  51.     t += 0x10000 * t_ovf;
  52.     last_capt = ICR1;
  53.  
  54.     // if pulse is longer than 3ms, then it's a sync pulse
  55.     if(t > width_500 * 6)
  56.     {
  57.         chan_cnt = 0;
  58.         if(data_ready == 0)
  59.         {
  60.             data_ready = 1;
  61.         }
  62.     }
  63.     else // if pulse is shorter than 3ms, then it's a servo pulse
  64.     {
  65.         chan_width[chan_cnt] = t; // store time
  66.         chan_width_temp[0] = chan_width[0]; chan_width_temp[1] = chan_width[1]; chan_width_temp[2] = chan_width[2]; chan_width_temp[3] = chan_width[3];
  67.         chan_width_temp[4] = chan_width[4]; chan_width_temp[5] = chan_width[5]; chan_width_temp[6] = chan_width[6]; chan_width_temp[7] = chan_width[7];
  68.         chan_cnt++; // next channel
  69.         if(chan_cnt >= 4 && data_ready != 0) // last channel, data is now good, reset to first pin
  70.         {
  71.             data_ready = 2;
  72.             mask_cnt = 0;
  73.         }
  74.     }
  75. }
  76.  
  77. // timer overflow interrupt vector
  78. ISR(TIMER1_OVF_vect)
  79. {
  80.     ovf_cnt++;
  81.     if(ovf_cnt >= 7) // if too many, then transmitter is missing
  82.     {
  83.         data_ready = 0;
  84.     }
  85. }
  86.  
  87. void setup(){
  88.     // initialize variables
  89.  
  90.     ovf_cnt = 0;
  91.     chan_cnt = 0;
  92.     mask_cnt = 0;
  93.     data_ready = 0;
  94.  
  95.     MCUCR |= _BV(PUD); // no pull-ups
  96.  
  97.     // initialize ports
  98.  
  99.     in_ddr |= _BV(5) | _BV(4);
  100.     in_ddr &= 0xFF ^ _BV(in_pin);
  101.  
  102.     // initialize timer
  103.  
  104.     TCCR1B = 1 | _BV(ICES1); // start timer, input capture on rising edge
  105.     TIMSK1 = _BV(TOIE1) | _BV(ICIE1); // enable interrupts
  106.  
  107.     sei(); // enable global interrupts
  108. }
  109.  
  110. void loop(){
  111.     _delay_ms(10);
  112.        
  113.     if(data_ready == 2){
  114.         // enable output if data is good, light LED
  115.         digitalWrite(LED_PIN, HIGH);
  116.         PWM_ENABLE = true;
  117.     }
  118.     else{
  119.         // disable output if transmitter is missing, LED off
  120.         digitalWrite(LED_PIN, LOW);
  121.         PWM_ENABLE = false;
  122.     }
  123.    
  124.     if (PWM_ENABLE){
  125.         for (byte i = 0; i <= 7; i++){
  126.             // min servo = 10 * width 0.1, max = 20 * width 0.1
  127.             analogWrite((2 + i), ((( chan_width_temp[i] * width_01) / (( 20 * width_01) - (10 * width_01)) ) * 255));
  128.         }
  129.     }
  130.    
  131.     if (!PWM_ENABLE){
  132.         for (byte i = 0; i <= 7; i++){
  133.             analogWrite((2+i), 0);
  134.         }
  135.     }
  136. }
Advertisement
Add Comment
Please, Sign In to add comment