Initial commit
Dependencies: ConfigFile FXOS8700CQ M2XStreamClient-JMF MODSERIAL SDFileSystem WNCInterface jsonlite mbed-rtos mbed
Fork of StarterKit_M2X_DevLab by
sensors.cpp
00001 /* =================================================================== 00002 Copyright © 2016, AVNET Inc. 00003 00004 Licensed under the Apache License, Version 2.0 (the "License"); 00005 you may not use this file except in compliance with the License. 00006 You may obtain a copy of the License at 00007 00008 http://www.apache.org/licenses/LICENSE-2.0 00009 00010 Unless required by applicable law or agreed to in writing, 00011 software distributed under the License is distributed on an 00012 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 00013 either express or implied. See the License for the specific 00014 language governing permissions and limitations under the License. 00015 00016 ======================================================================== */ 00017 00018 #include "mbed.h" 00019 #include "sensors.h" 00020 #include "FXOS8700CQ.h" 00021 #include "HTS221.h" 00022 #include <string> 00023 00024 //I2C for pmod sensors: 00025 #define Si1145_PMOD_I2C_ADDR 0xC0 //this is for 7-bit addr 0x60 for the Si7020 00026 #define Si7020_PMOD_I2C_ADDR 0x80 //this is for 7-bit addr 0x4 for the Si7020 00027 00028 // Storage for the data from the motion sensor 00029 SRAWDATA accel_data; 00030 SRAWDATA magn_data; 00031 //InterruptIn fxos_int1(PTC6); // unused, common with SW2 on FRDM-K64F 00032 InterruptIn fxos_int2(PTC13); // should just be the Data-Ready interrupt 00033 bool fxos_int2_triggered = false; 00034 void trigger_fxos_int2(void) 00035 { 00036 fxos_int2_triggered = true; 00037 00038 } 00039 00040 /*------------------------------------------------------------------------------ 00041 * Perform I2C single read. 00042 *------------------------------------------------------------------------------*/ 00043 unsigned char I2C_ReadSingleByte(unsigned char ucDeviceAddress) 00044 { 00045 char rxbuffer [1]; 00046 i2c.read(ucDeviceAddress, rxbuffer, 1 ); 00047 return (unsigned char)rxbuffer[0]; 00048 } //I2C_ReadSingleByte() 00049 00050 /*------------------------------------------------------------------------------ 00051 * Perform I2C single read from address. 00052 *------------------------------------------------------------------------------*/ 00053 unsigned char I2C_ReadSingleByteFromAddr(unsigned char ucDeviceAddress, unsigned char Addr) 00054 { 00055 char txbuffer [1]; 00056 char rxbuffer [1]; 00057 txbuffer[0] = (char)Addr; 00058 i2c.write(ucDeviceAddress, txbuffer, 1 ); 00059 i2c.read(ucDeviceAddress, rxbuffer, 1 ); 00060 return (unsigned char)rxbuffer[0]; 00061 } //I2C_ReadSingleByteFromAddr() 00062 00063 /*------------------------------------------------------------------------------ 00064 * Perform I2C read of more than 1 byte. 00065 *------------------------------------------------------------------------------*/ 00066 int I2C_ReadMultipleBytes(unsigned char ucDeviceAddress, char *ucData, unsigned char ucLength) 00067 { 00068 int status; 00069 status = i2c.read(ucDeviceAddress, ucData, ucLength); 00070 return status; 00071 } //I2C_ReadMultipleBytes() 00072 00073 /*------------------------------------------------------------------------------ 00074 * Perform I2C write of a single byte. 00075 *------------------------------------------------------------------------------*/ 00076 int I2C_WriteSingleByte(unsigned char ucDeviceAddress, unsigned char Data, bool bSendStop) 00077 { 00078 int status; 00079 char txbuffer [1]; 00080 txbuffer[0] = (char)Data; //data 00081 status = i2c.write(ucDeviceAddress, txbuffer, 1, !bSendStop); //true: do not send stop 00082 return status; 00083 } //I2C_WriteSingleByte() 00084 00085 /*------------------------------------------------------------------------------ 00086 * Perform I2C write of 1 byte to an address. 00087 *------------------------------------------------------------------------------*/ 00088 int I2C_WriteSingleByteToAddr(unsigned char ucDeviceAddress, unsigned char Addr, unsigned char Data, bool bSendStop) 00089 { 00090 int status; 00091 char txbuffer [2]; 00092 txbuffer[0] = (char)Addr; //address 00093 txbuffer[1] = (char)Data; //data 00094 //status = i2c.write(ucDeviceAddress, txbuffer, 2, false); //stop at end 00095 status = i2c.write(ucDeviceAddress, txbuffer, 2, !bSendStop); //true: do not send stop 00096 return status; 00097 } //I2C_WriteSingleByteToAddr() 00098 00099 /*------------------------------------------------------------------------------ 00100 * Perform I2C write of more than 1 byte. 00101 *------------------------------------------------------------------------------*/ 00102 int I2C_WriteMultipleBytes(unsigned char ucDeviceAddress, char *ucData, unsigned char ucLength, bool bSendStop) 00103 { 00104 int status; 00105 status = i2c.write(ucDeviceAddress, ucData, ucLength, !bSendStop); //true: do not send stop 00106 return status; 00107 } //I2C_WriteMultipleBytes() 00108 00109 bool bSi7020_present = false; 00110 void Init_Si7020(void) 00111 { 00112 char SN_7020 [8]; 00113 //SN part 1: 00114 I2C_WriteSingleByteToAddr(Si7020_PMOD_I2C_ADDR, 0xFA, 0x0F, false); 00115 I2C_ReadMultipleBytes(Si7020_PMOD_I2C_ADDR, &SN_7020[0], 4); 00116 00117 //SN part 1: 00118 I2C_WriteSingleByteToAddr(Si7020_PMOD_I2C_ADDR, 0xFC, 0xC9, false); 00119 I2C_ReadMultipleBytes(Si7020_PMOD_I2C_ADDR, &SN_7020[4], 4); 00120 00121 char Ver_7020 [2]; 00122 //FW version: 00123 I2C_WriteSingleByteToAddr(Si7020_PMOD_I2C_ADDR, 0x84, 0xB8, false); 00124 I2C_ReadMultipleBytes(Si7020_PMOD_I2C_ADDR, &Ver_7020[0], 2); 00125 00126 if (SN_7020[4] != 0x14) 00127 { 00128 bSi7020_present = false; 00129 PRINTF("Si7020 sensor not found\r\n"); 00130 } 00131 else 00132 { 00133 bSi7020_present = true; 00134 PRINTF("Si7020 SN = 0x%02X%02X%02X%02X%02X%02X%02X%02X\n", SN_7020[0], SN_7020[1], SN_7020[2], SN_7020[3], SN_7020[4], SN_7020[5], SN_7020[6], SN_7020[7]); 00135 PRINTF("Si7020 Version# = 0x%02X\n", Ver_7020[0]); 00136 } //bool bSi7020_present = true 00137 00138 } //Init_Si7020() 00139 00140 void Read_Si7020(void) 00141 { 00142 if (bSi7020_present) 00143 { 00144 char Humidity [2]; 00145 char Temperature [2]; 00146 //Command to measure humidity (temperature also gets measured): 00147 I2C_WriteSingleByte(Si7020_PMOD_I2C_ADDR, 0xF5, false); //no hold, must do dummy read 00148 I2C_ReadMultipleBytes(Si7020_PMOD_I2C_ADDR, &Humidity[0], 1); //dummy read, should get an nack until it is done 00149 wait (0.05); //wait for measurement. Can also keep reading until no NACK is received 00150 //I2C_WriteSingleByte(Si7020_PMOD_I2C_ADDR, 0xE5, false); //Hold mod, the device does a clock stretch on the read until it is done (crashes the I2C bus... 00151 I2C_ReadMultipleBytes(Si7020_PMOD_I2C_ADDR, &Humidity[0], 2); //read humidity 00152 //PRINTF("Read Si7020 Humidity = 0x%02X%02X\n", Humidity[0], Humidity[1]); 00153 int rh_code = (Humidity[0] << 8) + Humidity[1]; 00154 float fRh = (125.0*rh_code/65536.0) - 6.0; //from datasheet 00155 SENSOR_DATA.Humidity_Si7020 = fRh; 00156 00157 //Command to read temperature when humidity is already done: 00158 I2C_WriteSingleByte(Si7020_PMOD_I2C_ADDR, 0xE0, false); 00159 I2C_ReadMultipleBytes(Si7020_PMOD_I2C_ADDR, &Temperature[0], 2); //read temperature 00160 //PRINTF("Read Si7020 Temperature = 0x%02X%02X\n", Temperature[0], Temperature[1]); 00161 int temp_code = (Temperature[0] << 8) + Temperature[1]; 00162 float fTemp = (175.72*temp_code/65536.0) - 46.85; //from datasheet in Celcius 00163 SENSOR_DATA.Temperature_Si7020 = fTemp; 00164 } //bool bSi7020_present = true 00165 00166 } //Read_Si7020() 00167 00168 /*------------------------------------------------------------------------------ 00169 * The following are aliases so that the Si1145 coding examples can be used as-is. 00170 *------------------------------------------------------------------------------*/ 00171 unsigned char ReadFrom_Si1145_Register(unsigned char reg) //returns byte from I2C Register 'reg' 00172 { 00173 unsigned char result = I2C_ReadSingleByteFromAddr(Si1145_PMOD_I2C_ADDR, reg); 00174 return (result); 00175 } //ReadFrom_Si1145_Register() 00176 00177 void WriteTo_Si1145_Register(unsigned char reg, unsigned char value) //writes 'value' into I2C Register reg' 00178 { 00179 I2C_WriteSingleByteToAddr(Si1145_PMOD_I2C_ADDR, reg, value, true); 00180 } //WriteTo_Si1145_Register() 00181 00182 #define REG_PARAM_WR 0x17 00183 #define REG_PARAM_RD 0x2E 00184 #define REG_COMMAND 0x18 00185 #define REG_RESPONSE 0x20 00186 #define REG_HW_KEY 0x07 00187 #define HW_KEY_VAL0 0x17 00188 #define REG_MEAS_RATE_LSB 0x08 00189 #define REG_MEAS_RATE_MSB 0x09 00190 #define REG_PS_LED21 0x0F 00191 #define REG_PS_LED3 0x10 00192 #define MAX_LED_CURRENT 0xF 00193 #define PARAM_CH_LIST 0x01 00194 #define REG_ALS_VIS_DATA0 0x22 00195 #define REG_ALS_VIS_DATA1 0x23 00196 #define REG_ALS_IR_DATA0 0x24 00197 #define REG_ALS_IR_DATA1 0x25 00198 #define REG_PS1_DATA0 0x26 00199 #define REG_PS1_DATA1 0x27 00200 #define REG_PS2_DATA0 0x28 00201 #define REG_PS2_DATA1 0x29 00202 #define REG_PS3_DATA0 0x2A 00203 #define REG_PS3_DATA1 0x2B 00204 #define REG_UVINDEX0 0x2C 00205 #define REG_UVINDEX1 0x2D 00206 int Si1145_ParamSet(unsigned char address, unsigned char value) //writes 'value' into Parameter 'address' 00207 { 00208 char txbuffer [3]; 00209 txbuffer[0] = (char)REG_PARAM_WR; //destination 00210 txbuffer[1] = (char)value; 00211 txbuffer[2] = (char)(0xA0 + (address & 0x1F)); 00212 int retval; 00213 //if((retval = _waitUntilSleep(si114x_handle))!=0) return retval; 00214 retval = I2C_WriteMultipleBytes(Si1145_PMOD_I2C_ADDR, &txbuffer[0], 3, true); 00215 if(retval!=0) return retval; 00216 while(1) 00217 { 00218 retval=ReadFrom_Si1145_Register(REG_PARAM_RD); 00219 if (retval==value) break; 00220 } 00221 return (0); 00222 } //Si1145_ParamSet() 00223 00224 void PsAlsForce(void) //equivalent to WriteTo_Si1145_Register(REG_COMMAND,0x07). This forces PS and ALS measurements 00225 { 00226 WriteTo_Si1145_Register(REG_COMMAND,0x07); 00227 } //PsAlsForce() 00228 00229 bool bSi1145_present = false; 00230 void Init_Si1145(void) 00231 { 00232 unsigned char readbyte; 00233 //Read Si1145 part ID: 00234 readbyte = ReadFrom_Si1145_Register(0x00); 00235 if (readbyte != 0x45) 00236 { 00237 bSi1145_present = false; 00238 PRINTF("Si1145 sensor not found\r\n"); 00239 } 00240 else 00241 { 00242 bSi1145_present = true; 00243 PRINTF("Si1145 Part ID : 0x%02X\n", readbyte); 00244 //Initialize Si1145 by writing to HW_KEY (I2C Register 0x07 = 0x17) 00245 WriteTo_Si1145_Register(REG_HW_KEY, HW_KEY_VAL0); 00246 00247 // Initialize LED Current 00248 // I2C Register 0x0F = 0xFF 00249 // I2C Register 0x10 = 0x0F 00250 WriteTo_Si1145_Register(REG_PS_LED21,(MAX_LED_CURRENT<<4) + MAX_LED_CURRENT); 00251 WriteTo_Si1145_Register(REG_PS_LED3, MAX_LED_CURRENT); 00252 00253 // Parameter 0x01 = 0x37 00254 //Si1145_ParamSet(PARAM_CH_LIST, ALS_IR_TASK + ALS_VIS_TASK + PS1_TASK + PS2_TASK + PS3_TASK); 00255 //Si1145_ParamSet(0x01, 0x37); //CHLIST is address 0x01 in the parameter RAM. It defines which sensors are enabled (here, some) 00256 Si1145_ParamSet(0x01, 0x7F); //CHLIST is address 0x01 in the parameter RAM. It defines which sensors are enabled (here, all but UV. One can only use AUX or UV but here we use AUX because UV does not work...) 00257 // I2C Register 0x18 = 0x0x07 //This is PSALS_FORCE to the Command register => Force a single PS (proximity sensor) and ALS (ambient light sensor) reading - The factory code has this as 0x05 which only does PS... 00258 PsAlsForce(); // can also be written as WriteTo_Si1145_Register(REG_COMMAND,0x07); 00259 WriteTo_Si1145_Register(REG_COMMAND, 0x0F);//command to put it into auto mode 00260 //Set MES_RATE to 0x1000. I.e. the device will automatically wake up every 16 * 256* 31.25 us = 0.128 seconds to measure 00261 WriteTo_Si1145_Register(REG_MEAS_RATE_LSB, 0x00); 00262 WriteTo_Si1145_Register(REG_MEAS_RATE_MSB, 0x10); 00263 } //bSi1145_present = true 00264 } //Init_Si1145() 00265 00266 void Read_Si1145(void) 00267 { 00268 if (bSi1145_present) 00269 { 00270 // Once the measurements are completed, here is how to reconstruct them 00271 // Note very carefully that 16-bit registers are in the 'Little Endian' byte order 00272 // It may be more efficient to perform block I2C Reads, but this example shows 00273 // individual reads of registers 00274 00275 int PS1 = ReadFrom_Si1145_Register(REG_PS1_DATA0) + 256 * ReadFrom_Si1145_Register(REG_PS1_DATA1); 00276 int PS2 = ReadFrom_Si1145_Register(REG_PS2_DATA0) + 256 * ReadFrom_Si1145_Register(REG_PS2_DATA1); 00277 int PS3 = ReadFrom_Si1145_Register(REG_PS3_DATA0) + 256 * ReadFrom_Si1145_Register(REG_PS3_DATA1); 00278 //PRINTF("PS1_Data = %d\n", PS1); 00279 //PRINTF("PS2_Data = %d\n", PS2); 00280 //PRINTF("PS3_Data = %d\n", PS3); 00281 //OBJECT PRESENT? 00282 #if (0) 00283 if(PS1 < 22000){ 00284 //PRINTF("Object Far\n"); 00285 sprintf(SENSOR_DATA.Proximity, "Object Far\0"); 00286 } 00287 else if(PS1 < 24000) 00288 { 00289 //PRINTF("Object in Vicinity\n"); 00290 sprintf(SENSOR_DATA.Proximity, "Object in Vicinity\0"); 00291 } 00292 else if (PS1 < 30000) 00293 { 00294 //PRINTF("Object Near\n"); 00295 sprintf(SENSOR_DATA.Proximity, "Object Near\0"); 00296 } 00297 else 00298 { 00299 //PRINTF("Object Very Near\n"); 00300 sprintf(SENSOR_DATA.Proximity, "Object Very Near\0"); 00301 } 00302 #else 00303 SENSOR_DATA.Proximity = PS1; 00304 #endif 00305 00306 //Force ALS read: 00307 //WriteTo_Si1145_Register(REG_COMMAND, 0x06); 00308 //wait (0.1); 00309 int ALS_VIS = ReadFrom_Si1145_Register(REG_ALS_VIS_DATA0) + 256 * ReadFrom_Si1145_Register(REG_ALS_VIS_DATA1); 00310 int ALS_IR = ReadFrom_Si1145_Register(REG_ALS_IR_DATA0) + 256 * ReadFrom_Si1145_Register(REG_ALS_IR_DATA1); 00311 int UV_INDEX = ReadFrom_Si1145_Register(REG_UVINDEX0) + 256 * ReadFrom_Si1145_Register(REG_UVINDEX1); 00312 //PRINTF("ALS_VIS_Data = %d\n", ALS_VIS); 00313 //PRINTF("ALS_IR_Data = %d\n", ALS_IR); 00314 //PRINTF("UV_INDEX_Data = %d\n", UV_INDEX); 00315 00316 //PRINTF("Ambient Light Visible Sensor = %d\n", ALS_VIS); 00317 SENSOR_DATA.AmbientLightVis = ALS_VIS; 00318 //PRINTF("Ambient Light Infrared Sensor = %d\n", ALS_IR); 00319 SENSOR_DATA.AmbientLightIr = ALS_IR; 00320 //float fUV_value = (UV_INDEX -50.0)/10000.0; 00321 float fUV_value = (UV_INDEX)/100.0; //this is the aux reading 00322 //PRINTF("UV_Data = %0.2f\n", fUV_value); 00323 SENSOR_DATA.UVindex = fUV_value; 00324 } //bSi1145_present = true 00325 } //Read_Si1145() 00326 00327 //******************************************************************************************************************************************** 00328 //* Read the FXOS8700CQ - 6-axis combo Sensor Accelerometer and Magnetometer 00329 //******************************************************************************************************************************************** 00330 bool bMotionSensor_present = false; 00331 void Init_motion_sensor() 00332 { 00333 // Note: this class is instantiated here because if it is statically declared, the cellular shield init kills the I2C bus... 00334 // Class instantiation with pin names for the motion sensor on the FRDM-K64F board: 00335 FXOS8700CQ fxos(PTE25, PTE24, FXOS8700CQ_SLAVE_ADDR1); // SDA, SCL, (addr << 1) 00336 int iWhoAmI = fxos.get_whoami(); 00337 00338 PRINTF("FXOS8700CQ WhoAmI = %X\r\n", iWhoAmI); 00339 // Iterrupt for active-low interrupt line from FXOS 00340 // Configured with only one interrupt on INT2 signaling Data-Ready 00341 //fxos_int2.fall(&trigger_fxos_int2); 00342 if (iWhoAmI != 0xC7) 00343 { 00344 bMotionSensor_present = false; 00345 PRINTF("FXOS8700CQ motion sensor not found\r\n"); 00346 } 00347 else 00348 { 00349 bMotionSensor_present = true; 00350 fxos.enable(); 00351 } 00352 } //Init_motion_sensor() 00353 00354 void Read_motion_sensor() 00355 { 00356 // Note: this class is instantiated here because if it is statically declared, the cellular shield init kills the I2C bus... 00357 // Class instantiation with pin names for the motion sensor on the FRDM-K64F board: 00358 FXOS8700CQ fxos(PTE25, PTE24, FXOS8700CQ_SLAVE_ADDR1); // SDA, SCL, (addr << 1) 00359 if (bMotionSensor_present) 00360 { 00361 fxos.enable(); 00362 fxos.get_data(&accel_data, &magn_data); 00363 //PRINTF("Roll=%5d, Pitch=%5d, Yaw=%5d;\r\n", magn_data.x, magn_data.y, magn_data.z); 00364 SENSOR_DATA.MagnetometerX = magn_data.x; 00365 SENSOR_DATA.MagnetometerY = magn_data.y; 00366 SENSOR_DATA.MagnetometerZ = magn_data.z; 00367 00368 //Try to normalize (/2048) the values so they will match the eCompass output: 00369 float fAccelScaled_x, fAccelScaled_y, fAccelScaled_z; 00370 int trunc = accel_data.x/2048.0 * 10.0; 00371 fAccelScaled_x = trunc / 10.0; 00372 trunc = accel_data.y/2048.0 * 10.0; 00373 fAccelScaled_y = trunc / 10.0; 00374 trunc = accel_data.z/2048.0 * 10.0; 00375 fAccelScaled_z = trunc / 10.0; 00376 //PRINTF("Acc: X=%2.3f Y=%2.3f Z=%2.3f;\r\n", fAccelScaled_x, fAccelScaled_y, fAccelScaled_z); 00377 SENSOR_DATA.AccelX = fAccelScaled_x; 00378 SENSOR_DATA.AccelY = fAccelScaled_y; 00379 SENSOR_DATA.AccelZ = fAccelScaled_z; 00380 } //bMotionSensor_present 00381 } //Read_motion_sensor() 00382 00383 00384 //******************************************************************************************************************************************** 00385 //* Read the HTS221 temperature & humidity sensor on the Cellular Shield 00386 //******************************************************************************************************************************************** 00387 // These are to be built on the fly 00388 string my_temp; 00389 string my_humidity; 00390 HTS221 hts221; 00391 00392 #define CTOF(x) ((x)*1.8+32) 00393 bool bHTS221_present = false; 00394 void Init_HTS221() 00395 { 00396 int i; 00397 void hts221_init(void); 00398 i = hts221.begin(); 00399 if (i) 00400 { 00401 bHTS221_present = true; 00402 PRINTF(BLU "HTS221 Detected (0x%02X)\n\r",i); 00403 PRINTF(" Temp is: %0.2f F \n\r",CTOF(hts221.readTemperature())); 00404 PRINTF(" Humid is: %02d %%\n\r",hts221.readHumidity()); 00405 } 00406 else 00407 { 00408 bHTS221_present = false; 00409 PRINTF(RED "HTS221 NOT DETECTED!\n\r"); 00410 } 00411 } //Init_HTS221() 00412 00413 void Read_HTS221() 00414 { 00415 if (bHTS221_present) 00416 { 00417 double fTemp = hts221.readTemperature(); 00418 double fRh = hts221.readHumidity(); 00419 SENSOR_DATA.Temperature = fTemp; 00420 SENSOR_DATA.Humidity = fRh; 00421 00422 } //bHTS221_present 00423 } //Read_HTS221() 00424 00425 00426 void sensors_init(void) 00427 { 00428 Init_HTS221(); 00429 Init_Si7020(); 00430 Init_Si1145(); 00431 Init_motion_sensor(); 00432 } //sensors_init 00433 00434 void read_sensors(void) 00435 { 00436 Read_HTS221(); 00437 Read_Si7020(); 00438 Read_Si1145(); 00439 Read_motion_sensor(); 00440 } //read_sensors
Generated on Fri Jul 15 2022 01:40:15 by 1.7.2