Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of LIS3DH by
LIS3DH.cpp
00001 /* 00002 * 2018: Eric Tsai's Modifications of Kenji Arai's original LIS3DH library 00003 * modified <initialize> and added threshold <setAct> call 00004 * 00005 * 00006 * mbed library program 00007 * LIS3DH MEMS motion sensor: 3-axis "nano" accelerometer, made by STMicroelectronics 00008 * http://www.st-japan.co.jp/web/jp/catalog/sense_power/FM89/SC444/PF250725 00009 * 00010 * Copyright (c) 2014,'15,'17 Kenji Arai / JH1PJL 00011 * http://www.page.sannet.ne.jp/kenjia/index.html 00012 * http://mbed.org/users/kenjiArai/ 00013 * Created: July 14th, 2014 00014 * Revised: August 23rd, 2017 00015 */ 00016 00017 #include "LIS3DH.h" 00018 00019 LIS3DH::LIS3DH (PinName p_sda, PinName p_scl, 00020 uint8_t addr, uint8_t data_rate, uint8_t fullscale) 00021 : _i2c_p(new I2C(p_sda, p_scl)), _i2c(*_i2c_p) 00022 { 00023 _i2c.frequency(400000); 00024 initialize (addr, data_rate, fullscale); 00025 } 00026 00027 LIS3DH::LIS3DH (PinName p_sda, PinName p_scl, uint8_t addr) 00028 : _i2c_p(new I2C(p_sda, p_scl)), _i2c(*_i2c_p) 00029 { 00030 _i2c.frequency(400000); 00031 //initialize (addr, LIS3DH_DR_NR_LP_50HZ, LIS3DH_FS_8G); //tsai: change this to 10Hz, 16uA to 8uA. 00032 //itialize (addr, LIS3DH_DR_NR_LP_10HZ, LIS3DH_FS_8G); //8uA consumption at 10Hz 00033 00034 initialize (addr, LIS3DH_DR_NR_LP_10HZ, LIS3DH_FS_2G); //8uA @ 10Hz, 2G scale, really sensitive. 00035 // LIS3DH_DR_NR_LP_10HZ = 2 00036 // LIS3DH_FS_8G = 2, full scale 00037 } 00038 00039 LIS3DH::LIS3DH (I2C& p_i2c, 00040 uint8_t addr, uint8_t data_rate, uint8_t fullscale) 00041 : _i2c(p_i2c) 00042 { 00043 _i2c.frequency(400000); 00044 initialize (addr, data_rate, fullscale); 00045 } 00046 00047 LIS3DH::LIS3DH (I2C& p_i2c, uint8_t addr) 00048 : _i2c(p_i2c) 00049 { 00050 _i2c.frequency(400000); 00051 initialize (addr, LIS3DH_DR_NR_LP_50HZ, LIS3DH_FS_8G); 00052 } 00053 00054 void LIS3DH::initialize (uint8_t addr, uint8_t data_rate, uint8_t fullscale) 00055 { 00056 // Check acc is available of not 00057 acc_addr = addr; 00058 dt[0] = LIS3DH_WHO_AM_I; 00059 _i2c.write(acc_addr, dt, 1, true); 00060 _i2c.read(acc_addr, dt, 1, false); 00061 if (dt[0] == I_AM_LIS3DH) { 00062 acc_ready = 1; 00063 } else { 00064 acc_ready = 0; 00065 return; // acc chip is NOT on I2C line then terminate 00066 } 00067 // Reg.1 00068 dt[0] = LIS3DH_CTRL_REG1; 00069 dt[1] = 0x07; //0000 0111 00070 dt[1] |= data_rate << 4; // 0000 0111 |= 0010 0000 ---> 0010 0111; 10Hz, high res, xyz enbabled. 00071 00072 //note: dt[1]=0x0F; //low resolution; @ datarate; Must also zero out CTRL_REG4[3] 00073 //dt[1] = 0x07; 00074 _i2c.write(acc_addr, dt, 2, false); //address, command, bytes 00075 00076 00077 00078 // Reg.4 00079 dt[0] = LIS3DH_CTRL_REG4; 00080 dt[1] = 0x08; // High resolution //0000 1000 00081 dt[1] |= fullscale << 4; // 00082 //fullscale = 0000 0010 00083 //fullscale << 4 = 0010 0000 00084 //result of OR = 0010 1000 ----> 00085 // continuous update 00086 // endian, LSB @ lowest address 00087 // 10 = 8G scale 00088 // High resolution (10bit) ENABLED 00089 // 0, 0 N/A 00090 00091 _i2c.write(acc_addr, dt, 2, false); 00092 00093 00094 00095 00096 00097 00098 switch (fullscale) { 00099 case LIS3DH_FS_2G: 00100 fs_factor = LIS3DH_SENSITIVITY_2G; 00101 break; 00102 case LIS3DH_FS_4G: 00103 fs_factor = LIS3DH_SENSITIVITY_4G; 00104 break; 00105 case LIS3DH_FS_8G: 00106 fs_factor = LIS3DH_SENSITIVITY_8G; 00107 break; 00108 case LIS3DH_FS_16G: 00109 fs_factor = LIS3DH_SENSITIVITY_16G; 00110 break; 00111 default: 00112 ; 00113 } 00114 } 00115 00116 00117 00118 void LIS3DH::read_reg_data(char *data) 00119 { 00120 // X,Y & Z 00121 // manual said that 00122 // In order to read multiple bytes, it is necessary to assert the most significant bit 00123 // of the subaddress field. 00124 // In other words, SUB(7) must be equal to ‘1’ while SUB(6-0) represents the address 00125 // of the first register to be read. 00126 dt[0] = LIS3DH_OUT_X_L | 0x80; 00127 _i2c.write(acc_addr, dt, 1, true); 00128 _i2c.read(acc_addr, data, 6, false); 00129 } 00130 00131 void LIS3DH::read_mg_data(float *dt_usr) 00132 { 00133 char data[6]; 00134 00135 if (acc_ready == 0) { 00136 dt_usr[0] = 0; 00137 dt_usr[1] = 0; 00138 dt_usr[2] = 0; 00139 return; 00140 } 00141 read_reg_data(data); 00142 // change data type 00143 #if OLD_REV // Fixed bugs -> (1) unit is not mg but g (2) shift right 4bit = /16 00144 dt_usr[0] = float(short((data[1] << 8) | data[0])) * fs_factor / 15; 00145 dt_usr[1] = float(short((data[3] << 8) | data[2])) * fs_factor / 15; 00146 dt_usr[2] = float(short((data[5] << 8) | data[4])) * fs_factor / 15; 00147 #else 00148 dt_usr[0] = float(short((data[1] << 8) | data[0]) >> 4) * fs_factor; 00149 dt_usr[1] = float(short((data[3] << 8) | data[2]) >> 4) * fs_factor; 00150 dt_usr[2] = float(short((data[5] << 8) | data[4]) >> 4) * fs_factor; 00151 #endif 00152 } 00153 00154 void LIS3DH::read_data(float *dt_usr) 00155 { 00156 char data[6]; 00157 00158 if (acc_ready == 0) { 00159 dt_usr[0] = 0; 00160 dt_usr[1] = 0; 00161 dt_usr[2] = 0; 00162 return; 00163 } 00164 read_reg_data(data); 00165 // change data type 00166 #if OLD_REV // Fixed bugs -> shift right 4bit = /16 (not /15) 00167 dt_usr[0] = float(short((data[1] << 8) | data[0])) * fs_factor / 15 * GRAVITY; 00168 dt_usr[1] = float(short((data[3] << 8) | data[2])) * fs_factor / 15 * GRAVITY; 00169 dt_usr[2] = float(short((data[5] << 8) | data[4])) * fs_factor / 15 * GRAVITY; 00170 #else 00171 dt_usr[0] = float(short((data[1] << 8) | data[0]) >> 4) * fs_factor * GRAVITY; 00172 dt_usr[1] = float(short((data[3] << 8) | data[2]) >> 4) * fs_factor * GRAVITY; 00173 dt_usr[2] = float(short((data[5] << 8) | data[4]) >> 4) * fs_factor * GRAVITY; 00174 #endif 00175 } 00176 00177 uint8_t LIS3DH::read_id() 00178 { 00179 dt[0] = LIS3DH_WHO_AM_I; 00180 _i2c.write(acc_addr, dt, 1, true); 00181 _i2c.read(acc_addr, dt, 1, false); 00182 return (uint8_t)dt[0]; 00183 } 00184 00185 uint8_t LIS3DH::data_ready() 00186 { 00187 if (acc_ready == 1) { 00188 dt[0] = LIS3DH_STATUS_REG_AUX; 00189 _i2c.write(acc_addr, dt, 1, true); 00190 _i2c.read(acc_addr, dt, 1, false); 00191 if (!(dt[0] & 0x01)) { 00192 return 0; 00193 } 00194 } 00195 return 1; 00196 } 00197 00198 void LIS3DH::frequency(int hz) 00199 { 00200 _i2c.frequency(hz); 00201 } 00202 00203 uint8_t LIS3DH::read_reg(uint8_t addr) 00204 { 00205 if (acc_ready == 1) { 00206 dt[0] = addr; 00207 _i2c.write(acc_addr, dt, 1, true); 00208 _i2c.read(acc_addr, dt, 1, false); 00209 } else { 00210 dt[0] = 0xff; 00211 } 00212 return (uint8_t)dt[0]; 00213 } 00214 00215 void LIS3DH::write_reg(uint8_t addr, uint8_t data) 00216 { 00217 if (acc_ready == 1) { 00218 dt[0] = addr; 00219 dt[1] = data; 00220 _i2c.write(acc_addr, dt, 2, false); 00221 } 00222 } 00223 00224 // Tsai 00225 // See ST app note AN3308 00226 // Add interrupt output from motion. 00227 // Should parameterize threshold, latch, etc... 00228 uint8_t LIS3DH::setAct(uint8_t addr) 00229 { 00230 uint8_t ret_val; 00231 00232 // Check acc is available of not 00233 acc_addr = addr; 00234 dt[0] = LIS3DH_WHO_AM_I; 00235 _i2c.write(acc_addr, dt, 1, true); 00236 _i2c.read(acc_addr, dt, 1, false); 00237 if (dt[0] == I_AM_LIS3DH) { 00238 acc_ready = 1; 00239 ret_val=1; 00240 } else { 00241 acc_ready = 0; 00242 ret_val=2; 00243 return ret_val; // acc chip is NOT on I2C line then terminate 00244 } 00245 00246 //Tsai: set CTRL_REG2, high pass filter, 00247 //value = 0100 0000 00248 dt[0] = LIS3DH_CTRL_REG2; 00249 dt[1] = 0x09; // 0000 1001, enable filter, on IA1 00250 _i2c.write(acc_addr, dt, 2, false); 00251 00252 00253 //Tsai: set CTRL_REG3, 00254 //value = 0100 0000 00255 dt[0] = LIS3DH_CTRL_REG3; 00256 dt[1] = 0x40; // 0100 0000, enable I1_IA1 INT1 00257 _i2c.write(acc_addr, dt, 2, false); 00258 00259 00260 //tsai: reg. INT1_CFG 00261 dt[0] = LIS3DH_INT1_CFG; 00262 dt[1] = 0x7f; // 0111 1111 = movement in all xyz 00263 _i2c.write(acc_addr, dt, 2, false); 00264 00265 00266 //tsai: reg. LIS3DH_INT1_THS, threshold for activity 00267 dt[0] = LIS3DH_INT1_THS; 00268 //0-127; I was at 10 out of 127 @ 16mg LSB; 00269 dt[1] = 0x02; // 0000 0010 //@2G scale-> 16mg*3 = 48mg motion 00270 _i2c.write(acc_addr, dt, 2, false); 00271 00272 /* 00273 //tsai: reg. INT1_DURATION 00274 dt[0] = LIS3DH_INT1_DURATION; 00275 dt[1] = 0x01; // short? 00276 _i2c.write(acc_addr, dt, 2, false); 00277 */ 00278 00279 //tsai: reg. LIS3DH_CTRL_REG5, latching interrupt? 00280 dt[0] = LIS3DH_CTRL_REG5; 00281 //0-127; I was at 10 out of 127 @ 16mg LSB; 00282 //dt[1] = 0x00; // 0000 0000, don't latch interrupt 00283 //dt[1] = 0x08; // 0000 1000, latch int1 00284 dt[1] = 0x0C; // 0000 1100, latch int1, enable 4D 00285 //dt[1] = 0x04; // 0000 0100, dont latch int1, enable 4D 00286 _i2c.write(acc_addr, dt, 2, false); 00287 00288 00289 return ret_val; 00290 }
Generated on Sun Jul 24 2022 15:23:42 by
1.7.2
