This program simply connects to a HTS221 I2C device to read Temperature

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