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