UAVX Multicopter Flight Controller.

Dependencies:   mbed

accel.c

Committer:
gke
Date:
2011-02-25
Revision:
1:1e3318a30ddd
Parent:
0:62a1c91a859a
Child:
2:90292f8bd179

File content as of revision 1:1e3318a30ddd:

// ===============================================================================================
// =                              UAVXArm Quadrocopter Controller                                =
// =                           Copyright (c) 2008 by Prof. Greg Egan                             =
// =                 Original V3.15 Copyright (c) 2007 Ing. Wolfgang Mahringer                   =
// =                     http://code.google.com/p/uavp-mods/ http://uavp.ch                      =
// ===============================================================================================

//    This is part of UAVXArm.

//    UAVXArm is free software: you can redistribute it and/or modify it under the terms of the GNU
//    General Public License as published by the Free Software Foundation, either version 3 of the
//    License, or (at your option) any later version.

//    UAVXArm is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without
//    even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//    See the GNU General Public License for more details.

//    You should have received a copy of the GNU General Public License along with this program.
//    If not, see http://www.gnu.org/licenses/

#include "UAVXArm.h"

void ShowAccType(void);
void ReadAccelerometers(void);
void GetAccelerations(void);
void GetNeutralAccelerations(void);
void AccelerometerTest(void);
void InitAccelerometers(void);

real32 Vel[3], Acc[3], AccNeutral[3], Accp[3];
int16 NewAccNeutral[3];
uint8 AccelerometerType;

void ShowAccType(void) {
    switch ( AccelerometerType ) {
        case LISLAcc:
            TxString("LIS3L");
            break;
        case ADXL345Acc:
            TxString("ADXL345");
            break;
        case AccUnknown:
            TxString("unknown");
            break;
        default:
            ;
    } // switch
} // ShowAccType

void ReadAccelerometers(void) {
    switch ( AccelerometerType ) {
        case LISLAcc:
            ReadLISLAcc();
            break;
        case ADXL345Acc:
            ReadADXL345Acc();
            break;
            // other accelerometers
        default:
            Acc[BF] = Acc[LR] = 0.0;
            Acc[UD] = 1.0;
            break;
    } // switch
} // ReadAccelerometers

void GetNeutralAccelerations(void) {
    static uint8 i, a;
    static real32 Temp[3] = {0.0, 0.0, 0.0};

    if ( F.AccelerationsValid ) {
        for ( i = 16; i; i--) {
            ReadAccelerometers();
            for ( a = 0; a <(uint8)3; a++ )
                Temp[a] += Acc[a];
        }

        for ( a = 0; a <(uint8)3; a++ )
            Temp[a] = Temp[a] * 0.0625;

        NewAccNeutral[BF] = Limit((int16)(Temp[BF] * 1000.0 ), -99, 99);
        NewAccNeutral[LR] = Limit( (int16)(Temp[LR] * 1000.0 ), -99, 99);
        NewAccNeutral[UD] = Limit( (int16)(( Temp[UD] - 1.0 ) * 1000.0) , -99, 99);

    } else
        for ( a = 0; a <(uint8)3; a++ )
            AccNeutral[a] = 0.0;

} // GetNeutralAccelerations

void GetAccelerations(void) {

    static real32 AccA;
    static uint8 a;

    if ( F.AccelerationsValid ) {
        ReadAccelerometers();

        // Neutral[ {LR, BF, UD} ] pass through UAVPSet
        // and come back as AccMiddle[LR] etc.

        Acc[BF] -= K[MiddleBF];
        Acc[LR] -= K[MiddleLR];
        Acc[UD] -= K[MiddleUD];

        AccA = dT / ( OneOnTwoPiAccF + dT );
        for ( a = 0; a < (uint8)3; a++ ) {
            Acc[a] = Accp[a] + (Acc[a] - Accp[a]) * AccA;
            Accp[a] = Acc[a];
        }

    } else {
        Acc[LR] = Acc[BF] = 0;
        Acc[UD] = 1.0;
    }
} // GetAccelerations

void AccelerometerTest(void) {
    TxString("\r\nAccelerometer test -");
    ShowAccType();
    TxString("\r\nRead once - no averaging\r\n");

    InitAccelerometers();

    if ( F.AccelerationsValid ) {
        ReadAccelerometers();

        TxString("\tL->R: \t");
        TxVal32( Acc[LR] * 1000.0, 3, 'G');
        if ( fabs(Acc[LR]) > 0.2 )
            TxString(" fault?");
        TxNextLine();

        TxString("\tB->F: \t");
        TxVal32( Acc[BF] * 1000.0, 3, 'G');
        if ( fabs(Acc[BF]) > 0.2 )
            TxString(" fault?");
        TxNextLine();


        TxString("\tU->D:    \t");
        TxVal32( Acc[UD] * 1000.0, 3, 'G');
        if ( fabs(Acc[UD]) > 1.2 )
            TxString(" fault?");
        TxNextLine();
    }
} // AccelerometerTest

void InitAccelerometers(void) {
    static uint8 a;

    F.AccelerationsValid = true; // optimistic

    for ( a = 0; a < (uint8)3; a++ ) {
        NewAccNeutral[a] = Acc[a] = Accp[a] = Vel[a] = 0.0;
        Comp[a] = 0;
    }
    Acc[2] = Accp[2] = 1.0;

    if ( ADXL345AccActive() ) {
        InitADXL345Acc();
        AccelerometerType = ADXL345Acc;

    } else
        if ( LISLAccActive() )
            AccelerometerType = LISLAcc;
        else
            // check for other accs in preferred order
        {
            AccelerometerType = AccUnknown;
            F.AccelerationsValid = false;
        }

    if ( F.AccelerationsValid ) {
        LEDYellow_ON;
        GetNeutralAccelerations();
        LEDYellow_OFF;
    } else
        F.AccFailure = true;
} // InitAccelerometers

//________________________________________________________________________________________

// ADXL345 3 Axis Accelerometer

void ReadADXL345Acc(void);
void InitADXL345Acc(void);
boolean ADXL345AccActive(void);

const float GRAVITY_ADXL345 = 250.0; // ~4mG/LSB

void ReadADXL345Acc(void) {

    static uint8 a, r;
    static char b[6];
    static i16u X, Y, Z;

    /*
    r = 0;
    while ( r == 0 ) {
        I2CACC.start();
        r = I2CACC.write(ADXL345_ID);
        r = I2CACC.write(0x30);
        r = I2CACC.read(true) & 0x80;
        I2CACC.stop();
    }
    */

    I2CACC.start();
    r = I2CACC.write(ADXL345_WR);
    r = I2CACC.write(0x32); // point to acc data
    I2CACC.stop();

    I2CACC.blockread(ADXL345_ID, b, 6);

    X.b1 = b[1];
    X.b0 = b[0];
    Y.b1 = b[3];
    Y.b0  =b[2];
    Z.b1 = b[5];
    Z.b0 = b[4];

    if ( F.Using9DOF ) { // SparkFun/QuadroUFO 9DOF breakouts pins forward components up
        Acc[BF] = -Y.i16;
        Acc[LR] = -X.i16;
        Acc[UD] = -Z.i16;
    } else {// SparkFun 6DOF breakouts pins forward components down 
        Acc[BF] = -X.i16;
        Acc[LR] = -Y.i16;
        Acc[UD] = -Z.i16; 
    }

    // LP filter here?

    for ( a = 0; a < (int8)3; a++ )
        Acc[a] /= GRAVITY_ADXL345;

} // ReadADXL345Acc

void InitADXL345Acc() {
    static uint8 r;

    I2CACC.start();
    I2CACC.write(ADXL345_WR);
    r = I2CACC.write(0x2D);  // power register
    r = I2CACC.write(0x08);  // measurement mode
    I2CACC.stop();

    Delay1mS(5);

    I2CACC.start();
    r = I2CACC.write(ADXL345_WR);
    r =  I2CACC.write(0x31);  // format
    r =  I2CACC.write(0x08);  // full resolution, 2g
    I2CACC.stop();

    Delay1mS(5);

    I2CACC.start();
    r =  I2CACC.write(ADXL345_WR);
    r =  I2CACC.write(0x2C);  // Rate
    r =  I2CACC.write(0x09);  // 50Hz, 400Hz 0x0C
    I2CACC.stop();

    Delay1mS(5);

} // InitADXL345Acc

boolean ADXL345AccActive(void) {

    I2CACC.start();
    F.AccelerationsValid = I2CACC.write(ADXL345_WR) == I2C_ACK;
    I2CACC.stop();
    
    TrackMinI2CRate(400000);
     
    return( true ); //zzz F.AccelerationsValid );

} // ADXL345AccActive

//________________________________________________________________________________________

// LIS3LV02DG Accelerometer 400KHz

void WriteLISL(uint8, uint8);
void ReadLISLAcc(void);
boolean LISLAccActive(void);

const float GRAVITY_LISL = 1024.0;

void ReadLISLAcc(void) {
    static uint8 a;
    static char b[6];
    static i16u X, Y, Z;

    F.AccelerationsValid = I2CACCAddressResponds( LISL_ID ); // Acc still there?
    if ( F.AccelerationsValid ) {

        // Ax.b0 = I2CACC.write(LISL_OUTX_L + LISL_INCR_ADDR + LISL_READ);

        I2CACC.blockread(LISL_READ, b, 6);

        X.b1 = b[1];
        X.b0 = b[0];
        Y.b1 = b[3];
        Y.b0 = b[2];
        Z.b1 = b[5];
        Z.b0 = b[4];

        Acc[BF] = Z.i16;
        Acc[LR] = -X.i16;
        Acc[UD] = Y.i16;

        // LP Filter here?

        for ( a = 0; a < (uint8)3; a++ )
            Acc[a] /= GRAVITY_LISL;

    } else {
        for ( a = 0; a < (uint8)3; a++ )
            Acc[a] = AccNeutral[a];
        Acc[UD] += 1.0;

        if ( State == InFlight ) {
            Stats[AccFailS]++;    // data over run - acc out of range
            // use neutral values!!!!
            F.AccFailure = true;
        }
    }
} // ReadLISLAccelerometers

void WriteLISL(uint8 d, uint8 a) {
    I2CACC.start();
    I2CACC.write(a);
    I2CACC.write(d);
    I2CACC.stop();
} // WriteLISL

boolean LISLAccActive(void) {
    F.AccelerationsValid = false;
    /*
        WriteLISL(0x4a, LISL_CTRLREG_2);           // enable 3-wire, BDU=1, +/-2g

        if ( I2CACC.write(LISL_ID) == I2C_ACK ) {
            WriteLISL(0xc7, LISL_CTRLREG_1);       // on always, 40Hz sampling rate,  10Hz LP cutoff, enable all axes
            WriteLISL(0, LISL_CTRLREG_3);
            WriteLISL(0x40, LISL_FF_CFG);          // latch, no interrupts;
            WriteLISL(0, LISL_FF_THS_L);
            WriteLISL(0xFC, LISL_FF_THS_H);        // -0,5g threshold
            WriteLISL(255, LISL_FF_DUR);
            WriteLISL(0, LISL_DD_CFG);
            F.AccelerationsValid = true;
        } else
            F.AccFailure = true;
    */
    
    TrackMinI2CRate(400000);
        
    return ( false );//F.AccelerationsValid );
} // LISLAccActive