Initial commit

Dependencies:   ConfigFile FXOS8700CQ M2XStreamClient-JMF MODSERIAL SDFileSystem WNCInterface jsonlite mbed-rtos mbed

Fork of StarterKit_M2X_DevLab by Jan Korycan

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sensors.cpp Source File

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