Based on https://os.mbed.com/users/Airium/code/module_LSM303DLHC/ Main difference is the usage of the I2C - now it is passed as parameter making cooperative use easier. LSM303DLHC Full Driver: Readings For Acc, Mag and Temp; Class Method for frequently-used 13 sensor parameters; Class Method to direct modify registers; Support Calibration (offset scale);

LSM303DLHC.h

Committer:
Pythia
Date:
2020-02-03
Revision:
1:4ee6df2df73a
Parent:
0:a4131de4bddd

File content as of revision 1:4ee6df2df73a:

/* COMPACT USER INSTRUCTION OF LSM303DLHC

-- ACCELEROMETER PART
void GetAcc( float arr[3] ) // Get Acceleration Value
    arr[3] is the xyz-axis acc data 
    // default range from -2048 to +2047 with step=1 (12bit high prec) or step=4 (10bit normal prec)
    // and roughly 1000/g(+/-2g) 500/g(+/-4g) 200/g(+/-8g) 80/g(+/-16g) depend on your device and ACC_FS
    // note your calibration setting will change the range
void ACtrl( enum cmd ) e.g. ACtrl(LSM303DLHC::LP_ON)
    enum ACC_LPen {LP_OFF,LP_ON} // to ctrl acc power mode
    enum ACC_ODR  {PW_D,ADR1,ADR2,ADR3,ADR4,ADR5,ADR6,ADR7,ADR8,ADR9} // to ctrl acc data rate
    enum ACC_AXIS {NONE,X,Y,XY,Z,XZ,YZ,XYZ} // to sel the acc data of axis you want
    enum ACC_HPM  {HPF_NORM_R,HPF_REF,HPF_NORM,HPF_AUTO} // to sel acc internal HPF model       
    enum ACC_HPCF {HPF_CF0,HPF_CF1,HPF_CF2,HPF_CF3} // to switch acc internal HPF cutoff freq
    enum ACC_FDS  {HPF_OFF,HPF_ON} // to switch on/off acc internal HPF for output                                 
    enum ACC_BDU  {BDU_CONT,BDU_HOLD} // to sel acc data update mode
    enum ACC_FS   {G2,G4,G8,G16} // to sel acc full scale of data
    enum ACC_HR   {LOW_R,HIGH_R} // to sel acc output data precision
void ACal( float offset[3], float scale[3] ); // Acc Calibration Setting
    // affect data of GetAcc() by output = scale * ( offset + original )
    // but if internal HPF enable then output = scale * original
    // note linear acc has no offset

-- MAGNETOMETER PART
void GetMag( float arr[3] );  // Get magnetic flux density
    arr[3] is the xyz-axis mag data
    // default range from -2048 to +2047 with step=1
    // note your calibration setting will change the range
void MCtrl( enum cmd ) e.g. MCtrl(LSM303DLHC::MDR3);      
    enum MAG_DR {MDR0,MDR1,MDR2,MDR3,MDR4,MDR5,MDR6,MDR7} // to ctrl mag data rate
    enum MAG_GN {GN1,GN2,GN3,GN4,GN5,GN6,GN7) // to ctrl mag full scale of data
    enum MAG_MD {MD_CONT,MD_SING,MD_SLP,MD_SLP2}; 
void MCal(float offset[3], float scale[3]); // Mag Calibration
    // affect data of GetMag() by output = scale * ( offset + original )
    
-- TEMPERATURE METER PART
void GetTemp( float arr[1] ); // Get temperature
    arr[1] is the temperture
    // default range from -2048 to +2047
void TCal( enum cmd )
    enum TEMP_EN{TEMP_OFF,TEMP_ON}; // to switch on/off TEMP
void TempCal(float offset[1], float scale[1]); // Mag Calibration 
    //affect data of GetMag() by output = scale * ( offset + original )

-- DIRECT WRITE REG
void WriteReg(int sad, char d[2]); // Write value to reg
    sad = ACC_ADDRESS or MAG_ADDRESS
    d[0] = Register Address
    d[1] = Register Value
    CAUTION: THE FUNTION USES UNFRIENDLY ASSIGN
    CAUTION: WRITING TO RESERVED REG MAY CAUSE PERMANENT DAMAGE
    PLEASE FOLLOW DATASHEET RIGIDLY        
*/


#ifndef LSM303DLHC_H
#define LSM303DLHC_H
#include "mbed.h"
#include "LSM303DLHC_REG.h"

class LSM303DLHC {
    public:
        //// PORT
        LSM303DLHC(I2C &i2c);
        
        //// REG CTRL
        // modify the default in LSM303DLHC.cpp
        
        //// CTRL_REG1_A (20h)
        // ACC Low Power Mode ON/OFF
        enum ACC_LPen { LP_OFF = 0, LP_ON = 1} ;
        void ACtrl(ACC_LPen cmd); 
        // ACC Data Rate        NOTE: ACC SWITCH IS HERE
        enum ACC_ODR { PW_D = 0, ADR1 = 1, ADR2 = 2, ADR3 = 3, ADR4 = 4, ADR5 = 5, ADR6 = 6,  ADR7 = 7, ADR8 = 8, ADR9 = 9};
             //        PW Down   1Hz       10Hz      25Hz      50Hz      100Hz     200Hz      400Hz     1620Hz@LP 1344Hz@NM/5376HZ@LP  
        void ACtrl(ACC_ODR cmd); 
        // ACC AXIS SEL
        enum ACC_AXIS { NONE = 0, X = 1, Y = 2, XY = 3, Z = 4, XZ = 5, YZ = 6, XYZ = 7 };
        void ACtrl(ACC_AXIS cmd);
        
        //// CTRL_REG2_A (21h)
        // ACC HPF Mode
        enum ACC_HPM { HPF_NORM_R = 0, HPF_REF = 1, HPF_NORM = 2, HPF_AUTO = 3 };
        void ACtrl(ACC_HPM cmd);
        // ACC HPF Cutoff Freq             
        enum ACC_HPCF { HPF_CF0 = 0, HPF_CF1 = 1, HPF_CF2 = 2, HPF_CF3 = 3};
        void ACtrl(ACC_HPCF cmd);
        // ACC HPF ON/OFF for output
        enum ACC_FDS { HPF_OFF = 0, HPF_ON = 1 };                                 
        void ACtrl(ACC_FDS cmd);     
                
        //// CTRL_REG4_A (23h)
        // ACC Block Date Update Mode
        enum ACC_BDU { BDU_CONT = 0, BDU_HOLD = 1 };
        void ACtrl(ACC_BDU cmd); 
        // ACC Output Full-Scale SEL    
        enum ACC_FS {G2 = 0b00, G4 = 0b01, G8 = 0b10, G16= 0b11 }; 
             //      +/-2g      +/-4g      +/-8g      +/-16g 
        void ACtrl(ACC_FS cmd);
        // ACC Output in High/Low Resolution (Precision SEL)      
        enum ACC_HR { LOW_R = 0, HIGH_R = 1 }; 
             //       10bit      12bit
        void ACtrl(ACC_HR cmd);
                
        //// CRA_REG_M (00h)
        // TEMP Sensor En       NOTE: TEMP SWITCH IS HERE
        enum TEMP_EN { TEMP_OFF = 0, TEMP_ON = 1};
        void TCtrl(TEMP_EN cmd);       
        // MAG Data Rate (Note: MAG_DR determines DRDY pin)
        enum MAG_DR { MDR0 = 0, MDR1 = 1, MDR2 = 2, MDR3 = 3, MDR4 = 4, MDR5 = 5, MDR6 = 6, MDR7 = 7};
             //       0.75Hz   1.5Hz    3Hz      7.5Hz        15Hz     30Hz     75Hz     220Hz
        void MCtrl(MAG_DR cmd);     // MAG Date Rate
                
        //// CRB_REG_M (01h)
        // MAG Gain (Range SEL)
        enum MAG_GN { GN1 = 1, GN2 = 2, GN3 = 3, GN4 = 4, GN5 = 5, GN6 = 6, GN7 = 7};
             //       1.3      1.9      2.5      4.0      4.7      5.6      8.1    (+/- Gauss)    
        void MCtrl(MAG_GN cmd);     // MAG Measure Range
                
        //// MR_REG_M (02h)
        // MAG Mode     NOTE: MAG SWITCH IS HERE
        enum MAG_MD { MD_CONT = 0, MD_SING = 1, MD_SLP = 2, MD_SLP2 = 3}; 
             //       Continuous   single-conv  sleep-mode  sleep-mode
        void MCtrl(MAG_MD cmd);     

        //// Change more regs        
        void WriteReg(int sad, char d[2]); // Write value to reg
        // sad = ACC_ADDRESS or MAG_ADDRESS
        // d[0] = Register Address and d[1] = Register Value
        // CAUTION: THE FUNTION USES UNFRIENDLY ASSIGN AND WRITING TO RESERVED REG MAY CAUSE PERMANENT DAMAGE
        // PLEASE FOLLOW DATASHEET RIGIDLY        

        //// Get Data
        // please refer to the top: COMPACT USER INSTRUCTION        
        int GetAcc(float arr[3]);  // Get acc
        int GetMag(float arr[3]);  // Get mag
        int GetTemp(float arr[1]); // Get temp
        
        //// sensor reading calibration
        // please refer to the top: COMPACT USER INSTRUCTION
        void ACal(float offset[3], float scale[3]); // Acc Calibration
        void MCal(float offset[3], float scale[3]); // Mag Calibration
        void TCal(float offset[1], float scale[1]); // Mag Calibration    
        
          
        //// Not implemented function
        bool isAccRdy(); // Check if acc has new data 
        // one way is to use high freq ticker to check STATUS_REG_A (27h)
        // I2C@400kHz just enough to check Max Normal Mode Data Rate (1344Hz)
        // or someone to teach me how to use CTRL_REG6_A THX THX THX (:
        bool isMagRdy(); // check if mag has new data
        // one way is to use InterruptIn to trigger from DRDY pin
        // DRDY pin freq defined by MAG_DR
        
    private:
        I2C *_i2c;
        
        char data[6];       // used as main data exchange
               
        // use offset to calibrate zero reading
        float acc_offset[3];
        float mag_offset[3];
        float temp_offset[1];
        
        //use scale to adjust the range to required
        float acc_scale[3];
        float mag_scale[3];
        float temp_scale[1];
        
        // chip count to unit conversion
        float acc_scale_multiplier;
        float mag_scale_x_multiplier;
        float mag_scale_y_multiplier;
        float mag_scale_z_multiplier;
};

/*
Original main.c

#include "mbed.h"
#include "LSM303DLHC.h"

// LSM303DLHC sensor(p9,p10);

Serial pc(USBTX,USBRX);
Ticker ticker;

float acc[3] = { 0 };
float mag[3] = { 0 };
float tmp[1] = { 0 };

void CallBack();

int main(){
    pc.baud(921600);
    
    // example setup
    // refer to LSM303DLHC.h for more overloaded details for ACtrl() MCtrl() TCtrl()   
    sensor.MCtrl(LSM303DLHC::GN1);          // set mag range +/-1.3Gausee
    sensor.MCtrl(LSM303DLHC::MDR3);          // set mag date rate 7.5Hz
    sensor.ACtrl(LSM303DLHC::G8);           // set acc range +/-8g
    sensor.ACtrl(LSM303DLHC::ADR2);         // set acc date rate 10Hz
    sensor.ACtrl(LSM303DLHC::HPF_OFF);      // disable internal acc HPF

    float acc_offset[3] = { 6.5, 5, 12.5 };  // acc offset
    float acc_scale[3] = { 3.9, 4, 4 };      // acc scale
    sensor.ACal(acc_offset,acc_scale);    // set acc calibration
    
    ticker.attach(&CallBack, 0.2);  // read and refresh disp with 200ms interval   
 
    while (1) 
        wait_us(1);
}

void CallBack(){
    sensor.GetAcc(acc);
    sensor.GetMag(mag);
    sensor.GetTemp(tmp);

    pc.printf("A %5f %5f %5f\n\r", acc[0], acc[1], acc[2]);
    pc.printf("M %5f %5f %5f\n\r", mag[0], mag[1], mag[2]);
    pc.printf("T %5f\n\r", tmp[0]);  
}
    
*/


#endif