Analog Devices 3-axis accelerometer. I2C interface
Embed:
(wiki syntax)
Show/hide line numbers
ADXL345.cpp
00001 /* 00002 * mbed library program 00003 * ADXL345: 3-axis accelerometer, made by Analog Devices 00004 * http://www.analog.com/static/imported-files/data_sheets/ADXL345.pdf 00005 * 00006 * Copyright (c) 2017 Kenji Arai / JH1PJL 00007 * http://www.page.sannet.ne.jp/kenjia/index.html 00008 * http://mbed.org/users/kenjiArai/ 00009 * Modify: August 13th, 2017 00010 * Revised: September 23rd, 2017 00011 * 00012 */ 00013 00014 #include "ADXL345.h" 00015 00016 // definition for Nomalization 00017 #define ADXL345_SENSITIVITY_2G 4.0f 00018 #define ADXL345_SENSITIVITY_4G 8.0f 00019 #define ADXL345_SENSITIVITY_8G 16.0f 00020 #define ADXL345_SENSITIVITY_16G 32.0f 00021 #define ADXL345_SEN_FULL_RES 4.0f 00022 00023 //Gravity at Earth's surface in m/s/s 00024 #define GRAVITY (9.80665f / 1000) 00025 00026 #if MBED_MAJOR_VERSION == 2 00027 #define WAIT_MS(x) wait_ms(x) 00028 #elif MBED_MAJOR_VERSION == 5 00029 #define WAIT_MS(x) Thread::wait(x) 00030 #else 00031 #error "Running on Unknown OS" 00032 #endif 00033 00034 ADXL345::ADXL345 (PinName p_sda, PinName p_scl, 00035 uint8_t addr, uint8_t data_rate, uint8_t fullscale) : 00036 _i2c_p(new I2C(p_sda, p_scl)), _i2c(*_i2c_p) 00037 { 00038 _i2c.frequency(400000); 00039 initialize (addr, data_rate, fullscale); 00040 } 00041 00042 ADXL345::ADXL345 (PinName p_sda, PinName p_scl, uint8_t addr) : 00043 _i2c_p(new I2C(p_sda, p_scl)), _i2c(*_i2c_p) 00044 { 00045 _i2c.frequency(400000); 00046 initialize (addr, ADXL345_DR_200HZ, ADXL345_FULL_RES_16G); 00047 } 00048 00049 ADXL345::ADXL345 (PinName p_sda, PinName p_scl) : 00050 _i2c_p(new I2C(p_sda, p_scl)), _i2c(*_i2c_p) 00051 { 00052 _i2c.frequency(400000); 00053 initialize(ADXL345_V_CHIP_ADDR, ADXL345_DR_200HZ, ADXL345_FULL_RES_16G); 00054 if (acc_ready == false){ 00055 initialize(ADXL345_G_CHIP_ADDR, ADXL345_DR_200HZ, ADXL345_FULL_RES_16G); 00056 } 00057 } 00058 00059 ADXL345::ADXL345 (I2C& p_i2c, 00060 uint8_t addr, uint8_t data_rate, uint8_t fullscale) : _i2c(p_i2c) 00061 { 00062 _i2c.frequency(400000); 00063 initialize (addr, data_rate, fullscale); 00064 } 00065 00066 ADXL345::ADXL345 (I2C& p_i2c, uint8_t addr) : _i2c(p_i2c) 00067 { 00068 _i2c.frequency(400000); 00069 initialize (addr, ADXL345_DR_200HZ, ADXL345_FULL_RES_16G); 00070 } 00071 00072 ADXL345::ADXL345 (I2C& p_i2c) : _i2c(p_i2c) 00073 { 00074 _i2c.frequency(400000); 00075 initialize(ADXL345_V_CHIP_ADDR, ADXL345_DR_200HZ, ADXL345_FULL_RES_16G); 00076 if (acc_ready == false){ 00077 initialize(ADXL345_G_CHIP_ADDR, ADXL345_DR_200HZ, ADXL345_FULL_RES_16G); 00078 } 00079 } 00080 00081 void ADXL345::initialize (uint8_t addr, uint8_t data_rate, uint8_t fullscale) 00082 { 00083 // Check acc is available or not 00084 acc_addr = addr; 00085 dt[0] = ADXL345_DEVID; 00086 _i2c.write(acc_addr, dt, 1, true); 00087 _i2c.read(acc_addr, dt, 1, false); 00088 if (dt[0] == ADXL345_DEVICE_ID){ 00089 acc_ready = true; 00090 } else { 00091 acc_ready = false; 00092 return; // acc chip is NOT on I2C line then terminate 00093 } 00094 // BW Rate 00095 dt[0] = ADXL345_BW_RATE; 00096 dt[1] = data_rate | ADXL345_NOT_LOW_PWR; // normal(not low power mode) 00097 setting_data[0] = dt[1]; 00098 _i2c.write(acc_addr, dt, 2, false); 00099 // Data format (measurement range) 00100 dt[0] = ADXL345_DATA_FORMAT; 00101 dt[1] = fullscale; 00102 setting_data[1] = dt[1]; 00103 _i2c.write(acc_addr, dt, 2, false); 00104 switch (fullscale){ 00105 case ADXL345_FS_2G: 00106 fs_factor = ADXL345_SENSITIVITY_2G; 00107 break; 00108 case ADXL345_FS_4G: 00109 fs_factor = ADXL345_SENSITIVITY_4G; 00110 break; 00111 case ADXL345_FS_8G: 00112 fs_factor = ADXL345_SENSITIVITY_8G; 00113 break; 00114 case ADXL345_FS_16G: 00115 fs_factor = ADXL345_SENSITIVITY_16G; 00116 break; 00117 case ADXL345_FULL_RES_16G: 00118 fs_factor = ADXL345_SEN_FULL_RES; 00119 break; 00120 default: 00121 fs_factor = 1.0f; 00122 break; 00123 } 00124 // Data ready flag 00125 dt[0] = ADXL345_INT_ENABLE; 00126 dt[1] = 0x80; 00127 setting_data[2] = dt[1]; 00128 _i2c.write(acc_addr, dt, 2, false); 00129 // Start measurement mode 00130 dt[0] = ADXL345_POWER_CTL; 00131 dt[1] = 0x08; 00132 setting_data[3] = dt[1]; 00133 _i2c.write(acc_addr, dt, 2, false); 00134 // offset compensation 00135 dt[0] = ADXL345_OFSX; 00136 dt[1] = 0x01; 00137 _i2c.write(acc_addr, dt, 2, false); 00138 dt[0] = ADXL345_OFSY; 00139 dt[1] = 0x00; 00140 _i2c.write(acc_addr, dt, 2, false); 00141 dt[0] = ADXL345_OFSZ; 00142 dt[1] = 0x00; 00143 _i2c.write(acc_addr, dt, 2, false); 00144 } 00145 00146 void ADXL345::read_reg_data(char *data) 00147 { 00148 // read all of X,Y & Z 00149 dt[0] = ADXL345_DATAX0; 00150 _i2c.write(acc_addr, dt, 1, true); 00151 _i2c.read(acc_addr, data, 6, false); 00152 } 00153 00154 void ADXL345::read_mg_data(float *dt_usr) 00155 { 00156 return read_mg_g_data(dt_usr, 0); 00157 } 00158 00159 void ADXL345::read_g_data(float *dt_usr) 00160 { 00161 return read_mg_g_data(dt_usr, 1); 00162 } 00163 00164 void ADXL345::read_data(float *dt_usr) 00165 { 00166 return read_mg_g_data(dt_usr, 2); 00167 } 00168 00169 void ADXL345::read_mg_g_data(float *dt_usr, uint8_t n) 00170 { 00171 char data[6]; 00172 float fct; 00173 00174 if (acc_ready == false){ 00175 dt_usr[0] = 0; 00176 dt_usr[1] = 0; 00177 dt_usr[2] = 0; 00178 return; 00179 } 00180 read_reg_data(data); 00181 if (n == 0){ 00182 fct = fs_factor; 00183 } else if (n == 1){ 00184 fct = fs_factor / 1000.0f; 00185 } else { 00186 fct = fs_factor * GRAVITY; 00187 } 00188 // change data type 00189 dt_usr[0] = float(int16_t((data[1] << 8) | data[0])) * fct; 00190 dt_usr[1] = float(int16_t((data[3] << 8) | data[2])) * fct; 00191 dt_usr[2] = float(int16_t((data[5] << 8) | data[4])) * fct; 00192 } 00193 00194 uint8_t ADXL345::read_id() 00195 { 00196 dt[0] = ADXL345_DEVID; 00197 _i2c.write(acc_addr, dt, 1, true); 00198 _i2c.read(acc_addr, dt, 1, false); 00199 return (uint8_t)dt[0]; 00200 } 00201 00202 bool ADXL345::data_ready() 00203 { 00204 if (acc_ready == true){ 00205 dt[0] = ADXL345_INT_SOURCE; 00206 _i2c.write(acc_addr, dt, 1, true); 00207 _i2c.read(acc_addr, dt, 1, false); 00208 if (dt[0] & 0x80){ // Check ready bit 00209 return true; 00210 } else { 00211 return false; 00212 } 00213 } 00214 return false; 00215 } 00216 00217 void ADXL345::frequency(int hz) 00218 { 00219 _i2c.frequency(hz); 00220 } 00221 00222 uint8_t ADXL345::read_reg(uint8_t addr) 00223 { 00224 if (acc_ready == true){ 00225 dt[0] = addr; 00226 _i2c.write(acc_addr, dt, 1, true); 00227 _i2c.read(acc_addr, dt, 1, false); 00228 } else { 00229 dt[0] = 0xff; 00230 } 00231 return (uint8_t)dt[0]; 00232 } 00233 00234 void ADXL345::write_reg(uint8_t addr, uint8_t data) 00235 { 00236 if (acc_ready == true){ 00237 dt[0] = addr; 00238 dt[1] = data; 00239 _i2c.write(acc_addr, dt, 2, false); 00240 } 00241 } 00242 00243 void ADXL345::debug_print(void) 00244 { 00245 printf("ADXL345 3-axes accelerometer\r\n"); 00246 printf(" DEVID=0x%02x\r\n", read_reg(ADXL345_DEVID)); 00247 printf(" THRESH_TAP=0x%02x\r\n", read_reg(ADXL345_THRESH_TAP)); 00248 printf(" OFSX=0x%02x,", read_reg(ADXL345_OFSX)); 00249 printf(" OFSY=0x%02x,", read_reg(ADXL345_OFSY)); 00250 printf(" OFSZ=0x%02x\r\n", read_reg(ADXL345_OFSZ)); 00251 printf(" DUR=0x%02x,", read_reg(ADXL345_DUR)); 00252 printf(" LATENT=0x%02x,", read_reg(ADXL345_LATENT)); 00253 printf(" WINDOW=0x%02x\r\n", read_reg(ADXL345_WINDOW)); 00254 printf(" THRESH_ACT=0x%02x,", read_reg(ADXL345_THRESH_ACT)); 00255 printf(" THRESH_INACT=0x%02x\r\n", read_reg(ADXL345_THRESH_INACT)); 00256 printf(" TIME_INACT=0x%02x,", read_reg(ADXL345_TIME_INACT)); 00257 printf(" ACT_INACT_CTL=0x%02x\r\n", 00258 read_reg(ADXL345_ACT_INACT_CTL)); 00259 printf(" THRESH_FF=0x%02x,", read_reg(ADXL345_THRESH_FF)); 00260 printf(" TIME_FF=0x%02x,", read_reg(ADXL345_TIME_FF)); 00261 printf(" TAP_AXES=0x%02x,", read_reg(ADXL345_TAP_AXES)); 00262 printf(" ACT_TAP_STATUS=0x%02x\r\n", 00263 read_reg(ADXL345_ACT_TAP_STATUS)); 00264 printf(" BW_RATE=0x%02x\r\n", read_reg(ADXL345_BW_RATE)); 00265 printf(" POWER_CTL=0x%02x\r\n", read_reg(ADXL345_POWER_CTL)); 00266 printf(" INT_ENABLE=0x%02x,", read_reg(ADXL345_INT_ENABLE)); 00267 printf(" INT_MAP=0x%02x,", read_reg(ADXL345_INT_MAP)); 00268 printf(" INT_SOURCE=0x%02x\r\n", read_reg(ADXL345_INT_SOURCE)); 00269 printf(" DATA_FORMAT=0x%02x\r\n", read_reg(ADXL345_DATA_FORMAT)); 00270 printf(" DATAX0=0x%02x,", read_reg(ADXL345_DATAX0)); 00271 printf(" 1=0x%02x,", read_reg(ADXL345_DATAX1)); 00272 printf(" DATAY0=0x%02x,", read_reg(ADXL345_DATAY0)); 00273 printf(" 1=0x%02x,", read_reg(ADXL345_DATAY1)); 00274 printf(" DATAZ0=0x%02x,", read_reg(ADXL345_DATAZ0)); 00275 printf(" 1=0x%02x\r\n", read_reg(ADXL345_DATAZ1)); 00276 printf(" FIFO_CTL=0x%02x,", read_reg(ADXL345_FIFO_CTL)); 00277 printf(" FIFO_STATUS=0x%02x\r\n", read_reg(ADXL345_FIFO_STATUS)); 00278 // internal data 00279 printf(" ---- fs_factor=%f, acc_addr=0x%02x\r\n", fs_factor, acc_addr); 00280 } 00281 00282 void ADXL345::self_test(void) 00283 { 00284 float dt0[3] ={0}; 00285 float dt1[3] ={0}; 00286 float dt2[3]; 00287 00288 dt[0] = ADXL345_DATA_FORMAT; 00289 dt[1] = 0x0B; 00290 _i2c.write(acc_addr, dt, 2, false); 00291 dt[0] = ADXL345_POWER_CTL; 00292 dt[1] = 0x08; 00293 _i2c.write(acc_addr, dt, 2, false); 00294 dt[0] = ADXL345_INT_ENABLE; 00295 dt[1] = 0x80; 00296 _i2c.write(acc_addr, dt, 2, false); 00297 WAIT_MS(40); 00298 for(uint8_t n = 0; n < 100; n++){ 00299 read_data(dt2); 00300 dt0[0] += dt2[0]; 00301 dt0[1] += dt2[1]; 00302 dt0[2] += dt2[2]; 00303 } 00304 dt0[0] /= 100; 00305 dt0[1] /= 100; 00306 dt0[2] /= 100; 00307 // 00308 dt[0] = ADXL345_DATA_FORMAT; 00309 dt[1] = 0x8B; 00310 _i2c.write(acc_addr, dt, 2, false); 00311 WAIT_MS(40); 00312 for(uint8_t n = 0; n < 100; n++){ 00313 read_data(dt2); 00314 dt1[0] += dt2[0]; 00315 dt1[1] += dt2[1]; 00316 dt1[2] += dt2[2]; 00317 } 00318 dt1[0] /= 100; 00319 dt1[1] /= 100; 00320 dt1[2] /= 100; 00321 printf("X, 1st, %+8.4f, 2nd, %+8.4f, diff, %+8.4f\r\n", 00322 dt0[0], dt1[0], dt0[0] - dt1[0]); 00323 printf("Y, 1st, %+8.4f, 2nd, %+8.4f, diff, %+8.4f\r\n", 00324 dt0[1], dt1[1], dt0[1] - dt1[1]); 00325 printf("Z, 1st, %+8.4f, 2nd, %+8.4f, diff, %+8.4f\r\n", 00326 dt0[2], dt1[2], dt0[2] - dt1[2]); 00327 //Recover original setting 00328 // BW Rate 00329 dt[0] = ADXL345_BW_RATE; 00330 dt[1] = setting_data[0]; 00331 _i2c.write(acc_addr, dt, 2, false); 00332 // Data format (measurement range) 00333 dt[0] = ADXL345_DATA_FORMAT; 00334 dt[1] = setting_data[1]; 00335 _i2c.write(acc_addr, dt, 2, false); 00336 // Data ready flag 00337 dt[0] = ADXL345_INT_ENABLE; 00338 dt[1] = setting_data[2]; 00339 _i2c.write(acc_addr, dt, 2, false); 00340 // Start measurement mode 00341 dt[0] = ADXL345_POWER_CTL; 00342 dt[1] = setting_data[3]; 00343 _i2c.write(acc_addr, dt, 2, false); 00344 WAIT_MS(40); 00345 read_data(dt2); // dummy read 00346 }
Generated on Wed Jul 27 2022 17:10:48 by 1.7.2