publish final code
Dependencies: FXOS8700CQ Pubnub_mbed2_sync2 SoftSerial TinyGPSplus WNCInterface2 mbed-rtos mbed
main.cpp
- Committer:
- cswiger
- Date:
- 2017-02-21
- Revision:
- 0:1092494506a3
File content as of revision 0:1092494506a3:
/* ===================================================================== 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; }