Nathen Gallardojohnson / Mbed 2 deprecated RTFS_Tower_Logger

Dependencies:   mbed FXOS8700CQ mbed-rtos WNCInterface M2XStreamClient-JMF jsonlite

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 "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