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

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