Subversion Repositories FlightCtrl

Compare Revisions

Ignore whitespace Rev 2245 → Rev 2246

/branches/V0.76g_dk9nw_balancekopter/analog.c
0,0 → 1,316
/*****************************************************************************************************************************
* File: analog.c
*
* Purpose: collecting ADC analog inputs from PORTA
*
* Functions: void ADC_Init(void)
* void SucheLuftruckOffset(void)
* void SucheGyroOffset(void)
* ISR(ADC_vect)
*
*****************************************************************************************************************************/
#include "analog.h"
#include "main.h"
 
volatile int Aktuell_Nick, Aktuell_Roll, Aktuell_Gier, Aktuell_ax, Aktuell_ay, Aktuell_az, UBat = 100;
volatile int AdWertNickFilter = 0, AdWertRollFilter = 0, AdWertGierFilter = 0;
volatile int HiResNick = 2500, HiResRoll = 2500;
volatile int AdWertNick = 0, AdWertRoll = 0, AdWertGier = 0;
volatile int AdWertAccRoll = 0, AdWertAccNick = 0, AdWertAccHoch = 0;
volatile char messanzahl_AccHoch = 0;
volatile long Luftdruck = 32000;
volatile long SummenHoehe = 0;
volatile int StartLuftdruck;
volatile unsigned int MessLuftdruck = 1023;
unsigned char DruckOffsetSetting;
signed char ExpandBaro = 0;
volatile int VarioMeter = 0;
volatile unsigned int ZaehlMessungen = 0;
unsigned char AnalogOffsetNick = 115, AnalogOffsetRoll = 115, AnalogOffsetGier = 115;
unsigned char GyroDefektN = 0, GyroDefektR = 0, GyroDefektG = 0;
volatile unsigned char AdReady = 1;
 
 
// *************************************************************************************************************************************
// initialize the analog digital converter ADC
// -------------------------------------------------------------------------------------------------------------------------------------
void ADC_Init(void)
{
// ADMUX = ADC Multiplexer Selection Register –> REFS1 REFS0 ADLAR MUX4 MUX3 MUX2 MUX1 MUX0
// -----------------------------------------------------------------------------------------
// REFS1:0 = Reference Selection Bits
// ADLAR = ADC Left Adjust Result
// MUX4:0 = Analog Channel and Gain Selection Bits
//
ADMUX = 0; // AREF, Internal Vref is turned off
// // the result is right adjusted
// // MUX = 00000 = ADC0
// ADCSRA = Analog Digital Conversion Status Register A -> ADEN ADSC ADATE ADIF ADIE ADPS2 ADPS1 ADPS0
// ---------------------------------------------------------------------------------------------------
// ADEN = Writing this bit to one enables the ADC
// ADSC = start conversion
// ADATE = When this bit is written to one, Auto Triggering of the ADC is enabled
// ADIE = ADC Interrupt Enable. When this bit is written to one and the I-bit in SREG is set, the ADC Conversion Complete Interrupt is activated.
// ADPS = These bits determine the division factor between the XTAL frequency and the input clock to the ADC.
// Prescaler with ADPS2 ADPS1 ADPS0 = 111 = Division Factor 128 = 156.25 kHz
//
ANALOG_ON; // #define ANALOG_ON ADCSRA=(1<<ADEN)|(1<<ADSC)|(0<<ADATE)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
}
// *** EOF: void ADC_Init(void) ************************************************************************************
 
 
#define DESIRED_H_ADC 800
 
 
 
// *********************************************************************************************************************************
// initialize the air pressure offset
// ------------------------------------
void SucheLuftruckOffset(void)
{
unsigned int off;
off = eeprom_read_byte(&EEPromArray[EEPROM_ADR_LAST_OFFSET]);
if(off > 20) off -= 10;
OCR0A = off; // Timer/Counter0 Output Compare Register A
ExpandBaro = 0;
Delay_ms_Mess(100); // -> timer0.c
if(MessLuftdruck < DESIRED_H_ADC) off = 0; // #define DESIRED_H_ADC 800
for(; off < 250;off++)
{
OCR0A = off;
Delay_ms_Mess(50);
printf(".");
if(MessLuftdruck < DESIRED_H_ADC) break;
}
eeprom_write_byte(&EEPromArray[EEPROM_ADR_LAST_OFFSET], off);
DruckOffsetSetting = off;
Delay_ms_Mess(300);
}
// *** EOF: SucheLuftruckOffset(void) **********************************************************************************************
 
 
 
// *********************************************************************************************************************************
// initialize the Gyro-Offset
// ---------------------------
void SucheGyroOffset(void)
{
unsigned char i, ready = 0;
int timeout;
GyroDefektN = 0; GyroDefektR = 0; GyroDefektG = 0;
timeout = SetDelay(2000);
for(i=140; i != 0; i--)
{
if(ready==3 && i>10) i = 9;
ready = 0;
if(AdWertNick < 1020) AnalogOffsetNick--; else if(AdWertNick > 1030) AnalogOffsetNick++; else ready++;
if(AdWertRoll < 1020) AnalogOffsetRoll--; else if(AdWertRoll > 1030) AnalogOffsetRoll++; else ready++;
if(AdWertGier < 1020) AnalogOffsetGier--; else if(AdWertGier > 1030) AnalogOffsetGier++; else ready++;
twi_state = 8;
i2c_start();
if(AnalogOffsetNick < 10) { GyroDefektN = 1; AnalogOffsetNick = 10;}; if(AnalogOffsetNick > 245) { GyroDefektN = 1; AnalogOffsetNick = 245;};
if(AnalogOffsetRoll < 10) { GyroDefektR = 1; AnalogOffsetRoll = 10;}; if(AnalogOffsetRoll > 245) { GyroDefektR = 1; AnalogOffsetRoll = 245;};
if(AnalogOffsetGier < 10) { GyroDefektG = 1; AnalogOffsetGier = 10;}; if(AnalogOffsetGier > 245) { GyroDefektG = 1; AnalogOffsetGier = 245;};
while(twi_state) if(CheckDelay(timeout)) {printf("\n\r DAC or I2C ERROR! Check I2C, 3Vref, DAC and BL-Ctrl"); break;}
AdReady = 0;
ANALOG_ON; // #define ANALOG_ON ADCSRA=(1<<ADEN)|(1<<ADSC)|(0<<ADATE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)|(1<<ADIE)
while(!AdReady);
if(i<10) Delay_ms_Mess(10);
}
Delay_ms_Mess(70);
}
// *** EOF: SucheGyroOffset(void) **************************************************************************************************
 
 
 
// *********************************************************************************************************************************
// read analog input with the following sequence:
// ---------------------------------------------------------------------------------------------------
// case:
// 0 nick-gyro
// 1 roll-gyro
// 2 gier-gyro
// 3 y acc roll
// 4 x acc nick
// 5 nick-gyro
// 6 roll-gyro
// 7 voltage V
// 8 z acc
// 9 air pressure
// 10 nick-gyro
// 11 roll-gyro
// 12 gier-gyro
// 13 y acc roll
// 14 x acc nick
// 15 nick-gyro
// 16 roll-gyro
// 17 air pressure
// ---------------------------------------------------------------------------------------------------
ISR(ADC_vect)
{
static unsigned char kanal=0,state = 0;
static signed int gier1, roll1, nick1, nick_filter, roll_filter;
static signed int accy, accx;
static long tmpLuftdruck = 0;
static char messanzahl_Druck = 0;
 
switch(state++)
{
case 0: // nick gyro
nick1 = ADC; // Messwert Nick aus dem Gyroskop (kippen nach vorne-hinten)
kanal = AD_ROLL; // #define AD_ROLL 1
break;
case 1: // roll gyro
roll1 = 512; // Messwert Roll aus dem Gyroskop (kippen nach rechts-links)
kanal = AD_GIER; // #define AD_GIER 0
break;
case 2: // gier gyro
gier1 = 512; // Messwert Gier aus dem Gyroskop (drehen um Hochachse)
kanal = AD_ACC_Y; // #define AD_ACC_Y 6 // Rollen
break;
case 3: // y acc roll
Aktuell_ay = NeutralAccY - 512;
accy = Aktuell_ay; // Messwert Y=Roll des ACC Sensors
kanal = AD_ACC_X; // #define AD_ACC_X 7 // Nicken
break;
case 4:
Aktuell_ax = ADC - NeutralAccX; // Messwert X=Nick des ACC Sensors
accx = Aktuell_ax;
kanal = AD_NICK; // #define AD_NICK 2
break;
case 5:
nick1 += ADC; // Messwert Nick aus dem Gyroskop (kippen nach vorne-hinten)
kanal = AD_ROLL; // #define AD_ROLL 1
break;
case 6:
roll1 += 512; // Messwert Roll aus dem Gyroskop (kippen nach rechts-links)
kanal = AD_UBAT; // #define AD_UBAT 4
break;
case 7:
UBat = (3 * UBat + ADC / 3) / 4; // Voltage
kanal = AD_ACC_Z; // #define AD_ACC_Z 5
break;
case 8: // Z acc Sensor
AdWertAccHoch = 512 - NeutralAccZ;
if(AdWertAccHoch > 1)
{
if(NeutralAccZ < 750)
{
NeutralAccZ += 0.02;
if(modell_fliegt < 500) NeutralAccZ += 0.1;
}
}
else if(AdWertAccHoch < -1)
{
if(NeutralAccZ > 550)
{
NeutralAccZ-= 0.02;
if(modell_fliegt < 500) NeutralAccZ -= 0.1;
}
}
messanzahl_AccHoch = 1; // Messwert Z des ACC Sensors
Aktuell_az = 512;
Mess_Integral_Hoch += AdWertAccHoch; // Integrieren
Mess_Integral_Hoch -= Mess_Integral_Hoch / 1024; // dämfen
kanal = AD_DRUCK;
break;
// "case 9:" fehlt hier absichtlich
case 10:
nick1 += ADC;
kanal = AD_ROLL; // #define AD_ROLL 1
break;
case 11:
roll1 += 512;
kanal = AD_GIER; // #define AD_GIER 0
break;
case 12:
AdWertGier = (512 + gier1); // AdWertGier müsste so um die 1020 liegen
kanal = AD_ACC_Y; // #define AD_ACC_Y 6
break;
case 13:
Aktuell_ay = NeutralAccY - 512;
AdWertAccRoll = (Aktuell_ay + accy); // Messwert Roll des ACC Sensors
kanal = AD_ACC_X; // #define AD_ACC_X 7
break;
case 14:
Aktuell_ax = ADC - NeutralAccX;
AdWertAccNick = (Aktuell_ax + accx); // 2nd measure of ACC Nick Sensor 0...512
kanal = AD_NICK; // #define AD_NICK 2
break;
case 15:
nick1 += ADC;
nick1 *= 4;
AdWertNick = nick1 / 8; // dieser Wert ist doppelt so hoch wie ADC
nick_filter = (nick_filter + nick1) / 2; // nick_filter müsste mit ca 500 passen
HiResNick = nick_filter - AdNeutralNick; // der Wert wird hier auf den Nullpunkt normiert
AdWertNickFilter = (AdWertNickFilter + HiResNick) / 2; // und gefiltert
kanal = AD_ROLL; // #define AD_ROLL 1
break;
case 16:
roll1 += 512;
roll1 *= 4;
AdWertRoll = roll1 / 8; // dieser Wert ist doppelt so hoch wie ADC
roll_filter = (roll_filter + roll1) / 2; // ähnlich wie bei Nick in case 15
HiResRoll = roll_filter - AdNeutralRoll; // der Wert wird hier auf den Nullpunkt normiert
AdWertRollFilter = (AdWertRollFilter + HiResRoll) / 2; // und gefiltert
kanal = AD_DRUCK; // #define AD_DRUCK 3
break;
case 17:
state = 0;
AdReady = 1; // alle Analogeingänge sind nun bedient worden
ZaehlMessungen++; // counts one up as all cases have been passed through
// "break" fehlt hier absichtlich
case 9:
MessLuftdruck = 512;
tmpLuftdruck += MessLuftdruck;
if(++messanzahl_Druck >= 18)
{
Luftdruck = (7 * Luftdruck + tmpLuftdruck - (18 * 523) * (long)ExpandBaro + 4) / 8; // -523.19 counts per 10 counts offset step
HoehenWert = StartLuftdruck - Luftdruck;
SummenHoehe -= SummenHoehe / SM_FILTER; // #define SM_FILTER 16
SummenHoehe += HoehenWert;
VarioMeter = (15 * VarioMeter + 8 * (int)(HoehenWert - SummenHoehe/SM_FILTER))/16;
tmpLuftdruck /= 2;
messanzahl_Druck = 18/2;
}
kanal = AD_NICK; // #define AD_NICK 2
break;
default:
kanal = 0; state = 0; kanal = AD_NICK; // #define AD_NICK 2
break;
}
ADMUX = kanal;
if(state != 0) ANALOG_ON; // #define ANALOG_ON ADCSRA=(1<<ADEN)|(1<<ADSC)|(0<<ADATE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)|(1<<ADIE)
}
// EOF : ISR(ADC_vect) ****************************************************************************************************************