Rev 683 |
Blame |
Last modification |
View Log
| RSS feed
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 04.2007 Holger Buss
// + only for non-profit use
// + www.MikroKopter.com
// + see the File "License.txt" for further Informations
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include "analog.h"
#include "main.h"
#include "timer0.h"
#include "fc.h"
#include "printf_P.h"
volatile int16_t Current_Nick
= 0, Current_Roll
= 0, Current_Gier
= 0;
volatile int16_t Current_AccX
= 0, Current_AccY
= 0, Current_AccZ
= 0;
volatile int16_t UBat
= 100;
volatile int16_t AdValueGyrNick
= 0, AdValueGyrRoll
= 0, AdValueGyrGier
= 0;
volatile int16_t AdValueAccRoll
= 0, AdValueAccNick
= 0, AdValueAccTop
= 0;
volatile uint8_t messanzahl_AccHoch
= 0;
volatile int32_t Luftdruck
= 32000;
volatile int16_t StartLuftdruck
;
volatile uint16_t MessLuftdruck
= 1023;
uint8_t DruckOffsetSetting
;
volatile int16_t HoeheD
= 0;
volatile int16_t tmpLuftdruck
;
volatile uint16_t ZaehlMessungen
= 0;
/*****************************************************/
/* Initialize Analog Digital Converter */
/*****************************************************/
void ADC_Init
(void)
{
uint8_t sreg
= SREG
;
// disable all interrupts before reconfiguration
cli
();
//ADC0 ... ADC7 is connected to PortA pin 0 ... 7
DDRA
= 0x00;
PORTA
= 0x00;
// Digital Input Disable Register 0
// Disable digital input buffer for analog adc_channel pins
DIDR0
= 0xFF;
// external reference, adjust data to the right
ADMUX
&= ~
((1 << REFS1
)|(1 << REFS0
)|(1 << ADLAR
));
// set muxer to ADC adc_channel 0 (0 to 7 is a valid choice)
ADMUX
= (ADMUX
& 0xE0) | 0x00;
//Set ADC Control and Status Register A
//Auto Trigger Enable, Prescaler Select Bits to Division Factor 128, i.e. ADC clock = SYSCKL/128 = 156.25 kHz
ADCSRA
= (1<<ADATE
)|(1<<ADPS2
)|(1<<ADPS1
)|(1<<ADPS0
);
//Set ADC Control and Status Register B
//Trigger Source to Free Running Mode
ADCSRB
&= ~
((1 << ADTS2
)|(1 << ADTS1
)|(1 << ADTS0
));
// Enable AD conversion
ADC_Enable
();
// restore global interrupt flags
SREG
= sreg
;
}
void SucheLuftruckOffset
(void)
{
unsigned int off
;
off
= eeprom_read_byte
(&EEPromArray
[EEPROM_ADR_LAST_OFFSET
]);
if(off
> 20) off
-= 10;
OCR0A
= off
;
Delay_ms_Mess
(100);
if(MessLuftdruck
< 850) off
= 0;
for(; off
< 250;off
++)
{
OCR0A
= off
;
Delay_ms_Mess
(50);
printf(".");
if(MessLuftdruck
< 900) break;
}
eeprom_write_byte
(&EEPromArray
[EEPROM_ADR_LAST_OFFSET
], off
);
DruckOffsetSetting
= off
;
Delay_ms_Mess
(300);
}
/*****************************************************/
/* Interrupt Service Routine for ADC */
/*****************************************************/
ISR
(ADC_vect
)
{
static uint8_t adc_channel
= 0, state
= 0;
static uint16_t gier1
, roll1
, nick1
;
static uint8_t messanzahl_Druck
= 0;
// disable further AD conversion
ADC_Disable
();
// state machine
switch(state
++)
{
case 0:
gier1
= ADC
; // get Gyro Gier Voltage 1st sample
adc_channel
= 1; // set next channel to ADC1 = ROLL GYRO
ZaehlMessungen
++; // increment total measurement counter
break;
case 1:
roll1
= ADC
; // get Gyro Roll Voltage 1st sample
adc_channel
= 2; // set next channel to ADC2 = NICK GYRO
break;
case 2:
nick1
= ADC
; // get Gyro Nick Voltage 1st sample
adc_channel
= 4; // set next channel to ADC4 = UBAT
break;
case 3:
// get actual UBat (Volts*10) is ADC*30V/1024*10 = ADC/3
UBat
= (3 * UBat
+ ADC
/ 3) / 4; // low pass filter updates UBat only to 1 quater with actual ADC value
adc_channel
= 6; // set next channel to ADC6 = ACC_Y
break;
case 4:
Current_AccY
= NeutralAccY
- ADC
; // get acceleration in Y direction
AdValueAccRoll
= Current_AccY
;
adc_channel
= 7; // set next channel to ADC7 = ACC_X
break;
case 5:
Current_AccX
= ADC
- NeutralAccX
; // get acceleration in X direction
AdValueAccNick
= Current_AccX
;
adc_channel
= 0; // set next channel to ADC7 = GIER GYRO
break;
case 6:
// average over two samples to create current ADValueGier
if(BoardRelease
== 10) AdValueGyrGier
= (ADC
+ gier1
) / 2;
else AdValueGyrGier
= ADC
+ gier1
; // gain is 2 times lower on FC 1.1
adc_channel
= 1; // set next channel to ADC7 = ROLL GYRO
break;
case 7:
// average over two samples to create current ADValueRoll
if(BoardRelease
== 10) AdValueGyrRoll
= (ADC
+ roll1
) / 2;
else AdValueGyrRoll
= ADC
+ roll1
; // gain is 2 times lower on FC 1.1
adc_channel
= 2; // set next channel to ADC2 = NICK GYRO
break;
case 8:
// average over two samples to create current ADValueNick
if(BoardRelease
== 10) AdValueGyrNick
= (ADC
+ nick1
) / 2;
else AdValueGyrNick
= ADC
+ nick1
; // gain is 2 times lower on FC 1.1
adc_channel
= 5; // set next channel to ADC5 = ACC_Z
break;
case 9:
// get z acceleration
AdValueAccTop
= (int16_t) ADC
- NeutralAccZ
; // get plain acceleration in Z direction
AdValueAccTop
+= abs(Current_AccY
) / 4 + abs(Current_AccX
) / 4;
if(AdValueAccTop
> 1)
{
if(NeutralAccZ
< 800) NeutralAccZ
+= 0.02;
}
else if(AdValueAccTop
< -1)
{
if(NeutralAccZ
> 600) NeutralAccZ
-= 0.02;
}
messanzahl_AccHoch
= 1;
Current_AccZ
= ADC
;
Mess_Integral_Hoch
+= AdValueAccTop
; // Integrieren
Mess_Integral_Hoch
-= Mess_Integral_Hoch
/ 1024; // dämfen
adc_channel
= 3; // set next channel to ADC3 = air pressure
break;
case 10:
tmpLuftdruck
+= ADC
; // sum vadc values
if(++messanzahl_Druck
>= 5) // if 5 values are summerized for averaging
{
MessLuftdruck
= ADC
; // update measured air pressure
messanzahl_Druck
= 0; // reset air pressure measurement counter
HoeheD
= (int16_t)(StartLuftdruck
- tmpLuftdruck
- HoehenWert
); // D-Anteil = neuerWert - AlterWert
Luftdruck
= (tmpLuftdruck
+ 3 * Luftdruck
) / 4; // averaging using history
HoehenWert
= StartLuftdruck
- Luftdruck
;
tmpLuftdruck
= 0;
}
adc_channel
= 0; // set next channel to ADC0 = GIER GYRO
state
= 0; // reset state
break;
default:
adc_channel
= 0;
state
= 0;
break;
}
// set adc muxer to next adc_channel
ADMUX
= (ADMUX
& 0xE0) | adc_channel
;
// ??
if(state
!= 0) ADC_Enable
();
}