j

bma220/bma220.cpp

Committer:
zinnetyazicii53
Date:
2019-09-11
Revision:
1:dc9389ccc09d

File content as of revision 1:dc9389ccc09d:

#include "bma220.h"

Serial dbug(USBTX, USBRX);

BMA220::BMA220(I2C *_i2c)
{
    i2c = _i2c;
    G[0].Ax = 0;
    G[0].Ay = 0;
    G[0].Az = 0;
}

BMA220::BMA220()
{
    i2c = new I2C(I2C_SDA, I2C_SCL);
    i2c->frequency(400000);
    G[0].Ax = 0;
    G[0].Ay = 0;
    G[0].Az = 0;
}

bool BMA220::begin(void)
{   
    uint8_t chip_id = readRegister(CHIPID_REG);
    printf("chip_id : %x\n", chip_id);
    if(chip_id != 0xDD) {
        dbug.printf("Chip ID is not valid\n");
        return false;
    }
    dbug.printf("Chip ID is valid\n");

    resetvalue = readRegister(SOFTRESET_REG); // change mode
    if (resetvalue == 0xFF) {  // was in reset mode, is in operation mode now
        resetvalue = readRegister(SOFTRESET_REG);  // sensor should be in reset mode now
    }

    if (resetvalue != 0x00) {
        return false;
    }
    // sensor should be in reset mode
    resetvalue = readRegister(SOFTRESET_REG);
    if (resetvalue != 0xFF) {  // sensor was not in reset mode
        return false;
    }
    return true;

}

void BMA220::setRegister(uint8_t reg, uint8_t value)
{
    char data[2];
    data[0] = reg;
    data[1] = value;
    i2c->write(BMA220_ADDR, data, 2, false);    
}

uint8_t BMA220::readRegister(uint8_t reg)
{
    char buffer_out[1];
    char buffer_in[1];
    buffer_in[0] = 0x0;
    buffer_out[0] = reg;
    i2c->write(BMA220_ADDR, buffer_out, 1, true);
    i2c->read(BMA220_ADDR, buffer_in, 1,false);

    return (uint8_t)buffer_in[0];
}

void BMA220::readAcceleration(int sensitivity)
{
    G[1].Ax = G[0].Ax;
    G[1].Ay = G[0].Ay;
    G[1].Az = G[0].Az;      //Acc After= Acc Before

    this->Ax = ((float)readRegister(XAXIS))/sensitivity;
    this->Ay = ((float)readRegister(YAXIS))/sensitivity;
    this->Az = ((float)readRegister(ZAXIS))/sensitivity;

    // Calculate Roll and Pitch (rotation around X-axis, rotation around Y-axis)
    // Pitch (rho) is defined as the angle of the X-axis relative to ground. Roll (phi) is defined as the angle of the Y-axis relative to the ground. Theta is the angle of the Z axis relative to gravity.”
    int r = atan(Ay / sqrt(pow(Ax, 2) + pow(Az, 2))) * 180 / PI;
    int p = atan(Ax / sqrt(pow(Ay, 2) + pow(Az, 2))) * 180 / PI;
    int t = atan(sqrt(pow(Ax, 2) + pow(Ay, 2)) / Az) * 180 / PI;

    // Low-pass filter
    this->roll = r;//(0.94*this->roll)+0.06*r;
    this->pitch = p;//(0.94*this->pitch)+0.06*p;
    this->theta = t;//(0.94*this->theta)+0.06*t;

    G[0].Ax = Ax;
    G[0].Ay = Ay;
    G[0].Az = Az;     //Acc Before=Present Acc

    FallDetection();
}

void BMA220::FallDetection()
{
    Calculate_Q1();
    Calculate_Q2();
    Calculate_Q3();

    /*Serial.println("Q0: ");
    display(Quanterion_2_Matrix(this->Q[0]));
    Serial.println("Q1: ");
    display(Quanterion_2_Matrix(this->Q[1]));
    Serial.println("Q2: ");
    display(Quanterion_2_Matrix(this->Q[2]));*/


    std::vector<std::vector<float> > Q;
    Q.resize(4, std::vector<float>(4));

    Q=MatrixMult(MatrixMult(Quanterion_2_Matrix(this->Q[0]), Quanterion_2_Matrix(this->Q[1])), Quanterion_2_Matrix(this->Q[2]));

    this->Q_result1.q0 = Q[0][0];
    this->Q_result1.q1 = Q[1][0];
    this->Q_result1.q2 = Q[2][0];
    this->Q_result1.q3 = Q[3][0];
    this->Q_result2.q0 = Q[3][3];
    this->Q_result2.q1 = -1 * Q[2][3];
    this->Q_result2.q2 = Q[1][3];
    this->Q_result2.q3 = -1 * Q[0][3];

    //result1.display();
    //result2.display();
}

void BMA220::Calculate_Q1()
{
    float theta1 = atan(G[0].Az / sqrt(pow(G[0].Ax, 2) + pow(G[0].Ay, 2))) * 180 / PI;
    float sin_alpha = (-1* (G[0].Ay / sqrt(pow(G[0].Ax, 2) + pow(G[0].Ay, 2)))) * 180 / PI;
    float cos_alpha = (G[0].Ax / sqrt(pow(G[0].Ax, 2) + pow(G[0].Ay, 2))) * 180 / PI;

    this->Q[0].q0 = cos(theta1 / 2);
    this->Q[0].q1 = sin(theta1 / 2) * sin_alpha;
    this->Q[0].q2 = sin(theta1 / 2) * cos_alpha;
    this->Q[0].q3 = 0;
}

void BMA220::Calculate_Q2()
{
    float theta2 = (atan((2 * G[1].Ay) / G[1].Ax) - atan((2 * G[0].Ay) / G[0].Ax)) * 180 / PI;

    this->Q[1].q0 = cos(theta2 / 2);
    this->Q[1].q1 = 0;
    this->Q[1].q2 = 0;
    this->Q[1].q3 = sin(theta2 / 2);
}

void BMA220::Calculate_Q3()
{
       float theta3 = -1 * atan(G[1].Az / sqrt(pow(G[1].Ax, 2) + pow(G[1].Ay, 2))) * 180 / PI;
       float sin_beta = (-1 * (G[1].Ay / sqrt(pow(G[1].Ax, 2) + pow(G[1].Ay, 2)))) * 180 / PI;
       float cos_beta = (G[1].Ax / sqrt(pow(G[1].Ax, 2) + pow(G[1].Ay, 2))) * 180 / PI;

       this->Q[2].q0 = cos(theta3 / 2);
       this->Q[2].q1 = sin(theta3 / 2) * sin_beta;
       this->Q[2].q2 = sin(theta3 / 2) * cos_beta;
       this->Q[2].q3 = 0;
}

std::vector<std::vector<float> > BMA220::Quanterion_2_Matrix(const Quanterion &Q)
{
    std::vector<std::vector<float> > result;
    result.resize(4, std::vector<float>(4));

    result[0][0] = Q.q0;
    result[0][1] = -1 * Q.q1;
    result[0][2] = -1 * Q.q2;
    result[0][3] = -1 * Q.q3;
    result[1][0] = Q.q1;
    result[1][1] = Q.q0;
    result[1][2] = -1 * Q.q3;
    result[1][3] = -1 * Q.q2;
    result[2][0] = Q.q2;
    result[2][1] = Q.q3;
    result[2][2] = Q.q0;
    result[2][3] = -1 * Q.q1;
    result[3][0] = Q.q3;
    result[3][1] = -1 * Q.q2;
    result[3][2] = Q.q1;
    result[3][3] = Q.q0;
    return result;
}

float BMA220::getAcceleration_X() const
{
    return Ax;
}

float BMA220::getAcceleration_Y() const
{
    return Ay;
}

float BMA220::getAcceleration_Z() const
{
    return Az;
}

float BMA220::getPitch() const
{
    return pitch;
}

float BMA220::getRoll() const
{
    return roll;
}

float BMA220::getTheta() const
{
    return theta;
}

float BMA220::getMag() const
{
    return  sqrt(pow(Ax, 2) + pow(Ay, 2)+ pow(Az, 2));
}

void BMA220::reset(void)
{
    ;
    resetvalue = readRegister(SOFTRESET_REG);
    if (resetvalue == 0x00) {
        // BMA220 is in reset mode now. Reading soft reset register
        // again, brings the sensor back to operation mode.
        resetvalue = readRegister(SOFTRESET_REG);
    }
}