code:ground_control
This is an old revision of the document!
Table of Contents
Input capture based version
volatile u08 counter; //globals volatile s16 diff; ISR(TIMER1_CAPT_vect) { static u16 start; if(TCCR1B|0x40) //start of a pulse { TCCR1B&=~0x40; //set to trigger on falling edge start=ICP1; //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=ICP1-start; //set the global volatile u16 diff if(start>ICP1) //our pwm pulse spans a timer overflow { diff+=TOP_COUNT; } if(diff>PULSE_MIN && diff<PULSE_MAX) //test against criterion { if(counter&0xEF<30) //30 consecutive pulses { counter+=3; //the 20ms timer1 overflow subtracts 2 from counter } } else { counter&=0xEF; //set the last 7 bits to zero } } } }
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 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.
ground.h
#define pwm_record_factor ((float)F_CPU*0.0005/256.0) //500us #define lower_pwm_bound (u08)(pwm_record_factor*4.25) //valid pwm limits #define upper_pwm_bound (u08)(pwm_record_factor*1.75) #define GROUND #define check_input PORTC & 0x01 #define copy_pwm PORTB=(PORTB & ~0x03)|(PORTC & 0x03); //move PORTC 0,1 to PORTB 0,1 void enable_ground_control(); void disable_ground_control();
ground.c
#include "main.h" #include "ground.h" volatile u08 pwm_counter=0x00; volatile u08 pwm_period=0x00; 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; if(check_input) //start of pulse { TCNT0=0x00; //reset timer at start of C.0 pulse pulse=TRUE; } else if(pulse) //end of C.0 pulse { pulse=FALSE; if(TCNT0>upper_pwm_bound && TCNT0<lower_pwm_bound) //valid pwm { if(pwm_counter<0x0A) { pwm_counter++; } else { pwm_period=TCNT0; //store the pwm period, the kalman filter will like it! } } else { sbi(TCCR1A,COM1A1); //reenable the PWM pwm_counter=0x00; } } } ISR(TIMER0_OVF_vect) { sbi(TCCR1A,COM1A1); //reenable the PWM pwm_counter=0x00; //with valid pwm, there will be no overflows } void enable_ground_control() { sbi(TIMSK0, TOIE0); //Timer0 interrupts on sbi(PCICR, PCIE1); //Pin change interrupts on } void disable_ground_control() { cbi(TIMSK0, TOIE0); //Timer0 interrupts on cbi(PCICR, PCIE1); pwm_counter=0x00; //Pin change interrupts on }
code/ground_control.1225343932.txt.gz · Last modified: 2008/10/30 05:18 by laurenceb