Gaëtan Debontride
/
Nucleo_i2c_LIS2DW12_Dubald_Picard
Programme STM32
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); }