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@1:4ee6df2df73a, 2020-02-03 (annotated)
- Committer:
- Pythia
- Date:
- Mon Feb 03 07:43:48 2020 +0000
- Revision:
- 1:4ee6df2df73a
- Parent:
- 0:a4131de4bddd
Version working. Temperature sensor provide strange results. Is to be extended with orientation measurement.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Pythia | 0:a4131de4bddd | 1 | /* COMPACT USER INSTRUCTION OF LSM303DLHC |
Pythia | 0:a4131de4bddd | 2 | |
Pythia | 0:a4131de4bddd | 3 | -- ACCELEROMETER PART |
Pythia | 0:a4131de4bddd | 4 | void GetAcc( float arr[3] ) // Get Acceleration Value |
Pythia | 0:a4131de4bddd | 5 | arr[3] is the xyz-axis acc data |
Pythia | 0:a4131de4bddd | 6 | // default range from -2048 to +2047 with step=1 (12bit high prec) or step=4 (10bit normal prec) |
Pythia | 0:a4131de4bddd | 7 | // and roughly 1000/g(+/-2g) 500/g(+/-4g) 200/g(+/-8g) 80/g(+/-16g) depend on your device and ACC_FS |
Pythia | 0:a4131de4bddd | 8 | // note your calibration setting will change the range |
Pythia | 0:a4131de4bddd | 9 | void ACtrl( enum cmd ) e.g. ACtrl(LSM303DLHC::LP_ON) |
Pythia | 0:a4131de4bddd | 10 | enum ACC_LPen {LP_OFF,LP_ON} // to ctrl acc power mode |
Pythia | 0:a4131de4bddd | 11 | enum ACC_ODR {PW_D,ADR1,ADR2,ADR3,ADR4,ADR5,ADR6,ADR7,ADR8,ADR9} // to ctrl acc data rate |
Pythia | 0:a4131de4bddd | 12 | enum ACC_AXIS {NONE,X,Y,XY,Z,XZ,YZ,XYZ} // to sel the acc data of axis you want |
Pythia | 0:a4131de4bddd | 13 | enum ACC_HPM {HPF_NORM_R,HPF_REF,HPF_NORM,HPF_AUTO} // to sel acc internal HPF model |
Pythia | 0:a4131de4bddd | 14 | enum ACC_HPCF {HPF_CF0,HPF_CF1,HPF_CF2,HPF_CF3} // to switch acc internal HPF cutoff freq |
Pythia | 0:a4131de4bddd | 15 | enum ACC_FDS {HPF_OFF,HPF_ON} // to switch on/off acc internal HPF for output |
Pythia | 0:a4131de4bddd | 16 | enum ACC_BDU {BDU_CONT,BDU_HOLD} // to sel acc data update mode |
Pythia | 0:a4131de4bddd | 17 | enum ACC_FS {G2,G4,G8,G16} // to sel acc full scale of data |
Pythia | 0:a4131de4bddd | 18 | enum ACC_HR {LOW_R,HIGH_R} // to sel acc output data precision |
Pythia | 0:a4131de4bddd | 19 | void ACal( float offset[3], float scale[3] ); // Acc Calibration Setting |
Pythia | 0:a4131de4bddd | 20 | // affect data of GetAcc() by output = scale * ( offset + original ) |
Pythia | 0:a4131de4bddd | 21 | // but if internal HPF enable then output = scale * original |
Pythia | 0:a4131de4bddd | 22 | // note linear acc has no offset |
Pythia | 0:a4131de4bddd | 23 | |
Pythia | 0:a4131de4bddd | 24 | -- MAGNETOMETER PART |
Pythia | 0:a4131de4bddd | 25 | void GetMag( float arr[3] ); // Get magnetic flux density |
Pythia | 0:a4131de4bddd | 26 | arr[3] is the xyz-axis mag data |
Pythia | 0:a4131de4bddd | 27 | // default range from -2048 to +2047 with step=1 |
Pythia | 0:a4131de4bddd | 28 | // note your calibration setting will change the range |
Pythia | 0:a4131de4bddd | 29 | void MCtrl( enum cmd ) e.g. MCtrl(LSM303DLHC::MDR3); |
Pythia | 0:a4131de4bddd | 30 | enum MAG_DR {MDR0,MDR1,MDR2,MDR3,MDR4,MDR5,MDR6,MDR7} // to ctrl mag data rate |
Pythia | 0:a4131de4bddd | 31 | enum MAG_GN {GN1,GN2,GN3,GN4,GN5,GN6,GN7) // to ctrl mag full scale of data |
Pythia | 0:a4131de4bddd | 32 | enum MAG_MD {MD_CONT,MD_SING,MD_SLP,MD_SLP2}; |
Pythia | 0:a4131de4bddd | 33 | void MCal(float offset[3], float scale[3]); // Mag Calibration |
Pythia | 0:a4131de4bddd | 34 | // affect data of GetMag() by output = scale * ( offset + original ) |
Pythia | 0:a4131de4bddd | 35 | |
Pythia | 0:a4131de4bddd | 36 | -- TEMPERATURE METER PART |
Pythia | 0:a4131de4bddd | 37 | void GetTemp( float arr[1] ); // Get temperature |
Pythia | 0:a4131de4bddd | 38 | arr[1] is the temperture |
Pythia | 0:a4131de4bddd | 39 | // default range from -2048 to +2047 |
Pythia | 0:a4131de4bddd | 40 | void TCal( enum cmd ) |
Pythia | 0:a4131de4bddd | 41 | enum TEMP_EN{TEMP_OFF,TEMP_ON}; // to switch on/off TEMP |
Pythia | 0:a4131de4bddd | 42 | void TempCal(float offset[1], float scale[1]); // Mag Calibration |
Pythia | 0:a4131de4bddd | 43 | //affect data of GetMag() by output = scale * ( offset + original ) |
Pythia | 0:a4131de4bddd | 44 | |
Pythia | 0:a4131de4bddd | 45 | -- DIRECT WRITE REG |
Pythia | 0:a4131de4bddd | 46 | void WriteReg(int sad, char d[2]); // Write value to reg |
Pythia | 0:a4131de4bddd | 47 | sad = ACC_ADDRESS or MAG_ADDRESS |
Pythia | 0:a4131de4bddd | 48 | d[0] = Register Address |
Pythia | 0:a4131de4bddd | 49 | d[1] = Register Value |
Pythia | 0:a4131de4bddd | 50 | CAUTION: THE FUNTION USES UNFRIENDLY ASSIGN |
Pythia | 0:a4131de4bddd | 51 | CAUTION: WRITING TO RESERVED REG MAY CAUSE PERMANENT DAMAGE |
Pythia | 0:a4131de4bddd | 52 | PLEASE FOLLOW DATASHEET RIGIDLY |
Pythia | 0:a4131de4bddd | 53 | */ |
Pythia | 0:a4131de4bddd | 54 | |
Pythia | 0:a4131de4bddd | 55 | |
Pythia | 0:a4131de4bddd | 56 | #ifndef LSM303DLHC_H |
Pythia | 0:a4131de4bddd | 57 | #define LSM303DLHC_H |
Pythia | 0:a4131de4bddd | 58 | #include "mbed.h" |
Pythia | 0:a4131de4bddd | 59 | #include "LSM303DLHC_REG.h" |
Pythia | 0:a4131de4bddd | 60 | |
Pythia | 0:a4131de4bddd | 61 | class LSM303DLHC { |
Pythia | 0:a4131de4bddd | 62 | public: |
Pythia | 0:a4131de4bddd | 63 | //// PORT |
Pythia | 0:a4131de4bddd | 64 | LSM303DLHC(I2C &i2c); |
Pythia | 0:a4131de4bddd | 65 | |
Pythia | 0:a4131de4bddd | 66 | //// REG CTRL |
Pythia | 0:a4131de4bddd | 67 | // modify the default in LSM303DLHC.cpp |
Pythia | 0:a4131de4bddd | 68 | |
Pythia | 0:a4131de4bddd | 69 | //// CTRL_REG1_A (20h) |
Pythia | 0:a4131de4bddd | 70 | // ACC Low Power Mode ON/OFF |
Pythia | 0:a4131de4bddd | 71 | enum ACC_LPen { LP_OFF = 0, LP_ON = 1} ; |
Pythia | 0:a4131de4bddd | 72 | void ACtrl(ACC_LPen cmd); |
Pythia | 0:a4131de4bddd | 73 | // ACC Data Rate NOTE: ACC SWITCH IS HERE |
Pythia | 0:a4131de4bddd | 74 | enum ACC_ODR { PW_D = 0, ADR1 = 1, ADR2 = 2, ADR3 = 3, ADR4 = 4, ADR5 = 5, ADR6 = 6, ADR7 = 7, ADR8 = 8, ADR9 = 9}; |
Pythia | 0:a4131de4bddd | 75 | // PW Down 1Hz 10Hz 25Hz 50Hz 100Hz 200Hz 400Hz 1620Hz@LP 1344Hz@NM/5376HZ@LP |
Pythia | 0:a4131de4bddd | 76 | void ACtrl(ACC_ODR cmd); |
Pythia | 0:a4131de4bddd | 77 | // ACC AXIS SEL |
Pythia | 0:a4131de4bddd | 78 | enum ACC_AXIS { NONE = 0, X = 1, Y = 2, XY = 3, Z = 4, XZ = 5, YZ = 6, XYZ = 7 }; |
Pythia | 0:a4131de4bddd | 79 | void ACtrl(ACC_AXIS cmd); |
Pythia | 0:a4131de4bddd | 80 | |
Pythia | 0:a4131de4bddd | 81 | //// CTRL_REG2_A (21h) |
Pythia | 0:a4131de4bddd | 82 | // ACC HPF Mode |
Pythia | 0:a4131de4bddd | 83 | enum ACC_HPM { HPF_NORM_R = 0, HPF_REF = 1, HPF_NORM = 2, HPF_AUTO = 3 }; |
Pythia | 0:a4131de4bddd | 84 | void ACtrl(ACC_HPM cmd); |
Pythia | 0:a4131de4bddd | 85 | // ACC HPF Cutoff Freq |
Pythia | 0:a4131de4bddd | 86 | enum ACC_HPCF { HPF_CF0 = 0, HPF_CF1 = 1, HPF_CF2 = 2, HPF_CF3 = 3}; |
Pythia | 0:a4131de4bddd | 87 | void ACtrl(ACC_HPCF cmd); |
Pythia | 0:a4131de4bddd | 88 | // ACC HPF ON/OFF for output |
Pythia | 0:a4131de4bddd | 89 | enum ACC_FDS { HPF_OFF = 0, HPF_ON = 1 }; |
Pythia | 0:a4131de4bddd | 90 | void ACtrl(ACC_FDS cmd); |
Pythia | 0:a4131de4bddd | 91 | |
Pythia | 0:a4131de4bddd | 92 | //// CTRL_REG4_A (23h) |
Pythia | 0:a4131de4bddd | 93 | // ACC Block Date Update Mode |
Pythia | 0:a4131de4bddd | 94 | enum ACC_BDU { BDU_CONT = 0, BDU_HOLD = 1 }; |
Pythia | 0:a4131de4bddd | 95 | void ACtrl(ACC_BDU cmd); |
Pythia | 0:a4131de4bddd | 96 | // ACC Output Full-Scale SEL |
Pythia | 0:a4131de4bddd | 97 | enum ACC_FS {G2 = 0b00, G4 = 0b01, G8 = 0b10, G16= 0b11 }; |
Pythia | 0:a4131de4bddd | 98 | // +/-2g +/-4g +/-8g +/-16g |
Pythia | 0:a4131de4bddd | 99 | void ACtrl(ACC_FS cmd); |
Pythia | 0:a4131de4bddd | 100 | // ACC Output in High/Low Resolution (Precision SEL) |
Pythia | 0:a4131de4bddd | 101 | enum ACC_HR { LOW_R = 0, HIGH_R = 1 }; |
Pythia | 0:a4131de4bddd | 102 | // 10bit 12bit |
Pythia | 0:a4131de4bddd | 103 | void ACtrl(ACC_HR cmd); |
Pythia | 0:a4131de4bddd | 104 | |
Pythia | 0:a4131de4bddd | 105 | //// CRA_REG_M (00h) |
Pythia | 0:a4131de4bddd | 106 | // TEMP Sensor En NOTE: TEMP SWITCH IS HERE |
Pythia | 0:a4131de4bddd | 107 | enum TEMP_EN { TEMP_OFF = 0, TEMP_ON = 1}; |
Pythia | 0:a4131de4bddd | 108 | void TCtrl(TEMP_EN cmd); |
Pythia | 0:a4131de4bddd | 109 | // MAG Data Rate (Note: MAG_DR determines DRDY pin) |
Pythia | 0:a4131de4bddd | 110 | enum MAG_DR { MDR0 = 0, MDR1 = 1, MDR2 = 2, MDR3 = 3, MDR4 = 4, MDR5 = 5, MDR6 = 6, MDR7 = 7}; |
Pythia | 0:a4131de4bddd | 111 | // 0.75Hz 1.5Hz 3Hz 7.5Hz 15Hz 30Hz 75Hz 220Hz |
Pythia | 0:a4131de4bddd | 112 | void MCtrl(MAG_DR cmd); // MAG Date Rate |
Pythia | 0:a4131de4bddd | 113 | |
Pythia | 0:a4131de4bddd | 114 | //// CRB_REG_M (01h) |
Pythia | 0:a4131de4bddd | 115 | // MAG Gain (Range SEL) |
Pythia | 0:a4131de4bddd | 116 | enum MAG_GN { GN1 = 1, GN2 = 2, GN3 = 3, GN4 = 4, GN5 = 5, GN6 = 6, GN7 = 7}; |
Pythia | 0:a4131de4bddd | 117 | // 1.3 1.9 2.5 4.0 4.7 5.6 8.1 (+/- Gauss) |
Pythia | 0:a4131de4bddd | 118 | void MCtrl(MAG_GN cmd); // MAG Measure Range |
Pythia | 0:a4131de4bddd | 119 | |
Pythia | 0:a4131de4bddd | 120 | //// MR_REG_M (02h) |
Pythia | 0:a4131de4bddd | 121 | // MAG Mode NOTE: MAG SWITCH IS HERE |
Pythia | 0:a4131de4bddd | 122 | enum MAG_MD { MD_CONT = 0, MD_SING = 1, MD_SLP = 2, MD_SLP2 = 3}; |
Pythia | 0:a4131de4bddd | 123 | // Continuous single-conv sleep-mode sleep-mode |
Pythia | 0:a4131de4bddd | 124 | void MCtrl(MAG_MD cmd); |
Pythia | 0:a4131de4bddd | 125 | |
Pythia | 0:a4131de4bddd | 126 | //// Change more regs |
Pythia | 0:a4131de4bddd | 127 | void WriteReg(int sad, char d[2]); // Write value to reg |
Pythia | 0:a4131de4bddd | 128 | // sad = ACC_ADDRESS or MAG_ADDRESS |
Pythia | 0:a4131de4bddd | 129 | // d[0] = Register Address and d[1] = Register Value |
Pythia | 0:a4131de4bddd | 130 | // CAUTION: THE FUNTION USES UNFRIENDLY ASSIGN AND WRITING TO RESERVED REG MAY CAUSE PERMANENT DAMAGE |
Pythia | 0:a4131de4bddd | 131 | // PLEASE FOLLOW DATASHEET RIGIDLY |
Pythia | 0:a4131de4bddd | 132 | |
Pythia | 0:a4131de4bddd | 133 | //// Get Data |
Pythia | 0:a4131de4bddd | 134 | // please refer to the top: COMPACT USER INSTRUCTION |
Pythia | 1:4ee6df2df73a | 135 | int GetAcc(float arr[3]); // Get acc |
Pythia | 1:4ee6df2df73a | 136 | int GetMag(float arr[3]); // Get mag |
Pythia | 1:4ee6df2df73a | 137 | int GetTemp(float arr[1]); // Get temp |
Pythia | 0:a4131de4bddd | 138 | |
Pythia | 0:a4131de4bddd | 139 | //// sensor reading calibration |
Pythia | 0:a4131de4bddd | 140 | // please refer to the top: COMPACT USER INSTRUCTION |
Pythia | 0:a4131de4bddd | 141 | void ACal(float offset[3], float scale[3]); // Acc Calibration |
Pythia | 0:a4131de4bddd | 142 | void MCal(float offset[3], float scale[3]); // Mag Calibration |
Pythia | 0:a4131de4bddd | 143 | void TCal(float offset[1], float scale[1]); // Mag Calibration |
Pythia | 0:a4131de4bddd | 144 | |
Pythia | 0:a4131de4bddd | 145 | |
Pythia | 0:a4131de4bddd | 146 | //// Not implemented function |
Pythia | 0:a4131de4bddd | 147 | bool isAccRdy(); // Check if acc has new data |
Pythia | 0:a4131de4bddd | 148 | // one way is to use high freq ticker to check STATUS_REG_A (27h) |
Pythia | 0:a4131de4bddd | 149 | // I2C@400kHz just enough to check Max Normal Mode Data Rate (1344Hz) |
Pythia | 0:a4131de4bddd | 150 | // or someone to teach me how to use CTRL_REG6_A THX THX THX (: |
Pythia | 0:a4131de4bddd | 151 | bool isMagRdy(); // check if mag has new data |
Pythia | 0:a4131de4bddd | 152 | // one way is to use InterruptIn to trigger from DRDY pin |
Pythia | 0:a4131de4bddd | 153 | // DRDY pin freq defined by MAG_DR |
Pythia | 0:a4131de4bddd | 154 | |
Pythia | 0:a4131de4bddd | 155 | private: |
Pythia | 0:a4131de4bddd | 156 | I2C *_i2c; |
Pythia | 0:a4131de4bddd | 157 | |
Pythia | 0:a4131de4bddd | 158 | char data[6]; // used as main data exchange |
Pythia | 0:a4131de4bddd | 159 | |
Pythia | 0:a4131de4bddd | 160 | // use offset to calibrate zero reading |
Pythia | 0:a4131de4bddd | 161 | float acc_offset[3]; |
Pythia | 0:a4131de4bddd | 162 | float mag_offset[3]; |
Pythia | 0:a4131de4bddd | 163 | float temp_offset[1]; |
Pythia | 0:a4131de4bddd | 164 | |
Pythia | 0:a4131de4bddd | 165 | //use scale to adjust the range to required |
Pythia | 0:a4131de4bddd | 166 | float acc_scale[3]; |
Pythia | 0:a4131de4bddd | 167 | float mag_scale[3]; |
Pythia | 0:a4131de4bddd | 168 | float temp_scale[1]; |
Pythia | 0:a4131de4bddd | 169 | |
Pythia | 0:a4131de4bddd | 170 | // chip count to unit conversion |
Pythia | 0:a4131de4bddd | 171 | float acc_scale_multiplier; |
Pythia | 0:a4131de4bddd | 172 | float mag_scale_x_multiplier; |
Pythia | 0:a4131de4bddd | 173 | float mag_scale_y_multiplier; |
Pythia | 0:a4131de4bddd | 174 | float mag_scale_z_multiplier; |
Pythia | 0:a4131de4bddd | 175 | }; |
Pythia | 0:a4131de4bddd | 176 | |
Pythia | 0:a4131de4bddd | 177 | /* |
Pythia | 0:a4131de4bddd | 178 | Original main.c |
Pythia | 0:a4131de4bddd | 179 | |
Pythia | 0:a4131de4bddd | 180 | #include "mbed.h" |
Pythia | 0:a4131de4bddd | 181 | #include "LSM303DLHC.h" |
Pythia | 0:a4131de4bddd | 182 | |
Pythia | 0:a4131de4bddd | 183 | // LSM303DLHC sensor(p9,p10); |
Pythia | 0:a4131de4bddd | 184 | |
Pythia | 0:a4131de4bddd | 185 | Serial pc(USBTX,USBRX); |
Pythia | 0:a4131de4bddd | 186 | Ticker ticker; |
Pythia | 0:a4131de4bddd | 187 | |
Pythia | 0:a4131de4bddd | 188 | float acc[3] = { 0 }; |
Pythia | 0:a4131de4bddd | 189 | float mag[3] = { 0 }; |
Pythia | 0:a4131de4bddd | 190 | float tmp[1] = { 0 }; |
Pythia | 0:a4131de4bddd | 191 | |
Pythia | 0:a4131de4bddd | 192 | void CallBack(); |
Pythia | 0:a4131de4bddd | 193 | |
Pythia | 0:a4131de4bddd | 194 | int main(){ |
Pythia | 0:a4131de4bddd | 195 | pc.baud(921600); |
Pythia | 0:a4131de4bddd | 196 | |
Pythia | 0:a4131de4bddd | 197 | // example setup |
Pythia | 0:a4131de4bddd | 198 | // refer to LSM303DLHC.h for more overloaded details for ACtrl() MCtrl() TCtrl() |
Pythia | 0:a4131de4bddd | 199 | sensor.MCtrl(LSM303DLHC::GN1); // set mag range +/-1.3Gausee |
Pythia | 0:a4131de4bddd | 200 | sensor.MCtrl(LSM303DLHC::MDR3); // set mag date rate 7.5Hz |
Pythia | 0:a4131de4bddd | 201 | sensor.ACtrl(LSM303DLHC::G8); // set acc range +/-8g |
Pythia | 0:a4131de4bddd | 202 | sensor.ACtrl(LSM303DLHC::ADR2); // set acc date rate 10Hz |
Pythia | 0:a4131de4bddd | 203 | sensor.ACtrl(LSM303DLHC::HPF_OFF); // disable internal acc HPF |
Pythia | 0:a4131de4bddd | 204 | |
Pythia | 0:a4131de4bddd | 205 | float acc_offset[3] = { 6.5, 5, 12.5 }; // acc offset |
Pythia | 0:a4131de4bddd | 206 | float acc_scale[3] = { 3.9, 4, 4 }; // acc scale |
Pythia | 0:a4131de4bddd | 207 | sensor.ACal(acc_offset,acc_scale); // set acc calibration |
Pythia | 0:a4131de4bddd | 208 | |
Pythia | 0:a4131de4bddd | 209 | ticker.attach(&CallBack, 0.2); // read and refresh disp with 200ms interval |
Pythia | 0:a4131de4bddd | 210 | |
Pythia | 0:a4131de4bddd | 211 | while (1) |
Pythia | 0:a4131de4bddd | 212 | wait_us(1); |
Pythia | 0:a4131de4bddd | 213 | } |
Pythia | 0:a4131de4bddd | 214 | |
Pythia | 0:a4131de4bddd | 215 | void CallBack(){ |
Pythia | 0:a4131de4bddd | 216 | sensor.GetAcc(acc); |
Pythia | 0:a4131de4bddd | 217 | sensor.GetMag(mag); |
Pythia | 0:a4131de4bddd | 218 | sensor.GetTemp(tmp); |
Pythia | 0:a4131de4bddd | 219 | |
Pythia | 0:a4131de4bddd | 220 | pc.printf("A %5f %5f %5f\n\r", acc[0], acc[1], acc[2]); |
Pythia | 0:a4131de4bddd | 221 | pc.printf("M %5f %5f %5f\n\r", mag[0], mag[1], mag[2]); |
Pythia | 0:a4131de4bddd | 222 | pc.printf("T %5f\n\r", tmp[0]); |
Pythia | 0:a4131de4bddd | 223 | } |
Pythia | 0:a4131de4bddd | 224 | |
Pythia | 0:a4131de4bddd | 225 | */ |
Pythia | 0:a4131de4bddd | 226 | |
Pythia | 0:a4131de4bddd | 227 | |
Pythia | 0:a4131de4bddd | 228 | #endif |