This program simply connects to a HTS221 I2C device to proximity sensor

Dependencies:   FXOS8700CQ mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sensors.cpp Source File

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