Exemplo n.º 1
0
void CalibrateGyrosSlow(void)
{
	uint8_t axis;
	uint8_t Gyro_seconds = 0;
	uint8_t Gyro_TCNT2 = 0;
	uint16_t Gyro_timeout = 0;
	bool	Gyros_Stable = false;
	float 	GyroSmooth[NUMBEROFAXIS];

	// Force recalculation
	for (axis = 0; axis < NUMBEROFAXIS; axis++) 
	{
// Optimise starting point for each board
#ifdef KK21
		GyroSmooth[axis] = 0;
#else
		GyroSmooth[axis] = 500;
#endif
	}

	// Wait until gyros stable. Timeout after 5 seconds
	while (!Gyros_Stable && (Gyro_seconds <= 5))
	{
		// Update status timeout
		Gyro_timeout += (uint8_t) (TCNT2 - Gyro_TCNT2);
		Gyro_TCNT2 = TCNT2;

		// Count elapsed seconds
		if (Gyro_timeout > SECOND_TIMER)
		{
			Gyro_seconds++;
			Gyro_timeout = 0;
		}

		get_raw_gyros();

		// Calculate very long rolling average
		for (axis = 0; axis < NUMBEROFAXIS; axis++) 
		{
			GyroSmooth[axis] = ((GyroSmooth[axis] * (float)999) + (float)(gyroADC[axis])) / (float)1000;
			Config.gyroZero[axis] = (int16_t)GyroSmooth[axis];
		}

		// Check for movement
		ReadGyros();

		if ((gyroADC[ROLL] > GYROS_STABLE) || (gyroADC[ROLL] < -GYROS_STABLE) ||
			(gyroADC[PITCH] > GYROS_STABLE) || (gyroADC[PITCH] < -GYROS_STABLE) ||
			(gyroADC[YAW] > GYROS_STABLE) || (gyroADC[YAW] < -GYROS_STABLE))
		{
			Gyros_Stable = false;
		}
		else
		{
			Gyros_Stable = true;
		}
	}
}
Exemplo n.º 2
0
void Display_sensors(void)
{
	while(BUTTON1 != 0)
	{
		if (BUTTON4 == 0)
		{
			_delay_ms(500);
			CalibrateAcc();
			CalibrateGyros();
		}

		if (BUTTON3 == 0)
		{
			_delay_ms(500);
			CalibrateInvAcc();
		}

		ReadGyros();
		ReadAcc();

		LCD_Display_Text(26,(prog_uchar*)Verdana8,0,0); 	// Gyro
		LCD_Display_Text(30,(prog_uchar*)Verdana8,70,0); 	// Acc
		LCD_Display_Text(27,(prog_uchar*)Verdana8,10,15);	// X
		LCD_Display_Text(28,(prog_uchar*)Verdana8,10,25);	// Y
		LCD_Display_Text(29,(prog_uchar*)Verdana8,10,35);	// Z

		mugui_lcd_puts(itoa(gyroADC[PITCH],pBuffer,10),(prog_uchar*)Verdana8,30,15);
		mugui_lcd_puts(itoa(gyroADC[ROLL],pBuffer,10),(prog_uchar*)Verdana8,30,25);
		mugui_lcd_puts(itoa(gyroADC[YAW],pBuffer,10),(prog_uchar*)Verdana8,30,35);
		mugui_lcd_puts(itoa(accADC[PITCH],pBuffer,10),(prog_uchar*)Verdana8,80,15);
		mugui_lcd_puts(itoa(accADC[ROLL],pBuffer,10),(prog_uchar*)Verdana8,80,25);
		mugui_lcd_puts(itoa(accADC[YAW],pBuffer,10),(prog_uchar*)Verdana8,80,35);

		// Print bottom markers
		LCD_Display_Text(12, (prog_uchar*)Wingdings, 0, 57); 	// Left
		LCD_Display_Text(157, (prog_uchar*)Verdana8, 75, 55); 	// Inverted Calibrate
		LCD_Display_Text(60, (prog_uchar*)Verdana8, 108, 55); 	// Calibrate

		// Update buffer
		write_buffer(buffer,1);
		clear_buffer(buffer);
		_delay_ms(100);
	}
}
Exemplo n.º 3
0
void init(void)
{
	//***********************************************************
	// I/O setup
	//***********************************************************

	// Set port directions
	DDRA		= 0x00;		// Port A
	DDRB		= 0x0A;		// Port B
	DDRC		= 0xFF;		// Port C
	DDRD		= 0xF2;		// Port D

	MOTORS		= 0;		// Hold all PWM outputs low to stop glitches

	// Preset I/O pins
	LED1 		= 0;		// LED1 off
	LVA 		= 0; 		// LVA alarm OFF
	LCD_CSI		= 1;
	LCD_SCL		= 1;
	LCD_RES		= 1;

	// Set/clear pull-ups (1 = set, 0 = clear)
	PINB		= 0xF5;		// Set PB pull-ups
	PIND		= 0x0D;		// Set PD pull-ups

	//***********************************************************
	// Timers
	//***********************************************************
	// Timer0 (8bit) - run @ 20MHz (50ns) - max 12.8us
	// Fast timer for small, precise interval timing
	TCCR0A = 0;							// Normal operation
	TCCR0B = (1 << CS00);				// Clk / 1 = 20MHz = 50ns
	TIMSK0 = 0; 						// No interrupts

	// Timer1 (16bit) - run @ 2.5MHz (400ns) - max 26.2ms
	// Used to measure Rx Signals & control ESC/servo output rate
	TCCR1A = 0;
	TCCR1B = (1 << CS11);				// Clk/8 = 2.5MHz

	// Timer2 8bit - run @ 20MHz / 1024 = 19.531kHz or 51.2us - max 13.1ms
	// Used to time arm/disarm intervals
	TCCR2A = 0;	
	TCCR2B = 0x07;						// Clk/1024 = 19.531kHz
	TIMSK2 = 0;
	TIFR2 = 0;
	TCNT2 = 0;							// Reset counter

	//***********************************************************
	// Interrupts and pin function setup
	//***********************************************************

	// Pin change interrupt enables PCINT1, PCINT2 and PCINT3 (Throttle, Aux and CPPM input)
	PCICR  = 0x0A;						// PCINT8  to PCINT15 (PCINT1 group - AUX)
										// PCINT24 to PCINT31 (PCINT3 group - THR)
	PCMSK1 |= (1 << PCINT8);			// PB0 (Aux pin change mask)
	PCMSK3 |= (1 << PCINT24);			// PD0 (Throttle pin change mask)
	PCIFR  = 0x0F;						// Clear PCIF0 interrupt flag 
										// Clear PCIF1 interrupt flag 
										// Clear PCIF2 interrupt flag 
										// Clear PCIF3 interrupt flag 

	// External interrupts INT0 (Elevator) and INT1 (Aileron) and INT2 (Rudder)
	EIMSK = 0x07;						// Enable INT0 (Elevator input)
										// Enable INT1 (Aileron input)
										// Enable INT2 (Rudder/CPPM input)
	EICRA = 0x15;						// Any change INT0
										// Any change INT1
										// Any change INT2
	EIFR  = 0x07; 						// Clear INT0 interrupt flag (Elevator)
										// Clear INT1 interrupt flag (Aileron)
										// Clear INT2 interrupt flag (Rudder/CPPM)

	//***********************************************************

	RC_Lock = false;						// Preset important flags
	Failsafe = false;
	AutoLevel = false;
	Stability = false;
	FirstTimeIMU = true;

	// Button acceleration
	button_multiplier = 1;

	Initial_EEPROM_Config_Load();			// Loads config at start-up 
	UpdateLimits();							// Update travel limts	
	UpdateIMUvalues();						// Update IMU factors
	Init_ADC();

	// Flash LED
	LED1 = 1;
	_delay_ms(150);
	LED1 = 0;

	// Initialise the GLCD
	st7565_init();
	st7565_command(CMD_DISPLAY_ON); 		// Check (AF)
	st7565_command(CMD_SET_ALLPTS_NORMAL);	// Check (A4)
	st7565_set_brightness(0x26);
	write_buffer(buffer,0);					// Display logo
	_delay_ms(1000);
	clear_buffer(buffer);					// Clear
	write_buffer(buffer,1);
	st7565_command(CMD_SET_COM_NORMAL); 	// For text
	clear_buffer(buffer);					// Clear

	// Reset I-terms
	IntegralGyro[ROLL] = 0;	
	IntegralGyro[PITCH] = 0;
	IntegralGyro[YAW] = 0;

	// Calibrate gyros, hopefully after motion minimised
	CalibrateGyros();			


	//***********************************************************
	//* Reload eeprom settings if all buttons are pressed 
	//***********************************************************

	if ((PINB & 0xf0) == 0)
	{

		LCD_Display_Text(1,(prog_uchar*)Verdana14,15,10);
		LCD_Display_Text(2,(prog_uchar*)Verdana14,31,30);

		write_buffer(buffer,1);
		clear_buffer(buffer);				// Clear
		Set_EEPROM_Default_Config();
		Save_Config_to_EEPROM();
	}

	//***********************************************************

	sei();									// Enable global Interrupts 

	// Check to see that gyros are stable
	ReadGyros();

	if ((gyroADC[ROLL] > GYROS_STABLE) || (gyroADC[ROLL] < -GYROS_STABLE) ||
	 	(gyroADC[PITCH] > GYROS_STABLE) || (gyroADC[PITCH] < -GYROS_STABLE) ||
		(gyroADC[YAW] > GYROS_STABLE) || (gyroADC[YAW] < -GYROS_STABLE))
	{
		General_error |= (1 << SENSOR_ERROR); 	// Set sensor error bit
	}

	// Check to see that throttle is low if in CPPM mode if RC detected
	// Don't bother if in CamStab mode
	_delay_ms(100);
	if ((Config.RxMode == CPPM_MODE) && RC_Lock && (Config.CamStab == OFF))
	{
		RxGetChannels();
		if (RCinputs[THROTTLE] > 300)
		{
			General_error |= (1 << THROTTLE_HIGH); 	// Set throttle high error bit
		}
	}

	// Beep that all sensors have been handled
	menu_beep(1);

} // init()
Exemplo n.º 4
0
void Display_sensors(void)
{
	bool	first_time = true;
		
	clear_buffer(buffer);
		
	// While BACK not pressed
	while(BUTTON1 != 0)
	{
		ReadGyros();
		ReadAcc();

		LCD_Display_Text(26,(const unsigned char*)Verdana8,37,0); 	// Gyro
		LCD_Display_Text(30,(const unsigned char*)Verdana8,77,0); 	// Acc
		//
		LCD_Display_Text(27,(const unsigned char*)Verdana8,5,13);	// Roll
		LCD_Display_Text(28,(const unsigned char*)Verdana8,5,23);	// Pitch
		LCD_Display_Text(29,(const unsigned char*)Verdana8,5,33);	// Yaw/Z
		//
		mugui_lcd_puts(itoa(gyroADC[ROLL],pBuffer,10),(const unsigned char*)Verdana8,40,13);
		mugui_lcd_puts(itoa(gyroADC[PITCH],pBuffer,10),(const unsigned char*)Verdana8,40,23);
		mugui_lcd_puts(itoa(gyroADC[YAW],pBuffer,10),(const unsigned char*)Verdana8,40,33);
		mugui_lcd_puts(itoa(accADC[ROLL],pBuffer,10),(const unsigned char*)Verdana8,80,13);
		mugui_lcd_puts(itoa(accADC[PITCH],pBuffer,10),(const unsigned char*)Verdana8,80,23);
		mugui_lcd_puts(itoa(accADC[YAW],pBuffer,10),(const unsigned char*)Verdana8,80,33);

		// Print bottom markers
		LCD_Display_Text(12, (const unsigned char*)Wingdings, 0, 57); 	// Left
		LCD_Display_Text(37, (const unsigned char*)Verdana8, 75, 55); 	// Inverted Calibrate
		LCD_Display_Text(60, (const unsigned char*)Verdana8, 108, 55); 	// Calibrate

		// Update buffer
		write_buffer(buffer);
		clear_buffer(buffer);

		if (first_time)
		{
			// Wait until finger off button
			Wait_BUTTON4();
			
			first_time = false;
		}
		
		// Normal calibrate button pressed
		if (BUTTON4 == 0)
		{
			// Wait until finger off button
			Wait_BUTTON4();
			
			// Pause until steady
			_delay_ms(250);
			
			// Calibrate sensors
			CalibrateGyrosFast();
			CalibrateAcc(NORMAL);
		}

		// Inverted calibrate button pressed
		if (BUTTON3 == 0)
		{
			// Wait until button snap dissipated
			_delay_ms(250);
			CalibrateAcc(REVERSED);
		}
	}
}
Exemplo n.º 5
0
void init(void)
{
	//***********************************************************
	// I/O setup
	//***********************************************************
	// Set port directions
	// KK2.0 and KK2.1 are different
#ifdef KK21
	DDRA		= 0x30;		// Port A
	DDRC		= 0xFC;		// Port C
#else
	DDRA		= 0x00;		// Port A
	DDRC		= 0xFF;		// Port C
#endif
	DDRB		= 0x0A;		// Port B
	DDRD		= 0xF2;		// Port D

	// Hold all PWM outputs low to stop glitches
	// M5 and M6 are on PortA for KK2.1
	MOTORS		= 0;
	M5			= 0;
	M6			= 0;		

	// Preset I/O pins
	LED1 		= 0;		// LED1 off
	LVA 		= 0; 		// LVA alarm OFF
	LCD_SCL		= 1;		// GLCD clock high

	// Set/clear pull-ups (1 = set, 0 = clear)
	PINB		= 0xF5;		// Set PB pull-ups
	PIND		= 0x0C;		// Set PD pull-ups (Don't pull up RX yet)

	//***********************************************************
	// Spektrum receiver binding
	//***********************************************************

	_delay_ms(63);				// Pause while satellite wakes up	
								// and pull-ups have time to rise.
								// Tweak until bind pulses about 68ms after power-up

	// Bind as master if ONLY button 4 pressed
	if ((PINB & 0xf0) == 0xE0)
	{
		DDRD		= 0xF3;		// Switch PD0 to output
		bind_master();
	}

	DDRD		= 0xF2;			// Reset Port D directions

	// Set/clear pull-ups (1 = set, 0 = clear)
	PIND		= 0x0D;			// Set PD pull-ups (now pull up RX as well)

	//***********************************************************
	// Timers
	//***********************************************************
	// Timer0 (8bit) - run @ 20MHz (50ns) - max 12.8us
	// Fast timer for small, precise interval timing
	TCCR0A = 0;								// Normal operation
	TCCR0B = (1 << CS00);					// Clk / 1 = 20MHz = 50ns
	TIMSK0 = 0; 							// No interrupts

	// Timer1 (16bit) - run @ 2.5MHz (400ns) - max 26.2ms
	// Used to measure Rx Signals & control ESC/servo output rate
	TCCR1A = 0;
	TCCR1B = (1 << CS11);					// Clk/8 = 2.5MHz

	// Timer2 8bit - run @ 20MHz / 1024 = 19.531kHz or 51.2us - max 13.1ms
	// Used to time arm/disarm intervals
	TCCR2A = 0;	
	TCCR2B = 0x07;							// Clk/1024 = 19.531kHz
	TIMSK2 = 0;
	TIFR2 = 0;
	TCNT2 = 0;								// Reset counter

	//***********************************************************
	// Interrupts and pin function setup
	//***********************************************************

	// Pin change interrupt enables PCINT1, PCINT2 and PCINT3 (Throttle, AUX and CPPM input)
	PCICR  = 0x0A;							// PCINT8  to PCINT15 (PCINT1 group - AUX)
											// PCINT24 to PCINT31 (PCINT3 group - THR)
	PCIFR  = 0x0F;							// Clear PCIF0 interrupt flag 
											// Clear PCIF1 interrupt flag 
											// Clear PCIF2 interrupt flag 
											// Clear PCIF3 interrupt flag 

	// External interrupts INT0 (Elevator) and INT1 (Aileron) and INT2 (Rudder)
	EICRA = 0x15;							// Any change INT0
											// Any change INT1
											// Any change INT2
	EIFR  = 0x07; 							// Clear INT0 interrupt flag (Elevator)
											// Clear INT1 interrupt flag (Aileron)
											// Clear INT2 interrupt flag (Rudder/CPPM)

	//***********************************************************
	// i2c init for KK2.1
	//***********************************************************	

#ifdef KK21
	i2c_init();
	init_i2c_gyros();
	init_i2c_accs();
#endif

	//***********************************************************
	// Start up
	//***********************************************************

	// Preset important flags
	Interrupted  = false;						
	Main_flags |= (1 << FirstTimeIMU);
	Main_flags |= (1 << FirstTimeFlightMode);

	// Initialise the GLCD
	st7565_init();
	st7565_command(CMD_DISPLAY_ON);
	st7565_command(CMD_SET_ALLPTS_NORMAL);
	st7565_set_brightness(0x26);
	st7565_command(CMD_SET_COM_REVERSE); 	// For logo

	// Make sure the LCD is blank
	clear_screen();

	// This delay prevents the GLCD flashing up a ghost image of old data
	_delay_ms(300);	

	// Reload default eeprom settings if middle two buttons are pressed (or all, for older users)
	if (((PINB & 0xf0) == 0x90) || ((PINB & 0xf0) == 0x00))
	{
		// Display reset message
		st7565_command(CMD_SET_COM_NORMAL); 	// For text (not for logo)
		clear_buffer(buffer);
		LCD_Display_Text(1,(prog_uchar*)Verdana14,40,25);
		write_buffer(buffer,1);
		clear_buffer(buffer);

		Set_EEPROM_Default_Config();
		Save_Config_to_EEPROM();
	}
	// Load "Config" global data structure
	else
	{
		Initial_EEPROM_Config_Load();
	}		

	// Now set contrast to the previously saved value
	st7565_set_brightness((uint8_t)Config.Contrast);
						
#ifdef KK21
	// Write logo from buffer
	write_buffer(buffer,0);
	_delay_ms(500);
#endif

#ifndef KK21
	// Display "Hold steady" message for KK2.0
	st7565_command(CMD_SET_COM_NORMAL); 	// For text (not for logo)
	clear_buffer(buffer);
	LCD_Display_Text(2,(prog_uchar*)Verdana14,18,25);
	write_buffer(buffer,1);
	clear_buffer(buffer);
#endif
		
	// Do startup tasks
	UpdateLimits();							// Update travel limts	
	UpdateIMUvalues();						// Update IMU factors
	Init_ADC();
	init_int();								// Intialise interrupts based on RC input mode

	// Initialise UART
	init_uart();

	// Initial gyro calibration
	CalibrateGyrosSlow();

	// Check to see that gyros are stable
	ReadGyros();

	if ((gyroADC[ROLL] > GYROS_STABLE) || (gyroADC[ROLL] < -GYROS_STABLE) ||
	 	(gyroADC[PITCH] > GYROS_STABLE) || (gyroADC[PITCH] < -GYROS_STABLE) ||
		(gyroADC[YAW] > GYROS_STABLE) || (gyroADC[YAW] < -GYROS_STABLE))
	{
		General_error |= (1 << SENSOR_ERROR); 	// Set sensor error bit
	}

	// Check to see that throttle is low if in serial mode.
	// Don't bother if in CamStab mode
	_delay_ms(100);
	if (
		(
		 (Config.RxMode == CPPM_MODE) ||
		 (Config.RxMode == XTREME) ||
		 (Config.RxMode == SBUS) ||
		 (Config.RxMode == SPEKTRUM)
		)
		&& (Config.CamStab == OFF)
	   )
	{
		RxGetChannels();
		if (RCinputs[THROTTLE] > -900)
		{
			General_error |= (1 << THROTTLE_HIGH); 	// Set throttle high error bit
		}
	}

	// Flash LED
	LED1 = 1;
	_delay_ms(150);
	LED1 = 0;

	// Beep that all sensors have been handled
	menu_beep(1);

	// Set text display mode back to normal
	st7565_command(CMD_SET_COM_NORMAL); 	// For text (not for logo)

} // init()