Programme STM32

Dependencies:   mbed

main.cpp

Committer:
debontrg
Date:
2017-06-15
Revision:
0:029ef7913b96

File content as of revision 0:029ef7913b96:

#include "mbed.h"

#define N_mean 1000         // Number of elements for computed means
#define LIS2DW12_ADDR     (0x19<<1) // LIS2DW12 address
#define LIS2DW12_REG_CTRL1 (0x20) // CTRL registers
#define LIS2DW12_REG_CTRL2 (0x21)
#define LIS2DW12_REG_CTRL4 (0x23) // CTRL4 register
#define LIS2DW12_REG_INT_CFG (0x3F) // ABS_INT_CFG register
#define LIS2DW12_REG_ACC (0x28) // Acceleration Registers
#define LIS2DW12_REG_ID (0x0F) // Who am I Register


/////////////////////////   Calibration example   ///////////////////
/*

Calibration selon la note d'application ST DT0053 : 6-point tumble sensor calibration

[AccX]   [ Xgain  YtoX  ZtoX ][aX]   [Xofs]
[AccY] = [ XtoY   Ygain ZtoY ][aY] + [Yofs]
[AccZ]   [ XtoZ   YtoZ  Zgain][aZ]   [Zofs]

But de la calibration : Trouver les gains, cross-gains, et offsets.

Calibration : g = x : aX1=-16602 aY1=-420 aZ1=2001
Calibration : g = -x : aX2=16200 aY2=200 aZ2=-1180
Calibration : g = y : aX3=-540 aY3=-17045 aZ3=1150
Calibration : g = -y : aX4=-145 aY4=15980 aZ4=-417
Calibration : g = z : aX5=-500 aY5=-2000 aZ5=-15545
Calibration : g = -z : aX6=-474 aY6=-347 aZ6=17168

Xofs = mean([0.5*(aX1+aX2) 0.5*(aX3+aX4) 0.5*(aX5+aX6)]) = -343
Yofs = mean([0.5*(aY1+aY2) 0.5*(aY3+aY4) 0.5*(aY5+aY6)]) = -605
Zofs = mean([0.5*(aZ1+aZ2) 0.5*(aZ3+aZ4) 0.5*(aZ5+aZ6)]) = 529

Xgain = mean([aX1-Xofs -aX2+Xofs]) = -16401
XtoY = mean([aY1-Yofs -aY2+Yofs]) = -310
XtoZ = mean([aZ1-Zofs -aZ2+Zofs]) = 1590
YtoX = mean([aX3-Xofs -aX4+Xofs]) = -198
Ygain = mean([aY3-Yofs -aY4+Yofs]) -16513
YtoZ = mean([aZ3-Zofs -aZ4+Zofs]) = 783
ZtoX = mean([aX5-Xofs -aX6+Xofs]) = -13
ZtoY = mean([aY5-Yofs -aY6+Yofs]) = -826
Zgain = mean([aZ5-Zofs -aZ6+Zofs]) = -16357

*/

/////////////////// Input/Ouput definition /////////////////////////

I2C i2c(I2C_SDA, I2C_SCL);  // Add 1k pull-up with large cables

DigitalOut myled(LED1);

Serial pc(SERIAL_TX, SERIAL_RX);

InterruptIn Int1(PA_0);

AnalogOut AccAnalog(PA_4);

//////////////// Calibration Data ///////////
const float Xgain_B=-6.06830846623604e-05;
const float XtoY_B=2.05742031334719e-07;
const float XtoZ_B=2.97540475917473e-07;
const float YtoX_B=-4.01620573479568e-07;
const float Ygain_B=-6.04205456102837e-05;
const float YtoZ_B=7.50810587950758e-07;
const float ZtoX_B=-1.44447651263556e-07;
const float ZtoY_B=-8.29506849179693e-07;
const float Zgain_B=-6.10409298116465e-05;

const float Xofs=237.666666666667;
const float Yofs=-740.166666666667;
const float Zofs=803.166666666667;

/////////////  I2C buffers /////////////

char data_write[7];
char data_read[51];

/////////// Acceleration buffer ////////////
float real_acc[3]={0};

//////////// INT1 flag ////////////////
char flag=0;


/////////// Function prototypes (definition below) /////////////
void get_data(); // read acceleration in data_read[0:5]

void soft_reset(); // reset accelerometer internal parameters ("factory reset")

void powerup_accelerometer(); // power-up accelerometer and set basics parameters

void read_registers();  // read all accelerometer registers and print it on serial

void compute_acc(int16_t aX,int16_t aY,int16_t aZ); // compute real acceleration with calibration data

void mean_acc(int16_t aX,int16_t aY,int16_t aZ); // print mean accelerations on serial (N_mean samples)

///////// Interrupt function ///////////
// Each time INT1 rises, data are updated and can be read -> flag = 1
void int1_flag()
{
    flag=1;
}
    

int main()
{

// int16_t : signed integer, 16 bits
    int16_t aX;
    int16_t aY;
    int16_t aZ;
  
    pc.baud(115200); // Serial frequency = 115200 bit/s
    i2c.frequency(400000); //i2c frequency = 400000 bit/s
    
    // Hello
    pc.printf("\r\nHello world\r\n"); 
 
    // Set up interrutions ( a rising edge on INT1 triggers int1_flag)
    Int1.rise(&int1_flag);
    
    // Power-up and tune accelerometer
    powerup_accelerometer();
    wait(0.2);
    
 //////////// Uncomment / Comment each program section for different purposes

/////////// Section 1 : read and print all registers : debug purpose  //////    
/*
    read_registers();
*/


////////// Section 2 : Ask Accelerometer ID : debug purpose ///////   
 /*   
    
    // Read Accelerometer ID 
     data_write[0] = LIS2DW12_REG_ID;
    status = i2c.write(LIS2DW12_ADDR, data_write, 1, 1); // no stop
    // pc.printf("statuswrite=%d\t",status);
    status=i2c.read(LIS2DW12_ADDR, data_read, 1, 0);
    // pc.printf("statusread=%d\n\r",status);
    pc.printf("I am n°%d ",data_read[0]); 
*/
/////////////////////////////////////////////////////////////////////
/////////// Section 3 : print on serial adresses (in STM32 memory) of accelerations (computed = float, raw=int16_t)  ///////
 /*   pc.printf("adresse de aX, aY et aZ : %x %x %x \n\r",real_acc,&real_acc[1],&real_acc[2]);
    pc.printf("adresse de aXraw, aYraw et aZraw : %x %x %x \n\r",&aX,&aY,&aZ);
 */   
// End of intialization, main loop following :
    while (1) {
        if (flag==1) // INT1 rised, flag=1 => new data are readable
        {
        // Read acceleration register
        get_data();
           
        //Aggregate and cast acceleration data (2x8 bits -> 16 bits)
        
        aX= (int16_t)((int16_t)data_read[1] << 8) | data_read[0];
        aY= (int16_t)((int16_t)data_read[3] << 8) | data_read[2];
        aZ= (int16_t)((int16_t)data_read[5] << 8) | data_read[4];

////////////////// Section 4 : Mean raw accelerations  /////////
        mean_acc(aX,aY,aZ);  // print mean accelerations on serial (N_mean samples)


///////////////// Section 5 : Compute real accelerations with calibration parameters    /////
        // compute_acc(aX,aY,aZ); // Real acceleration are stored in real_acc[0:2]
       
   
        // Display result // Print raw acceleration and real acceleration /!\ It takes time and can slow the acquisition data rate
       // pc.printf("ax = %5d\t ay = %5d\t az=%5d\t ax = %2.2f\t ay = %2.2f\t az=%2.2f\r", aX,aY,aZ,real_acc[0],real_acc[1],real_acc[2]);

/////////////Section 6 : Write Acceleration on DAC//////////////////////////////////////////////
        
         // AccAnalog=(real_acc[2]);
  
        
        flag=0; // Lower the flag : new data can be read

        }
        else {

        }
    }

}

void get_data()
{
    
    data_write[0] = LIS2DW12_REG_ACC;
    i2c.write(LIS2DW12_ADDR, data_write, 1, 1); // no stop
    i2c.read(LIS2DW12_ADDR, data_read, 6, 0); // read 6 registers, beginning with LIS2DW12_REG_ACC
    data_read[6]=0;

}

void soft_reset()
{
    data_write[0] = LIS2DW12_REG_CTRL2;
    data_write[1] = 1<<6;
    i2c.write(LIS2DW12_ADDR, data_write, 2, 0);
}

void powerup_accelerometer()
{
    char status;
    // reset accelerometer registers
    soft_reset();
    
    // Switch on accelerometer + parameters :

    data_write[0] = LIS2DW12_REG_CTRL1;
    data_write[1] = (8<<4) |(1<<2);   // CTRL1 : High performance mode (14 bits res), 800Hz (i2c : t>185us pr récupérer les données, com: t>547us pour les transférer)
    data_write[2] = (1<<7) | (1<<2);   // CTRL2 : update trimming parameters, register adress +1 auto pr multiread (i2c)
    data_write[3] = 0x0;   // CTRL3 : self test off
    data_write[4] = 0x1;    // CTRL4 : int1 when data ready
  
    status = i2c.write(LIS2DW12_ADDR, data_write, 5, 0);

    if (status != 0) { // blink led if communication error
        while (1) {
            myled = !myled;
            wait(0.2);
        }
    }
 
    // Configure interruptions
    data_write[0] = LIS2DW12_REG_INT_CFG;
    data_write[1] =  (1<<7) | (1<<5);    // enable interrupt
    i2c.write(LIS2DW12_ADDR, data_write, 2, 0);
}

void read_registers()
{
    int i;
    char N=51;
    data_write[0] = 0x0d;
 /*   i2c.write(LIS2DW12_ADDR, data_write, 1, 1); // no stop
    i2c.read(LIS2DW12_ADDR, data_read, N, 0);
    for (i=0;i<N;i++)
    {
        pc.printf("register %X = %X \n\r",i+0x0D,data_read[i]);    
    }
*/    
    pc.printf("Registre par registre : \r\n");
    for (i=0;i<N;i++)
    {
        data_write[0] = 0x0d+i;
        i2c.write(LIS2DW12_ADDR, data_write, 1, 1); // no stop
        i2c.read(LIS2DW12_ADDR, data_read, 1, 0);
        pc.printf("register %X = %X \n\r",i+0x0D,data_read[0]);    
    }
}

void mean_acc(int16_t aX,int16_t aY,int16_t aZ)
{
    static int i=0;
    static int32_t moyaX=0;
    static int32_t moyaY=0;
    static int32_t moyaZ=0;
    moyaX=moyaX+aX;
    moyaY=moyaY+aY;
    moyaZ=moyaZ+aZ;
    i++;
    if(i==N_mean-1)
    {
        pc.printf("aX=%6d \t aY=%6d \t aZ=%6d \r",moyaX/N_mean,moyaY/N_mean,moyaZ/N_mean);
        i=0;
        moyaX=0;
        moyaY=0;
        moyaZ=0;
    }
}

void compute_acc(int16_t aX,int16_t aY,int16_t aZ)
{
            
       real_acc[0] = Xgain_B*(aX-Xofs) + YtoX_B*(aY-Yofs) + ZtoX_B*(aZ-Zofs);
       real_acc[1] = XtoY_B*(aX-Xofs) + Ygain_B*(aY-Yofs) + ZtoY_B*(aZ-Zofs);
       real_acc[2] = XtoZ_B*(aX-Xofs) + YtoZ_B*(aY-Yofs) + Zgain_B*(aZ-Zofs);
       
}