UKHAS Wiki

UK High Altitude Society

User Tools

Site Tools


code:ground_control

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
code:ground_control [2008/05/01 00:07]
laurenceb
code:ground_control [2008/11/13 09:50] (current)
laurenceb
Line 1: Line 1:
- This AVR code constantly checks the PWM input for pulse lenght. If a stream of 10 pulses are detected that match the criterion, the input PWM in routed to the output. A single failing PWM pulse will cause control to revert back to internal guidance. Useful for UAVs, allowing control to be regained from the ground in the event of a faulty control algorthym.+===== Input capture based version ===== 
 +This uses the input capture function on timer1 (atmega168). The ICNC1 bit in the TCCR1B register need to be set to enable oversampling to give more noise tolerance. A second function running approx every 20ms is needed to decrement counter by two and check if counter>​=30. If this is the case there is a valid pwm stream and the diff variable can be used to set the pwm output.  
 + 
 +==== Header ==== 
 +<code c> 
 +void enable_ground_control();​ //​enables the input capture interrupt 
 +void disable_ground_control();​ //​disables input capture interrupt 
 +#define PULSE_MIN (s16)(0.001*(float)F_CPU/​16.0) //​pwm must be in the range 1 to 2 ms 
 +#define PULSE_MAX (s16)(0.002*(float)F_CPU/​16.0) //​due to the bit shift we divide by 16 
 +#define GROUND_LED_ON PORTD|=(1<<​3) 
 +#define GROUND_LED_OFF PORTD&​=~(1<<​3) 
 +#define GROUND_LED_SET PORTD&​(1<<​3) 
 +void run_ground_control();​ 
 +</​code>​ 
 + 
 + 
 +====Main code=== 
 + 
 +<code c> 
 +#ifdef GROUND 
 +#include "​main.h"​ 
 +extern volatile u08 counter;​ //​globals 
 +extern volatile u16 diff; 
 +  
 +  
 +ISR(TIMER1_CAPT_vect) 
 +
 + static u16 start;  
 + if(TCCR1B&​0x40) //​start of a pulse 
 +
 + TCCR1B&​=~0x40;​ //​set to trigger on falling edge 
 + start=ICR1;​ //​record start of the pulse 
 +
 + else 
 +
 + TCCR1B|=0x40;​ //​set to trigger on rising edge 
 + if(!(counter&​0x80)) //​the lock bit isn't set, so we are free to run 
 +
 + diff=ICR1;​ //​set the global volatile s16 diff 
 + if(start>​diff) //​our pwm pulse spans a timer overflow 
 +
 + diff+=TOP_COUNT;​ 
 +
 + diff-=start;​ 
 + if(diff>​PULSE_MIN && diff<​PULSE_MAX) //​test against criterion 
 +
 + if((counter&​(~0x80))<​30) //​30 consecutive ​ pulses 
 + {  
 + counter+=3;​ //​the 20ms timer1 overflow subtracts 2 from counter 
 +
 +
 + else 
 +
 + counter&​=0x80;​ //​set the last 7 bits to zero 
 +
 +
 +
 +
 + 
 +void run_ground_control() 
 +
 + if((~0x80&​counter)>​=28) 
 +
 + counter|=0x80;​ //​lock the diff variable using the counter flag bit 
 + OCR1B=diff;​ 
 + counter&​=~0x80;​ 
 + GROUND_LED_ON;​ 
 +
 + else 
 +
 + GROUND_LED_OFF;​ 
 +
 + if(counter&​~0x80) //​if the counter variable >0, decrement by 2 
 + counter-=2;​ 
 +
 + 
 +void enable_ground_control() 
 +
 + TIMSK1|=(1<<​ICIE1);​ 
 + counter=0;​ 
 +
 + 
 +void disable_ground_control() 
 +
 + TIMSK1&​=~(1<<​ICIE1);​ 
 + GROUND_LED_OFF;​ 
 + counter=0;​ 
 + diff=0;  
 +
 +#endif 
 +</​code>​ 
 + 
 + 
 + 
 +===== Pin change based version ===== 
 + 
 + 
 + This AVR code constantly checks the PWM input for pulse lenght. If a stream of 10 pulses are detected that match the criterion, the input PWM is routed to the output. A single failing PWM pulse will cause control to revert back to internal guidance. Useful for UAVs, allowing control to be regained from the ground in the event of a faulty control algorthym.
  
 ===== ground.h ===== ===== ground.h =====
Line 12: Line 109:
 void disable_ground_control();​ void disable_ground_control();​
 </​code>​ </​code>​
- 
  
 ===== ground.c ===== ===== ground.c =====
  
-<code c> +<code c>#​include "​main.h"​
-#include "​main.h"​+
 #include "​ground.h"​ #include "​ground.h"​
 + 
 volatile u08 pwm_counter=0x00;​ volatile u08 pwm_counter=0x00;​
 volatile u08 pwm_period=0x00;​ volatile u08 pwm_period=0x00;​
 + 
 ISR(PCINT1_vect) ISR(PCINT1_vect)
 { {
 + if(pwm_counter==0x0A) //​a stream of valid pwm
 + {
 + cbi(TCCR1A,​COM1A1);​ //​turn off PWM output to servo
 + copy_pwm;
 + }
  static u08 pulse;  static u08 pulse;
- if(PORTC & 0x01) //start of C.0 pulse+ if(check_input) //start of pulse
  {  {
  TCNT0=0x00;​ //​reset timer at start of C.0 pulse  TCNT0=0x00;​ //​reset timer at start of C.0 pulse
Line 50: Line 150:
  pwm_counter=0x00;​  pwm_counter=0x00;​
  }  }
- } 
- if(pwm_counter==0x0A) //​a stream of valid pwm 
- { 
- cbi(TCCR1A,​COM1A1);​ //​turn off PWM output to servo 
- PORTB=(PORTB & ~0x03)|(PORTC & 0x03);​ //​move PORTC 0,1 to PORTB 0,1 
  }  }
 } }
 + 
 ISR(TIMER0_OVF_vect) ISR(TIMER0_OVF_vect)
 { {
Line 63: Line 158:
  pwm_counter=0x00;​ //​with valid pwm, there will be no overflows  pwm_counter=0x00;​ //​with valid pwm, there will be no overflows
 } }
 + 
 void enable_ground_control() void enable_ground_control()
 { {
Line 69: Line 164:
  sbi(PCICR, PCIE1);​ //​Pin change interrupts on  sbi(PCICR, PCIE1);​ //​Pin change interrupts on
 } }
 + 
 void disable_ground_control() void disable_ground_control()
 { {
code/ground_control.1209600474.txt.gz · Last modified: 2008/07/19 23:31 (external edit)