code including all sensors

Dependencies:   LAAP AK8963

main.cpp

Committer:
Glaxys_finest1
Date:
2019-11-25
Revision:
0:66a265dc3146

File content as of revision 0:66a265dc3146:

/* mbed Microcontroller Library
 * Copyright (c) 2018 ARM Limited
 * SPDX-License-Identifier: Apache-2.0
 */

#include "mbed.h"
#include "ak8963.h"
#include <stddef.h>
#include <stdio.h>                // This ert_main.c example uses printf/fflush
#include "LAAP.h"                      // Model's header file
#include "rtwtypes.h"

static LAAPModelClass rtObj;           // Instance of model class

void rt_OneStep(void);
void rt_OneStep(void)
{
  static boolean_T OverrunFlag = false;

  // Disable interrupts here

  // Check for overrun
  if (OverrunFlag) {
    rtmSetErrorStatus(rtObj.getRTM(), "Overrun");
    return;
  }

  OverrunFlag = true;

  // Save FPU context here (if necessary)
  // Re-enable timer or interrupt here
  // Set model inputs here

  // Step the model
  rtObj.step();

  // Get model outputs here

  // Indicate task complete
  OverrunFlag = false;

  // Disable interrupts here
  // Restore FPU context here (if necessary)
  // Enable interrupts here
}
/*
#define AK8963_ADDRESS   0x0C
#define WHO_AM_I_AK8963  0x00 // should return 0x48
#define INFO             0x01
#define AK8963_ST1       0x02  // data ready status bit 0
#define AK8963_XOUT_L    0x03  // data
#define AK8963_XOUT_H    0x04
#define AK8963_YOUT_L    0x05
#define AK8963_YOUT_H    0x06
#define AK8963_ZOUT_L    0x07
#define AK8963_ZOUT_H    0x08
#define AK8963_ST2       0x09  // Data overflow bit 3 and data read error status bit 2
#define AK8963_CNTL      0x0A  // Power down (0000), single-measurement (0001), self-test (1000) and Fuse ROM (1111) modes on bits 3:0
#define AK8963_ASTC      0x0C  // Self test control
#define AK8963_I2CDIS    0x0F  // I2C disable
#define AK8963_ASAX      0x10  // Fuse ROM x-axis sensitivity adjustment value
#define AK8963_ASAY      0x11  // Fuse ROM y-axis sensitivity adjustment value
#define AK8963_ASAZ      0x12  // Fuse ROM z-axis sensitivity adjustment value
*/
#define USER_CTRL        0x6A;
#define I2C_MST_EN       0x20;

#define MPU6050_ADDR         0xD0
#define MPU6050_SMPLRT_DIV   0x19
#define MPU6050_CONFIG       0x1a
#define MPU6050_GYRO_CONFIG  0x1b
#define MPU6050_ACCEL_CONFIG 0x1c
#define MPU6050_WHO_AM_I     0x75
#define MPU6050_PWR_MGMT_1   0x6b
#define ACCEL_XOUT_H_REG 0x3B
#define Alfa_comp 0.96

    double  Ax, Ay, Az, Gx, Gy, Gz,Mx,My,Mz;
    
    double   H_senx,H_seny,H_senz;
    char   name[1];
     
    int16_t Mag_X_RAW = 0;
    int16_t Mag_Y_RAW = 0;
    int16_t Mag_Z_RAW = 0;

    double avgx,avgy,avgz;
    double rate,bias=0; 
    double angle;
    
    double pitch_acc=0, roll_acc=0;
    double pitch_gyro=0, roll_gyro=0;
    double pitch=0, roll=0,yaw=0;
    double dtx,dtx1,dtx2,dt=0,dt1,dt2;
    //global variables for meaured pwm values
    uint16_t Rip_chnl_n[6],Rip_chnl_p[6];
    
    int distx,disty,distz;
    int distxo,distyo,distzo;
    int velocityx,velocityy,velocityz;
    
//////////////////////To measure pwm using interrupts and timer///////////////////////////////
InterruptIn ch1(PG_2);
InterruptIn ch2(PG_3);
InterruptIn ch3(A4);
InterruptIn ch4(A5);
InterruptIn ch5(PG_0);
InterruptIn ch6(PG_1);
///////////////////////////////////////////////////////////////////////////////////////////
//////////////////// pwm out for ESC inputs////////////////////////////////////////////////
PwmOut u1(PE_9);
PwmOut u2(PE_11);
PwmOut u3(PE_12);
PwmOut u4(PE_14);
///////////////////////////I2C/////////////////////////////////////////////////////////////
I2C i2c(PF_15,PF_14);
//////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////LIDAR serial ports/////////////////////////////////////////
RawSerial rawz(PD_5,PD_6);
RawSerial rawx(PC_10,PC_11);
RawSerial rawy(PC_12,PD_2); 
//////////////////////////////////////////////////////////////////////////////////////////
//////////blue light indicator for error in i2c///////////////////////////////////////////
DigitalOut myled(LED2); 
//////////////////////////////////////////////////////////////////////////////////////////
Serial pc(SERIAL_TX, SERIAL_RX);

Timeout onestep;

Timer timer1,timer2;
////////////////////////////////function initializations/////////////////////////////////
void stop_counter();
void start_counter();
void counters_init();

void dist_x();
void dist_y();
void dist_z();

void mpu_init();
void mpu_read();
void get_angle();
void mpu_calibrate();
void Mag_init();
void Mag_read();

onestep.attach_us(&rt_OneStep(),100);

int main()
{   
    counters_init();
    
    pc.baud(115200);
    
    rawx.baud(115200);
    rawy.baud(115200);
    rawz.baud(115200);
    
    rawx.attach(&dist_x);
    rawy.attach(&dist_y);
    rawz.attach(&dist_z);
    
    mpu_init();
    //Mag_init();  
    /*AK8963 mag(&i2c, AK8963::SLAVE_ADDR_1);
    if(mag.checkConnection() != AK8963::SUCCESS){
        pc.printf("check connection");
        
        }
    if(mag.setOperationMode(AK8963::MODE_CONTINUOUS_1) != AK8963::SUCCESS){
        while(1){pc.printf("failed continious mode");}
        }*/
    timer1.start(); //////////////timer for channel  
    timer2.start(); /////////////timer for dt to calculate dt
   
    //mpu_calibrate();
    
    
    u1.period_us(20000);
    u2.period_us(20000);
    u3.period_us(20000);
    u4.period_us(20000);
      
    
    while(timer2.read_ms()<5000)
    {    u1.write((float)rtObj.getu1_());
        u2.write((float)rtObj.getu2_());
        u3.write((float)rtObj.getu3 ());
        u4.write((float)rtObj.getu4 ());
        
        }
     
    


    while (true) 
    {   int i;
        //int statusAK8963= AK8963::NOT_DATA_READY;
    
         
        get_angle();
        
       /* if(statusAK8963 == AK8963::DATA_READY){
            AK8963::MagneticVector mag1;
            mag.getMagneticVector(&mag1);
            pc.printf("%5.1f,%5.1f,%5.1f\n",mag1.mx,mag1.my,mag1.mz);
            statusAK8963 = AK8963::NOT_DATA_READY;
            } else if (statusAK8963 == AK8963::NOT_DATA_READY){
                }
        
        
        for(int i=1000;i<2000;i++){
         u1.write((float)i/20000.0);
        u2.write((float)i/20000.0);
        u3.write((float)i/20000.0);
        u4.write((float)i/20000.0);
        wait(0.0001);}
        for(int i=2000;i>1000;i--){
         u1.write((float)i/20000.0);
        u2.write((float)i/20000.0);
        u3.write((float)i/20000.0);
        u4.write((float)i/20000.0);
        wait(0.0001);}*/
       // Mag_read();
       //for(i=0;i<6;i++)
        //pc.printf("%d\t",Rip_chnl_n[i]);
      // pc.printf("\n");
     /*  pc.printf("pitch =  %f\t",pitch);
       pc.printf("roll =  %f\t",roll);
       pc.printf("yaw =  %f\t",yaw);
       */
       pc.printf("x =  %d\t",distx);
       pc.printf("y =  %d\t",disty);
       pc.printf("z =  %d\n",distz);
       
       
       
       //pc.printf("magx =  %d\t",name[0]);
       //pc.printf("raw =  %d\t",Mag_X_RAW);
       //pc.printf("mx =  %f\t",Mx);
       //wait(0.01);
      // 
       }
}


///////////////////////////////////////////////////////////////functions//////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////********************************functions for interrupts*****************************////////////////
void start_counter_1()
{
     Rip_chnl_p[0]=timer1.read_us();
    }
void start_counter_2(){
    Rip_chnl_p[1]=timer1.read_us();
    }
void start_counter_3(){
    Rip_chnl_p[2]=timer1.read_us();
    }
void start_counter_4(){
   Rip_chnl_p[3]=timer1.read_us();
    }
void start_counter_5(){
    Rip_chnl_p[4]=timer1.read_us();
    }
void start_counter_6(){
    Rip_chnl_p[5]=timer1.read_us();
    }
void stop_counter_1(){
   uint32_t x;
    x=timer1.read_us();
   Rip_chnl_n[0]=x-Rip_chnl_p[0];
    }
void stop_counter_2(){
    uint32_t x;
    x=timer1.read_us();
   Rip_chnl_n[1]=x-Rip_chnl_p[1];
    }
void stop_counter_3(){
   uint32_t x;
    x=timer1.read_us();
   Rip_chnl_n[2]=x-Rip_chnl_p[2];
    }
void stop_counter_4(){
    uint32_t x;
    x=timer1.read_us();
   Rip_chnl_n[3]=x-Rip_chnl_p[3];
    }
void stop_counter_5(){
    uint32_t x;
    x=timer1.read_us();
   Rip_chnl_n[4]=x-Rip_chnl_p[4];
    }
void stop_counter_6(){
    uint32_t x;
    x=timer1.read_us();
   Rip_chnl_n[5]=x-Rip_chnl_p[5];
    }

void counters_init(){
    ch1.rise(&start_counter_1);
    ch2.rise(&start_counter_2);
    ch3.rise(&start_counter_3);
    ch4.rise(&start_counter_4);
    ch5.rise(&start_counter_5);
    ch6.rise(&start_counter_6);
    ch1.fall(&stop_counter_1);
    ch2.fall(&stop_counter_2);
    ch3.fall(&stop_counter_3);
    ch4.fall(&stop_counter_4);
    ch5.fall(&stop_counter_5);
    ch6.fall(&stop_counter_6);
    }
    

//////////////////////////////***********************************LIDAR********************************************////////////////
void dist_x() ///////////*******use this function to get distance it has object of rawserial as argument*******////////////
    { //int distance;//actual distance measurements of LiDAR
    int strength;//signal strength of LiDAR
    int check;//save check value
    int i;
    int uartx[9];//save data measured by LiDAR
    
        if (rawx.readable())//check if serial port has data input
    {       
        if(rawx.getc()==0x59)//assess data package frame header 0x59
        {
            uartx[0]=0x59;
            if(rawx.getc()==0x59)//assess data package frame header 0x59
                {
                    uartx[1]=0x59;
                    for(i=2;i<9;i++)//save data in array
                        {
                        uartx[i]=rawx.getc();
                        }
                    check=uartx[0]+uartx[1]+uartx[2]+uartx[3]+uartx[4]+uartx[5]+uartx[6]+uartx[7];
                    if(uartx[8]==(check&0xff))//verify the received data as per protocol
                        {
                            
                            
                        strength=uartx[4]+uartx[5]*256;//calculate signal strength value
                        distx=uartx[2]+uartx[3]*256;//calculate distance value in cm
                        //velocityx = distx - distxo;  ////velocity in meters
                          //distxo = distx;
                        }
                }
        }
    } 
    
  }
void dist_y() ///////////*******use this function to get distance it has object of rawserial as argument*******////////////
    { 
    int strength;//signal strength of LiDAR
    int check;//save check value
    int i;
    int uarty[9];//save data measured by LiDAR
    
        if (rawy.readable())//check if serial port has data input
    {
        if(rawy.getc()==0x59)//assess data package frame header 0x59
        {
            uarty[0]=0x59;
            if(rawy.getc()==0x59)//assess data package frame header 0x59
                {
                    uarty[1]=0x59;
                    for(i=2;i<9;i++)//save data in array
                        {
                        uarty[i]=rawy.getc();
                        }
                    check=uarty[0]+uarty[1]+uarty[2]+uarty[3]+uarty[4]+uarty[5]+uarty[6]+uarty[7];
                    if(uarty[8]==(check&0xff))//verify the received data as per protocol
                        {
                            
                        strength=uarty[4]+uarty[5]*256;//calculate signal strength value
                        disty=uarty[2]+uarty[3]*256;//calculate distance value
                         //velocityy = disty - distyo;  ////velocity in meters
                          //distyo = disty;
                        }
                        
                }
        }
    } 
    
  }
  void dist_z() ///////////*******use this function to get distance it has object of rawserial as argument*******////////////
    { 
    int strength;//signal strength of LiDAR
    int check;//save check value
    int i;
    int uartz[9];//save data measured by LiDAR
    
        if (rawz.readable())//check if serial port has data input
    {
        if(rawz.getc()==0x59)//assess data package frame header 0x59
        {
            uartz[0]=0x59;
            if(rawz.getc()==0x59)//assess data package frame header 0x59
                {
                    uartz[1]=0x59;
                    for(i=2;i<9;i++)//save data in array
                        {
                        uartz[i]=rawz.getc();
                        }
                    check=uartz[0]+uartz[1]+uartz[2]+uartz[3]+uartz[4]+uartz[5]+uartz[6]+uartz[7];
                    if(uartz[8]==(check&0xff))//verify the received data as per protocol
                        { 
                        strength=uartz[4]+uartz[5]*256;//calculate signal strength value
                        distz=uartz[2]+uartz[3]*256;//calculate distance value
                         //velocityz = distz - distzo;  ////velocity in meters
                          //distzo = distz;
                        }
                }
        }
    } 
    
  }
  //////////////////////////////////**********velocity**************//////////////////////////////////////
 

/////////////////////////////////***********************mpu****************************///////////////////////////////

 void mpu_init()
 {
     i2c.frequency(100000);
    char data_write[2];
    
    data_write[0] = MPU6050_PWR_MGMT_1;
    data_write[1] = 0x00;
    
    int status = i2c.write(MPU6050_ADDR, data_write, 2, 0);
    
    if (status != 0)
     { // Error
             while (1)
          {
            myled = !myled;
            wait(0.2);
           }
    }
    data_write[0] = USER_CTRL;
    data_write[1] = I2C_MST_EN;
    i2c.write(MPU6050_ADDR, data_write, 2, 0);
    
     data_write[0] = 0x37;//INT_PIN_CFG;
    data_write[1] = 0x02;
    i2c.write(MPU6050_ADDR, data_write, 2, 0);
    
    data_write[0] = MPU6050_SMPLRT_DIV;
    data_write[1] = 0x07;
    i2c.write(MPU6050_ADDR, data_write, 2, 0);
    
    data_write[0] = MPU6050_ACCEL_CONFIG;
    data_write[1] = 0x00;
    i2c.write(MPU6050_ADDR, data_write, 2, 0);
    data_write[0] = 0x1d;
    data_write[1] = 0x06;
    i2c.write(MPU6050_ADDR, data_write, 2, 0);
    data_write[0] = MPU6050_CONFIG;
    data_write[1] = 0x00;
    i2c.write(MPU6050_ADDR, data_write, 2, 0);
    
    data_write[0] = MPU6050_GYRO_CONFIG;
    data_write[1] = 0x00;
    i2c.write(MPU6050_ADDR, data_write, 2, 0);
    wait(0.2);
 }

void mpu_read(){
    char Rec_Data[14];
    int16_t Accel_X_RAW = 0;
    int16_t Accel_Y_RAW = 0;
    int16_t Accel_Z_RAW = 0;
    int16_t Temp_raw = 0;
    int16_t Gyro_X_RAW = 0;
    int16_t Gyro_Y_RAW = 0;
    int16_t Gyro_Z_RAW = 0;
    char data_write[1];
    
    // Read 1 BYTES of data starting from ACCEL_XOUT_H register
    data_write[0] = ACCEL_XOUT_H_REG;
        i2c.write(MPU6050_ADDR, data_write, 1, 1); // no stop
        i2c.read(MPU6050_ADDR, Rec_Data, 14);
    Accel_X_RAW = (int16_t)(Rec_Data[0] << 8 | Rec_Data [1]);
    Accel_Y_RAW = (int16_t)(Rec_Data[2] << 8 | Rec_Data [3]);
    Accel_Z_RAW = (int16_t)(Rec_Data[4] << 8 | Rec_Data [5]);
    
    Temp_raw = (int16_t)(Rec_Data[6] << 8 | Rec_Data [7]);
    
    Gyro_X_RAW = (int16_t)(Rec_Data[8] << 8 | Rec_Data [9]);
    Gyro_Y_RAW = (int16_t)(Rec_Data[10] << 8 | Rec_Data [11]);
    Gyro_Z_RAW = (int16_t)(Rec_Data[12] << 8 | Rec_Data [13]);
    /*** convert the RAW values into acceleration in 'g'
         we have to divide according to the Full scale value set in FS_SEL
         I have configured FS_SEL = 0. So I am dividing by 16384.0
         for more details check ACCEL_CONFIG Register              ****/

    Ax = Accel_X_RAW/16384.0;
    Ay = Accel_Y_RAW/16384.0;
    Az = Accel_Z_RAW/16384.0;
    
    Gx = Gyro_X_RAW/131.0;
    Gy = Gyro_Y_RAW/131.0;
    Gz = Gyro_Z_RAW/131.0;
    
    }
   
     
 void get_angle(){
    
      mpu_read();
        dt2=timer2.read_ms();                 ////////****very imp self note check the order of dt1 and dt2*********/////////// 
        dt=dt2-dt1;
        dt=dt/1000;
        
            roll_acc = (atan2((Ay),sqrt(pow((Ax),2) + pow((Az),2))))*(90*7/11);
            pitch_acc = ((atan2((-Ax),sqrt(pow((Ay),2) + pow((Az),2))))*(90*7/11));
       
              /* COMPLIMENTARY FILTER*/
            pitch = Alfa_comp*(pitch + Gy*dt) + (1-Alfa_comp)*pitch_acc ;
            
            roll = Alfa_comp*(roll + Gx*dt) + (1-Alfa_comp)*roll_acc ;
            if(abs(Gz)>1)
           yaw += Gz*dt;
       dt1=timer2.read_ms();
         
         }
 void mpu_calibrate(void){
        int i;
        for(i=0;i<=3000;i++)
    {
        //dt2=timer2.read_ms();
        if(i>0){
        get_angle();}
       
       // dt1=timer2.read_ms();
        //dt=dt1-dt2;
        
        avgx+=roll;
        avgy+=pitch;
        //avgz+=yaw;
     }
        avgx=avgx/3000;
        avgy=avgy/3000;
       // avgz=avgz/2000;
        }
 /*void Mag_init(){
     char raw[3];
     char data_write[2];

///////////////////////////////////////// Power down magnetometer///////////////////////////////////////////////////////  
    data_write[0] = AK8963_CNTL;
    data_write[1] = 0x00;
    
      int status = i2c.write(AK8963_ADDRESS, data_write, 2, 0);
       if (status != 0)
     { // Error
             while (1)
          {
            myled = !myled;
            wait(0.2);
           }
    }
    
    wait(0.01);
    data_write[0] = 0x6B;                   //////////////////rest magnetometer
    data_write[1] = 0x80;
    
     i2c.write(MPU6050_ADDR, data_write, 2, 0);
    
    
    wait(0.01);
///////////////////////////////////////// Enter Fuse ROM access mode///////////////////////////////////////////////////  
  data_write[0] = AK8963_CNTL;
    data_write[1] = 0x0F;
    i2c.write(AK8963_ADDRESS, data_write, 2, 0);
  
   wait(0.01);
///////////////////////////////////////// Read the x-, y-, and z-axis calibration values//////////////////////////////   
   data_write[0] = AK8963_ASAX;
    i2c.write(AK8963_ADDRESS, data_write, 1, 0);
    i2c.read(AK8963_ADDRESS, raw, 3);
// Return x-axis sensitivity adjustment values, etc.    
  H_senx =  (float)(raw[0] - 128)/256.0f + 1.0f;   
  H_seny =  (float)(raw[1] - 128)/256.0f + 1.0f;  
  H_senz =  (float)(raw[2] - 128)/256.0f + 1.0f; 
   
    data_write[0] = AK8963_CNTL;
    data_write[1] = 0x16;
    i2c.write(AK8963_ADDRESS, data_write, 2, 0);
    wait(0.01);
    data_write[0] = 0x0B;
    data_write[1] = 0x01;
    i2c.write(AK8963_ADDRESS, data_write, 2, 0);
    wait(0.01);
  // Configure the magnetometer for continuous read and highest resolution
  // set Mscale bit 4 to 1 (0) to enable 16 (14) bit resolution in CNTL register,
  // and enable continuous mode data acquisition Mmode (bits [3:0]), 0010 for 8 Hz and 0110 for 100 Hz sample rates
 
     }
void Mag_read(){
    
    char data_write[1];
    char x[1];
    char rawData[7]; 
 /////////////read name///////////////////////////////////     
data_write[0] = WHO_AM_I_AK8963;
    i2c.write(AK8963_ADDRESS, data_write, 1, 0);
   i2c.read(AK8963_ADDRESS, name, 1);
   
    //////////////////////////////////////
    data_write[0] = AK8963_ST1;
    i2c.write(AK8963_ADDRESS, data_write, 1, 0);
    i2c.read(AK8963_ADDRESS, x, 1);
    
   if(x[0] & 0x01) { // wait for magnetometer data ready bit to be set
    data_write[0] = AK8963_XOUT_L;// Read the six raw data and ST2 registers sequentially into data array
    i2c.write(AK8963_ADDRESS, data_write, 1, 1);
    i2c.read(AK8963_ADDRESS, rawData, 7);
 
  uint8_t c = rawData[6]; // End data read by reading ST2 register
    if(!(c & 0x08)) { // Check if magnetic sensor overflow set, if not then report data
    Mag_X_RAW = (int16_t)((rawData[1] << 8) | rawData[0]);  // Turn the MSB and LSB into a signed 16-bit value
    Mag_Y_RAW = (int16_t)((rawData[3] << 8) | rawData[2]) ;  // Data stored as little Endian
    Mag_Z_RAW = (int16_t)((rawData[5] << 8) | rawData[4]) ; 
                   }
          }
    Mx = Mag_X_RAW*H_senx;
    My = Mag_Y_RAW*H_seny;
    Mz = Mag_Z_RAW*H_senz;
 }*/