AT&T IoT hackster.io contest entry: Carpal2

Dependencies:   FXOS8700CQ Pubnub_mbed2_sync WNCInterface mbed-rtos mbed

Committer:
cswiger
Date:
Tue Dec 20 16:44:32 2016 +0000
Revision:
0:d2425a595807
Child:
1:610520d32d22
AT&T IoT hackster.io contest entry Carpal2

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 rled = 1;
cswiger 0:d2425a595807 220 pc.printf("Refresh...\n\r");
cswiger 0:d2425a595807 221 Refresh();
cswiger 0:d2425a595807 222 pc.printf("Get coolant temp...\n\r");
cswiger 0:d2425a595807 223 get_pid(COOLANT_TEMP,&coolant_temp);
cswiger 0:d2425a595807 224 pc.printf("Get rpm...\n\r");
cswiger 0:d2425a595807 225 get_pid(ENGINE_RPM,&engine_rpm);
cswiger 0:d2425a595807 226 get_pid(LOAD_VALUE,&engine_load);
cswiger 0:d2425a595807 227 get_pid(VEHICLE_SPEED,&vehicle_speed);
cswiger 0:d2425a595807 228 pc.printf("Coolant: %d\n\rRPM: %d\n\r",coolant_temp,engine_rpm);
cswiger 0:d2425a595807 229 // short keys to keep air co$t$ down
cswiger 0:d2425a595807 230 // oc or os ol - obd2 coolant temp, rpm, speed, load
cswiger 0:d2425a595807 231 // la lo - gps latitude, longitude
cswiger 0:d2425a595807 232 // ax ay - accelarometer X,Y
cswiger 0:d2425a595807 233 pc.printf("Read sensors\n\r");
cswiger 0:d2425a595807 234 read_sensors();
cswiger 0:d2425a595807 235 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 0:d2425a595807 236 // publish json and wait for result
cswiger 0:d2425a595807 237 pubnub_res rslt = pubnub_publish(pbp, "carpal2", data);
cswiger 0:d2425a595807 238 if (rslt != PNR_STARTED) {
cswiger 0:d2425a595807 239 pc.printf("Failed to start publishing, rslt=%d"CRLF, rslt);
cswiger 0:d2425a595807 240 rled = 1;
cswiger 0:d2425a595807 241 gled = 0;
cswiger 0:d2425a595807 242 } else {
cswiger 0:d2425a595807 243 rslt = pubnub_await(pbp);
cswiger 0:d2425a595807 244 if (rslt != PNR_OK) {
cswiger 0:d2425a595807 245 pc.printf("Failed to finished publishing, rslt=%d"CRLF, rslt);
cswiger 0:d2425a595807 246 rled = 1;
cswiger 0:d2425a595807 247 gled = 0;
cswiger 0:d2425a595807 248 } else {
cswiger 0:d2425a595807 249 pc.printf("Published! Response from Pubnub: %s"CRLF, pubnub_last_publish_result(pbp));
cswiger 0:d2425a595807 250 rled = 0;
cswiger 0:d2425a595807 251 gled = 1;
cswiger 0:d2425a595807 252 }
cswiger 0:d2425a595807 253 }
cswiger 0:d2425a595807 254
cswiger 0:d2425a595807 255 rslt = pubnub_subscribe(pbp, "carpal2", 0);
cswiger 0:d2425a595807 256 if (rslt != PNR_STARTED) {
cswiger 0:d2425a595807 257 pc.printf("Failed to start subscribing, rslt=%d"CRLF, rslt);
cswiger 0:d2425a595807 258 rled = 1;
cswiger 0:d2425a595807 259 gled = 0;
cswiger 0:d2425a595807 260 } else {
cswiger 0:d2425a595807 261 rslt = pubnub_await(pbp);
cswiger 0:d2425a595807 262 if (rslt != PNR_OK) {
cswiger 0:d2425a595807 263 pc.printf("Failed to finished subscribing, rslt=%d"CRLF, rslt);\
cswiger 0:d2425a595807 264 rled = 1;
cswiger 0:d2425a595807 265 gled = 0;
cswiger 0:d2425a595807 266 } else {
cswiger 0:d2425a595807 267 pc.printf("Subscribed! Received messages follow:"CRLF);
cswiger 0:d2425a595807 268 while (char const *msg = pubnub_get(pbp)) {
cswiger 0:d2425a595807 269 pc.printf("subscribe got: %s"CRLF, msg);
cswiger 0:d2425a595807 270 parse_JSON(msg);
cswiger 0:d2425a595807 271 }
cswiger 0:d2425a595807 272 }
cswiger 0:d2425a595807 273 rled = 0;
cswiger 0:d2425a595807 274 gled = 1;
cswiger 0:d2425a595807 275 } // subscribe result
cswiger 0:d2425a595807 276 } // end timer expired
cswiger 0:d2425a595807 277 } // end infinite loop
cswiger 0:d2425a595807 278 }
cswiger 0:d2425a595807 279
cswiger 0:d2425a595807 280 char pid_reslen[] =
cswiger 0:d2425a595807 281 {
cswiger 0:d2425a595807 282 // pid 0x00 to 0x1F
cswiger 0:d2425a595807 283 4,4,2,2,1,1,1,1,1,1,1,1,2,1,1,1,
cswiger 0:d2425a595807 284 2,1,1,1,2,2,2,2,2,2,2,2,1,1,1,4,
cswiger 0:d2425a595807 285
cswiger 0:d2425a595807 286 // pid 0x20 to 0x3F
cswiger 0:d2425a595807 287 4,2,2,2,4,4,4,4,4,4,4,4,1,1,1,1,
cswiger 0:d2425a595807 288 1,2,2,1,4,4,4,4,4,4,4,4,2,2,2,2,
cswiger 0:d2425a595807 289
cswiger 0:d2425a595807 290 // pid 0x40 to 0x4E
cswiger 0:d2425a595807 291 4,8,2,2,2,1,1,1,1,1,1,1,1,2,2
cswiger 0:d2425a595807 292 };
cswiger 0:d2425a595807 293
cswiger 0:d2425a595807 294
cswiger 0:d2425a595807 295
cswiger 0:d2425a595807 296 /***********************
cswiger 0:d2425a595807 297 Init
cswiger 0:d2425a595807 298 ***********************/
cswiger 0:d2425a595807 299 char Init()
cswiger 0:d2425a595807 300 {
cswiger 0:d2425a595807 301 obd2.baud(OBDBAUD);
cswiger 0:d2425a595807 302 char str[STRLEN];
cswiger 0:d2425a595807 303 // reset
cswiger 0:d2425a595807 304 stn1110_command(str, "ATWS\r");
cswiger 0:d2425a595807 305 // turn echo off
cswiger 0:d2425a595807 306 stn1110_command(str, "ATE0\r");
cswiger 0:d2425a595807 307
cswiger 0:d2425a595807 308 // send 01 00 until we are connected
cswiger 0:d2425a595807 309 do
cswiger 0:d2425a595807 310 {
cswiger 0:d2425a595807 311 stn1110_command(str, "0100\r");
cswiger 0:d2425a595807 312 wait(1); // might want to change this to return non-zero for engine off or something, otherwise it's stuck here
cswiger 0:d2425a595807 313 }
cswiger 0:d2425a595807 314 while(stn1110_check_response("0100", str)!=0);
cswiger 0:d2425a595807 315
cswiger 0:d2425a595807 316 // ask protocol
cswiger 0:d2425a595807 317 stn1110_command(str, "ATDPN\r");
cswiger 0:d2425a595807 318
cswiger 0:d2425a595807 319 check_supported_pids();
cswiger 0:d2425a595807 320
cswiger 0:d2425a595807 321 return 0;
cswiger 0:d2425a595807 322 }
cswiger 0:d2425a595807 323
cswiger 0:d2425a595807 324 char stn1110_read(char *str, char size)
cswiger 0:d2425a595807 325 {
cswiger 0:d2425a595807 326 int b;
cswiger 0:d2425a595807 327 char i=0;
cswiger 0:d2425a595807 328
cswiger 0:d2425a595807 329 // wait for something on com port
cswiger 0:d2425a595807 330 while((b=obd2.getc())!=PROMPT && i<size) // this blocks! Arduino Serial.read would return -1
cswiger 0:d2425a595807 331 {
cswiger 0:d2425a595807 332 if(b>=' ')
cswiger 0:d2425a595807 333 str[i++]=b;
cswiger 0:d2425a595807 334 }
cswiger 0:d2425a595807 335
cswiger 0:d2425a595807 336 if(i!=size) // we got a prompt
cswiger 0:d2425a595807 337 {
cswiger 0:d2425a595807 338 str[i]=NUL; // replace CR by NUL
cswiger 0:d2425a595807 339 return PROMPT;
cswiger 0:d2425a595807 340 }
cswiger 0:d2425a595807 341 else
cswiger 0:d2425a595807 342 return DATA;
cswiger 0:d2425a595807 343 }
cswiger 0:d2425a595807 344
cswiger 0:d2425a595807 345 void stn1110_write(char *str)
cswiger 0:d2425a595807 346 {
cswiger 0:d2425a595807 347 while(*str!=NUL)
cswiger 0:d2425a595807 348 obd2.putc(*str++);
cswiger 0:d2425a595807 349 }
cswiger 0:d2425a595807 350
cswiger 0:d2425a595807 351 char stn1110_check_response(const char *cmd, char *str)
cswiger 0:d2425a595807 352 {
cswiger 0:d2425a595807 353 // cmd is something like "010D"
cswiger 0:d2425a595807 354 // str should be "41 0D blabla"
cswiger 0:d2425a595807 355 if(cmd[0]+4 != str[0]
cswiger 0:d2425a595807 356 || cmd[1]!=str[1]
cswiger 0:d2425a595807 357 || cmd[2]!=str[3]
cswiger 0:d2425a595807 358 || cmd[3]!=str[4])
cswiger 0:d2425a595807 359 return 1;
cswiger 0:d2425a595807 360
cswiger 0:d2425a595807 361 return 0; // no error
cswiger 0:d2425a595807 362 }
cswiger 0:d2425a595807 363
cswiger 0:d2425a595807 364 char stn1110_compact_response(char *buf, char *str)
cswiger 0:d2425a595807 365 {
cswiger 0:d2425a595807 366 char i=0;
cswiger 0:d2425a595807 367
cswiger 0:d2425a595807 368 str+=6;
cswiger 0:d2425a595807 369 while(*str!=NUL)
cswiger 0:d2425a595807 370 buf[i++]=strtoul(str, &str, 16); // 16 = hex
cswiger 0:d2425a595807 371
cswiger 0:d2425a595807 372 return i;
cswiger 0:d2425a595807 373 }
cswiger 0:d2425a595807 374
cswiger 0:d2425a595807 375 char stn1110_command(char *str, char *cmd)
cswiger 0:d2425a595807 376 {
cswiger 0:d2425a595807 377 strcpy(str, cmd);
cswiger 0:d2425a595807 378 stn1110_write(str);
cswiger 0:d2425a595807 379 return stn1110_read(str, STRLEN);
cswiger 0:d2425a595807 380 }
cswiger 0:d2425a595807 381
cswiger 0:d2425a595807 382 void check_supported_pids(void)
cswiger 0:d2425a595807 383 {
cswiger 0:d2425a595807 384
cswiger 0:d2425a595807 385 // on some ECU first PID read attemts some time fails, changed to 3 attempts
cswiger 0:d2425a595807 386 for (char i=0; i<3; i++)
cswiger 0:d2425a595807 387 {
cswiger 0:d2425a595807 388 pid01to20_support = (get_pid(PID_SUPPORT00, &tempLong)) ? tempLong : 0;
cswiger 0:d2425a595807 389 if (pid01to20_support)
cswiger 0:d2425a595807 390 break;
cswiger 0:d2425a595807 391 }
cswiger 0:d2425a595807 392
cswiger 0:d2425a595807 393 if(is_pid_supported(PID_SUPPORT20))
cswiger 0:d2425a595807 394 if (get_pid(PID_SUPPORT20, &tempLong))
cswiger 0:d2425a595807 395 pid21to40_support = tempLong;
cswiger 0:d2425a595807 396
cswiger 0:d2425a595807 397 if(is_pid_supported(PID_SUPPORT40))
cswiger 0:d2425a595807 398 if (get_pid(PID_SUPPORT40, &tempLong))
cswiger 0:d2425a595807 399 pid41to60_support = tempLong;
cswiger 0:d2425a595807 400 }
cswiger 0:d2425a595807 401
cswiger 0:d2425a595807 402 char is_pid_supported(char pid)
cswiger 0:d2425a595807 403 {
cswiger 0:d2425a595807 404 if(pid==0)
cswiger 0:d2425a595807 405 return 1;
cswiger 0:d2425a595807 406 else
cswiger 0:d2425a595807 407 if(pid<=0x20)
cswiger 0:d2425a595807 408 {
cswiger 0:d2425a595807 409 if(1L<<(char)(0x20-pid) & pid01to20_support)
cswiger 0:d2425a595807 410 return 1;
cswiger 0:d2425a595807 411 }
cswiger 0:d2425a595807 412 else
cswiger 0:d2425a595807 413 if(pid<=0x40)
cswiger 0:d2425a595807 414 {
cswiger 0:d2425a595807 415 if(1L<<(char)(0x40-pid) & pid21to40_support)
cswiger 0:d2425a595807 416 return 1;
cswiger 0:d2425a595807 417 }
cswiger 0:d2425a595807 418 else
cswiger 0:d2425a595807 419 if(pid<=0x60)
cswiger 0:d2425a595807 420 {
cswiger 0:d2425a595807 421 if(1L<<(char)(0x60-pid) & pid41to60_support)
cswiger 0:d2425a595807 422 return 1;
cswiger 0:d2425a595807 423 }
cswiger 0:d2425a595807 424
cswiger 0:d2425a595807 425 return 0;
cswiger 0:d2425a595807 426 }
cswiger 0:d2425a595807 427
cswiger 0:d2425a595807 428
cswiger 0:d2425a595807 429 char get_pid(char pid, long *ret)
cswiger 0:d2425a595807 430 {
cswiger 0:d2425a595807 431 char cmd_str[6]; // to send to STN1110
cswiger 0:d2425a595807 432 char str[STRLEN]; // to receive from STN1110
cswiger 0:d2425a595807 433 char i;
cswiger 0:d2425a595807 434 char buf[10]; // to receive the result
cswiger 0:d2425a595807 435 char reslen;
cswiger 0:d2425a595807 436
cswiger 0:d2425a595807 437 // check if PID is supported
cswiger 0:d2425a595807 438 if(!is_pid_supported(pid))
cswiger 0:d2425a595807 439 {
cswiger 0:d2425a595807 440 // Not Supported
cswiger 0:d2425a595807 441 return 0;
cswiger 0:d2425a595807 442 }
cswiger 0:d2425a595807 443
cswiger 0:d2425a595807 444 // receive length depends on pid
cswiger 0:d2425a595807 445 reslen=pid_reslen[pid];
cswiger 0:d2425a595807 446
cswiger 0:d2425a595807 447 sprintf(cmd_str, "01%02X\r", pid);
cswiger 0:d2425a595807 448 stn1110_write(cmd_str);
cswiger 0:d2425a595807 449 stn1110_read(str, STRLEN);
cswiger 0:d2425a595807 450
cswiger 0:d2425a595807 451 if(stn1110_check_response(cmd_str, str)!=0)
cswiger 0:d2425a595807 452 {
cswiger 0:d2425a595807 453 return 0;
cswiger 0:d2425a595807 454 }
cswiger 0:d2425a595807 455 stn1110_compact_response(buf, str);
cswiger 0:d2425a595807 456
cswiger 0:d2425a595807 457 *ret=buf[0]*256U+buf[1];
cswiger 0:d2425a595807 458
cswiger 0:d2425a595807 459 // Calculate different for each PID
cswiger 0:d2425a595807 460 switch(pid)
cswiger 0:d2425a595807 461 {
cswiger 0:d2425a595807 462 case ENGINE_RPM:
cswiger 0:d2425a595807 463 *ret=*ret/4U;
cswiger 0:d2425a595807 464 break;
cswiger 0:d2425a595807 465 case MAF_AIR_FLOW:
cswiger 0:d2425a595807 466 break;
cswiger 0:d2425a595807 467 case VEHICLE_SPEED:
cswiger 0:d2425a595807 468 *ret=buf[0];
cswiger 0:d2425a595807 469 break;
cswiger 0:d2425a595807 470 case FUEL_STATUS:
cswiger 0:d2425a595807 471 case LOAD_VALUE:
cswiger 0:d2425a595807 472 case THROTTLE_POS:
cswiger 0:d2425a595807 473 case REL_THR_POS:
cswiger 0:d2425a595807 474 case EGR:
cswiger 0:d2425a595807 475 case EGR_ERROR:
cswiger 0:d2425a595807 476 case FUEL_LEVEL:
cswiger 0:d2425a595807 477 case ABS_THR_POS_B:
cswiger 0:d2425a595807 478 case ABS_THR_POS_C:
cswiger 0:d2425a595807 479 case ACCEL_PEDAL_D:
cswiger 0:d2425a595807 480 case ACCEL_PEDAL_E:
cswiger 0:d2425a595807 481 case ACCEL_PEDAL_F:
cswiger 0:d2425a595807 482 case CMD_THR_ACTU:
cswiger 0:d2425a595807 483 *ret=(buf[0]*100U)/255U;
cswiger 0:d2425a595807 484 break;
cswiger 0:d2425a595807 485 case ABS_LOAD_VAL:
cswiger 0:d2425a595807 486 *ret=(*ret*100)/255;
cswiger 0:d2425a595807 487 break;
cswiger 0:d2425a595807 488 case B1S1_O2_V:
cswiger 0:d2425a595807 489 case B1S2_O2_V:
cswiger 0:d2425a595807 490 case B1S3_O2_V:
cswiger 0:d2425a595807 491 case B1S4_O2_V:
cswiger 0:d2425a595807 492 case B2S1_O2_V:
cswiger 0:d2425a595807 493 case B2S2_O2_V:
cswiger 0:d2425a595807 494 case B2S3_O2_V:
cswiger 0:d2425a595807 495 case B2S4_O2_V:
cswiger 0:d2425a595807 496 case O2S1_WR_V:
cswiger 0:d2425a595807 497 case O2S2_WR_V:
cswiger 0:d2425a595807 498 case O2S3_WR_V:
cswiger 0:d2425a595807 499 case O2S4_WR_V:
cswiger 0:d2425a595807 500 case O2S5_WR_V:
cswiger 0:d2425a595807 501 case O2S6_WR_V:
cswiger 0:d2425a595807 502 case O2S7_WR_V:
cswiger 0:d2425a595807 503 case O2S8_WR_V:
cswiger 0:d2425a595807 504 case O2S1_WR_C:
cswiger 0:d2425a595807 505 case O2S2_WR_C:
cswiger 0:d2425a595807 506 case O2S3_WR_C:
cswiger 0:d2425a595807 507 case O2S4_WR_C:
cswiger 0:d2425a595807 508 case O2S5_WR_C:
cswiger 0:d2425a595807 509 case O2S6_WR_C:
cswiger 0:d2425a595807 510 case O2S7_WR_C:
cswiger 0:d2425a595807 511 case O2S8_WR_C:
cswiger 0:d2425a595807 512 case CMD_EQUIV_R:
cswiger 0:d2425a595807 513 case DIST_MIL_ON:
cswiger 0:d2425a595807 514 case DIST_MIL_CLR:
cswiger 0:d2425a595807 515 case TIME_MIL_ON:
cswiger 0:d2425a595807 516 case TIME_MIL_CLR:
cswiger 0:d2425a595807 517 case INT_AIR_TEMP:
cswiger 0:d2425a595807 518 case AMBIENT_TEMP:
cswiger 0:d2425a595807 519 case CAT_TEMP_B1S1:
cswiger 0:d2425a595807 520 case CAT_TEMP_B2S1:
cswiger 0:d2425a595807 521 case CAT_TEMP_B1S2:
cswiger 0:d2425a595807 522 case CAT_TEMP_B2S2:
cswiger 0:d2425a595807 523 case STFT_BANK1:
cswiger 0:d2425a595807 524 case LTFT_BANK1:
cswiger 0:d2425a595807 525 case STFT_BANK2:
cswiger 0:d2425a595807 526 case LTFT_BANK2:
cswiger 0:d2425a595807 527 case FUEL_PRESSURE:
cswiger 0:d2425a595807 528 case MAN_PRESSURE:
cswiger 0:d2425a595807 529 case BARO_PRESSURE:
cswiger 0:d2425a595807 530 *ret=buf[0];
cswiger 0:d2425a595807 531 if(pid==FUEL_PRESSURE)
cswiger 0:d2425a595807 532 *ret*=3U;
cswiger 0:d2425a595807 533 break;
cswiger 0:d2425a595807 534 case COOLANT_TEMP:
cswiger 0:d2425a595807 535 *ret=buf[0]-40U;
cswiger 0:d2425a595807 536 break;
cswiger 0:d2425a595807 537 case EVAP_PRESSURE:
cswiger 0:d2425a595807 538 *ret=((int)buf[0]*256+buf[1])/4;
cswiger 0:d2425a595807 539 break;
cswiger 0:d2425a595807 540 case TIMING_ADV:
cswiger 0:d2425a595807 541 *ret=(buf[0]/2)-64;
cswiger 0:d2425a595807 542 break;
cswiger 0:d2425a595807 543 case CTRL_MOD_V:
cswiger 0:d2425a595807 544 break;
cswiger 0:d2425a595807 545 case RUNTIME_START:
cswiger 0:d2425a595807 546 break;
cswiger 0:d2425a595807 547 case OBD_STD:
cswiger 0:d2425a595807 548 *ret=buf[0];
cswiger 0:d2425a595807 549 break;
cswiger 0:d2425a595807 550 default:
cswiger 0:d2425a595807 551 *ret=0;
cswiger 0:d2425a595807 552 for(i=0; i<reslen; i++)
cswiger 0:d2425a595807 553 {
cswiger 0:d2425a595807 554 *ret*=256L;
cswiger 0:d2425a595807 555 *ret+=buf[i];
cswiger 0:d2425a595807 556 }
cswiger 0:d2425a595807 557 break;
cswiger 0:d2425a595807 558 }
cswiger 0:d2425a595807 559
cswiger 0:d2425a595807 560 return 1;
cswiger 0:d2425a595807 561 }
cswiger 0:d2425a595807 562
cswiger 0:d2425a595807 563
cswiger 0:d2425a595807 564 char verifyECUAlive()
cswiger 0:d2425a595807 565 {
cswiger 0:d2425a595807 566 char cmd_str[6];
cswiger 0:d2425a595807 567 char str[STRLEN];
cswiger 0:d2425a595807 568 sprintf(cmd_str, "01%02X\r", ENGINE_RPM);
cswiger 0:d2425a595807 569 stn1110_write(cmd_str);
cswiger 0:d2425a595807 570 stn1110_read(str, STRLEN);
cswiger 0:d2425a595807 571
cswiger 0:d2425a595807 572 if(stn1110_check_response(cmd_str, str) == 0)
cswiger 0:d2425a595807 573 {
cswiger 0:d2425a595807 574 return 1;
cswiger 0:d2425a595807 575 }
cswiger 0:d2425a595807 576 else
cswiger 0:d2425a595807 577 {
cswiger 0:d2425a595807 578 return 0;
cswiger 0:d2425a595807 579 }
cswiger 0:d2425a595807 580 }
cswiger 0:d2425a595807 581
cswiger 0:d2425a595807 582
cswiger 0:d2425a595807 583 char Refresh()
cswiger 0:d2425a595807 584 {
cswiger 0:d2425a595807 585 //debug
cswiger 0:d2425a595807 586 isIgnitionOn = verifyECUAlive();
cswiger 0:d2425a595807 587
cswiger 0:d2425a595807 588 //If ignition is on, check for engine
cswiger 0:d2425a595807 589 if (isIgnitionOn) {
cswiger 0:d2425a595807 590 isEngineOn = (get_pid(ENGINE_RPM, &engineRPM) && engineRPM > 0) ? 1 : 0;
cswiger 0:d2425a595807 591 } else { // else engine must be off
cswiger 0:d2425a595807 592 isEngineOn = 0;
cswiger 0:d2425a595807 593 }
cswiger 0:d2425a595807 594 return 0;
cswiger 0:d2425a595807 595 }
cswiger 0:d2425a595807 596
cswiger 0:d2425a595807 597
cswiger 0:d2425a595807 598
cswiger 0:d2425a595807 599 bool dtc_clear(void)
cswiger 0:d2425a595807 600 {
cswiger 0:d2425a595807 601 char cmd_answer[DTC_BUFFER]="";
cswiger 0:d2425a595807 602
cswiger 0:d2425a595807 603 stn1110_write("04\r");
cswiger 0:d2425a595807 604 stn1110_read(cmd_answer,DTC_BUFFER);
cswiger 0:d2425a595807 605 strip_answer(cmd_answer);
cswiger 0:d2425a595807 606
cswiger 0:d2425a595807 607 if (strcmp(cmd_answer, "44")!=0)
cswiger 0:d2425a595807 608 {
cswiger 0:d2425a595807 609 return false;
cswiger 0:d2425a595807 610 } else
cswiger 0:d2425a595807 611 {
cswiger 0:d2425a595807 612 has_dtc=false;
cswiger 0:d2425a595807 613 return true;
cswiger 0:d2425a595807 614 }
cswiger 0:d2425a595807 615 }
cswiger 0:d2425a595807 616
cswiger 0:d2425a595807 617
cswiger 0:d2425a595807 618 bool dtc_read(void)
cswiger 0:d2425a595807 619 {
cswiger 0:d2425a595807 620 char cmd_answer[DTC_BUFFER]="";
cswiger 0:d2425a595807 621 has_dtc=false;
cswiger 0:d2425a595807 622
cswiger 0:d2425a595807 623 stn1110_write("03\r");
cswiger 0:d2425a595807 624 stn1110_read(cmd_answer,DTC_BUFFER);
cswiger 0:d2425a595807 625
cswiger 0:d2425a595807 626 for (char i=0;i<MAX_DTC_READ;i++)
cswiger 0:d2425a595807 627 {
cswiger 0:d2425a595807 628 strcpy(DTC[i].code,"");
cswiger 0:d2425a595807 629 }
cswiger 0:d2425a595807 630
cswiger 0:d2425a595807 631 strip_answer(cmd_answer);
cswiger 0:d2425a595807 632
cswiger 0:d2425a595807 633 if (strstr(cmd_answer, "NODATA"))
cswiger 0:d2425a595807 634 {
cswiger 0:d2425a595807 635 //No errors
cswiger 0:d2425a595807 636 return true;
cswiger 0:d2425a595807 637 }
cswiger 0:d2425a595807 638
cswiger 0:d2425a595807 639 if (strncmp(cmd_answer, "43", 2)!=0)
cswiger 0:d2425a595807 640 {
cswiger 0:d2425a595807 641 //ERROR: Incorrect answer
cswiger 0:d2425a595807 642 return false;
cswiger 0:d2425a595807 643 }
cswiger 0:d2425a595807 644
cswiger 0:d2425a595807 645 char *ss=cmd_answer+2;
cswiger 0:d2425a595807 646 char dtclen=0;
cswiger 0:d2425a595807 647
cswiger 0:d2425a595807 648 while (strlen(ss) >= 4)
cswiger 0:d2425a595807 649 {
cswiger 0:d2425a595807 650 const char *prefix[16]=
cswiger 0:d2425a595807 651 {
cswiger 0:d2425a595807 652 "P0", "P1", "P2", "P3",
cswiger 0:d2425a595807 653 "C0", "C1", "C2", "C3",
cswiger 0:d2425a595807 654 "B0", "B1", "B2", "B3",
cswiger 0:d2425a595807 655 "U0", "U1", "U2", "U3",
cswiger 0:d2425a595807 656 };
cswiger 0:d2425a595807 657 uint8_t p=0;
cswiger 0:d2425a595807 658 if ( ((*ss)>='0') && ((*ss)<='9') ) p=(*ss)-'0'; else
cswiger 0:d2425a595807 659 if ( ((*ss)>='A') && ((*ss)<='F') ) p=(*ss)-'A'+10; else
cswiger 0:d2425a595807 660 if ( ((*ss)>='a') && ((*ss)<='f') ) p=(*ss)-'a'+10;
cswiger 0:d2425a595807 661 char code[6];
cswiger 0:d2425a595807 662 strcpy(code, prefix[p]);
cswiger 0:d2425a595807 663 code[2]=ss[1];
cswiger 0:d2425a595807 664 code[3]=ss[2];
cswiger 0:d2425a595807 665 code[4]=ss[3];
cswiger 0:d2425a595807 666 code[5]=0;
cswiger 0:d2425a595807 667
cswiger 0:d2425a595807 668 if (strcmp(code, "P0000")!=0)
cswiger 0:d2425a595807 669 {
cswiger 0:d2425a595807 670 strcpy(DTC[dtclen].code,code);
cswiger 0:d2425a595807 671 has_dtc=true;
cswiger 0:d2425a595807 672 dtclen++;
cswiger 0:d2425a595807 673 }
cswiger 0:d2425a595807 674 ss+=4;
cswiger 0:d2425a595807 675 }
cswiger 0:d2425a595807 676
cswiger 0:d2425a595807 677 return true;
cswiger 0:d2425a595807 678 }
cswiger 0:d2425a595807 679
cswiger 0:d2425a595807 680 char *strip_answer(char *s)
cswiger 0:d2425a595807 681 {
cswiger 0:d2425a595807 682 char *ss;
cswiger 0:d2425a595807 683 for (ss=s; *s; s++)
cswiger 0:d2425a595807 684 {
cswiger 0:d2425a595807 685 if ( ((*s)!=' ') && ((*s)!='\t') && ((*s)!='\n') && ((*s)!='\r') )
cswiger 0:d2425a595807 686 (*ss++)=(*s);
cswiger 0:d2425a595807 687 }
cswiger 0:d2425a595807 688 (*ss)=0;
cswiger 0:d2425a595807 689
cswiger 0:d2425a595807 690 return s;
cswiger 0:d2425a595807 691 }
cswiger 0:d2425a595807 692