UKHAS Wiki

UK High Altitude Society

User Tools

Site Tools


code:ground_control

This is an old revision of the document!


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.

#define enable_ground_control	TIMSK1|=(1<<ICIE1)			//enables the input capture interrupt
#define disable_ground_control	TIMSK1&=~(1<<ICIE1)			//disables input capture interrupt

Main code

extern volatile u08 counter;						//globals
extern 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 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

#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.1225377492.txt.gz ยท Last modified: 2008/10/30 14:38 by rharrison1971