publish final code
Dependencies: FXOS8700CQ Pubnub_mbed2_sync2 SoftSerial TinyGPSplus WNCInterface2 mbed-rtos mbed
Revision 0:1092494506a3, committed 2017-02-21
- Comitter:
- cswiger
- Date:
- Tue Feb 21 22:28:26 2017 +0000
- Commit message:
- publish final code
Changed in this revision
diff -r 000000000000 -r 1092494506a3 FXOS8700CQ.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FXOS8700CQ.lib Tue Feb 21 22:28:26 2017 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/trm/code/FXOS8700CQ/#e2fe752b881e
diff -r 000000000000 -r 1092494506a3 HTS221.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTS221.h Tue Feb 21 22:28:26 2017 +0000 @@ -0,0 +1,108 @@ +/* =================================================================== +Copyright © 2016, AVNET Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the License for the specific +language governing permissions and limitations under the License. + +======================================================================== */ + +#ifndef HTS221_H_ +#define HTS221_H_ + +class HTS221 { +public: + HTS221(void); + int begin(void); + int activate(void); + int deactivate(void); + + int bduActivate(void); + int bduDeactivate(void); + + int readHumidity(void); + double readTemperature(void); +private: + int storeCalibration(void); + unsigned char _h0_rH, _h1_rH; + unsigned int _T0_degC, _T1_degC; + unsigned int _H0_T0, _H1_T0; + unsigned int _T0_OUT, _T1_OUT; + double _temperature; + int _humidity; + unsigned char _address; + + unsigned char readRegister(unsigned char slaveAddress, unsigned char regToRead); + int writeRegister(unsigned char slaveAddress, unsigned char regToWrite, unsigned char dataToWrite); +}; + +#define HTS221_ADDRESS 0xBF + +//Define a few of the registers that we will be accessing on the HTS221 +#define WHO_AM_I 0x0F +#define WHO_AM_I_RETURN 0xBC //This read-only register contains the device identifier, set to BCh + +#define AVERAGE_REG 0x10 // To configure humidity/temperature average. +#define AVERAGE_DEFAULT 0x1B + +/* + * [7] PD: power down control + * (0: power-down mode; 1: active mode) + * + * [6:3] Reserved + * + * [2] BDU: block data update + * (0: continuous update; 1: output registers not updated until MSB and LSB reading) +The BDU bit is used to inhibit the output register update between the reading of the upper +and lower register parts. In default mode (BDU = ?0?), the lower and upper register parts are +updated continuously. If it is not certain whether the read will be faster than output data rate, +it is recommended to set the BDU bit to ?1?. In this way, after the reading of the lower (upper) +register part, the content of that output register is not updated until the upper (lower) part is +read also. + * + * [1:0] ODR1, ODR0: output data rate selection (see table 17) + */ +#define CTRL_REG1 0x20 +#define POWER_UP 0x80 +#define BDU_SET 0x4 +#define ODR0_SET 0x1 // setting sensor reading period 1Hz + +#define CTRL_REG2 0x21 +#define CTRL_REG3 0x22 +#define REG_DEFAULT 0x00 + +#define STATUS_REG 0x27 +#define TEMPERATURE_READY 0x1 +#define HUMIDITY_READY 0x2 + +#define HUMIDITY_L_REG 0x28 +#define HUMIDITY_H_REG 0x29 +#define TEMP_L_REG 0x2A +#define TEMP_H_REG 0x2B +/* + * calibration registry should be read for temperature and humidity calculation. + * Before the first calculation of temperature and humidity, + * the master reads out the calibration coefficients. + * will do at init phase + */ +#define CALIB_START 0x30 +#define CALIB_END 0x3F +/* +#define CALIB_T0_DEGC_X8 0x32 +#define CALIB_T1_DEGC_X8 0x33 +#define CALIB_T1_T0_MSB 0x35 +#define CALIB_T0_OUT_L 0x3C +#define CALIB_T0_OUT_H 0x3D +#define CALIB_T1_OUT_L 0x3E +#define CALIB_T1_OUT_H 0x3F + */ + +#endif
diff -r 000000000000 -r 1092494506a3 Pubnub_mbed2_sync.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pubnub_mbed2_sync.lib Tue Feb 21 22:28:26 2017 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/users/cswiger/code/Pubnub_mbed2_sync2/#3ee9629861ab
diff -r 000000000000 -r 1092494506a3 SoftSerial.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SoftSerial.lib Tue Feb 21 22:28:26 2017 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/users/Sissors/code/SoftSerial/#a0029614de72
diff -r 000000000000 -r 1092494506a3 TinyGPSplus.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TinyGPSplus.lib Tue Feb 21 22:28:26 2017 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/users/Sir_Binky/code/TinyGPSplus/#9163a9f5fc36
diff -r 000000000000 -r 1092494506a3 WNCInterface.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WNCInterface.lib Tue Feb 21 22:28:26 2017 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/users/cswiger/code/WNCInterface2/#8b3599a611b3
diff -r 000000000000 -r 1092494506a3 hardware.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hardware.h Tue Feb 21 22:28:26 2017 +0000 @@ -0,0 +1,64 @@ +/* =================================================================== +Copyright © 2016, AVNET Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the License for the specific +language governing permissions and limitations under the License. + +======================================================================== */ + +#ifndef Hardware_H_ +#define Hardware_H_ +#include "MODSERIAL.h" + +extern I2C i2c; //SDA, SCL -- define the I2C pins being used +extern MODSERIAL pc; //UART to USB host +extern MODSERIAL mdm; //UART to WNC modem +//extern SerialBuffered mdm; //UART to WNC modem + +//Un-comment the definition below if you want to use the USB rx for another purpose. +//otherwise the USB rx will be used to receive virtual sensor data from Avnet's +//"Sensor Simulator Dashboard" utility +#define USE_VIRTUAL_SENSORS + +// comment out the following line if color is not supported on the terminal +#define USE_COLOR +#ifdef USE_COLOR + #define BLK "\033[30m" + #define RED "\033[31m" + #define GRN "\033[32m" + #define YEL "\033[33m" + #define BLU "\033[34m" + #define MAG "\033[35m" + #define CYN "\033[36m" + #define WHT "\033[37m" + #define DEF "\033[39m" +#else + #define BLK + #define RED + #define GRN + #define YEL + #define BLU + #define MAG + #define CYN + #define WHT + #define DEF +#endif + +#ifdef _ULINK_PRINT +#include "itm_output.h" +#else +#define PRINTF pc.printf +#define PUTS pc.puts +#endif + + +#endif
diff -r 000000000000 -r 1092494506a3 hts221_driver.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hts221_driver.cpp Tue Feb 21 22:28:26 2017 +0000 @@ -0,0 +1,266 @@ +/* =================================================================== +Copyright © 2016, AVNET Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the License for the specific +language governing permissions and limitations under the License. + +======================================================================== */ + +#include "HTS221.h" + + +// ------------------------------------------------------------------------------ +//jmf -- define I2C pins and functions to read & write to I2C device + +#include <string> +#include "mbed.h" + +#include "hardware.h" +//I2C i2c(PTC11, PTC10); //SDA, SCL -- define the I2C pins being used. Defined in a +//common locatioin since sensors also use I2C + +// Read a single unsigned char from addressToRead and return it as a unsigned char +unsigned char HTS221::readRegister(unsigned char slaveAddress, unsigned char ToRead) +{ + char data = ToRead; + + //i2c.write(slaveAddress, &data, 1, 0); + i2c.write(slaveAddress, &data, 1, 1); //by Stefan + i2c.read(slaveAddress, &data, 1, 0); + return data; +} + +// Writes a single unsigned char (dataToWrite) into regToWrite +int HTS221::writeRegister(unsigned char slaveAddress, unsigned char regToWrite, unsigned char dataToWrite) +{ + const char data[] = {regToWrite, dataToWrite}; + + return i2c.write(slaveAddress,data,2,0); +} + + +//jmf end +// ------------------------------------------------------------------------------ + +//static inline int humidityReady(uint8_t data) { +// return (data & 0x02); +//} +//static inline int temperatureReady(uint8_t data) { +// return (data & 0x01); +//} + + +HTS221::HTS221(void) : _address(HTS221_ADDRESS) +{ + _temperature = 0; + _humidity = 0; +} + + +int HTS221::begin(void) +{ + uint8_t data; + + data = readRegister(_address, WHO_AM_I); + if (data == WHO_AM_I_RETURN){ + if (activate()){ + storeCalibration(); + return data; + } + } + + return 0; +} + +int +HTS221::storeCalibration(void) +{ + uint8_t data; + uint16_t tmp; + + for (int reg=CALIB_START; reg<=CALIB_END; reg++) { + if ((reg!=CALIB_START+8) && (reg!=CALIB_START+9) && (reg!=CALIB_START+4)) { + + data = readRegister(HTS221_ADDRESS, reg); + + switch (reg) { + case CALIB_START: + _h0_rH = data; + break; + case CALIB_START+1: + _h1_rH = data; + break; + case CALIB_START+2: + _T0_degC = data; + break; + case CALIB_START+3: + _T1_degC = data; + break; + + case CALIB_START+5: + tmp = _T0_degC; + _T0_degC = (data&0x3)<<8; + _T0_degC |= tmp; + + tmp = _T1_degC; + _T1_degC = ((data&0xC)>>2)<<8; + _T1_degC |= tmp; + break; + case CALIB_START+6: + _H0_T0 = data; + break; + case CALIB_START+7: + _H0_T0 |= data<<8; + break; + case CALIB_START+0xA: + _H1_T0 = data; + break; + case CALIB_START+0xB: + _H1_T0 |= data <<8; + break; + case CALIB_START+0xC: + _T0_OUT = data; + break; + case CALIB_START+0xD: + _T0_OUT |= data << 8; + break; + case CALIB_START+0xE: + _T1_OUT = data; + break; + case CALIB_START+0xF: + _T1_OUT |= data << 8; + break; + + + case CALIB_START+8: + case CALIB_START+9: + case CALIB_START+4: + //DO NOTHING + break; + + // to cover any possible error + default: + return false; + } /* switch */ + } /* if */ + } /* for */ + return true; +} + + +int +HTS221::activate(void) +{ + uint8_t data; + + data = readRegister(_address, CTRL_REG1); + data |= POWER_UP; + data |= ODR0_SET; + writeRegister(_address, CTRL_REG1, data); + + return true; +} + + +int HTS221::deactivate(void) +{ + uint8_t data; + + data = readRegister(_address, CTRL_REG1); + data &= ~POWER_UP; + writeRegister(_address, CTRL_REG1, data); + return true; +} + + +int +HTS221::bduActivate(void) +{ + uint8_t data; + + data = readRegister(_address, CTRL_REG1); + data |= BDU_SET; + writeRegister(_address, CTRL_REG1, data); + + return true; +} + + +int +HTS221::bduDeactivate(void) +{ + uint8_t data; + + data = readRegister(_address, CTRL_REG1); + data &= ~BDU_SET; + writeRegister(_address, CTRL_REG1, data); + return true; +} + + +int +HTS221::readHumidity(void) +{ + uint8_t data = 0; + uint16_t h_out = 0; + double h_temp = 0.0; + double hum = 0.0; + + data = readRegister(_address, STATUS_REG); + + if (data & HUMIDITY_READY) { + data = readRegister(_address, HUMIDITY_H_REG); + h_out = data << 8; // MSB + data = readRegister(_address, HUMIDITY_L_REG); + h_out |= data; // LSB + + // Decode Humidity + hum = ((int16_t)(_h1_rH) - (int16_t)(_h0_rH))/2.0; // remove x2 multiple + + // Calculate humidity in decimal of grade centigrades i.e. 15.0 = 150. + h_temp = (((int16_t)h_out - (int16_t)_H0_T0) * hum) / ((int16_t)_H1_T0 - (int16_t)_H0_T0); + hum = ((int16_t)_h0_rH) / 2.0; // remove x2 multiple + _humidity = (int16_t)((hum + h_temp)); // provide signed % measurement unit + } + return _humidity; +} + + + +double +HTS221::readTemperature(void) +{ + uint8_t data = 0; + uint16_t t_out = 0; + double t_temp = 0.0; + double deg = 0.0; + + data = readRegister(_address, STATUS_REG); + + if (data & TEMPERATURE_READY) { + + data= readRegister(_address, TEMP_H_REG); + t_out = data << 8; // MSB + data = readRegister(_address, TEMP_L_REG); + t_out |= data; // LSB + + // Decode Temperature + deg = ((int16_t)(_T1_degC) - (int16_t)(_T0_degC))/8.0; // remove x8 multiple + + // Calculate Temperature in decimal of grade centigrades i.e. 15.0 = 150. + t_temp = (((int16_t)t_out - (int16_t)_T0_OUT) * deg) / ((int16_t)_T1_OUT - (int16_t)_T0_OUT); + deg = ((int16_t)_T0_degC) / 8.0; // remove x8 multiple + _temperature = deg + t_temp; // provide signed celsius measurement unit + } + + return _temperature; +}
diff -r 000000000000 -r 1092494506a3 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Tue Feb 21 22:28:26 2017 +0000 @@ -0,0 +1,726 @@ +/* ===================================================================== + Copyright © 2016, Avnet (R) + + Contributors: + * James M Flynn, www.em.avnet.com + * Chuck Swiger + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific + language governing permissions and limitations under the License. + + @file WNC_Pubnub_obd2b + @version 1.0b + @date Dec 2016 + + - This version has the AccelX,Y,Z sensor and code for GPS +======================================================================== */ + +#include "mbed.h" +#include "WNCInterface.h" +#include "main.h" // obd2 includes +//#include "MODSERIAL.h" // already exists in WNCInterface +#include "SoftSerial.h" +#include "pubnub_sync.h" +#include "sensors.h" +#include "hardware.h" +#include "TinyGPSplus.h" + +#define DEBUG +#define MBED_PLATFORM + +#define CRLF "\n\r" + +I2C i2c(PTC11, PTC10); //SDA, SCL -- define the I2C pins being used + +WNCInterface wnc; +MODSERIAL pc(USBTX,USBRX,256,256); +MODSERIAL obd2(PTC15,PTC14,256,256); // (TX,RX,txbuffer,rxbuffer) + // This is the Bluetooth J199 connector - pin3 PTC14 RX, pin4 PTC15 TX +SoftSerial gpss2(PTC7,PTC5); // Moved from uart0 to softserial - this worked! + +pubnub_t *pbp = pubnub_alloc(); + +TinyGPSPlus gps; + +DigitalOut rled(PTB19); // RED panel lamp +DigitalOut gled(PTB18); // GREEN + + +long GPSBAUD = 9600; +long OBDBAUD = 9600; +long PCBAUD = 115200; + +K64F_Sensors_t SENSOR_DATA = +{ + .Temperature = "0", + .Humidity = "0", + .AccelX = "0", + .AccelY = "0", + .AccelZ = "0", +}; + +void feedGPS() { + while (gpss2.readable()) { + gps.encode(gpss2.getc()); + } +} + + +char* itoa(int val, int base){ + static char buf[32] = {0}; + int i = 30; + for(; val && i ; --i, val /= base) + buf[i] = "0123456789abcdef"[val % base]; + return &buf[i+1]; +} + + +//Periodic timer +Ticker OneMsTicker; +volatile bool bTimerExpiredFlag = false; +int OneMsTicks = 0; +int iTimer1Interval_ms = 1000; + +void OneMsFunction() +{ + OneMsTicks++; + if ((OneMsTicks % iTimer1Interval_ms) == 0) + { + bTimerExpiredFlag = true; + } +} //OneMsFunction() + + +void GetDTC(void) +{ + char jsonreply[140] = {'\0'}; + dtc_read(); // populate the DTC struct if any + if(has_dtc) { + strcpy(jsonreply,"{\""); + for (int i=0; i<MAX_DTC_READ; i++) { + strcat(jsonreply,itoa((i+1),10)); + strcat(jsonreply,"\":\""); + if(i!=MAX_DTC_READ-1) { // last one? + strcat(jsonreply,DTC[i].code); + strcat(jsonreply,"\",\""); + } else { + strcat(jsonreply,DTC[i].code); + strcat(jsonreply,"\"}"); + } + } + } else { + strcpy(jsonreply,"{\"1\":\"none\"}"); + } + pubnub_res rslt = pubnub_publish(pbp, "carpal2", jsonreply); + if (rslt != PNR_STARTED) + pc.printf("Failed to start publishing, rslt=%d"CRLF, rslt); + else { + rslt = pubnub_await(pbp); + if (rslt != PNR_OK) + pc.printf("Failed to finished publishing, rslt=%d"CRLF, rslt); + else { + pc.printf("Published! Response from Pubnub: %s"CRLF, pubnub_last_publish_result(pbp)); + } + } + +} // GetDTC + +bool parse_JSON(char const* json_string) +{ + char const* beginquote; + char token[] = "get:"; + beginquote = strstr(json_string, token ); + if ((beginquote != 0)) + { + char getreq = beginquote[strlen(token)]; // this only gets a single letter at the position after 'get:' + PRINTF(GRN "get Found : %c" DEF "\r\n", getreq); + switch(getreq) + { + case 'd': + { // dtc + GetDTC(); + break; + } + default: + { + break; + } + } //switch(getreq) + return true; + } + else + { + return false; + } +} //parse_JSON + + +int main() +{ + char data[256]; + int ret; + + long vehicle_speed = 0; + long engine_rpm = 0; + long fuel_status = 0; + long engine_load = 0; + long coolant_temp = 0; + long stft_b1 = 0; + long ltft_b1 = 0; + long stft_b2 = 0; + long ltft_b2 = 0; + long timing_adv = 0; + long int_air_temp = 0; + long maf_air_flow = 0; + long throttle_pos = 0; + long b1s2_o2_v = 0; + + + rled = 1; // red panel lamp while initializing + gled = 0; + + // Configure PC BAUD + pc.baud(PCBAUD); + gpss2.baud(GPSBAUD); + + + //debug + //wait(10); // wait for terminal connected - not needed for normal use + pc.printf(WHT "STARTING WNCInterface PubNub Test" CRLF); + + //Create a 1ms timer tick function: + iTimer1Interval_ms = SENSOR_UPDATE_INTERVAL_MS; + OneMsTicker.attach(OneMsFunction, 0.001f) ; + + //Initialize the I2C sensors that are present + sensors_init(); + read_sensors(); + + // init and connect the WNCInterface cell modem + pc.printf(DEF "init() returned 0x%04X" CRLF, wnc.init(NULL,&pc)); + ret = wnc.connect(); // this does NOT really connect, connect happens in wnc.init() above + // it just returns 0 for ok and -1 for not connected + if (ret) NVIC_SystemReset(); // so if not connected, reset! + wnc.doDebug(0); // if you want a LOT of AT commands logged (1) + + pc.printf("IP Address: %s " CRLF, wnc.getIPAddress()); + pc.printf("-------------------------------------" CRLF); + pc.printf("starting PubNub sync..." CRLF); + + // create the Pubnub interface + pubnub_init(pbp, "pub-c-a7e5745b-0ad1-42ac-8cce-229057b406ed", "sub-c-4df1fc96-825f-11e5-8495-02ee2ddab7fe"); + + // Setup STN1110 UART + pc.printf("Configuring OBD UART\r\n"); + Init(); + pc.printf("Configure done..\r\n"); + + while(1) { + feedGPS(); + if (bTimerExpiredFlag) + { + bTimerExpiredFlag = false; + ret = wnc.connect(); // check if still connected - it just returns 0 for ok and -1 for not connected + if (ret) NVIC_SystemReset(); // so if not connected, reset! + pc.printf("Refresh...\n\r"); + Refresh(); + pc.printf("Ignition on: %d\n\r",isIgnitionOn); + pc.printf("Engine on: %d\n\r",isEngineOn); + if(isIgnitionOn) { + rled = 1; + pc.printf("Get coolant temp...\n\r"); + get_pid(COOLANT_TEMP,&coolant_temp); + pc.printf("Get rpm...\n\r"); + get_pid(ENGINE_RPM,&engine_rpm); + get_pid(LOAD_VALUE,&engine_load); + get_pid(VEHICLE_SPEED,&vehicle_speed); + pc.printf("Coolant: %d\n\rRPM: %d\n\r",coolant_temp,engine_rpm); + // short keys to keep air co$t$ down + // oc or os ol - obd2 coolant temp, rpm, speed, load + // la lo - gps latitude, longitude + // ax ay - accelarometer X,Y + pc.printf("Read sensors\n\r"); + read_sensors(); + pc.printf("GPS chars processed: %d\n\r",gps.charsProcessed()); + if(gps.location.isValid()) { + snprintf(data,256,"{\"la\":%f,\"lo\":%f,\"ax\":%s,\"ay\":%s,\"oc\":%d,\"or\":%d,\"ol\":%d,\"os\":%d}",gps.location.lat(),gps.location.lng(),SENSOR_DATA.AccelX,SENSOR_DATA.AccelY,coolant_temp,engine_rpm,engine_load,vehicle_speed); + } else { + snprintf(data,256,"{\"ax\":%s,\"ay\":%s,\"oc\":%d,\"or\":%d,\"ol\":%d,\"os\":%d}",SENSOR_DATA.AccelX,SENSOR_DATA.AccelY,coolant_temp,engine_rpm,engine_load,vehicle_speed); + } + ret = wnc.connect(); // check if still connected - it just returns 0 for ok and -1 for not connected + if (ret) NVIC_SystemReset(); // so if not connected, reset! + // publish json and wait for result + pubnub_res rslt = pubnub_publish(pbp, "carpal2", data); + if (rslt != PNR_STARTED) { + pc.printf("Failed to start publishing, rslt=%d"CRLF, rslt); + rled = 1; + gled = 0; + } else { + rslt = pubnub_await(pbp); + if (rslt != PNR_OK) { + pc.printf("Failed to finished publishing, rslt=%d"CRLF, rslt); + rled = 1; + gled = 0; + } else { + pc.printf("Published! Response from Pubnub: %s"CRLF, pubnub_last_publish_result(pbp)); + rled = 0; + gled = 1; + } + } + ret = wnc.connect(); // check if still connected - it just returns 0 for ok and -1 for not connected + if (ret) NVIC_SystemReset(); // so if not connected, reset! + rslt = pubnub_subscribe(pbp, "carpal2", 0); + if (rslt != PNR_STARTED) { + pc.printf("Failed to start subscribing, rslt=%d"CRLF, rslt); + rled = 1; + gled = 0; + } else { + rslt = pubnub_await(pbp); + if (rslt != PNR_OK) { + pc.printf("Failed to finished subscribing, rslt=%d"CRLF, rslt);\ + rled = 1; + gled = 0; + } else { + pc.printf("Subscribed! Received messages follow:"CRLF); + while (char const *msg = pubnub_get(pbp)) { + pc.printf("subscribe got: %s"CRLF, msg); + parse_JSON(msg); + } + } + rled = 0; + gled = 1; + } // subscribe result + } else { + rled = 1; + gled = 0; + pc.printf("Ignition off... attempting Init()\n\r"); + Init(); + } // end isIgnitionOn + } // end timer expired + } // end infinite loop + } + +char pid_reslen[] = +{ + // pid 0x00 to 0x1F + 4,4,2,2,1,1,1,1,1,1,1,1,2,1,1,1, + 2,1,1,1,2,2,2,2,2,2,2,2,1,1,1,4, + + // pid 0x20 to 0x3F + 4,2,2,2,4,4,4,4,4,4,4,4,1,1,1,1, + 1,2,2,1,4,4,4,4,4,4,4,4,2,2,2,2, + + // pid 0x40 to 0x4E + 4,8,2,2,2,1,1,1,1,1,1,1,1,2,2 +}; + + + +/*********************** + Init + ***********************/ +char Init() +{ + obd2.baud(OBDBAUD); + char str[STRLEN]; + // reset + stn1110_command(str, "ATWS\r"); + // turn echo off + stn1110_command(str, "ATE0\r"); + + // send 01 00 until we are connected + do + { + stn1110_command(str, "0100\r"); + wait(1); // might want to change this to return non-zero for engine off or something, otherwise it's stuck here + } + while(stn1110_check_response("0100", str)!=0); + + // ask protocol + stn1110_command(str, "ATDPN\r"); + + check_supported_pids(); + + return 0; +} + +char stn1110_read(char *str, char size) +{ + int b; + char i=0; + + // wait for something on com port + while((b=obd2.getcNb())!=PROMPT && i<size) // getcNb() does NOT block, + { + if(b>=' ') + str[i++]=b; + } + + if(i!=size) // we got a prompt + { + str[i]=NUL; // replace CR by NUL + return PROMPT; + } + else + return DATA; +} + +void stn1110_write(char *str) +{ + while(*str!=NUL) + obd2.putc(*str++); +} + +char stn1110_check_response(const char *cmd, char *str) +{ + // cmd is something like "010D" + // str should be "41 0D blabla" + if(cmd[0]+4 != str[0] + || cmd[1]!=str[1] + || cmd[2]!=str[3] + || cmd[3]!=str[4]) + return 1; + + return 0; // no error +} + +char stn1110_compact_response(char *buf, char *str) +{ + char i=0; + + str+=6; + while(*str!=NUL) + buf[i++]=strtoul(str, &str, 16); // 16 = hex + + return i; +} + +char stn1110_command(char *str, char *cmd) +{ + strcpy(str, cmd); + stn1110_write(str); + return stn1110_read(str, STRLEN); +} + +void check_supported_pids(void) +{ + + // on some ECU first PID read attemts some time fails, changed to 3 attempts + for (char i=0; i<3; i++) + { + pid01to20_support = (get_pid(PID_SUPPORT00, &tempLong)) ? tempLong : 0; + if (pid01to20_support) + break; + } + + if(is_pid_supported(PID_SUPPORT20)) + if (get_pid(PID_SUPPORT20, &tempLong)) + pid21to40_support = tempLong; + + if(is_pid_supported(PID_SUPPORT40)) + if (get_pid(PID_SUPPORT40, &tempLong)) + pid41to60_support = tempLong; +} + +char is_pid_supported(char pid) +{ + if(pid==0) + return 1; + else + if(pid<=0x20) + { + if(1L<<(char)(0x20-pid) & pid01to20_support) + return 1; + } + else + if(pid<=0x40) + { + if(1L<<(char)(0x40-pid) & pid21to40_support) + return 1; + } + else + if(pid<=0x60) + { + if(1L<<(char)(0x60-pid) & pid41to60_support) + return 1; + } + + return 0; +} + + +char get_pid(char pid, long *ret) +{ + char cmd_str[6]; // to send to STN1110 + char str[STRLEN]; // to receive from STN1110 + char i; + char buf[10]; // to receive the result + char reslen; + + // check if PID is supported + if(!is_pid_supported(pid)) + { + // Not Supported + return 0; + } + + // receive length depends on pid + reslen=pid_reslen[pid]; + + sprintf(cmd_str, "01%02X\r", pid); + pc.printf("get_pid - stn1110_write\n\r"); + stn1110_write(cmd_str); + pc.printf("get_pid - stn1110_read\n\r"); + stn1110_read(str, STRLEN); + + if(stn1110_check_response(cmd_str, str)!=0) + { + return 0; + } + stn1110_compact_response(buf, str); + + *ret=buf[0]*256U+buf[1]; + + // Calculate different for each PID + switch(pid) + { + case ENGINE_RPM: + *ret=*ret/4U; + break; + case MAF_AIR_FLOW: + break; + case VEHICLE_SPEED: + *ret=buf[0]; + break; + case FUEL_STATUS: + case LOAD_VALUE: + case THROTTLE_POS: + case REL_THR_POS: + case EGR: + case EGR_ERROR: + case FUEL_LEVEL: + case ABS_THR_POS_B: + case ABS_THR_POS_C: + case ACCEL_PEDAL_D: + case ACCEL_PEDAL_E: + case ACCEL_PEDAL_F: + case CMD_THR_ACTU: + *ret=(buf[0]*100U)/255U; + break; + case ABS_LOAD_VAL: + *ret=(*ret*100)/255; + break; + case B1S1_O2_V: + case B1S2_O2_V: + case B1S3_O2_V: + case B1S4_O2_V: + case B2S1_O2_V: + case B2S2_O2_V: + case B2S3_O2_V: + case B2S4_O2_V: + case O2S1_WR_V: + case O2S2_WR_V: + case O2S3_WR_V: + case O2S4_WR_V: + case O2S5_WR_V: + case O2S6_WR_V: + case O2S7_WR_V: + case O2S8_WR_V: + case O2S1_WR_C: + case O2S2_WR_C: + case O2S3_WR_C: + case O2S4_WR_C: + case O2S5_WR_C: + case O2S6_WR_C: + case O2S7_WR_C: + case O2S8_WR_C: + case CMD_EQUIV_R: + case DIST_MIL_ON: + case DIST_MIL_CLR: + case TIME_MIL_ON: + case TIME_MIL_CLR: + case INT_AIR_TEMP: + case AMBIENT_TEMP: + case CAT_TEMP_B1S1: + case CAT_TEMP_B2S1: + case CAT_TEMP_B1S2: + case CAT_TEMP_B2S2: + case STFT_BANK1: + case LTFT_BANK1: + case STFT_BANK2: + case LTFT_BANK2: + case FUEL_PRESSURE: + case MAN_PRESSURE: + case BARO_PRESSURE: + *ret=buf[0]; + if(pid==FUEL_PRESSURE) + *ret*=3U; + break; + case COOLANT_TEMP: + *ret=buf[0]-40U; + break; + case EVAP_PRESSURE: + *ret=((int)buf[0]*256+buf[1])/4; + break; + case TIMING_ADV: + *ret=(buf[0]/2)-64; + break; + case CTRL_MOD_V: + break; + case RUNTIME_START: + break; + case OBD_STD: + *ret=buf[0]; + break; + default: + *ret=0; + for(i=0; i<reslen; i++) + { + *ret*=256L; + *ret+=buf[i]; + } + break; + } + + return 1; +} + + +char verifyECUAlive() +{ + char cmd_str[6]; + char str[STRLEN]; + sprintf(cmd_str, "01%02X\r", ENGINE_RPM); + stn1110_write(cmd_str); + stn1110_read(str, STRLEN); + + if(stn1110_check_response(cmd_str, str) == 0) + { + return 1; + } + else + { + return 0; + } +} + + +char Refresh() +{ + //debug + isIgnitionOn = verifyECUAlive(); + + //If ignition is on, check for engine + if (isIgnitionOn) { + isEngineOn = (get_pid(ENGINE_RPM, &engineRPM) && engineRPM > 0) ? 1 : 0; + } else { // else engine must be off + isEngineOn = 0; + } + return 0; +} + + + +bool dtc_clear(void) +{ + char cmd_answer[DTC_BUFFER]=""; + + stn1110_write("04\r"); + stn1110_read(cmd_answer,DTC_BUFFER); + strip_answer(cmd_answer); + + if (strcmp(cmd_answer, "44")!=0) + { + return false; + } else + { + has_dtc=false; + return true; + } +} + + +bool dtc_read(void) +{ + char cmd_answer[DTC_BUFFER]=""; + has_dtc=false; + + stn1110_write("03\r"); + stn1110_read(cmd_answer,DTC_BUFFER); + + for (char i=0;i<MAX_DTC_READ;i++) + { + strcpy(DTC[i].code,""); + } + + strip_answer(cmd_answer); + + if (strstr(cmd_answer, "NODATA")) + { + //No errors + return true; + } + + if (strncmp(cmd_answer, "43", 2)!=0) + { + //ERROR: Incorrect answer + return false; + } + + char *ss=cmd_answer+2; + char dtclen=0; + + while (strlen(ss) >= 4) + { + const char *prefix[16]= + { + "P0", "P1", "P2", "P3", + "C0", "C1", "C2", "C3", + "B0", "B1", "B2", "B3", + "U0", "U1", "U2", "U3", + }; + uint8_t p=0; + if ( ((*ss)>='0') && ((*ss)<='9') ) p=(*ss)-'0'; else + if ( ((*ss)>='A') && ((*ss)<='F') ) p=(*ss)-'A'+10; else + if ( ((*ss)>='a') && ((*ss)<='f') ) p=(*ss)-'a'+10; + char code[6]; + strcpy(code, prefix[p]); + code[2]=ss[1]; + code[3]=ss[2]; + code[4]=ss[3]; + code[5]=0; + + if (strcmp(code, "P0000")!=0) + { + strcpy(DTC[dtclen].code,code); + has_dtc=true; + dtclen++; + } + ss+=4; + } + + return true; +} + +char *strip_answer(char *s) +{ + char *ss; + for (ss=s; *s; s++) + { + if ( ((*s)!=' ') && ((*s)!='\t') && ((*s)!='\n') && ((*s)!='\r') ) + (*ss++)=(*s); + } + (*ss)=0; + + return s; +} +
diff -r 000000000000 -r 1092494506a3 main.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.h Tue Feb 21 22:28:26 2017 +0000 @@ -0,0 +1,141 @@ +/* Library for the Sparkfun OBD2 uart - cloned from + * https://github.com/sigalabs/Vehicle-OBD2-Shield + */ + +#ifndef __OBD2_H +#define __OBD2_H + + +#define NUL '\0' +#define CR '\r' +#define PROMPT '>' +#define DATA 1 + +#define STRLEN 40 + +#define DTC_BUFFER (MAX_DTC_READ*6)+2 +//OBD2 PIDs + +#define PID_SUPPORT00 0x00 +#define MIL_CODE 0x01 +#define FREEZE_DTC 0x02 +#define FUEL_STATUS 0x03 +#define LOAD_VALUE 0x04 +#define COOLANT_TEMP 0x05 +#define STFT_BANK1 0x06 +#define LTFT_BANK1 0x07 +#define STFT_BANK2 0x08 +#define LTFT_BANK2 0x09 +#define FUEL_PRESSURE 0x0A +#define MAN_PRESSURE 0x0B +#define ENGINE_RPM 0x0C +#define VEHICLE_SPEED 0x0D +#define TIMING_ADV 0x0E +#define INT_AIR_TEMP 0x0F +#define MAF_AIR_FLOW 0x10 +#define THROTTLE_POS 0x11 +#define SEC_AIR_STAT 0x12 +#define OXY_SENSORS1 0x13 +#define B1S1_O2_V 0x14 +#define B1S2_O2_V 0x15 +#define B1S3_O2_V 0x16 +#define B1S4_O2_V 0x17 +#define B2S1_O2_V 0x18 +#define B2S2_O2_V 0x19 +#define B2S3_O2_V 0x1A +#define B2S4_O2_V 0x1B +#define OBD_STD 0x1C +#define OXY_SENSORS2 0x1D +#define AUX_INPUT 0x1E +#define RUNTIME_START 0x1F +#define PID_SUPPORT20 0x20 +#define DIST_MIL_ON 0x21 +#define FUEL_RAIL_P 0x22 +#define FUEL_RAIL_DIESEL 0x23 +#define O2S1_WR_V 0x24 +#define O2S2_WR_V 0x25 +#define O2S3_WR_V 0x26 +#define O2S4_WR_V 0x27 +#define O2S5_WR_V 0x28 +#define O2S6_WR_V 0x29 +#define O2S7_WR_V 0x2A +#define O2S8_WR_V 0x2B +#define EGR 0x2C +#define EGR_ERROR 0x2D +#define EVAP_PURGE 0x2E +#define FUEL_LEVEL 0x2F +#define WARM_UPS 0x30 +#define DIST_MIL_CLR 0x31 +#define EVAP_PRESSURE 0x32 +#define BARO_PRESSURE 0x33 +#define O2S1_WR_C 0x34 +#define O2S2_WR_C 0x35 +#define O2S3_WR_C 0x36 +#define O2S4_WR_C 0x37 +#define O2S5_WR_C 0x38 +#define O2S6_WR_C 0x39 +#define O2S7_WR_C 0x3A +#define O2S8_WR_C 0x3B +#define CAT_TEMP_B1S1 0x3C +#define CAT_TEMP_B2S1 0x3D +#define CAT_TEMP_B1S2 0x3E +#define CAT_TEMP_B2S2 0x3F +#define PID_SUPPORT40 0x40 +#define MONITOR_STAT 0x41 +#define CTRL_MOD_V 0x42 +#define ABS_LOAD_VAL 0x43 +#define CMD_EQUIV_R 0x44 +#define REL_THR_POS 0x45 +#define AMBIENT_TEMP 0x46 +#define ABS_THR_POS_B 0x47 +#define ABS_THR_POS_C 0x48 +#define ACCEL_PEDAL_D 0x49 +#define ACCEL_PEDAL_E 0x4A +#define ACCEL_PEDAL_F 0x4B +#define CMD_THR_ACTU 0x4C +#define TIME_MIL_ON 0x4D +#define TIME_MIL_CLR 0x4E +#define FUEL_TYPE 0x51 +#define ETHYL_FUEL 0x52 +#define LAST_PID 0x52 + + +//DTCs +#define MAX_DTC_READ 5 + + +// function prototypes +char Init(); +char stn1110_read(char *str, char size); +void stn1110_write(char *str); +char stn1110_check_response(const char *cmd, char *str); +char stn1110_compact_response(char *buf, char *str); +char stn1110_command(char *str, char *cmd); +void check_supported_pids(void); +char is_pid_supported(char pid); +char get_pid(char pid, long *ret); +char verifyECUAlive(void); +char Refresh(void); +bool dtc_read(void); +bool dtc_clear(void); + +//Structures +struct DTC_t { + char code[6]; +} DTC[MAX_DTC_READ]; + +//Variables +char isIgnitionOn; +char isEngineOn; +bool has_dtc; + + +char *strip_answer(char *s); +unsigned long pid01to20_support; +unsigned long pid21to40_support; +unsigned long pid41to60_support; +long tempLong; +long engineRPM; + + +#endif \ No newline at end of file
diff -r 000000000000 -r 1092494506a3 mbed-rtos.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-rtos.lib Tue Feb 21 22:28:26 2017 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed-rtos/#3da5f554d8bf
diff -r 000000000000 -r 1092494506a3 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Tue Feb 21 22:28:26 2017 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/d75b3fe1f5cb \ No newline at end of file
diff -r 000000000000 -r 1092494506a3 pubnub_config.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pubnub_config.h Tue Feb 21 22:28:26 2017 +0000 @@ -0,0 +1,106 @@ +/* -*- c-file-style:"stroustrup"; indent-tabs-mode: nil -*- */ +#if !defined INC_PUBNUB_CONFIG +#define INC_PUBNUB_CONFIG + + +/* -- Next few definitions can be tweaked by the user, but with care -- */ + +/** Maximum number of PubNub contexts. It is used only if the + * contexts are statically allocated. + * A context is used to publish messages or subscribe to (get) them. + * + * Doesn't make much sense to have less than 1. :) + * OTOH, don't put too many, as each context takes (for our purposes) + * a significant amount of memory - app. 128 + @ref PUBNUB_BUF_MAXLEN + + * @ref PUBNUB_REPLY_MAXLEN bytes. + * + * A typical configuration may consist of a single pubnub context for + * channel subscription and another pubnub context that will periodically + * publish messages about device status (with timeout lower than message + * generation frequency). + * + * Another typical setup may have a single subscription context and + * maintain a pool of contexts for each publish call triggered by an + * external event (e.g. a button push). + * + * Of course, there is nothing wrong with having just one context, but + * you can't publish and subscribe at the same time on the same context. + * This isn't as bad as it sounds, but may be a source of headaches + * (lost messages, etc). + */ +#define PUBNUB_CTX_MAX 2 + +/** Maximum length of the HTTP buffer. This is a major component of + * the memory size of the whole pubnub context, but it is also an + * upper bound on URL-encoded form of published message, so if you + * need to construct big messages, you may need to raise this. */ +#define PUBNUB_BUF_MAXLEN 32000 + +/** Set to 0 to use a static buffer and then set its size via + #PUBNUB_REPLY_MAXLEN. Set to anything !=0 to use a dynamic + buffer, that is, dynamically try to allocate as much memory as + needed for the buffer. + */ +#define PUBNUB_DYNAMIC_REPLY_BUFFER 1 + +#if !PUBNUB_DYNAMIC_REPLY_BUFFER + +/** Maximum length of the HTTP reply when using a static buffer. The + * other major component of the memory size of the PubNub context, + * beside #PUBNUB_BUF_MAXLEN. Replies of API calls longer than this + * will be discarded and an error will be reported. Specifically, this + * may cause lost messages returned by subscribe if too many too large + * messages got queued on the Pubnub server. */ +#define PUBNUB_REPLY_MAXLEN 32000 + +#endif + +/** This is the URL of the Pubnub server. Change only for testing + purposes. +*/ +#define PUBNUB_ORIGIN "pubsub.pubnub.com" + +/** Set to 0 to disable changing the origin from the default + #PUBNUB_ORIGIN. Set to anything != 0 to enable changing the + origin (per context). + */ +#define PUBNUB_ORIGIN_SETTABLE 1 + +/** Duration of the transaction timeout set during context initialization, + in milliseconds. Can be changed later by the user. + */ +#define PUBNUB_DEFAULT_TRANSACTION_TIMER 310000 + +#define PUBNUB_HAVE_MD5 0 +#define PUBNUB_HAVE_SHA1 0 + + +/** The size of the stack (in kilobytes) for the "polling" thread, when using + the callback interface. We don't need much, so, if you want to conserve + memory, you can try small values. It's hard to say what is the minumum, + as it depends on the OS functions we call, but, you probably + shouldn't try less than 64 KB. + + Set to `0` to use the default stack size. + */ +#define PUBNUB_CALLBACK_THREAD_STACK_SIZE_KB 0 + + +/** If true (!=0), enable support for (HTTP/S) proxy */ +#define PUBNUB_PROXY_API 0 + +/** The maximum length (in characters) of the host name of the proxy + that will be saved in the Pubnub context. +*/ +#define PUBNUB_MAX_PROXY_HOSTNAME_LENGTH 63 + +/** If true (!=0), enable support for message encryption/decryption */ +#define PUBNUB_CRYPTO_API 0 + + +#include <MODSERIAL.h> +extern MODSERIAL pc; +#define PUBNUB_LOG_PRINTF(...) pc.printf(__VA_ARGS__) + + +#endif /* !defined INC_PUBNUB_CONFIG */
diff -r 000000000000 -r 1092494506a3 sensors.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sensors.cpp Tue Feb 21 22:28:26 2017 +0000 @@ -0,0 +1,437 @@ +/* =================================================================== +Copyright © 2016, AVNET Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the License for the specific +language governing permissions and limitations under the License. + +======================================================================== */ + +#include "mbed.h" +#include "sensors.h" // has anything needed from config_me.h +#include "hardware.h" +//#include "config_me.h" +#include "FXOS8700CQ.h" +#include "HTS221.h" +#include <string> + +//I2C for pmod sensors: +#define Si1145_PMOD_I2C_ADDR 0xC0 //this is for 7-bit addr 0x60 for the Si7020 +#define Si7020_PMOD_I2C_ADDR 0x80 //this is for 7-bit addr 0x4 for the Si7020 + +// Storage for the data from the motion sensor +SRAWDATA accel_data; +SRAWDATA magn_data; +//InterruptIn fxos_int1(PTC6); // unused, common with SW2 on FRDM-K64F +InterruptIn fxos_int2(PTC13); // should just be the Data-Ready interrupt +bool fxos_int2_triggered = false; +void trigger_fxos_int2(void) +{ + fxos_int2_triggered = true; + +} + +/*------------------------------------------------------------------------------ + * Perform I2C single read. + *------------------------------------------------------------------------------*/ +unsigned char I2C_ReadSingleByte(unsigned char ucDeviceAddress) +{ + char rxbuffer [1]; + i2c.read(ucDeviceAddress, rxbuffer, 1 ); + return (unsigned char)rxbuffer[0]; +} //I2C_ReadSingleByte() + +/*------------------------------------------------------------------------------ + * Perform I2C single read from address. + *------------------------------------------------------------------------------*/ +unsigned char I2C_ReadSingleByteFromAddr(unsigned char ucDeviceAddress, unsigned char Addr) +{ + char txbuffer [1]; + char rxbuffer [1]; + txbuffer[0] = (char)Addr; + i2c.write(ucDeviceAddress, txbuffer, 1 ); + i2c.read(ucDeviceAddress, rxbuffer, 1 ); + return (unsigned char)rxbuffer[0]; +} //I2C_ReadSingleByteFromAddr() + +/*------------------------------------------------------------------------------ + * Perform I2C read of more than 1 byte. + *------------------------------------------------------------------------------*/ +int I2C_ReadMultipleBytes(unsigned char ucDeviceAddress, char *ucData, unsigned char ucLength) +{ + int status; + status = i2c.read(ucDeviceAddress, ucData, ucLength); + return status; +} //I2C_ReadMultipleBytes() + +/*------------------------------------------------------------------------------ + * Perform I2C write of a single byte. + *------------------------------------------------------------------------------*/ +int I2C_WriteSingleByte(unsigned char ucDeviceAddress, unsigned char Data, bool bSendStop) +{ + int status; + char txbuffer [1]; + txbuffer[0] = (char)Data; //data + status = i2c.write(ucDeviceAddress, txbuffer, 1, !bSendStop); //true: do not send stop + return status; +} //I2C_WriteSingleByte() + +/*------------------------------------------------------------------------------ + * Perform I2C write of 1 byte to an address. + *------------------------------------------------------------------------------*/ +int I2C_WriteSingleByteToAddr(unsigned char ucDeviceAddress, unsigned char Addr, unsigned char Data, bool bSendStop) +{ + int status; + char txbuffer [2]; + txbuffer[0] = (char)Addr; //address + txbuffer[1] = (char)Data; //data + //status = i2c.write(ucDeviceAddress, txbuffer, 2, false); //stop at end + status = i2c.write(ucDeviceAddress, txbuffer, 2, !bSendStop); //true: do not send stop + return status; +} //I2C_WriteSingleByteToAddr() + +/*------------------------------------------------------------------------------ + * Perform I2C write of more than 1 byte. + *------------------------------------------------------------------------------*/ +int I2C_WriteMultipleBytes(unsigned char ucDeviceAddress, char *ucData, unsigned char ucLength, bool bSendStop) +{ + int status; + status = i2c.write(ucDeviceAddress, ucData, ucLength, !bSendStop); //true: do not send stop + return status; +} //I2C_WriteMultipleBytes() + +bool bSi7020_present = false; +void Init_Si7020(void) +{ + char SN_7020 [8]; + //SN part 1: + I2C_WriteSingleByteToAddr(Si7020_PMOD_I2C_ADDR, 0xFA, 0x0F, false); + I2C_ReadMultipleBytes(Si7020_PMOD_I2C_ADDR, &SN_7020[0], 4); + + //SN part 1: + I2C_WriteSingleByteToAddr(Si7020_PMOD_I2C_ADDR, 0xFC, 0xC9, false); + I2C_ReadMultipleBytes(Si7020_PMOD_I2C_ADDR, &SN_7020[4], 4); + + char Ver_7020 [2]; + //FW version: + I2C_WriteSingleByteToAddr(Si7020_PMOD_I2C_ADDR, 0x84, 0xB8, false); + I2C_ReadMultipleBytes(Si7020_PMOD_I2C_ADDR, &Ver_7020[0], 2); + + if (SN_7020[4] != 0x14) + { + bSi7020_present = false; + PRINTF("Si7020 sensor not found\r\n"); + } + else + { + bSi7020_present = true; + 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]); + PRINTF("Si7020 Version# = 0x%02X\n", Ver_7020[0]); + } //bool bSi7020_present = true + +} //Init_Si7020() + +void Read_Si7020(void) +{ + if (bSi7020_present) + { + char Humidity [2]; + char Temperature [2]; + //Command to measure humidity (temperature also gets measured): + I2C_WriteSingleByte(Si7020_PMOD_I2C_ADDR, 0xF5, false); //no hold, must do dummy read + I2C_ReadMultipleBytes(Si7020_PMOD_I2C_ADDR, &Humidity[0], 1); //dummy read, should get an nack until it is done + wait (0.05); //wait for measurement. Can also keep reading until no NACK is received + //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... + I2C_ReadMultipleBytes(Si7020_PMOD_I2C_ADDR, &Humidity[0], 2); //read humidity + //PRINTF("Read Si7020 Humidity = 0x%02X%02X\n", Humidity[0], Humidity[1]); + int rh_code = (Humidity[0] << 8) + Humidity[1]; + float fRh = (125.0*rh_code/65536.0) - 6.0; //from datasheet + //PRINTF("Si7020 Humidity = %*.*f %%\n", 4, 2, fRh); //double % sign for escape //PRINTF("%*.*f\n", myFieldWidth, myPrecision, myFloatValue); + sprintf(SENSOR_DATA.Humidity_Si7020, "%0.2f", fRh); + + //Command to read temperature when humidity is already done: + I2C_WriteSingleByte(Si7020_PMOD_I2C_ADDR, 0xE0, false); + I2C_ReadMultipleBytes(Si7020_PMOD_I2C_ADDR, &Temperature[0], 2); //read temperature + //PRINTF("Read Si7020 Temperature = 0x%02X%02X\n", Temperature[0], Temperature[1]); + int temp_code = (Temperature[0] << 8) + Temperature[1]; + float fTemp = (175.72*temp_code/65536.0) - 46.85; //from datasheet in Celcius + //PRINTF("Si7020 Temperature = %*.*f deg C\n", 4, 2, fTemp); + sprintf(SENSOR_DATA.Temperature_Si7020, "%0.2f", fTemp); + } //bool bSi7020_present = true + +} //Read_Si7020() + +/*------------------------------------------------------------------------------ + * The following are aliases so that the Si1145 coding examples can be used as-is. + *------------------------------------------------------------------------------*/ +unsigned char ReadFrom_Si1145_Register(unsigned char reg) //returns byte from I2C Register 'reg' +{ + unsigned char result = I2C_ReadSingleByteFromAddr(Si1145_PMOD_I2C_ADDR, reg); + return (result); +} //ReadFrom_Si1145_Register() + +void WriteTo_Si1145_Register(unsigned char reg, unsigned char value) //writes 'value' into I2C Register reg' +{ + I2C_WriteSingleByteToAddr(Si1145_PMOD_I2C_ADDR, reg, value, true); +} //WriteTo_Si1145_Register() + +#define REG_PARAM_WR 0x17 +#define REG_PARAM_RD 0x2E +#define REG_COMMAND 0x18 +#define REG_RESPONSE 0x20 +#define REG_HW_KEY 0x07 +#define HW_KEY_VAL0 0x17 +#define REG_MEAS_RATE_LSB 0x08 +#define REG_MEAS_RATE_MSB 0x09 +#define REG_PS_LED21 0x0F +#define REG_PS_LED3 0x10 +#define MAX_LED_CURRENT 0xF +#define PARAM_CH_LIST 0x01 +#define REG_ALS_VIS_DATA0 0x22 +#define REG_ALS_VIS_DATA1 0x23 +#define REG_ALS_IR_DATA0 0x24 +#define REG_ALS_IR_DATA1 0x25 +#define REG_PS1_DATA0 0x26 +#define REG_PS1_DATA1 0x27 +#define REG_PS2_DATA0 0x28 +#define REG_PS2_DATA1 0x29 +#define REG_PS3_DATA0 0x2A +#define REG_PS3_DATA1 0x2B +#define REG_UVINDEX0 0x2C +#define REG_UVINDEX1 0x2D +int Si1145_ParamSet(unsigned char address, unsigned char value) //writes 'value' into Parameter 'address' +{ + char txbuffer [3]; + txbuffer[0] = (char)REG_PARAM_WR; //destination + txbuffer[1] = (char)value; + txbuffer[2] = (char)(0xA0 + (address & 0x1F)); + int retval; + //if((retval = _waitUntilSleep(si114x_handle))!=0) return retval; + retval = I2C_WriteMultipleBytes(Si1145_PMOD_I2C_ADDR, &txbuffer[0], 3, true); + if(retval!=0) return retval; + while(1) + { + retval=ReadFrom_Si1145_Register(REG_PARAM_RD); + if (retval==value) break; + } + return (0); +} //Si1145_ParamSet() + +void PsAlsForce(void) //equivalent to WriteTo_Si1145_Register(REG_COMMAND,0x07). This forces PS and ALS measurements +{ + WriteTo_Si1145_Register(REG_COMMAND,0x07); +} //PsAlsForce() + +bool bSi1145_present = false; +void Init_Si1145(void) +{ + unsigned char readbyte; + //Read Si1145 part ID: + readbyte = ReadFrom_Si1145_Register(0x00); + if (readbyte != 0x45) + { + bSi1145_present = false; + PRINTF("Si1145 sensor not found\r\n"); + } + else + { + bSi1145_present = true; + PRINTF("Si1145 Part ID : 0x%02X\n", readbyte); + //Initialize Si1145 by writing to HW_KEY (I2C Register 0x07 = 0x17) + WriteTo_Si1145_Register(REG_HW_KEY, HW_KEY_VAL0); + + // Initialize LED Current + // I2C Register 0x0F = 0xFF + // I2C Register 0x10 = 0x0F + WriteTo_Si1145_Register(REG_PS_LED21,(MAX_LED_CURRENT<<4) + MAX_LED_CURRENT); + WriteTo_Si1145_Register(REG_PS_LED3, MAX_LED_CURRENT); + + // Parameter 0x01 = 0x37 + //Si1145_ParamSet(PARAM_CH_LIST, ALS_IR_TASK + ALS_VIS_TASK + PS1_TASK + PS2_TASK + PS3_TASK); + //Si1145_ParamSet(0x01, 0x37); //CHLIST is address 0x01 in the parameter RAM. It defines which sensors are enabled (here, some) + 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...) + // 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... + PsAlsForce(); // can also be written as WriteTo_Si1145_Register(REG_COMMAND,0x07); + WriteTo_Si1145_Register(REG_COMMAND, 0x0F);//command to put it into auto mode + //Set MES_RATE to 0x1000. I.e. the device will automatically wake up every 16 * 256* 31.25 us = 0.128 seconds to measure + WriteTo_Si1145_Register(REG_MEAS_RATE_LSB, 0x00); + WriteTo_Si1145_Register(REG_MEAS_RATE_MSB, 0x10); + } //bSi1145_present = true +} //Init_Si1145() + +void Read_Si1145(void) +{ + if (bSi1145_present) + { + // Once the measurements are completed, here is how to reconstruct them + // Note very carefully that 16-bit registers are in the 'Little Endian' byte order + // It may be more efficient to perform block I2C Reads, but this example shows + // individual reads of registers + + int PS1 = ReadFrom_Si1145_Register(REG_PS1_DATA0) + 256 * ReadFrom_Si1145_Register(REG_PS1_DATA1); + int PS2 = ReadFrom_Si1145_Register(REG_PS2_DATA0) + 256 * ReadFrom_Si1145_Register(REG_PS2_DATA1); + int PS3 = ReadFrom_Si1145_Register(REG_PS3_DATA0) + 256 * ReadFrom_Si1145_Register(REG_PS3_DATA1); + //PRINTF("PS1_Data = %d\n", PS1); + //PRINTF("PS2_Data = %d\n", PS2); + //PRINTF("PS3_Data = %d\n", PS3); + //OBJECT PRESENT? +#if (0) + if(PS1 < 22000){ + //PRINTF("Object Far\n"); + sprintf(SENSOR_DATA.Proximity, "Object Far\0"); + } + else if(PS1 < 24000) + { + //PRINTF("Object in Vicinity\n"); + sprintf(SENSOR_DATA.Proximity, "Object in Vicinity\0"); + } + else if (PS1 < 30000) + { + //PRINTF("Object Near\n"); + sprintf(SENSOR_DATA.Proximity, "Object Near\0"); + } + else + { + //PRINTF("Object Very Near\n"); + sprintf(SENSOR_DATA.Proximity, "Object Very Near\0"); + } +#else + sprintf(SENSOR_DATA.Proximity, "%d\0", PS1); +#endif + + //Force ALS read: + //WriteTo_Si1145_Register(REG_COMMAND, 0x06); + //wait (0.1); + int ALS_VIS = ReadFrom_Si1145_Register(REG_ALS_VIS_DATA0) + 256 * ReadFrom_Si1145_Register(REG_ALS_VIS_DATA1); + int ALS_IR = ReadFrom_Si1145_Register(REG_ALS_IR_DATA0) + 256 * ReadFrom_Si1145_Register(REG_ALS_IR_DATA1); + int UV_INDEX = ReadFrom_Si1145_Register(REG_UVINDEX0) + 256 * ReadFrom_Si1145_Register(REG_UVINDEX1); + //PRINTF("ALS_VIS_Data = %d\n", ALS_VIS); + //PRINTF("ALS_IR_Data = %d\n", ALS_IR); + //PRINTF("UV_INDEX_Data = %d\n", UV_INDEX); + + //PRINTF("Ambient Light Visible Sensor = %d\n", ALS_VIS); + sprintf(SENSOR_DATA.AmbientLightVis, "%d", ALS_VIS); + //PRINTF("Ambient Light Infrared Sensor = %d\n", ALS_IR); + sprintf(SENSOR_DATA.AmbientLightIr, "%d", ALS_IR); + //float fUV_value = (UV_INDEX -50.0)/10000.0; + float fUV_value = (UV_INDEX)/100.0; //this is the aux reading + //PRINTF("UV_Data = %0.2f\n", fUV_value); + sprintf(SENSOR_DATA.UVindex, "%0.2f", fUV_value); + } //bSi1145_present = true +} //Read_Si1145() + +//******************************************************************************************************************************************** +//* Read the FXOS8700CQ - 6-axis combo Sensor Accelerometer and Magnetometer +//******************************************************************************************************************************************** +bool bMotionSensor_present = false; +void Init_motion_sensor() +{ + // Note: this class is instantiated here because if it is statically declared, the cellular shield init kills the I2C bus... + // Class instantiation with pin names for the motion sensor on the FRDM-K64F board: + FXOS8700CQ fxos(PTE25, PTE24, FXOS8700CQ_SLAVE_ADDR1); // SDA, SCL, (addr << 1) + int iWhoAmI = fxos.get_whoami(); + + PRINTF("FXOS8700CQ WhoAmI = %X\r\n", iWhoAmI); + // Iterrupt for active-low interrupt line from FXOS + // Configured with only one interrupt on INT2 signaling Data-Ready + //fxos_int2.fall(&trigger_fxos_int2); + if (iWhoAmI != 0xC7) + { + bMotionSensor_present = false; + PRINTF("FXOS8700CQ motion sensor not found\r\n"); + } + else + { + bMotionSensor_present = true; + fxos.enable(); + } +} //Init_motion_sensor() + +void Read_motion_sensor() +{ + // Note: this class is instantiated here because if it is statically declared, the cellular shield init kills the I2C bus... + // Class instantiation with pin names for the motion sensor on the FRDM-K64F board: + FXOS8700CQ fxos(PTE25, PTE24, FXOS8700CQ_SLAVE_ADDR1); // SDA, SCL, (addr << 1) + if (bMotionSensor_present) + { + fxos.enable(); + fxos.get_data(&accel_data, &magn_data); + //PRINTF("Roll=%5d, Pitch=%5d, Yaw=%5d;\r\n", magn_data.x, magn_data.y, magn_data.z); + sprintf(SENSOR_DATA.MagnetometerX, "%5d", magn_data.x); + sprintf(SENSOR_DATA.MagnetometerY, "%5d", magn_data.y); + sprintf(SENSOR_DATA.MagnetometerZ, "%5d", magn_data.z); + + //Try to normalize (/2048) the values so they will match the eCompass output: + float fAccelScaled_x, fAccelScaled_y, fAccelScaled_z; + fAccelScaled_x = (accel_data.x/2048.0); + fAccelScaled_y = (accel_data.y/2048.0); + fAccelScaled_z = (accel_data.z/2048.0); + //PRINTF("Acc: X=%2.3f Y=%2.3f Z=%2.3f;\r\n", fAccelScaled_x, fAccelScaled_y, fAccelScaled_z); + sprintf(SENSOR_DATA.AccelX, "%2.3f", fAccelScaled_x); + sprintf(SENSOR_DATA.AccelY, "%2.3f", fAccelScaled_y); + sprintf(SENSOR_DATA.AccelZ, "%2.3f", fAccelScaled_z); + } //bMotionSensor_present +} //Read_motion_sensor() + + +//******************************************************************************************************************************************** +//* Read the HTS221 temperature & humidity sensor on the Cellular Shield +//******************************************************************************************************************************************** +// These are to be built on the fly +string my_temp; +string my_humidity; +HTS221 hts221; + +#define CTOF(x) ((x)*1.8+32) +bool bHTS221_present = false; +void Init_HTS221() +{ + int i; + void hts221_init(void); + i = hts221.begin(); + if (i) + { + bHTS221_present = true; + PRINTF(BLU "HTS221 Detected (0x%02X)\n\r",i); + PRINTF(" Temp is: %0.2f F \n\r",CTOF(hts221.readTemperature())); + PRINTF(" Humid is: %02d %%\n\r",hts221.readHumidity()); + } + else + { + bHTS221_present = false; + PRINTF(RED "HTS221 NOT DETECTED!\n\r"); + } +} //Init_HTS221() + +void Read_HTS221() +{ + if (bHTS221_present) + { + sprintf(SENSOR_DATA.Temperature, "%0.2f", CTOF(hts221.readTemperature())); + sprintf(SENSOR_DATA.Humidity, "%02d", hts221.readHumidity()); + } //bHTS221_present +} //Read_HTS221() + +void sensors_init(void) +{ + Init_HTS221(); + Init_Si7020(); + Init_Si1145(); + Init_motion_sensor(); +} //sensors_init + +void read_sensors(void) +{ + Read_HTS221(); + Read_Si7020(); + Read_Si1145(); + Read_motion_sensor(); +} //read_sensors
diff -r 000000000000 -r 1092494506a3 sensors.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sensors.h Tue Feb 21 22:28:26 2017 +0000 @@ -0,0 +1,67 @@ +/* =================================================================== +Copyright © 2016, AVNET Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the License for the specific +language governing permissions and limitations under the License. + +======================================================================== */ + +#ifndef __SENSORS_H_ +#define __SENSORS_H_ + +// from config_me.h +#define TEMP_HUMIDITY_ACCELEROMETER 2 +#define TEMP_HUMIDITY_ACCELEROMETER_GPS 3 +static int iSensorsToReport = TEMP_HUMIDITY_ACCELEROMETER; //modify this to change your selection +#define SENSOR_UPDATE_INTERVAL_MS 30000; // 30 seconds +// end config_me.h + +void sensors_init(void); +void read_sensors(void); +void ProcessUsbInterface(void); + +#define SENSOR_FIELD_LEN_LIMIT 32 +typedef struct +{ + char Temperature[SENSOR_FIELD_LEN_LIMIT]; + char Humidity[SENSOR_FIELD_LEN_LIMIT]; + char AccelX[SENSOR_FIELD_LEN_LIMIT]; + char AccelY[SENSOR_FIELD_LEN_LIMIT]; + char AccelZ[SENSOR_FIELD_LEN_LIMIT]; + char MagnetometerX[SENSOR_FIELD_LEN_LIMIT]; + char MagnetometerY[SENSOR_FIELD_LEN_LIMIT]; + char MagnetometerZ[SENSOR_FIELD_LEN_LIMIT]; + char AmbientLightVis[SENSOR_FIELD_LEN_LIMIT]; + char AmbientLightIr[SENSOR_FIELD_LEN_LIMIT]; + char UVindex[SENSOR_FIELD_LEN_LIMIT]; + char Proximity[SENSOR_FIELD_LEN_LIMIT]; + char Temperature_Si7020[SENSOR_FIELD_LEN_LIMIT]; + char Humidity_Si7020[SENSOR_FIELD_LEN_LIMIT]; + char Virtual_Sensor1[SENSOR_FIELD_LEN_LIMIT]; + char Virtual_Sensor2[SENSOR_FIELD_LEN_LIMIT]; + char Virtual_Sensor3[SENSOR_FIELD_LEN_LIMIT]; + char Virtual_Sensor4[SENSOR_FIELD_LEN_LIMIT]; + char Virtual_Sensor5[SENSOR_FIELD_LEN_LIMIT]; + char Virtual_Sensor6[SENSOR_FIELD_LEN_LIMIT]; + char Virtual_Sensor7[SENSOR_FIELD_LEN_LIMIT]; + char Virtual_Sensor8[SENSOR_FIELD_LEN_LIMIT]; + char GPS_Satellites[SENSOR_FIELD_LEN_LIMIT]; + char GPS_Latitude[SENSOR_FIELD_LEN_LIMIT]; + char GPS_Longitude[SENSOR_FIELD_LEN_LIMIT]; + char GPS_Altitude[SENSOR_FIELD_LEN_LIMIT]; + char GPS_Speed[SENSOR_FIELD_LEN_LIMIT]; + char GPS_Course[SENSOR_FIELD_LEN_LIMIT]; +} K64F_Sensors_t ; + +extern K64F_Sensors_t SENSOR_DATA; + +#endif \ No newline at end of file