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