diff options
author | Stanley Huang <stanleyhuangyc@gmail.com> | 2014-11-10 21:07:33 +1100 |
---|---|---|
committer | Stanley Huang <stanleyhuangyc@gmail.com> | 2014-11-10 21:07:33 +1100 |
commit | 46428f1feedaf184adf2f4714041f7d340195d1f (patch) | |
tree | 19d1ea7d0eb0ec5ba347e25462f14f4b23f4a1b1 | |
parent | 60173a1bc7138965769b495067d774436e6b97cf (diff) | |
download | 2021-arduino-obd-46428f1feedaf184adf2f4714041f7d340195d1f.tar.gz 2021-arduino-obd-46428f1feedaf184adf2f4714041f7d340195d1f.tar.bz2 2021-arduino-obd-46428f1feedaf184adf2f4714041f7d340195d1f.zip |
Automatic detecting UART and I2C OBD adapter
-rw-r--r-- | megalogger/config.h | 6 | ||||
-rw-r--r-- | megalogger/megalogger.ino | 1121 |
2 files changed, 575 insertions, 552 deletions
diff --git a/megalogger/config.h b/megalogger/config.h index 62c9c96..e4345fb 100644 --- a/megalogger/config.h +++ b/megalogger/config.h @@ -2,11 +2,8 @@ #define CONFIG_H_INCLUDED /************************************** -* Choose model of OBD-II Adapter +* OBD-II Adapter options **************************************/ -// OBD_MODEL_I2C for I2C version -// OBD_MODEL_UART for UART version -#define OBD_MODEL OBD_MODEL_I2C #define OBD_PROTOCOL PROTO_AUTO /************************************** @@ -48,7 +45,6 @@ // 38400bps for G6010 5Hz GPS receiver // 115200bps for G7020 10Hz GPS receiver #define GPS_BAUDRATE 38400 /* bps */ -//#define GPS_OPEN_BAUDRATE 4800 /* bps */ /************************************** * Accelerometer & Gyro diff --git a/megalogger/megalogger.ino b/megalogger/megalogger.ino index b536e62..34d7840 100644 --- a/megalogger/megalogger.ino +++ b/megalogger/megalogger.ino @@ -7,9 +7,7 @@ *************************************************************************/ #include <Arduino.h> -#if OBD_MODEL == OBD_MODEL_I2C #include <Wire.h> -#endif #include <OBD.h> #include <SPI.h> #include <SD.h> @@ -46,6 +44,8 @@ TinyGPS gps; #endif +void doIdleTasks(); + static uint8_t lastFileSize = 0; static uint32_t lastGPSDataTime = 0; static uint32_t lastACCDataTime = 0; @@ -63,611 +63,528 @@ static byte pidTier3[] = {PID_COOLANT_TEMP, PID_INTAKE_TEMP, PID_AMBIENT_TEMP, P #define TIER_NUM2 sizeof(pidTier2) #define TIER_NUM3 sizeof(pidTier3) -#if OBD_MODEL == OBD_MODEL_I2C -class COBDLogger : public COBDI2C, public CDataLogger -#else -class COBDLogger : public COBD, public CDataLogger -#endif +byte state = 0; +COBD* obd = 0; +CDataLogger logger; + +class CMyOBD : public COBD { -public: - COBDLogger():state(0) {} - void setup() + void dataIdleLoop() { - lastGPSDataTime = 0; - - showStates(); - -#if USE_MPU6050 - if (MPU6050_init() == 0) state |= STATE_ACC_READY; - showStates(); -#endif + doIdleTasks(); + } +}; -#if USE_GPS - unsigned long t = millis(); - do { - if (GPSUART.available() && GPSUART.read() == '\r') { - state |= STATE_GPS_CONNECTED; - break; - } - } while (millis() - t <= 2000); -#endif +class CMyOBDI2C : public COBDI2C +{ + void dataIdleLoop() + { + doIdleTasks(); + } +}; - do { - showStates(); - } while (!init(OBD_PROTOCOL)); +void setColorByValue(int value, int threshold1, int threshold2, int threshold3) +{ + if (value < 0) value = -value; + if (value < threshold1) { + lcd.setColor(RGB16_WHITE); + } else if (value < threshold2) { + byte n = (uint32_t)(threshold2 - value) * 255 / (threshold2 - threshold1); + lcd.setColor(255, 255, n); + } else if (value < threshold3) { + byte n = (uint32_t)(threshold3 - value) * 255 / (threshold3 - threshold2); + lcd.setColor(255, n, 0); + } else { + lcd.setColor(255, 0, 0); + } +} - state |= STATE_OBD_READY; +void showSensorData(byte pid, int value) +{ + char buf[8]; + switch (pid) { + case PID_RPM: + lcd.setFontSize(FONT_SIZE_XLARGE); + lcd.setCursor(34, 6); + if (value >= 10000) break; + setColorByValue(value, 2500, 3500, 5000); + lcd.printInt(value, 4); + break; + case PID_SPEED: + lcd.setFontSize(FONT_SIZE_XLARGE); + lcd.setCursor(50, 2); + if (value > 350) break; + setColorByValue(value, 50, 80, 160); + lcd.printInt((unsigned int)value % 1000, 3); + break; + case PID_THROTTLE: + lcd.setFontSize(FONT_SIZE_SMALL); + lcd.setCursor(38, 10); + if (value >= 100) value = 99; + setColorByValue(value, 50, 75, 90); + lcd.printInt(value, 2); + break; + case PID_ENGINE_LOAD: + lcd.setFontSize(FONT_SIZE_SMALL); + lcd.setCursor(108, 10); + if (value >= 100) value = 99; + setColorByValue(value, 50, 75, 90); + lcd.printInt(value, 2); + break; + case PID_ENGINE_FUEL_RATE: + if (value < 1000) { + lcd.setFontSize(FONT_SIZE_SMALL); + lcd.setCursor(38, 12); + lcd.printInt(value); + } + break; + } + lcd.setColor(RGB16_WHITE); +} - showStates(); +void initScreen() +{ + lcd.clear(); + lcd.draw4bpp(frame0[0], 78, 58); + lcd.setXY(164, 0); + lcd.draw4bpp(frame0[0], 78, 58); + lcd.setXY(0, 124); + lcd.draw4bpp(frame0[0], 78, 58); + lcd.setXY(164, 124); + lcd.draw4bpp(frame0[0], 78, 58); + + lcd.setColor(RGB16_CYAN); + lcd.setFontSize(FONT_SIZE_SMALL); + lcd.setCursor(110, 4); + lcd.print("km/h"); + lcd.setCursor(110, 7); + lcd.print("rpm"); + lcd.setCursor(8, 10); + lcd.print("THR: %"); + lcd.setCursor(78, 10); + lcd.print("LOAD: %"); + lcd.setCursor(8, 12); + lcd.print("FUEL: L/h"); + lcd.setCursor(78, 12); + lcd.print("BATT: V"); + + //lcd.setFont(FONT_SIZE_MEDIUM); + lcd.setColor(RGB16_CYAN); + lcd.setCursor(185, 2); + lcd.print("ELAPSED:"); + lcd.setCursor(185, 5); + lcd.print("DISTANCE:"); + lcd.setCursor(185, 6); + lcd.print("(km)"); + lcd.setCursor(185, 8); + lcd.print("AVG SPEED:"); + lcd.setCursor(185, 9); + lcd.print("(km/h)"); + lcd.setCursor(185, 11); + lcd.print("OBD TIME:"); + lcd.setCursor(185, 12); + lcd.print("(ms)"); + + lcd.setCursor(20, 18); + lcd.print("LAT:"); + lcd.setCursor(20, 21); + lcd.print("LON:"); + lcd.setCursor(20, 24); + lcd.print("ALT:"); + lcd.setCursor(20, 27); + lcd.print("SAT:"); + + lcd.setFontSize(FONT_SIZE_SMALL); + lcd.setCursor(204, 18); + lcd.print("ACCELEROMETER"); + lcd.setCursor(214, 22); + lcd.print("GYROSCOPE"); + lcd.setCursor(185, 27); + lcd.print("LOG SIZE:"); + lcd.setCursor(185, 20); + lcd.setColor(RGB16_WHITE); + lcd.print("X: Y: Z:"); + lcd.setCursor(185, 24); + lcd.print("X: Y: Z:"); + + //lcd.setColor(0xFFFF); + /* + lcd.setCursor(32, 4); + lcd.print("%"); + lcd.setCursor(68, 5); + lcd.print("Intake Air"); + lcd.setCursor(112, 4); + lcd.print("C"); + */ + + state |= STATE_GUI_ON; +} - //lcd.setFont(FONT_SIZE_MEDIUM); - //lcd.setCursor(0, 14); - //lcd.print("VIN: XXXXXXXX"); +bool connectOBD() +{ + lcd.setCursor(60, 8); + lcd.print("UART"); + obd = new CMyOBD; + obd->begin(); + if (obd->init(OBD_PROTOCOL)) + return true; + obd->end(); + delete obd; + + lcd.setCursor(60, 8); + lcd.print("I2C "); + obd = (COBD*)new CMyOBDI2C; + obd->begin(); + if (obd->init(OBD_PROTOCOL)) + return true; + obd->end(); + delete obd; - // open file for logging - if (!(state & STATE_SD_READY)) { - if (checkSD()) { - state |= STATE_SD_READY; - showStates(); - } - } + obd = 0; + return false; +} +bool checkSD() +{ #if ENABLE_DATA_LOG - uint16_t index = openFile(); - lcd.setCursor(0, 16); - lcd.print("File ID:"); - lcd.printInt(index); -#endif + Sd2Card card; + SdVolume volume; + state &= ~STATE_SD_READY; + pinMode(SS, OUTPUT); + lcd.setCursor(0, 4); - showECUCap(); - delay(1000); - - initScreen(); - - startTime = millis(); - lastRefreshTime = millis(); - } - void loop() - { - static byte index = 0; - static byte index2 = 0; - static byte index3 = 0; - uint32_t t = millis(); - - logOBDData(pidTier1[index++]); - t = millis() - t; - - if (index == TIER_NUM1) { - index = 0; - if (index2 == TIER_NUM2) { - index2 = 0; - if (isValidPID(pidTier3[index3])) { - logOBDData(pidTier3[index3]); - } - index3 = (index3 + 1) % TIER_NUM3; - if (index3 == 0) { - int v = getVoltage(); - lcd.setFontSize(FONT_SIZE_SMALL); - lcd.setCursor(108, 12); - lcd.printInt(v / 10); - lcd.write('.'); - lcd.printInt(v % 10); - logData(PID_VOLTAGE, v); - } - } else { - if (isValidPID(pidTier2[index2])) { - logOBDData(pidTier2[index2]); - } - index2++; - } + lcd.setFontSize(FONT_SIZE_MEDIUM); + if (card.init(SPI_FULL_SPEED, SD_CS_PIN)) { + const char* type; + switch(card.type()) { + case SD_CARD_TYPE_SD1: + type = "SD1"; + break; + case SD_CARD_TYPE_SD2: + type = "SD2"; + break; + case SD_CARD_TYPE_SDHC: + type = "SDHC"; + break; + default: + type = "SDx"; } - if (dataTime - lastRefreshTime >= 1000) { - char buf[12]; - unsigned int sec = (dataTime - startTime) / 1000; - sprintf(buf, "%02u:%02u", sec / 60, sec % 60); - lcd.setFontSize(FONT_SIZE_MEDIUM); - lcd.setCursor(250, 2); - lcd.print(buf); - lcd.setCursor(250, 11); - if (t < 10000) { - lcd.printInt((uint16_t)t); - } - lastRefreshTime = dataTime; + lcd.print(type); + lcd.write(' '); + if (!volume.init(card)) { + lcd.print("No FAT!"); + return false; } - if (errors >= 3) { - reconnect(); - } + uint32_t volumesize = volume.blocksPerCluster(); + volumesize >>= 1; // 512 bytes per block + volumesize *= volume.clusterCount(); + volumesize >>= 10; -#if USE_GPS - if (millis() - lastGPSDataTime > GPS_DATA_TIMEOUT || gps.satellites() < 3) { - // GPS not ready - state &= ~STATE_GPS_READY; - } else { - // GPS ready - state |= STATE_GPS_READY; - } -#endif + lcd.print((int)volumesize); + lcd.print("MB"); + } else { + lcd.print("No SD Card"); + return false; } - bool checkSD() - { -#if ENABLE_DATA_LOG - Sd2Card card; - SdVolume volume; - state &= ~STATE_SD_READY; - pinMode(SS, OUTPUT); - lcd.setCursor(0, 4); - - lcd.setFontSize(FONT_SIZE_MEDIUM); - if (card.init(SPI_FULL_SPEED, SD_CS_PIN)) { - const char* type; - char buf[20]; - - switch(card.type()) { - case SD_CARD_TYPE_SD1: - type = "SD1"; - break; - case SD_CARD_TYPE_SD2: - type = "SD2"; - break; - case SD_CARD_TYPE_SDHC: - type = "SDHC"; - break; - default: - type = "SDx"; - } - - lcd.print(type); - lcd.write(' '); - if (!volume.init(card)) { - lcd.print("No FAT!"); - return false; - } - - uint32_t volumesize = volume.blocksPerCluster(); - volumesize >>= 1; // 512 bytes per block - volumesize *= volume.clusterCount(); - volumesize >>= 10; - - sprintf(buf, "%dMB", (int)volumesize); - lcd.print(buf); - } else { - lcd.print("No SD Card"); - return false; - } - lcd.setCursor(0, 6); - if (!SD.begin(SD_CS_PIN)) { - lcd.print("Bad SD"); - return false; - } - - state |= STATE_SD_READY; - return true; -#else + lcd.setCursor(0, 6); + if (!SD.begin(SD_CS_PIN)) { + lcd.print("Bad SD"); return false; -#endif } -private: - void dataIdleLoop() - { - // callback while waiting OBD data - if (state & STATE_GUI_ON) { - if (state & STATE_ACC_READY) { - processAccelerometer(); - } -#if USE_GPS - uint32_t t = millis(); - while (GPSUART.available() && millis() - t < MAX_GPS_PROCESS_TIME) { - processGPS(); - } + + state |= STATE_SD_READY; + return true; +#else + return false; #endif +} - if (getState() != OBD_CONNECTED) { - // display while initializing - char buf[10]; - unsigned int t = (millis() - startTime) / 1000; - sprintf(buf, "%02u:%02u", t / 60, t % 60); - lcd.setFontSize(FONT_SIZE_SMALL); - lcd.setCursor(0, 28); - lcd.print(buf); - } - return; - } - } #if USE_GPS - void processGPS() - { - // process GPS data - char c = GPSUART.read(); - if (!gps.encode(c)) - return; +void processGPS() +{ + // process GPS data + char c = GPSUART.read(); + if (!gps.encode(c)) + return; - // parsed GPS data is ready - uint32_t time; - uint32_t date; + // parsed GPS data is ready + uint32_t time; + uint32_t date; - dataTime = millis(); + logger.dataTime = millis(); - gps.get_datetime(&date, &time, 0); - logData(PID_GPS_TIME, (int32_t)time); + gps.get_datetime(&date, &time, 0); + logger.logData(PID_GPS_TIME, (int32_t)time); - int kph = gps.speed() * 1852 / 100000; - logData(PID_GPS_SPEED, kph); + int kph = gps.speed() * 1852 / 100000; + logger.logData(PID_GPS_SPEED, kph); - // no need to log GPS data when vehicle has not been moving - // that's when previous speed is zero and current speed is also zero - byte sat = gps.satellites(); - if (sat >= 3 && sat < 100) { - int32_t lat, lon; - gps.get_position(&lat, &lon, 0); - logData(PID_GPS_LATITUDE, lat); - logData(PID_GPS_LONGITUDE, lon); - logData(PID_GPS_ALTITUDE, (int)(gps.altitude() / 100)); + // no need to log GPS data when vehicle has not been moving + // that's when previous speed is zero and current speed is also zero + byte sat = gps.satellites(); + if (sat >= 3 && sat < 100) { + int32_t lat, lon; + gps.get_position(&lat, &lon, 0); + logger.logData(PID_GPS_LATITUDE, lat); + logger.logData(PID_GPS_LONGITUDE, lon); + logger.logData(PID_GPS_ALTITUDE, (int)(gps.altitude() / 100)); - lcd.setFontSize(FONT_SIZE_MEDIUM); - char buf[16]; - sprintf(buf, "%d.%ld", (int)(lat / 100000), abs(lat) % 100000); - lcd.setCursor(50, 18); - lcd.print(buf); - sprintf(buf, "%d.%ld", (int)(lon / 100000), abs(lon) % 100000); - lcd.setCursor(50, 21); + lcd.setFontSize(FONT_SIZE_MEDIUM); + char buf[16]; + sprintf(buf, "%d.%ld", (int)(lat / 100000), abs(lat) % 100000); + lcd.setCursor(50, 18); + lcd.print(buf); + sprintf(buf, "%d.%ld", (int)(lon / 100000), abs(lon) % 100000); + lcd.setCursor(50, 21); + lcd.print(buf); + int32_t alt = gps.altitude(); + if (alt < 1000000) { + sprintf(buf, "%dm ", (int)(alt / 100)); + lcd.setCursor(50, 24); lcd.print(buf); - int32_t alt = gps.altitude(); - if (alt < 1000000) { - sprintf(buf, "%dm ", (int)(alt / 100)); - lcd.setCursor(50, 24); - lcd.print(buf); - } - lcd.setCursor(50, 27); - lcd.printInt(gps.satellites()); - } - lastGPSDataTime = dataTime; + lcd.setCursor(50, 27); + lcd.printInt(gps.satellites()); } + lastGPSDataTime = logger.dataTime; +} #endif - void processAccelerometer() - { -#if USE_MPU6050 - dataTime = millis(); - - if (dataTime - lastACCDataTime < ACC_DATA_INTERVAL) { - return; - } - - char buf[8]; - accel_t_gyro_union data; - MPU6050_readout(&data); - - lcd.setFontSize(FONT_SIZE_SMALL); - data.value.x_accel /= ACC_DATA_RATIO; - data.value.y_accel /= ACC_DATA_RATIO; - data.value.z_accel /= ACC_DATA_RATIO; - data.value.x_gyro /= GYRO_DATA_RATIO; - data.value.y_gyro /= GYRO_DATA_RATIO; - data.value.z_gyro /= GYRO_DATA_RATIO; - - sprintf(buf, "%3d", data.value.x_accel); - setColorByValue(data.value.x_accel, 50, 100, 200); - lcd.setCursor(197, 20); - lcd.print(buf); - sprintf(buf, "%3d", data.value.y_accel); - setColorByValue(data.value.y_accel, 50, 100, 200); - lcd.setCursor(239, 20); - lcd.print(buf); - sprintf(buf, "%3d", data.value.z_accel); - setColorByValue(data.value.z_accel, 50, 100, 200); - lcd.setCursor(281, 20); - lcd.print(buf); +void processAccelerometer() +{ +#if USE_MPU6050 + logger.dataTime = millis(); - lcd.setColor(RGB16_WHITE); - sprintf(buf, "%3d ", data.value.x_gyro); - lcd.setCursor(197, 24); - lcd.print(buf); - sprintf(buf, "%3d ", data.value.y_gyro); - lcd.setCursor(239, 24); - lcd.print(buf); - sprintf(buf, "%3d ", data.value.z_gyro); - lcd.setCursor(281, 24); - lcd.print(buf); + if (logger.dataTime - lastACCDataTime < ACC_DATA_INTERVAL) { + return; + } - // log x/y/z of accelerometer - logData(PID_ACC, data.value.x_accel, data.value.y_accel, data.value.z_accel); - // log x/y/z of gyro meter - logData(PID_GYRO, data.value.x_gyro, data.value.y_gyro, data.value.z_gyro); + char buf[8]; + accel_t_gyro_union data; + MPU6050_readout(&data); + + lcd.setFontSize(FONT_SIZE_SMALL); + + data.value.x_accel /= ACC_DATA_RATIO; + data.value.y_accel /= ACC_DATA_RATIO; + data.value.z_accel /= ACC_DATA_RATIO; + data.value.x_gyro /= GYRO_DATA_RATIO; + data.value.y_gyro /= GYRO_DATA_RATIO; + data.value.z_gyro /= GYRO_DATA_RATIO; + + sprintf(buf, "%3d", data.value.x_accel); + setColorByValue(data.value.x_accel, 50, 100, 200); + lcd.setCursor(197, 20); + lcd.print(buf); + sprintf(buf, "%3d", data.value.y_accel); + setColorByValue(data.value.y_accel, 50, 100, 200); + lcd.setCursor(239, 20); + lcd.print(buf); + sprintf(buf, "%3d", data.value.z_accel); + setColorByValue(data.value.z_accel, 50, 100, 200); + lcd.setCursor(281, 20); + lcd.print(buf); - lastACCDataTime = dataTime; + lcd.setColor(RGB16_WHITE); + sprintf(buf, "%3d ", data.value.x_gyro); + lcd.setCursor(197, 24); + lcd.print(buf); + sprintf(buf, "%3d ", data.value.y_gyro); + lcd.setCursor(239, 24); + lcd.print(buf); + sprintf(buf, "%3d ", data.value.z_gyro); + lcd.setCursor(281, 24); + lcd.print(buf); + + // log x/y/z of accelerometer + logger.logData(PID_ACC, data.value.x_accel, data.value.y_accel, data.value.z_accel); + // log x/y/z of gyro meter + logger.logData(PID_GYRO, data.value.x_gyro, data.value.y_gyro, data.value.z_gyro); + + lastACCDataTime = logger.dataTime; #endif +} + +void logOBDData(byte pid) +{ + char buffer[OBD_RECV_BUF_SIZE]; + uint32_t start = millis(); + int value; + + // send query for OBD-II PID + obd->sendQuery(pid); + pid = 0; + // read responded PID and data + if (!obd->getResult(pid, value)) { + return; } - void logOBDData(byte pid) - { - char buffer[OBD_RECV_BUF_SIZE]; - uint32_t start = millis(); - // read OBD-II data - int value; - sendQuery(pid); - pid = 0; - if (!getResult(pid, value)) { - return; - } + logger.dataTime = millis(); + // display data + showSensorData(pid, value); - dataTime = millis(); - // display data - showSensorData(pid, value); - - // log data to SD card - logData(0x100 | pid, value); - - if (pid == PID_SPEED) { - if (lastSpeedTime) { - // estimate distance travelled since last speed update - distance += (uint32_t)(value + lastSpeed) * (dataTime - lastSpeedTime) / 2 / 3600; - // display speed - lcd.setFontSize(FONT_SIZE_MEDIUM); - lcd.setCursor(250, 5); - lcd.printInt(distance / 1000); - lcd.write('.'); - lcd.printInt(((uint16_t)distance % 1000) / 100); - // calculate and display average speed - int avgSpeed = (unsigned long)distance * 1000 / (millis() - startTime) * 36 / 10; - lcd.setCursor(250, 8); - lcd.printInt(avgSpeed); - } - lastSpeed = value; - lastSpeedTime = dataTime; + // log data to SD card + logger.logData(0x100 | pid, value); + + if (pid == PID_SPEED) { + if (lastSpeedTime) { + // estimate distance travelled since last speed update + distance += (uint32_t)(value + lastSpeed) * (logger.dataTime - lastSpeedTime) / 2 / 3600; + // display speed + lcd.setFontSize(FONT_SIZE_MEDIUM); + lcd.setCursor(250, 5); + lcd.printInt(distance / 1000); + lcd.write('.'); + lcd.printInt(((uint16_t)distance % 1000) / 100); + // calculate and display average speed + int avgSpeed = (unsigned long)distance * 1000 / (millis() - startTime) * 36 / 10; + lcd.setCursor(250, 8); + lcd.printInt(avgSpeed); } + lastSpeed = value; + lastSpeedTime = logger.dataTime; + } #if ENABLE_DATA_LOG - // flush SD data every 1KB - if ((dataSize >> 10) != lastFileSize) { - flushFile(); - // display logged data size - lcd.setFontSize(FONT_SIZE_SMALL); - lcd.setCursor(242, 27); - lcd.print((unsigned int)(dataSize >> 10)); - lcd.print("KB"); - lastFileSize = dataSize >> 10; - } + // flush SD data every 1KB + if ((logger.dataSize >> 10) != lastFileSize) { + logger.flushFile(); + // display logged data size + lcd.setFontSize(FONT_SIZE_SMALL); + lcd.setCursor(242, 27); + lcd.print((unsigned int)(logger.dataSize >> 10)); + lcd.print("KB"); + lastFileSize = logger.dataSize >> 10; + } #endif - // if OBD response is very fast, go on processing other data for a while + // if OBD response is very fast, go on processing other data for a while #ifdef OBD_MIN_INTERVAL - while (millis() - start < OBD_MIN_INTERVAL) { - dataIdleLoop(); - } -#endif + while (millis() - start < OBD_MIN_INTERVAL) { + doIdleTasks(); } - void showECUCap() - { - byte pidlist[] = {PID_RPM, PID_SPEED, PID_THROTTLE, PID_ENGINE_LOAD, PID_MAF_FLOW, PID_INTAKE_MAP, PID_FUEL_LEVEL, PID_FUEL_PRESSURE, PID_COOLANT_TEMP, PID_INTAKE_TEMP, PID_AMBIENT_TEMP, PID_TIMING_ADVANCE, PID_BAROMETRIC}; - const char* namelist[] = {"ENGINE RPM", "SPEED", "THROTTLE", "ENGINE LOAD", "MAF", "MAP", "FUEL LEVEL", "FUEL PRESSURE", "COOLANT TEMP", "INTAKE TEMP","AMBIENT TEMP", "IGNITION TIMING", "BAROMETER"}; +#endif +} - lcd.setFontSize(FONT_SIZE_MEDIUM); - for (byte i = 0; i < sizeof(pidlist) / sizeof(pidlist[0]); i++) { - lcd.setCursor(160, i * 2 + 4); - lcd.print(namelist[i]); - lcd.write(' '); - bool valid = isValidPID(pidlist[i]); - lcd.setColor(valid ? RGB16_GREEN : RGB16_RED); - lcd.draw(valid ? tick : cross, 16, 16); - lcd.setColor(RGB16_WHITE); +void showECUCap() +{ + byte pidlist[] = {PID_ENGINE_LOAD, PID_COOLANT_TEMP, PID_FUEL_PRESSURE, PID_INTAKE_MAP, PID_RPM, PID_SPEED, PID_TIMING_ADVANCE, PID_INTAKE_TEMP, PID_MAF_FLOW, PID_THROTTLE, PID_AUX_INPUT, + PID_EGR_ERROR, PID_COMMANDED_EVAPORATIVE_PURGE, PID_FUEL_LEVEL, PID_CONTROL_MODULE_VOLTAGE, PID_ABSOLUTE_ENGINE_LOAD, PID_AMBIENT_TEMP, PID_COMMANDED_THROTTLE_ACTUATOR, PID_ETHANOL_FUEL, + PID_FUEL_RAIL_PRESSURE, PID_HYBRID_BATTERY_PERCENTAGE, PID_ENGINE_OIL_TEMP, PID_FUEL_INJECTION_TIMING, PID_ENGINE_FUEL_RATE, PID_ENGINE_TORQUE_DEMANDED, PID_ENGINE_TORQUE_PERCENTAGE}; + + lcd.setFontSize(FONT_SIZE_MEDIUM); + for (byte i = 0; i < sizeof(pidlist) / sizeof(pidlist[0]); i += 2) { + lcd.setCursor(184, i + 4); + for (byte j = 0; j < 2; j++) { + lcd.print(" "); + lcd.print((int)pidlist[i + j] | 0x100, HEX); + bool valid = obd->isValidPID(pidlist[i + j]); + if (valid) { + lcd.setColor(RGB16_GREEN); + lcd.draw(tick, 16, 16); + lcd.setColor(RGB16_WHITE); + } else { + lcd.print(" "); + } } } - void reconnect() - { +} + +void reconnect() +{ + // fade out backlight + for (int n = 254; n >= 0; n--) { + lcd.setBackLight(n); + delay(20); + } #if ENABLE_DATA_LOG - closeFile(); + logger.closeFile(); #endif - uninit(); - lcd.clear(); - lcd.setFontSize(FONT_SIZE_MEDIUM); - lcd.print("Reconnecting..."); - state &= ~(STATE_OBD_READY | STATE_GUI_ON); - //digitalWrite(SD_CS_PIN, LOW); - for (uint16_t i = 0; ; i++) { - if (i == 3) { - // fade out backlight - for (int n = 254; n >= 0; n--) { - lcd.setBackLight(n); - delay(20); - } - lcd.clear(); - } - if ((getState() != OBD_CONNECTED || errors > 1) && !init()) - continue; + lcd.clear(); + state &= ~(STATE_OBD_READY | STATE_GUI_ON); + //digitalWrite(SD_CS_PIN, LOW); + for (;;) { + if (!obd->init()) + continue; - int value; - if (read(PID_RPM, value) && value > 0) - break; + int value; + if (obd->read(PID_RPM, value) && value > 0) + break; - Narcoleptic.delay(2000); - } - // re-initialize - state |= STATE_OBD_READY; - startTime = millis(); - lastSpeedTime = 0; - distance = 0; + Narcoleptic.delay(2000); + } + // re-initialize + state |= STATE_OBD_READY; + startTime = millis(); + lastSpeedTime = 0; + distance = 0; #if ENABLE_DATA_LOG - openFile(); + logger.openFile(); #endif - initScreen(); - // fade in backlight - for (int n = 1; n <= 255; n++) { - lcd.setBackLight(n); - delay(10); - } + initScreen(); + // fade in backlight + for (int n = 1; n <= 255; n++) { + lcd.setBackLight(n); + delay(10); } - byte state; +} - // screen layout related stuff - void showStates() - { - lcd.setFontSize(FONT_SIZE_MEDIUM); +// screen layout related stuff +void showStates() +{ + lcd.setFontSize(FONT_SIZE_MEDIUM); - lcd.setCursor(0, 8); - lcd.print("OBD "); - lcd.setColor((state & STATE_OBD_READY) ? RGB16_GREEN : RGB16_RED); - lcd.draw((state & STATE_OBD_READY) ? tick : cross, 16, 16); - lcd.setColor(RGB16_WHITE); - - lcd.setCursor(0, 10); - lcd.print("ACC "); - lcd.setColor((state & STATE_ACC_READY) ? RGB16_GREEN : RGB16_RED); - lcd.draw((state & STATE_ACC_READY) ? tick : cross, 16, 16); - lcd.setColor(RGB16_WHITE); - - lcd.setCursor(0, 12); - lcd.print("GPS "); - if (state & STATE_GPS_READY) { - lcd.setColor(RGB16_GREEN); - lcd.draw(tick, 16, 16); - } else if (state & STATE_GPS_CONNECTED) - lcd.print("--"); - else { - lcd.setColor(RGB16_RED); - lcd.draw(cross, 16, 16); - } - lcd.setColor(RGB16_WHITE); + lcd.setCursor(0, 8); + lcd.print("OBD "); + lcd.setColor((state & STATE_OBD_READY) ? RGB16_GREEN : RGB16_RED); + lcd.draw((state & STATE_OBD_READY) ? tick : cross, 16, 16); + lcd.setColor(RGB16_WHITE); + + lcd.setCursor(0, 10); + lcd.print("ACC "); + lcd.setColor((state & STATE_ACC_READY) ? RGB16_GREEN : RGB16_RED); + lcd.draw((state & STATE_ACC_READY) ? tick : cross, 16, 16); + lcd.setColor(RGB16_WHITE); + + lcd.setCursor(0, 12); + lcd.print("GPS "); + if (state & STATE_GPS_CONNECTED) { + lcd.setColor(RGB16_GREEN); + lcd.draw(tick, 16, 16); + } else { + lcd.setColor(RGB16_RED); + lcd.draw(cross, 16, 16); } - void setColorByValue(int value, int threshold1, int threshold2, int threshold3) - { - if (value < 0) value = -value; - if (value < threshold1) { - lcd.setColor(RGB16_WHITE); - } else if (value < threshold2) { - byte n = (uint32_t)(threshold2 - value) * 255 / (threshold2 - threshold1); - lcd.setColor(255, 255, n); - } else if (value < threshold3) { - byte n = (uint32_t)(threshold3 - value) * 255 / (threshold3 - threshold2); - lcd.setColor(255, n, 0); - } else { - lcd.setColor(255, 0, 0); - } + lcd.setColor(RGB16_WHITE); +} + +void doIdleTasks() +{ + if (!(state & STATE_GUI_ON)) + return; + + if (state & STATE_ACC_READY) { + processAccelerometer(); } - void showSensorData(byte pid, int value) - { - char buf[8]; - switch (pid) { - case PID_RPM: - lcd.setFontSize(FONT_SIZE_XLARGE); - lcd.setCursor(34, 6); - if (value >= 10000) break; - setColorByValue(value, 2500, 3500, 5000); - lcd.printInt(value, 4); - break; - case PID_SPEED: - lcd.setFontSize(FONT_SIZE_XLARGE); - lcd.setCursor(50, 2); - if (value > 350) break; - setColorByValue(value, 50, 80, 160); - lcd.printInt((unsigned int)value % 1000, 3); - break; - case PID_THROTTLE: - lcd.setFontSize(FONT_SIZE_SMALL); - lcd.setCursor(38, 10); - if (value >= 100) value = 99; - setColorByValue(value, 50, 75, 90); - lcd.printInt(value, 2); - break; - case PID_ENGINE_LOAD: - lcd.setFontSize(FONT_SIZE_SMALL); - lcd.setCursor(108, 10); - if (value >= 100) value = 99; - setColorByValue(value, 50, 75, 90); - lcd.printInt(value, 2); - break; - case PID_ENGINE_FUEL_RATE: - if (value < 1000) { - lcd.setFontSize(FONT_SIZE_SMALL); - lcd.setCursor(38, 12); - lcd.printInt(value); - } - break; - } - lcd.setColor(RGB16_WHITE); +#if USE_GPS + uint32_t t = millis(); + while (GPSUART.available() && millis() - t < MAX_GPS_PROCESS_TIME) { + processGPS(); } - void initScreen() - { - lcd.clear(); - lcd.draw4bpp(frame0[0], 78, 58); - lcd.setXY(164, 0); - lcd.draw4bpp(frame0[0], 78, 58); - lcd.setXY(0, 124); - lcd.draw4bpp(frame0[0], 78, 58); - lcd.setXY(164, 124); - lcd.draw4bpp(frame0[0], 78, 58); - - lcd.setColor(RGB16_CYAN); - lcd.setFontSize(FONT_SIZE_SMALL); - lcd.setCursor(110, 4); - lcd.print("km/h"); - lcd.setCursor(110, 7); - lcd.print("rpm"); - lcd.setCursor(8, 10); - lcd.print("THR: %"); - lcd.setCursor(78, 10); - lcd.print("LOAD: %"); - lcd.setCursor(8, 12); - lcd.print("FUEL: L/h"); - lcd.setCursor(78, 12); - lcd.print("BATT: V"); - - //lcd.setFont(FONT_SIZE_MEDIUM); - lcd.setColor(RGB16_CYAN); - lcd.setCursor(185, 2); - lcd.print("ELAPSED:"); - lcd.setCursor(185, 5); - lcd.print("DISTANCE:"); - lcd.setCursor(185, 6); - lcd.print("(km)"); - lcd.setCursor(185, 8); - lcd.print("AVG SPEED:"); - lcd.setCursor(185, 9); - lcd.print("(km/h)"); - lcd.setCursor(185, 11); - lcd.print("OBD TIME:"); - lcd.setCursor(185, 12); - lcd.print("(ms)"); - - lcd.setCursor(20, 18); - lcd.print("LAT:"); - lcd.setCursor(20, 21); - lcd.print("LON:"); - lcd.setCursor(20, 24); - lcd.print("ALT:"); - lcd.setCursor(20, 27); - lcd.print("SAT:"); +#endif + if (obd->getState() != OBD_CONNECTED) { + // display while initializing + char buf[10]; + unsigned int t = (millis() - startTime) / 1000; + sprintf(buf, "%02u:%02u", t / 60, t % 60); lcd.setFontSize(FONT_SIZE_SMALL); - lcd.setCursor(204, 18); - lcd.print("ACCELEROMETER"); - lcd.setCursor(214, 22); - lcd.print("GYROSCOPE"); - lcd.setCursor(185, 27); - lcd.print("LOG SIZE:"); - lcd.setCursor(185, 20); - lcd.setColor(RGB16_WHITE); - lcd.print("X: Y: Z:"); - lcd.setCursor(185, 24); - lcd.print("X: Y: Z:"); - - //lcd.setColor(0xFFFF); - /* - lcd.setCursor(32, 4); - lcd.print("%"); - lcd.setCursor(68, 5); - lcd.print("Intake Air"); - lcd.setCursor(112, 4); - lcd.print("C"); - */ - - state |= STATE_GUI_ON; + lcd.setCursor(0, 28); + lcd.print(buf); } -}; - -static COBDLogger logger; +} void setup() { @@ -677,9 +594,11 @@ void setup() lcd.print("MEGA LOGGER - OBD-II/GPS/G-FORCE"); lcd.setColor(RGB16_WHITE); + Wire.begin(); + for (int n = 0; n <= 255; n++) { lcd.setBackLight(n); - delay(10); + delay(5); } #if USE_GPS @@ -693,16 +612,124 @@ void setup() // switching to 10Hz mode, effective only for MTK3329 //GPSUART.println(PMTK_SET_NMEA_OUTPUT_ALLDATA); //GPSUART.println(PMTK_SET_NMEA_UPDATE_10HZ); + lastGPSDataTime = 0; #endif - logger.begin(); logger.initSender(); - logger.checkSD(); - logger.setup(); + checkSD(); + +#if USE_MPU6050 + if (MPU6050_init() == 0) state |= STATE_ACC_READY; +#endif + showStates(); + +#if USE_GPS + unsigned long t = millis(); + do { + if (GPSUART.available() && GPSUART.read() == '\r') { + state |= STATE_GPS_CONNECTED; + break; + } + } while (millis() - t <= 2000); + showStates(); +#endif + + delay(1000); + + while (!connectOBD()); + state |= STATE_OBD_READY; + + showStates(); + + //lcd.setFont(FONT_SIZE_MEDIUM); + //lcd.setCursor(0, 14); + //lcd.print("VIN: XXXXXXXX"); + + // open file for logging + if (!(state & STATE_SD_READY)) { + if (checkSD()) { + state |= STATE_SD_READY; + showStates(); + } + } + +#if ENABLE_DATA_LOG + uint16_t index = logger.openFile(); + lcd.setCursor(0, 16); + lcd.print("File ID:"); + lcd.println(index); +#endif + + showECUCap(); + delay(2000); + + initScreen(); + + startTime = millis(); + lastRefreshTime = millis(); } void loop() { - logger.loop(); + static byte index = 0; + static byte index2 = 0; + static byte index3 = 0; + uint32_t t = millis(); + + logOBDData(pidTier1[index++]); + t = millis() - t; + + if (index == TIER_NUM1) { + index = 0; + if (index2 == TIER_NUM2) { + index2 = 0; + if (obd->isValidPID(pidTier3[index3])) { + logOBDData(pidTier3[index3]); + } + index3 = (index3 + 1) % TIER_NUM3; + if (index3 == 0) { + int v = obd->getVoltage(); + lcd.setFontSize(FONT_SIZE_SMALL); + lcd.setCursor(108, 12); + lcd.printInt(v / 10); + lcd.write('.'); + lcd.printInt(v % 10); + logger.logData(PID_VOLTAGE, v); + } + } else { + if (obd->isValidPID(pidTier2[index2])) { + logOBDData(pidTier2[index2]); + } + index2++; + } + } + + if (logger.dataTime - lastRefreshTime >= 1000) { + char buf[12]; + unsigned int sec = (logger.dataTime - startTime) / 1000; + sprintf(buf, "%02u:%02u", sec / 60, sec % 60); + lcd.setFontSize(FONT_SIZE_MEDIUM); + lcd.setCursor(250, 2); + lcd.print(buf); + lcd.setCursor(250, 11); + if (t < 10000) { + lcd.printInt((uint16_t)t); + } + lastRefreshTime = logger.dataTime; + } + + if (obd->errors >= 3) { + reconnect(); + } + +#if USE_GPS + if (millis() - lastGPSDataTime > GPS_DATA_TIMEOUT || gps.satellites() < 3) { + // GPS not ready + state &= ~STATE_GPS_READY; + } else { + // GPS ready + state |= STATE_GPS_READY; + } +#endif } |