AT&T IoT hackster.io contest entry: Carpal2

Dependencies:   FXOS8700CQ Pubnub_mbed2_sync WNCInterface mbed-rtos mbed

Committer:
cswiger
Date:
Sat Dec 24 17:31:00 2016 +0000
Revision:
2:fe8e935b9342
Parent:
1:610520d32d22
added Ignition awareness so Carpal2 will resume working after car has been turned off and back on.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
cswiger 0:d2425a595807 1 /* =====================================================================
cswiger 0:d2425a595807 2 Copyright © 2016, Avnet (R)
cswiger 0:d2425a595807 3
cswiger 0:d2425a595807 4 Contributors:
cswiger 0:d2425a595807 5 * James M Flynn, www.em.avnet.com
cswiger 0:d2425a595807 6 * Chuck Swiger
cswiger 0:d2425a595807 7
cswiger 0:d2425a595807 8 Licensed under the Apache License, Version 2.0 (the "License");
cswiger 0:d2425a595807 9 you may not use this file except in compliance with the License.
cswiger 0:d2425a595807 10 You may obtain a copy of the License at
cswiger 0:d2425a595807 11
cswiger 0:d2425a595807 12 http://www.apache.org/licenses/LICENSE-2.0
cswiger 0:d2425a595807 13
cswiger 0:d2425a595807 14 Unless required by applicable law or agreed to in writing,
cswiger 0:d2425a595807 15 software distributed under the License is distributed on an
cswiger 0:d2425a595807 16 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
cswiger 0:d2425a595807 17 either express or implied. See the License for the specific
cswiger 0:d2425a595807 18 language governing permissions and limitations under the License.
cswiger 0:d2425a595807 19
cswiger 0:d2425a595807 20 @file WNC_Pubnub_obd2b
cswiger 0:d2425a595807 21 @version 1.0b
cswiger 0:d2425a595807 22 @date Dec 2016
cswiger 0:d2425a595807 23
cswiger 0:d2425a595807 24 - This version has the AccelX,Y,Z sensor and code for GPS
cswiger 0:d2425a595807 25 ======================================================================== */
cswiger 0:d2425a595807 26
cswiger 0:d2425a595807 27 #include "mbed.h"
cswiger 0:d2425a595807 28 #include "WNCInterface.h"
cswiger 0:d2425a595807 29 #include "main.h" // obd2 includes
cswiger 0:d2425a595807 30 //#include "MODSERIAL.h" // already exists in WNCInterface
cswiger 0:d2425a595807 31 #include "pubnub_sync.h"
cswiger 0:d2425a595807 32 #include "sensors.h"
cswiger 0:d2425a595807 33 #include "hardware.h"
cswiger 0:d2425a595807 34
cswiger 0:d2425a595807 35 #define DEBUG
cswiger 0:d2425a595807 36 #define MBED_PLATFORM
cswiger 0:d2425a595807 37
cswiger 0:d2425a595807 38 #define CRLF "\n\r"
cswiger 0:d2425a595807 39
cswiger 0:d2425a595807 40 I2C i2c(PTC11, PTC10); //SDA, SCL -- define the I2C pins being used
cswiger 0:d2425a595807 41
cswiger 0:d2425a595807 42 WNCInterface wnc;
cswiger 0:d2425a595807 43 MODSERIAL pc(USBTX,USBRX,256,256);
cswiger 0:d2425a595807 44 MODSERIAL obd2(PTC15,PTC14,256,256); // (TX,RX,txbuffer,rxbuffer)
cswiger 0:d2425a595807 45 // This is the Bluetooth J199 connector - pin3 DCT14 RX, pin4 DTC15 TX
cswiger 0:d2425a595807 46 pubnub_t *pbp = pubnub_alloc();
cswiger 0:d2425a595807 47
cswiger 0:d2425a595807 48
cswiger 0:d2425a595807 49 DigitalOut rled(PTB19); // RED panel lamp
cswiger 0:d2425a595807 50 DigitalOut gled(PTB18); // GREEN
cswiger 0:d2425a595807 51
cswiger 0:d2425a595807 52
cswiger 0:d2425a595807 53 long OBDBAUD = 9600;
cswiger 0:d2425a595807 54 long PCBAUD = 115200;
cswiger 0:d2425a595807 55
cswiger 0:d2425a595807 56 K64F_Sensors_t SENSOR_DATA =
cswiger 0:d2425a595807 57 {
cswiger 0:d2425a595807 58 .Temperature = "0",
cswiger 0:d2425a595807 59 .Humidity = "0",
cswiger 0:d2425a595807 60 .AccelX = "0",
cswiger 0:d2425a595807 61 .AccelY = "0",
cswiger 0:d2425a595807 62 .AccelZ = "0",
cswiger 0:d2425a595807 63 .GPS_Satellites = "0",
cswiger 0:d2425a595807 64 .GPS_Latitude = "0",
cswiger 0:d2425a595807 65 .GPS_Longitude = "0",
cswiger 0:d2425a595807 66 .GPS_Altitude = "0",
cswiger 0:d2425a595807 67 .GPS_Speed = "0",
cswiger 0:d2425a595807 68 .GPS_Course = "0"
cswiger 0:d2425a595807 69 };
cswiger 0:d2425a595807 70
cswiger 0:d2425a595807 71 char* itoa(int val, int base){
cswiger 0:d2425a595807 72 static char buf[32] = {0};
cswiger 0:d2425a595807 73 int i = 30;
cswiger 0:d2425a595807 74 for(; val && i ; --i, val /= base)
cswiger 0:d2425a595807 75 buf[i] = "0123456789abcdef"[val % base];
cswiger 0:d2425a595807 76 return &buf[i+1];
cswiger 0:d2425a595807 77 }
cswiger 0:d2425a595807 78
cswiger 0:d2425a595807 79
cswiger 0:d2425a595807 80 //Periodic timer
cswiger 0:d2425a595807 81 Ticker OneMsTicker;
cswiger 0:d2425a595807 82 volatile bool bTimerExpiredFlag = false;
cswiger 0:d2425a595807 83 int OneMsTicks = 0;
cswiger 0:d2425a595807 84 int iTimer1Interval_ms = 1000;
cswiger 0:d2425a595807 85
cswiger 0:d2425a595807 86 void OneMsFunction()
cswiger 0:d2425a595807 87 {
cswiger 0:d2425a595807 88 OneMsTicks++;
cswiger 0:d2425a595807 89 if ((OneMsTicks % iTimer1Interval_ms) == 0)
cswiger 0:d2425a595807 90 {
cswiger 0:d2425a595807 91 bTimerExpiredFlag = true;
cswiger 0:d2425a595807 92 }
cswiger 0:d2425a595807 93 } //OneMsFunction()
cswiger 0:d2425a595807 94
cswiger 0:d2425a595807 95
cswiger 0:d2425a595807 96 void GetDTC(void)
cswiger 0:d2425a595807 97 {
cswiger 0:d2425a595807 98 char jsonreply[140] = {'\0'};
cswiger 0:d2425a595807 99 dtc_read(); // populate the DTC struct if any
cswiger 0:d2425a595807 100 if(has_dtc) {
cswiger 0:d2425a595807 101 strcpy(jsonreply,"{\"");
cswiger 0:d2425a595807 102 for (int i=0; i<MAX_DTC_READ; i++) {
cswiger 0:d2425a595807 103 strcat(jsonreply,itoa((i+1),10));
cswiger 0:d2425a595807 104 strcat(jsonreply,"\":\"");
cswiger 0:d2425a595807 105 if(i!=MAX_DTC_READ-1) { // last one?
cswiger 0:d2425a595807 106 strcat(jsonreply,DTC[i].code);
cswiger 0:d2425a595807 107 strcat(jsonreply,"\",\"");
cswiger 0:d2425a595807 108 } else {
cswiger 0:d2425a595807 109 strcat(jsonreply,DTC[i].code);
cswiger 0:d2425a595807 110 strcat(jsonreply,"\"}");
cswiger 0:d2425a595807 111 }
cswiger 0:d2425a595807 112 }
cswiger 0:d2425a595807 113 } else {
cswiger 0:d2425a595807 114 strcpy(jsonreply,"{\"1\":\"none\"}");
cswiger 0:d2425a595807 115 }
cswiger 0:d2425a595807 116 pubnub_res rslt = pubnub_publish(pbp, "carpal2", jsonreply);
cswiger 0:d2425a595807 117 if (rslt != PNR_STARTED)
cswiger 0:d2425a595807 118 pc.printf("Failed to start publishing, rslt=%d"CRLF, rslt);
cswiger 0:d2425a595807 119 else {
cswiger 0:d2425a595807 120 rslt = pubnub_await(pbp);
cswiger 0:d2425a595807 121 if (rslt != PNR_OK)
cswiger 0:d2425a595807 122 pc.printf("Failed to finished publishing, rslt=%d"CRLF, rslt);
cswiger 0:d2425a595807 123 else {
cswiger 0:d2425a595807 124 pc.printf("Published! Response from Pubnub: %s"CRLF, pubnub_last_publish_result(pbp));
cswiger 0:d2425a595807 125 }
cswiger 0:d2425a595807 126 }
cswiger 0:d2425a595807 127
cswiger 0:d2425a595807 128 } // GetDTC
cswiger 0:d2425a595807 129
cswiger 0:d2425a595807 130 bool parse_JSON(char const* json_string)
cswiger 0:d2425a595807 131 {
cswiger 0:d2425a595807 132 char const* beginquote;
cswiger 0:d2425a595807 133 char token[] = "get:";
cswiger 0:d2425a595807 134 beginquote = strstr(json_string, token );
cswiger 0:d2425a595807 135 if ((beginquote != 0))
cswiger 0:d2425a595807 136 {
cswiger 0:d2425a595807 137 char getreq = beginquote[strlen(token)]; // this only gets a single letter at the position after 'get:'
cswiger 0:d2425a595807 138 PRINTF(GRN "get Found : %c" DEF "\r\n", getreq);
cswiger 0:d2425a595807 139 switch(getreq)
cswiger 0:d2425a595807 140 {
cswiger 0:d2425a595807 141 case 'd':
cswiger 0:d2425a595807 142 { // dtc
cswiger 0:d2425a595807 143 GetDTC();
cswiger 0:d2425a595807 144 break;
cswiger 0:d2425a595807 145 }
cswiger 0:d2425a595807 146 default:
cswiger 0:d2425a595807 147 {
cswiger 0:d2425a595807 148 break;
cswiger 0:d2425a595807 149 }
cswiger 0:d2425a595807 150 } //switch(getreq)
cswiger 0:d2425a595807 151 return true;
cswiger 0:d2425a595807 152 }
cswiger 0:d2425a595807 153 else
cswiger 0:d2425a595807 154 {
cswiger 0:d2425a595807 155 return false;
cswiger 0:d2425a595807 156 }
cswiger 0:d2425a595807 157 } //parse_JSON
cswiger 0:d2425a595807 158
cswiger 0:d2425a595807 159
cswiger 0:d2425a595807 160 int main()
cswiger 0:d2425a595807 161 {
cswiger 0:d2425a595807 162 char data[256];
cswiger 0:d2425a595807 163 int ret;
cswiger 0:d2425a595807 164
cswiger 0:d2425a595807 165 long vehicle_speed = 0;
cswiger 0:d2425a595807 166 long engine_rpm = 0;
cswiger 0:d2425a595807 167 long fuel_status = 0;
cswiger 0:d2425a595807 168 long engine_load = 0;
cswiger 0:d2425a595807 169 long coolant_temp = 0;
cswiger 0:d2425a595807 170 long stft_b1 = 0;
cswiger 0:d2425a595807 171 long ltft_b1 = 0;
cswiger 0:d2425a595807 172 long stft_b2 = 0;
cswiger 0:d2425a595807 173 long ltft_b2 = 0;
cswiger 0:d2425a595807 174 long timing_adv = 0;
cswiger 0:d2425a595807 175 long int_air_temp = 0;
cswiger 0:d2425a595807 176 long maf_air_flow = 0;
cswiger 0:d2425a595807 177 long throttle_pos = 0;
cswiger 0:d2425a595807 178 long b1s2_o2_v = 0;
cswiger 0:d2425a595807 179
cswiger 0:d2425a595807 180
cswiger 0:d2425a595807 181 rled = 1; // red panel lamp while initializing
cswiger 0:d2425a595807 182 gled = 0;
cswiger 0:d2425a595807 183
cswiger 0:d2425a595807 184 // Configure PC BAUD
cswiger 0:d2425a595807 185 pc.baud(PCBAUD);
cswiger 0:d2425a595807 186
cswiger 0:d2425a595807 187 //debug
cswiger 0:d2425a595807 188 wait(10); // wait for terminal connected
cswiger 0:d2425a595807 189 pc.printf(WHT "STARTING WNCInterface PubNub Test" CRLF);
cswiger 0:d2425a595807 190
cswiger 0:d2425a595807 191 //Create a 1ms timer tick function:
cswiger 0:d2425a595807 192 iTimer1Interval_ms = SENSOR_UPDATE_INTERVAL_MS;
cswiger 0:d2425a595807 193 OneMsTicker.attach(OneMsFunction, 0.001f) ;
cswiger 0:d2425a595807 194
cswiger 0:d2425a595807 195 //Initialize the I2C sensors that are present
cswiger 0:d2425a595807 196 sensors_init();
cswiger 0:d2425a595807 197 read_sensors();
cswiger 0:d2425a595807 198
cswiger 0:d2425a595807 199 // init and connect the WNCInterface cell modem
cswiger 0:d2425a595807 200 pc.printf(DEF "init() returned 0x%04X" CRLF, wnc.init(NULL,&pc));
cswiger 0:d2425a595807 201 ret = wnc.connect();
cswiger 0:d2425a595807 202 wnc.doDebug(0); // if you want a LOT of AT commands logged (1)
cswiger 0:d2425a595807 203
cswiger 0:d2425a595807 204 pc.printf("IP Address: %s " CRLF, wnc.getIPAddress());
cswiger 0:d2425a595807 205 pc.printf("-------------------------------------" CRLF);
cswiger 0:d2425a595807 206 pc.printf("starting PubNub sync..." CRLF);
cswiger 0:d2425a595807 207
cswiger 0:d2425a595807 208 // create the Pubnub interface
cswiger 0:d2425a595807 209 pubnub_init(pbp, "pub-c-xxxxxxxx-yyyy-zzzz-aaaa-bbbbbbbbbbbb", "sub-c-xxxxxxxx-yyyy-zzzz-aaaa-bbbbbbbbbbbb");
cswiger 0:d2425a595807 210
cswiger 0:d2425a595807 211 // Setup STN1110 UART
cswiger 0:d2425a595807 212 pc.printf("Configuring OBD UART\r\n");
cswiger 0:d2425a595807 213 Init();
cswiger 0:d2425a595807 214 pc.printf("Configure done..\r\n");
cswiger 0:d2425a595807 215 while(1) {
cswiger 0:d2425a595807 216 if (bTimerExpiredFlag)
cswiger 0:d2425a595807 217 {
cswiger 0:d2425a595807 218 bTimerExpiredFlag = false;
cswiger 0:d2425a595807 219 pc.printf("Refresh...\n\r");
cswiger 0:d2425a595807 220 Refresh();
cswiger 2:fe8e935b9342 221 pc.printf("Ignition on: %d\n\r",isIgnitionOn);
cswiger 2:fe8e935b9342 222 pc.printf("Engine on: %d\n\r",isEngineOn);
cswiger 2:fe8e935b9342 223 if(isIgnitionOn) {
cswiger 2:fe8e935b9342 224 rled = 1;
cswiger 2:fe8e935b9342 225 pc.printf("Get coolant temp...\n\r");
cswiger 2:fe8e935b9342 226 get_pid(COOLANT_TEMP,&coolant_temp);
cswiger 2:fe8e935b9342 227 pc.printf("Get rpm...\n\r");
cswiger 2:fe8e935b9342 228 get_pid(ENGINE_RPM,&engine_rpm);
cswiger 2:fe8e935b9342 229 get_pid(LOAD_VALUE,&engine_load);
cswiger 2:fe8e935b9342 230 get_pid(VEHICLE_SPEED,&vehicle_speed);
cswiger 2:fe8e935b9342 231 pc.printf("Coolant: %d\n\rRPM: %d\n\r",coolant_temp,engine_rpm);
cswiger 2:fe8e935b9342 232 // short keys to keep air co$t$ down
cswiger 2:fe8e935b9342 233 // oc or os ol - obd2 coolant temp, rpm, speed, load
cswiger 2:fe8e935b9342 234 // la lo - gps latitude, longitude
cswiger 2:fe8e935b9342 235 // ax ay - accelarometer X,Y
cswiger 2:fe8e935b9342 236 pc.printf("Read sensors\n\r");
cswiger 2:fe8e935b9342 237 read_sensors();
cswiger 2:fe8e935b9342 238 snprintf(data,256,"{\"la\":%s,\"lo\":%s,\"ax\":%s,\"ay\":%s,\"oc\":%d,\"or\":%d,\"ol\":%d,\"os\":%d}",SENSOR_DATA.GPS_Latitude,SENSOR_DATA.GPS_Longitude,SENSOR_DATA.AccelX,SENSOR_DATA.AccelY,coolant_temp,engine_rpm,engine_load,vehicle_speed);
cswiger 2:fe8e935b9342 239 // publish json and wait for result
cswiger 2:fe8e935b9342 240 pubnub_res rslt = pubnub_publish(pbp, "carpal2", data);
cswiger 2:fe8e935b9342 241 if (rslt != PNR_STARTED) {
cswiger 2:fe8e935b9342 242 pc.printf("Failed to start publishing, rslt=%d"CRLF, rslt);
cswiger 0:d2425a595807 243 rled = 1;
cswiger 0:d2425a595807 244 gled = 0;
cswiger 0:d2425a595807 245 } else {
cswiger 2:fe8e935b9342 246 rslt = pubnub_await(pbp);
cswiger 2:fe8e935b9342 247 if (rslt != PNR_OK) {
cswiger 2:fe8e935b9342 248 pc.printf("Failed to finished publishing, rslt=%d"CRLF, rslt);
cswiger 2:fe8e935b9342 249 rled = 1;
cswiger 2:fe8e935b9342 250 gled = 0;
cswiger 2:fe8e935b9342 251 } else {
cswiger 2:fe8e935b9342 252 pc.printf("Published! Response from Pubnub: %s"CRLF, pubnub_last_publish_result(pbp));
cswiger 2:fe8e935b9342 253 rled = 0;
cswiger 2:fe8e935b9342 254 gled = 1;
cswiger 2:fe8e935b9342 255 }
cswiger 0:d2425a595807 256 }
cswiger 0:d2425a595807 257
cswiger 2:fe8e935b9342 258 rslt = pubnub_subscribe(pbp, "carpal2", 0);
cswiger 2:fe8e935b9342 259 if (rslt != PNR_STARTED) {
cswiger 2:fe8e935b9342 260 pc.printf("Failed to start subscribing, rslt=%d"CRLF, rslt);
cswiger 0:d2425a595807 261 rled = 1;
cswiger 0:d2425a595807 262 gled = 0;
cswiger 0:d2425a595807 263 } else {
cswiger 2:fe8e935b9342 264 rslt = pubnub_await(pbp);
cswiger 2:fe8e935b9342 265 if (rslt != PNR_OK) {
cswiger 2:fe8e935b9342 266 pc.printf("Failed to finished subscribing, rslt=%d"CRLF, rslt);\
cswiger 2:fe8e935b9342 267 rled = 1;
cswiger 2:fe8e935b9342 268 gled = 0;
cswiger 2:fe8e935b9342 269 } else {
cswiger 2:fe8e935b9342 270 pc.printf("Subscribed! Received messages follow:"CRLF);
cswiger 2:fe8e935b9342 271 while (char const *msg = pubnub_get(pbp)) {
cswiger 2:fe8e935b9342 272 pc.printf("subscribe got: %s"CRLF, msg);
cswiger 2:fe8e935b9342 273 parse_JSON(msg);
cswiger 2:fe8e935b9342 274 }
cswiger 2:fe8e935b9342 275 }
cswiger 2:fe8e935b9342 276 rled = 0;
cswiger 2:fe8e935b9342 277 gled = 1;
cswiger 2:fe8e935b9342 278 } // subscribe result
cswiger 2:fe8e935b9342 279 } else {
cswiger 2:fe8e935b9342 280 rled = 1;
cswiger 2:fe8e935b9342 281 gled = 0;
cswiger 2:fe8e935b9342 282 pc.printf("Ignition off... attempting Init()\n\r");
cswiger 2:fe8e935b9342 283 Init();
cswiger 2:fe8e935b9342 284 } // end isIgnitionOn
cswiger 0:d2425a595807 285 } // end timer expired
cswiger 0:d2425a595807 286 } // end infinite loop
cswiger 0:d2425a595807 287 }
cswiger 0:d2425a595807 288
cswiger 0:d2425a595807 289 char pid_reslen[] =
cswiger 0:d2425a595807 290 {
cswiger 0:d2425a595807 291 // pid 0x00 to 0x1F
cswiger 0:d2425a595807 292 4,4,2,2,1,1,1,1,1,1,1,1,2,1,1,1,
cswiger 0:d2425a595807 293 2,1,1,1,2,2,2,2,2,2,2,2,1,1,1,4,
cswiger 0:d2425a595807 294
cswiger 0:d2425a595807 295 // pid 0x20 to 0x3F
cswiger 0:d2425a595807 296 4,2,2,2,4,4,4,4,4,4,4,4,1,1,1,1,
cswiger 0:d2425a595807 297 1,2,2,1,4,4,4,4,4,4,4,4,2,2,2,2,
cswiger 0:d2425a595807 298
cswiger 0:d2425a595807 299 // pid 0x40 to 0x4E
cswiger 0:d2425a595807 300 4,8,2,2,2,1,1,1,1,1,1,1,1,2,2
cswiger 0:d2425a595807 301 };
cswiger 0:d2425a595807 302
cswiger 0:d2425a595807 303
cswiger 0:d2425a595807 304
cswiger 0:d2425a595807 305 /***********************
cswiger 0:d2425a595807 306 Init
cswiger 0:d2425a595807 307 ***********************/
cswiger 0:d2425a595807 308 char Init()
cswiger 0:d2425a595807 309 {
cswiger 0:d2425a595807 310 obd2.baud(OBDBAUD);
cswiger 0:d2425a595807 311 char str[STRLEN];
cswiger 0:d2425a595807 312 // reset
cswiger 0:d2425a595807 313 stn1110_command(str, "ATWS\r");
cswiger 0:d2425a595807 314 // turn echo off
cswiger 0:d2425a595807 315 stn1110_command(str, "ATE0\r");
cswiger 0:d2425a595807 316
cswiger 0:d2425a595807 317 // send 01 00 until we are connected
cswiger 0:d2425a595807 318 do
cswiger 0:d2425a595807 319 {
cswiger 0:d2425a595807 320 stn1110_command(str, "0100\r");
cswiger 0:d2425a595807 321 wait(1); // might want to change this to return non-zero for engine off or something, otherwise it's stuck here
cswiger 0:d2425a595807 322 }
cswiger 0:d2425a595807 323 while(stn1110_check_response("0100", str)!=0);
cswiger 0:d2425a595807 324
cswiger 0:d2425a595807 325 // ask protocol
cswiger 0:d2425a595807 326 stn1110_command(str, "ATDPN\r");
cswiger 0:d2425a595807 327
cswiger 0:d2425a595807 328 check_supported_pids();
cswiger 0:d2425a595807 329
cswiger 0:d2425a595807 330 return 0;
cswiger 0:d2425a595807 331 }
cswiger 0:d2425a595807 332
cswiger 0:d2425a595807 333 char stn1110_read(char *str, char size)
cswiger 0:d2425a595807 334 {
cswiger 0:d2425a595807 335 int b;
cswiger 0:d2425a595807 336 char i=0;
cswiger 0:d2425a595807 337
cswiger 0:d2425a595807 338 // wait for something on com port
cswiger 1:610520d32d22 339 while((b=obd2.getcNb())!=PROMPT && i<size) // use MODSERIAL::getcNb() non-blocking to match Arduino Serial.read() behavior
cswiger 0:d2425a595807 340 {
cswiger 0:d2425a595807 341 if(b>=' ')
cswiger 0:d2425a595807 342 str[i++]=b;
cswiger 0:d2425a595807 343 }
cswiger 0:d2425a595807 344
cswiger 0:d2425a595807 345 if(i!=size) // we got a prompt
cswiger 0:d2425a595807 346 {
cswiger 0:d2425a595807 347 str[i]=NUL; // replace CR by NUL
cswiger 0:d2425a595807 348 return PROMPT;
cswiger 0:d2425a595807 349 }
cswiger 0:d2425a595807 350 else
cswiger 0:d2425a595807 351 return DATA;
cswiger 0:d2425a595807 352 }
cswiger 0:d2425a595807 353
cswiger 0:d2425a595807 354 void stn1110_write(char *str)
cswiger 0:d2425a595807 355 {
cswiger 0:d2425a595807 356 while(*str!=NUL)
cswiger 0:d2425a595807 357 obd2.putc(*str++);
cswiger 0:d2425a595807 358 }
cswiger 0:d2425a595807 359
cswiger 0:d2425a595807 360 char stn1110_check_response(const char *cmd, char *str)
cswiger 0:d2425a595807 361 {
cswiger 0:d2425a595807 362 // cmd is something like "010D"
cswiger 0:d2425a595807 363 // str should be "41 0D blabla"
cswiger 0:d2425a595807 364 if(cmd[0]+4 != str[0]
cswiger 0:d2425a595807 365 || cmd[1]!=str[1]
cswiger 0:d2425a595807 366 || cmd[2]!=str[3]
cswiger 0:d2425a595807 367 || cmd[3]!=str[4])
cswiger 0:d2425a595807 368 return 1;
cswiger 0:d2425a595807 369
cswiger 0:d2425a595807 370 return 0; // no error
cswiger 0:d2425a595807 371 }
cswiger 0:d2425a595807 372
cswiger 0:d2425a595807 373 char stn1110_compact_response(char *buf, char *str)
cswiger 0:d2425a595807 374 {
cswiger 0:d2425a595807 375 char i=0;
cswiger 0:d2425a595807 376
cswiger 0:d2425a595807 377 str+=6;
cswiger 0:d2425a595807 378 while(*str!=NUL)
cswiger 0:d2425a595807 379 buf[i++]=strtoul(str, &str, 16); // 16 = hex
cswiger 0:d2425a595807 380
cswiger 0:d2425a595807 381 return i;
cswiger 0:d2425a595807 382 }
cswiger 0:d2425a595807 383
cswiger 0:d2425a595807 384 char stn1110_command(char *str, char *cmd)
cswiger 0:d2425a595807 385 {
cswiger 0:d2425a595807 386 strcpy(str, cmd);
cswiger 0:d2425a595807 387 stn1110_write(str);
cswiger 0:d2425a595807 388 return stn1110_read(str, STRLEN);
cswiger 0:d2425a595807 389 }
cswiger 0:d2425a595807 390
cswiger 0:d2425a595807 391 void check_supported_pids(void)
cswiger 0:d2425a595807 392 {
cswiger 0:d2425a595807 393
cswiger 0:d2425a595807 394 // on some ECU first PID read attemts some time fails, changed to 3 attempts
cswiger 0:d2425a595807 395 for (char i=0; i<3; i++)
cswiger 0:d2425a595807 396 {
cswiger 0:d2425a595807 397 pid01to20_support = (get_pid(PID_SUPPORT00, &tempLong)) ? tempLong : 0;
cswiger 0:d2425a595807 398 if (pid01to20_support)
cswiger 0:d2425a595807 399 break;
cswiger 0:d2425a595807 400 }
cswiger 0:d2425a595807 401
cswiger 0:d2425a595807 402 if(is_pid_supported(PID_SUPPORT20))
cswiger 0:d2425a595807 403 if (get_pid(PID_SUPPORT20, &tempLong))
cswiger 0:d2425a595807 404 pid21to40_support = tempLong;
cswiger 0:d2425a595807 405
cswiger 0:d2425a595807 406 if(is_pid_supported(PID_SUPPORT40))
cswiger 0:d2425a595807 407 if (get_pid(PID_SUPPORT40, &tempLong))
cswiger 0:d2425a595807 408 pid41to60_support = tempLong;
cswiger 0:d2425a595807 409 }
cswiger 0:d2425a595807 410
cswiger 0:d2425a595807 411 char is_pid_supported(char pid)
cswiger 0:d2425a595807 412 {
cswiger 0:d2425a595807 413 if(pid==0)
cswiger 0:d2425a595807 414 return 1;
cswiger 0:d2425a595807 415 else
cswiger 0:d2425a595807 416 if(pid<=0x20)
cswiger 0:d2425a595807 417 {
cswiger 0:d2425a595807 418 if(1L<<(char)(0x20-pid) & pid01to20_support)
cswiger 0:d2425a595807 419 return 1;
cswiger 0:d2425a595807 420 }
cswiger 0:d2425a595807 421 else
cswiger 0:d2425a595807 422 if(pid<=0x40)
cswiger 0:d2425a595807 423 {
cswiger 0:d2425a595807 424 if(1L<<(char)(0x40-pid) & pid21to40_support)
cswiger 0:d2425a595807 425 return 1;
cswiger 0:d2425a595807 426 }
cswiger 0:d2425a595807 427 else
cswiger 0:d2425a595807 428 if(pid<=0x60)
cswiger 0:d2425a595807 429 {
cswiger 0:d2425a595807 430 if(1L<<(char)(0x60-pid) & pid41to60_support)
cswiger 0:d2425a595807 431 return 1;
cswiger 0:d2425a595807 432 }
cswiger 0:d2425a595807 433
cswiger 0:d2425a595807 434 return 0;
cswiger 0:d2425a595807 435 }
cswiger 0:d2425a595807 436
cswiger 0:d2425a595807 437
cswiger 0:d2425a595807 438 char get_pid(char pid, long *ret)
cswiger 0:d2425a595807 439 {
cswiger 0:d2425a595807 440 char cmd_str[6]; // to send to STN1110
cswiger 0:d2425a595807 441 char str[STRLEN]; // to receive from STN1110
cswiger 0:d2425a595807 442 char i;
cswiger 0:d2425a595807 443 char buf[10]; // to receive the result
cswiger 0:d2425a595807 444 char reslen;
cswiger 0:d2425a595807 445
cswiger 0:d2425a595807 446 // check if PID is supported
cswiger 0:d2425a595807 447 if(!is_pid_supported(pid))
cswiger 0:d2425a595807 448 {
cswiger 0:d2425a595807 449 // Not Supported
cswiger 0:d2425a595807 450 return 0;
cswiger 0:d2425a595807 451 }
cswiger 0:d2425a595807 452
cswiger 0:d2425a595807 453 // receive length depends on pid
cswiger 0:d2425a595807 454 reslen=pid_reslen[pid];
cswiger 0:d2425a595807 455
cswiger 0:d2425a595807 456 sprintf(cmd_str, "01%02X\r", pid);
cswiger 2:fe8e935b9342 457 pc.printf("get_pid - stn1110_write\n\r");
cswiger 0:d2425a595807 458 stn1110_write(cmd_str);
cswiger 2:fe8e935b9342 459 pc.printf("get_pid - stn1110_read\n\r");
cswiger 0:d2425a595807 460 stn1110_read(str, STRLEN);
cswiger 0:d2425a595807 461
cswiger 0:d2425a595807 462 if(stn1110_check_response(cmd_str, str)!=0)
cswiger 0:d2425a595807 463 {
cswiger 0:d2425a595807 464 return 0;
cswiger 0:d2425a595807 465 }
cswiger 0:d2425a595807 466 stn1110_compact_response(buf, str);
cswiger 0:d2425a595807 467
cswiger 0:d2425a595807 468 *ret=buf[0]*256U+buf[1];
cswiger 0:d2425a595807 469
cswiger 0:d2425a595807 470 // Calculate different for each PID
cswiger 0:d2425a595807 471 switch(pid)
cswiger 0:d2425a595807 472 {
cswiger 0:d2425a595807 473 case ENGINE_RPM:
cswiger 0:d2425a595807 474 *ret=*ret/4U;
cswiger 0:d2425a595807 475 break;
cswiger 0:d2425a595807 476 case MAF_AIR_FLOW:
cswiger 0:d2425a595807 477 break;
cswiger 0:d2425a595807 478 case VEHICLE_SPEED:
cswiger 0:d2425a595807 479 *ret=buf[0];
cswiger 0:d2425a595807 480 break;
cswiger 0:d2425a595807 481 case FUEL_STATUS:
cswiger 0:d2425a595807 482 case LOAD_VALUE:
cswiger 0:d2425a595807 483 case THROTTLE_POS:
cswiger 0:d2425a595807 484 case REL_THR_POS:
cswiger 0:d2425a595807 485 case EGR:
cswiger 0:d2425a595807 486 case EGR_ERROR:
cswiger 0:d2425a595807 487 case FUEL_LEVEL:
cswiger 0:d2425a595807 488 case ABS_THR_POS_B:
cswiger 0:d2425a595807 489 case ABS_THR_POS_C:
cswiger 0:d2425a595807 490 case ACCEL_PEDAL_D:
cswiger 0:d2425a595807 491 case ACCEL_PEDAL_E:
cswiger 0:d2425a595807 492 case ACCEL_PEDAL_F:
cswiger 0:d2425a595807 493 case CMD_THR_ACTU:
cswiger 0:d2425a595807 494 *ret=(buf[0]*100U)/255U;
cswiger 0:d2425a595807 495 break;
cswiger 0:d2425a595807 496 case ABS_LOAD_VAL:
cswiger 0:d2425a595807 497 *ret=(*ret*100)/255;
cswiger 0:d2425a595807 498 break;
cswiger 0:d2425a595807 499 case B1S1_O2_V:
cswiger 0:d2425a595807 500 case B1S2_O2_V:
cswiger 0:d2425a595807 501 case B1S3_O2_V:
cswiger 0:d2425a595807 502 case B1S4_O2_V:
cswiger 0:d2425a595807 503 case B2S1_O2_V:
cswiger 0:d2425a595807 504 case B2S2_O2_V:
cswiger 0:d2425a595807 505 case B2S3_O2_V:
cswiger 0:d2425a595807 506 case B2S4_O2_V:
cswiger 0:d2425a595807 507 case O2S1_WR_V:
cswiger 0:d2425a595807 508 case O2S2_WR_V:
cswiger 0:d2425a595807 509 case O2S3_WR_V:
cswiger 0:d2425a595807 510 case O2S4_WR_V:
cswiger 0:d2425a595807 511 case O2S5_WR_V:
cswiger 0:d2425a595807 512 case O2S6_WR_V:
cswiger 0:d2425a595807 513 case O2S7_WR_V:
cswiger 0:d2425a595807 514 case O2S8_WR_V:
cswiger 0:d2425a595807 515 case O2S1_WR_C:
cswiger 0:d2425a595807 516 case O2S2_WR_C:
cswiger 0:d2425a595807 517 case O2S3_WR_C:
cswiger 0:d2425a595807 518 case O2S4_WR_C:
cswiger 0:d2425a595807 519 case O2S5_WR_C:
cswiger 0:d2425a595807 520 case O2S6_WR_C:
cswiger 0:d2425a595807 521 case O2S7_WR_C:
cswiger 0:d2425a595807 522 case O2S8_WR_C:
cswiger 0:d2425a595807 523 case CMD_EQUIV_R:
cswiger 0:d2425a595807 524 case DIST_MIL_ON:
cswiger 0:d2425a595807 525 case DIST_MIL_CLR:
cswiger 0:d2425a595807 526 case TIME_MIL_ON:
cswiger 0:d2425a595807 527 case TIME_MIL_CLR:
cswiger 0:d2425a595807 528 case INT_AIR_TEMP:
cswiger 0:d2425a595807 529 case AMBIENT_TEMP:
cswiger 0:d2425a595807 530 case CAT_TEMP_B1S1:
cswiger 0:d2425a595807 531 case CAT_TEMP_B2S1:
cswiger 0:d2425a595807 532 case CAT_TEMP_B1S2:
cswiger 0:d2425a595807 533 case CAT_TEMP_B2S2:
cswiger 0:d2425a595807 534 case STFT_BANK1:
cswiger 0:d2425a595807 535 case LTFT_BANK1:
cswiger 0:d2425a595807 536 case STFT_BANK2:
cswiger 0:d2425a595807 537 case LTFT_BANK2:
cswiger 0:d2425a595807 538 case FUEL_PRESSURE:
cswiger 0:d2425a595807 539 case MAN_PRESSURE:
cswiger 0:d2425a595807 540 case BARO_PRESSURE:
cswiger 0:d2425a595807 541 *ret=buf[0];
cswiger 0:d2425a595807 542 if(pid==FUEL_PRESSURE)
cswiger 0:d2425a595807 543 *ret*=3U;
cswiger 0:d2425a595807 544 break;
cswiger 0:d2425a595807 545 case COOLANT_TEMP:
cswiger 0:d2425a595807 546 *ret=buf[0]-40U;
cswiger 0:d2425a595807 547 break;
cswiger 0:d2425a595807 548 case EVAP_PRESSURE:
cswiger 0:d2425a595807 549 *ret=((int)buf[0]*256+buf[1])/4;
cswiger 0:d2425a595807 550 break;
cswiger 0:d2425a595807 551 case TIMING_ADV:
cswiger 0:d2425a595807 552 *ret=(buf[0]/2)-64;
cswiger 0:d2425a595807 553 break;
cswiger 0:d2425a595807 554 case CTRL_MOD_V:
cswiger 0:d2425a595807 555 break;
cswiger 0:d2425a595807 556 case RUNTIME_START:
cswiger 0:d2425a595807 557 break;
cswiger 0:d2425a595807 558 case OBD_STD:
cswiger 0:d2425a595807 559 *ret=buf[0];
cswiger 0:d2425a595807 560 break;
cswiger 0:d2425a595807 561 default:
cswiger 0:d2425a595807 562 *ret=0;
cswiger 0:d2425a595807 563 for(i=0; i<reslen; i++)
cswiger 0:d2425a595807 564 {
cswiger 0:d2425a595807 565 *ret*=256L;
cswiger 0:d2425a595807 566 *ret+=buf[i];
cswiger 0:d2425a595807 567 }
cswiger 0:d2425a595807 568 break;
cswiger 0:d2425a595807 569 }
cswiger 0:d2425a595807 570
cswiger 0:d2425a595807 571 return 1;
cswiger 0:d2425a595807 572 }
cswiger 0:d2425a595807 573
cswiger 0:d2425a595807 574
cswiger 0:d2425a595807 575 char verifyECUAlive()
cswiger 0:d2425a595807 576 {
cswiger 0:d2425a595807 577 char cmd_str[6];
cswiger 0:d2425a595807 578 char str[STRLEN];
cswiger 0:d2425a595807 579 sprintf(cmd_str, "01%02X\r", ENGINE_RPM);
cswiger 0:d2425a595807 580 stn1110_write(cmd_str);
cswiger 0:d2425a595807 581 stn1110_read(str, STRLEN);
cswiger 0:d2425a595807 582
cswiger 0:d2425a595807 583 if(stn1110_check_response(cmd_str, str) == 0)
cswiger 0:d2425a595807 584 {
cswiger 0:d2425a595807 585 return 1;
cswiger 0:d2425a595807 586 }
cswiger 0:d2425a595807 587 else
cswiger 0:d2425a595807 588 {
cswiger 0:d2425a595807 589 return 0;
cswiger 0:d2425a595807 590 }
cswiger 0:d2425a595807 591 }
cswiger 0:d2425a595807 592
cswiger 0:d2425a595807 593
cswiger 0:d2425a595807 594 char Refresh()
cswiger 0:d2425a595807 595 {
cswiger 0:d2425a595807 596 //debug
cswiger 0:d2425a595807 597 isIgnitionOn = verifyECUAlive();
cswiger 0:d2425a595807 598
cswiger 0:d2425a595807 599 //If ignition is on, check for engine
cswiger 0:d2425a595807 600 if (isIgnitionOn) {
cswiger 0:d2425a595807 601 isEngineOn = (get_pid(ENGINE_RPM, &engineRPM) && engineRPM > 0) ? 1 : 0;
cswiger 0:d2425a595807 602 } else { // else engine must be off
cswiger 0:d2425a595807 603 isEngineOn = 0;
cswiger 0:d2425a595807 604 }
cswiger 0:d2425a595807 605 return 0;
cswiger 0:d2425a595807 606 }
cswiger 0:d2425a595807 607
cswiger 0:d2425a595807 608
cswiger 0:d2425a595807 609
cswiger 0:d2425a595807 610 bool dtc_clear(void)
cswiger 0:d2425a595807 611 {
cswiger 0:d2425a595807 612 char cmd_answer[DTC_BUFFER]="";
cswiger 0:d2425a595807 613
cswiger 0:d2425a595807 614 stn1110_write("04\r");
cswiger 0:d2425a595807 615 stn1110_read(cmd_answer,DTC_BUFFER);
cswiger 0:d2425a595807 616 strip_answer(cmd_answer);
cswiger 0:d2425a595807 617
cswiger 0:d2425a595807 618 if (strcmp(cmd_answer, "44")!=0)
cswiger 0:d2425a595807 619 {
cswiger 0:d2425a595807 620 return false;
cswiger 0:d2425a595807 621 } else
cswiger 0:d2425a595807 622 {
cswiger 0:d2425a595807 623 has_dtc=false;
cswiger 0:d2425a595807 624 return true;
cswiger 0:d2425a595807 625 }
cswiger 0:d2425a595807 626 }
cswiger 0:d2425a595807 627
cswiger 0:d2425a595807 628
cswiger 0:d2425a595807 629 bool dtc_read(void)
cswiger 0:d2425a595807 630 {
cswiger 0:d2425a595807 631 char cmd_answer[DTC_BUFFER]="";
cswiger 0:d2425a595807 632 has_dtc=false;
cswiger 0:d2425a595807 633
cswiger 0:d2425a595807 634 stn1110_write("03\r");
cswiger 0:d2425a595807 635 stn1110_read(cmd_answer,DTC_BUFFER);
cswiger 0:d2425a595807 636
cswiger 0:d2425a595807 637 for (char i=0;i<MAX_DTC_READ;i++)
cswiger 0:d2425a595807 638 {
cswiger 0:d2425a595807 639 strcpy(DTC[i].code,"");
cswiger 0:d2425a595807 640 }
cswiger 0:d2425a595807 641
cswiger 0:d2425a595807 642 strip_answer(cmd_answer);
cswiger 0:d2425a595807 643
cswiger 0:d2425a595807 644 if (strstr(cmd_answer, "NODATA"))
cswiger 0:d2425a595807 645 {
cswiger 0:d2425a595807 646 //No errors
cswiger 0:d2425a595807 647 return true;
cswiger 0:d2425a595807 648 }
cswiger 0:d2425a595807 649
cswiger 0:d2425a595807 650 if (strncmp(cmd_answer, "43", 2)!=0)
cswiger 0:d2425a595807 651 {
cswiger 0:d2425a595807 652 //ERROR: Incorrect answer
cswiger 0:d2425a595807 653 return false;
cswiger 0:d2425a595807 654 }
cswiger 0:d2425a595807 655
cswiger 0:d2425a595807 656 char *ss=cmd_answer+2;
cswiger 0:d2425a595807 657 char dtclen=0;
cswiger 0:d2425a595807 658
cswiger 0:d2425a595807 659 while (strlen(ss) >= 4)
cswiger 0:d2425a595807 660 {
cswiger 0:d2425a595807 661 const char *prefix[16]=
cswiger 0:d2425a595807 662 {
cswiger 0:d2425a595807 663 "P0", "P1", "P2", "P3",
cswiger 0:d2425a595807 664 "C0", "C1", "C2", "C3",
cswiger 0:d2425a595807 665 "B0", "B1", "B2", "B3",
cswiger 0:d2425a595807 666 "U0", "U1", "U2", "U3",
cswiger 0:d2425a595807 667 };
cswiger 0:d2425a595807 668 uint8_t p=0;
cswiger 0:d2425a595807 669 if ( ((*ss)>='0') && ((*ss)<='9') ) p=(*ss)-'0'; else
cswiger 0:d2425a595807 670 if ( ((*ss)>='A') && ((*ss)<='F') ) p=(*ss)-'A'+10; else
cswiger 0:d2425a595807 671 if ( ((*ss)>='a') && ((*ss)<='f') ) p=(*ss)-'a'+10;
cswiger 0:d2425a595807 672 char code[6];
cswiger 0:d2425a595807 673 strcpy(code, prefix[p]);
cswiger 0:d2425a595807 674 code[2]=ss[1];
cswiger 0:d2425a595807 675 code[3]=ss[2];
cswiger 0:d2425a595807 676 code[4]=ss[3];
cswiger 0:d2425a595807 677 code[5]=0;
cswiger 0:d2425a595807 678
cswiger 0:d2425a595807 679 if (strcmp(code, "P0000")!=0)
cswiger 0:d2425a595807 680 {
cswiger 0:d2425a595807 681 strcpy(DTC[dtclen].code,code);
cswiger 0:d2425a595807 682 has_dtc=true;
cswiger 0:d2425a595807 683 dtclen++;
cswiger 0:d2425a595807 684 }
cswiger 0:d2425a595807 685 ss+=4;
cswiger 0:d2425a595807 686 }
cswiger 0:d2425a595807 687
cswiger 0:d2425a595807 688 return true;
cswiger 0:d2425a595807 689 }
cswiger 0:d2425a595807 690
cswiger 0:d2425a595807 691 char *strip_answer(char *s)
cswiger 0:d2425a595807 692 {
cswiger 0:d2425a595807 693 char *ss;
cswiger 0:d2425a595807 694 for (ss=s; *s; s++)
cswiger 0:d2425a595807 695 {
cswiger 0:d2425a595807 696 if ( ((*s)!=' ') && ((*s)!='\t') && ((*s)!='\n') && ((*s)!='\r') )
cswiger 0:d2425a595807 697 (*ss++)=(*s);
cswiger 0:d2425a595807 698 }
cswiger 0:d2425a595807 699 (*ss)=0;
cswiger 0:d2425a595807 700
cswiger 0:d2425a595807 701 return s;
cswiger 0:d2425a595807 702 }
cswiger 0:d2425a595807 703