Subversion Repositories FlightCtrl

Rev

Blame | Last modification | View Log | RSS feed

/*****************************************************************************************************************************
* 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) ****************************************************************************************************************