From 91c65f3d117d942b1b4f8fd4bcc77683c3ef71c8 Mon Sep 17 00:00:00 2001 From: Stanley Huang Date: Thu, 7 Nov 2013 22:29:31 +1100 Subject: update OBD logger, config.h added for storing configurations default in acceleration timing mode --- obdlogger/MicroLCD.cpp | 109 +++--------- obdlogger/MicroLCD.h | 7 + obdlogger/config.h | 47 ++++++ obdlogger/datalogger.h | 31 ++-- obdlogger/images.h | 4 +- obdlogger/obdlogger.ino | 431 +++++++++++++++++++++++++++++++++--------------- 6 files changed, 389 insertions(+), 240 deletions(-) create mode 100644 obdlogger/config.h diff --git a/obdlogger/MicroLCD.cpp b/obdlogger/MicroLCD.cpp index da1cdc2..691b643 100644 --- a/obdlogger/MicroLCD.cpp +++ b/obdlogger/MicroLCD.cpp @@ -406,7 +406,9 @@ void LCD_SSD1306::writeDigit(byte n) } Wire.endTransmission(); m_col += 6; - } else if (m_font == FONT_SIZE_XLARGE) { + } else if (m_font == FONT_SIZE_MEDIUM) { + write(n <= 9 ? ('0' + n) : ' '); + } else if (m_font == FONT_SIZE_LARGE) { if (n <= 9) { byte i; ssd1306_command(0xB0 + m_row);//set page address @@ -416,7 +418,7 @@ void LCD_SSD1306::writeDigit(byte n) Wire.beginTransmission(_i2caddr); Wire.write(0x40); for (i = 0; i < 16; i ++) { - byte d = pgm_read_byte(&digits16x24[n][i * 3]); + byte d = pgm_read_byte(&digits16x16[n][i]); Wire.write(d); if (m_flags & FLAG_PIXEL_DOUBLE_H) Wire.write(d); } @@ -428,21 +430,8 @@ void LCD_SSD1306::writeDigit(byte n) Wire.beginTransmission(_i2caddr); Wire.write(0x40); - for (i = 0; i < 16; i ++) { - byte d = pgm_read_byte(&digits16x24[n][i * 3 + 1]); - Wire.write(d); - if (m_flags & FLAG_PIXEL_DOUBLE_H) Wire.write(d); - } - Wire.endTransmission(); - - ssd1306_command(0xB0 + m_row + 2);//set page address - ssd1306_command(m_col & 0xf);//set lower column address - ssd1306_command(0x10 | (m_col >> 4));//set higher column address - - Wire.beginTransmission(_i2caddr); - Wire.write(0x40); - for (i = 0; i < 16; i ++) { - byte d = pgm_read_byte(&digits16x24[n][i * 3 + 2]); + for (; i < 32; i ++) { + byte d = pgm_read_byte(&digits16x16[n][i]); Wire.write(d); if (m_flags & FLAG_PIXEL_DOUBLE_H) Wire.write(d); } @@ -469,31 +458,19 @@ void LCD_SSD1306::writeDigit(byte n) Wire.write(0); } Wire.endTransmission(); - - ssd1306_command(0xB0 + m_row + 2);//set page address - ssd1306_command(m_col & 0xf);//set lower column address - ssd1306_command(0x10 | (m_col >> 4));//set higher column address - - Wire.beginTransmission(_i2caddr); - Wire.write(0x40); - for (byte i = (m_flags & FLAG_PIXEL_DOUBLE_H) ? 32 : 16; i > 0; i--) { - Wire.write(0); - } - Wire.endTransmission(); } m_col += (m_flags & FLAG_PIXEL_DOUBLE_H) ? 30 : 16; -#ifndef MEMORY_SAVING - } else if (m_font == FONT_SIZE_MEDIUM) { + } else if (m_font == FONT_SIZE_XLARGE) { if (n <= 9) { - n += '0' - 0x21; + byte i; ssd1306_command(0xB0 + m_row);//set page address ssd1306_command(m_col & 0xf);//set lower column address ssd1306_command(0x10 | (m_col >> 4));//set higher column address Wire.beginTransmission(_i2caddr); Wire.write(0x40); - for (byte i = 0; i <= 14; i += 2) { - byte d = pgm_read_byte(&font8x16_terminal[n][i]); + for (i = 0; i < 16; i ++) { + byte d = pgm_read_byte(&digits16x24[n][i * 3]); Wire.write(d); if (m_flags & FLAG_PIXEL_DOUBLE_H) Wire.write(d); } @@ -505,66 +482,38 @@ void LCD_SSD1306::writeDigit(byte n) Wire.beginTransmission(_i2caddr); Wire.write(0x40); - for (byte i = 1; i <= 15; i += 2) { - byte d = pgm_read_byte(&font8x16_terminal[n][i]); + for (i = 0; i < 16; i ++) { + byte d = pgm_read_byte(&digits16x24[n][i * 3 + 1]); Wire.write(d); if (m_flags & FLAG_PIXEL_DOUBLE_H) Wire.write(d); } Wire.endTransmission(); - } else { - ssd1306_command(0xB0 + m_row);//set page address - ssd1306_command(m_col & 0xf);//set lower column address - ssd1306_command(0x10 | (m_col >> 4));//set higher column address - - Wire.beginTransmission(_i2caddr); - Wire.write(0x40); - for (byte i = (m_flags & FLAG_PIXEL_DOUBLE_H) ? 16 : 8; i > 0; i--) { - Wire.write(0); - } - Wire.endTransmission(); - ssd1306_command(0xB0 + m_row + 1);//set page address - ssd1306_command(m_col & 0xf);//set lower column address - ssd1306_command(0x10 | (m_col >> 4));//set higher column address - - Wire.beginTransmission(_i2caddr); - Wire.write(0x40); - for (byte i = (m_flags & FLAG_PIXEL_DOUBLE_H) ? 16 : 8; i > 0; i--) { - Wire.write(0); - } - Wire.endTransmission(); - } - m_col += (m_flags & FLAG_PIXEL_DOUBLE_H) ? 17 : 9; - } else { - if (n <= 9) { - byte i; - ssd1306_command(0xB0 + m_row);//set page address + ssd1306_command(0xB0 + m_row + 2);//set page address ssd1306_command(m_col & 0xf);//set lower column address ssd1306_command(0x10 | (m_col >> 4));//set higher column address Wire.beginTransmission(_i2caddr); Wire.write(0x40); for (i = 0; i < 16; i ++) { - byte d = pgm_read_byte(&digits16x16[n][i]); + byte d = pgm_read_byte(&digits16x24[n][i * 3 + 2]); Wire.write(d); if (m_flags & FLAG_PIXEL_DOUBLE_H) Wire.write(d); } Wire.endTransmission(); - - ssd1306_command(0xB0 + m_row + 1);//set page address + } else { + ssd1306_command(0xB0 + m_row);//set page address ssd1306_command(m_col & 0xf);//set lower column address ssd1306_command(0x10 | (m_col >> 4));//set higher column address Wire.beginTransmission(_i2caddr); Wire.write(0x40); - for (; i < 32; i ++) { - byte d = pgm_read_byte(&digits16x16[n][i]); - Wire.write(d); - if (m_flags & FLAG_PIXEL_DOUBLE_H) Wire.write(d); + for (byte i = (m_flags & FLAG_PIXEL_DOUBLE_H) ? 32 : 16; i > 0; i--) { + Wire.write(0); } Wire.endTransmission(); - } else { - ssd1306_command(0xB0 + m_row);//set page address + + ssd1306_command(0xB0 + m_row + 1);//set page address ssd1306_command(m_col & 0xf);//set lower column address ssd1306_command(0x10 | (m_col >> 4));//set higher column address @@ -575,7 +524,7 @@ void LCD_SSD1306::writeDigit(byte n) } Wire.endTransmission(); - ssd1306_command(0xB0 + m_row + 1);//set page address + ssd1306_command(0xB0 + m_row + 2);//set page address ssd1306_command(m_col & 0xf);//set lower column address ssd1306_command(0x10 | (m_col >> 4));//set higher column address @@ -587,22 +536,6 @@ void LCD_SSD1306::writeDigit(byte n) Wire.endTransmission(); } m_col += (m_flags & FLAG_PIXEL_DOUBLE_H) ? 30 : 16; -#else - } else { - Wire.beginTransmission(_i2caddr); - Wire.write(0x40); - if (n <= 9) { - for (byte i = 0; i < 8; i++) { - Wire.write(pgm_read_byte(&digits8x8[n][i])); - } - } else { - for (byte i = 0; i < 8; i++) { - Wire.write(0); - } - } - Wire.endTransmission(); - m_col += 8; -#endif } TWBR = twbrbackup; } diff --git a/obdlogger/MicroLCD.h b/obdlogger/MicroLCD.h index a22a2ce..1206414 100644 --- a/obdlogger/MicroLCD.h +++ b/obdlogger/MicroLCD.h @@ -21,6 +21,13 @@ typedef enum { #define FLAG_PIXEL_DOUBLE_V 4 #define FLAG_PIXEL_DOUBLE (FLAG_PIXEL_DOUBLE_H | FLAG_PIXEL_DOUBLE_V) +extern const PROGMEM unsigned char font5x8[][5]; +extern const PROGMEM unsigned char digits8x8[][8] ; +extern const PROGMEM unsigned char digits16x16[][32]; +extern const PROGMEM unsigned char digits16x24[][48]; +extern const PROGMEM unsigned char font8x16_doslike[][16]; +extern const PROGMEM unsigned char font8x16_terminal[][16]; + class LCD_Common { public: diff --git a/obdlogger/config.h b/obdlogger/config.h new file mode 100644 index 0000000..e00362c --- /dev/null +++ b/obdlogger/config.h @@ -0,0 +1,47 @@ +#ifndef CONFIG_H_INCLUDED +#define CONFIG_H_INCLUDED + +/************************************** +* Data logging/streaming out +**************************************/ +#define ENABLE_DATA_OUT 0 +#define ENABLE_DATA_LOG 1 +//this defines the format of log file +#define LOG_FORMAT FORMAT_CSV + +/************************************** +* Default working mode +**************************************/ +#define MODE_DEFAULT MODE_TIMER /* MODE_LOGGER */ +#define MODE_SWITCH_PIN 8 + +/************************************** +* Choose SD pin here +**************************************/ +//#define SD_CS_PIN SS // generic +//#define SD_CS_PIN 4 // ethernet shield +#define SD_CS_PIN 7 // microduino +//#define SD_CS_PIN 10 // SD breakout + +/************************************** +* Config GPS here +**************************************/ +#define USE_GPS 0 +#define GPS_BAUDRATE 38400 /* bps */ +//#define GPS_OPEN_BAUDRATE 4800 /* bps */ + +/************************************** +* Choose LCD model here +**************************************/ +LCD_SSD1306 lcd; +//LCD_ZTOLED lcd; + +/************************************** +* Other options +**************************************/ +#define USE_MPU6050 0 +#define OBD_MIN_INTERVAL 50 /* ms */ +#define GPS_DATA_TIMEOUT 2000 /* ms */ +//#define DEBUG Serial + +#endif // CONFIG_H_INCLUDED diff --git a/obdlogger/datalogger.h b/obdlogger/datalogger.h index f8653ca..ffc6c75 100644 --- a/obdlogger/datalogger.h +++ b/obdlogger/datalogger.h @@ -1,12 +1,6 @@ -// configurations -#define ENABLE_DATA_OUT 1 -#define ENABLE_DATA_LOG 1 - #define FORMAT_BIN 0 #define FORMAT_CSV 1 -//this defines the format of log file -#define LOG_FORMAT FORMAT_CSV typedef enum { LOG_TYPE_DEFAULT = 0, LOG_TYPE_0_60, @@ -95,6 +89,7 @@ typedef struct { #define FILE_NAME_FORMAT "/DAT%05d.LOG" +#if USE_SOFTSERIAL #if ENABLE_DATA_OUT #if defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__) SoftwareSerial mySerial(A8, A9); /* for BLE Shield on MEGA*/ @@ -105,12 +100,20 @@ typedef struct { #endif #endif +#define BT_SERIAL mySerial + +#else + +#define BT_SERIAL Serial + +#endif + class CDataLogger { public: void initSender() { #if ENABLE_DATA_OUT - mySerial.begin(9600); + BT_SERIAL.begin(9600); #endif #if ENABLE_DATA_LOG && LOG_FORMAT == FORMAT_CSV m_lastDataTime = 0; @@ -135,21 +138,21 @@ public: info.logType = hdr.logType; info.logFlags = hdr.flags; info.checksum = getChecksum((char*)&info, sizeof(info)); - mySerial.write((uint8_t*)&info, sizeof(info)); + BT_SERIAL.write((uint8_t*)&info, sizeof(info)); } void sendCommand(byte message, void* data = 0, byte bytes = 0) { LOG_DATA_COMMAND msg = {0, PID_MESSAGE, message}; if (data) memcpy(msg.data, data, bytes); msg.checksum = getChecksum((char*)&msg, sizeof(msg)); - mySerial.write((uint8_t*)&msg, sizeof(msg)); + BT_SERIAL.write((uint8_t*)&msg, sizeof(msg)); } bool receiveCommand(LOG_DATA_COMMAND& msg) { - if (!mySerial.available()) + if (!BT_SERIAL.available()) return false; - if (mySerial.readBytes((char*)&msg, sizeof(msg)) != sizeof(msg)) + if (BT_SERIAL.readBytes((char*)&msg, sizeof(msg)) != sizeof(msg)) return false; uint8_t checksum = msg.checksum; @@ -165,7 +168,7 @@ public: LOG_DATA_COMM ld = {dataTime, pid, 1, 0, value}; ld.checksum = getChecksum((char*)&ld, 12); #if ENABLE_DATA_OUT - mySerial.write((uint8_t*)&ld, 12); + BT_SERIAL.write((uint8_t*)&ld, 12); #endif #if ENABLE_DATA_LOG #if LOG_FORMAT == FORMAT_BIN @@ -187,7 +190,7 @@ public: LOG_DATA_COMM ld = {dataTime, pid, 2, 0, {value1, value2}}; ld.checksum = getChecksum((char*)&ld, 16); #if ENABLE_DATA_OUT - mySerial.write((uint8_t*)&ld, 16); + BT_SERIAL.write((uint8_t*)&ld, 16); #endif #if ENABLE_DATA_LOG #if LOG_FORMAT == FORMAT_BIN @@ -211,7 +214,7 @@ public: LOG_DATA_COMM ld = {dataTime, pid, 3, 0, {value1, value2, value3}}; ld.checksum = getChecksum((char*)&ld, 20); #if ENABLE_DATA_OUT - mySerial.write((uint8_t*)&ld, 20); + BT_SERIAL.write((uint8_t*)&ld, 20); #endif #if ENABLE_DATA_LOG #if LOG_FORMAT == FORMAT_BIN diff --git a/obdlogger/images.h b/obdlogger/images.h index 2f92ee1..0a0f0b6 100644 --- a/obdlogger/images.h +++ b/obdlogger/images.h @@ -1,5 +1,5 @@ -static const PROGMEM uint8_t tick[16 *16 / 8] = +const PROGMEM uint8_t tick[16 *16 / 8] = {0x00,0x80,0xC0,0xE0,0xC0,0x80,0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0x78,0x30,0x00,0x00,0x01,0x03,0x07,0x0F,0x1F,0x1F,0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00,0x00}; -static const PROGMEM uint8_t cross[16 *16 / 8] = +const PROGMEM uint8_t cross[16 *16 / 8] = {0x00,0x0C,0x1C,0x3C,0x78,0xF0,0xE0,0xC0,0xE0,0xF0,0x78,0x3C,0x1C,0x0C,0x00,0x00,0x00,0x30,0x38,0x3C,0x1E,0x0F,0x07,0x03,0x07,0x0F,0x1E,0x3C,0x38,0x30,0x00,0x00}; diff --git a/obdlogger/obdlogger.ino b/obdlogger/obdlogger.ino index ca5bf5c..0bbff55 100644 --- a/obdlogger/obdlogger.ino +++ b/obdlogger/obdlogger.ino @@ -8,51 +8,26 @@ #include #include #include +#include #include #include -#include #include "MicroLCD.h" #include "images.h" +#include "config.h" #include "datalogger.h" -/************************************** -* Choose SD pin here -**************************************/ -#define SD_CS_PIN SS // generic -//#define SD_CS_PIN 4 // ethernet shield -//#define SD_CS_PIN 7 // microduino -//#define SD_CS_PIN 10 // SD breakout - -/************************************** -* Config GPS here -**************************************/ -//#define USE_GPS -#define GPS_BAUDRATE 38400 /* bps */ -//#define GPS_OPEN_BAUDRATE 4800 /* bps */ - -/************************************** -* Choose LCD model here -**************************************/ -LCD_SSD1306 lcd; -//LCD_ZTOLED lcd; - -/************************************** -* Other options -**************************************/ -#define USE_MPU6050 0 -#define OBD_MIN_INTERVAL 50 /* ms */ -#define GPS_DATA_TIMEOUT 2000 /* ms */ -//#define DEBUG Serial - // logger states #define STATE_SD_READY 0x1 #define STATE_OBD_READY 0x2 -#define STATE_GPS_CONNECTED 0x4 +#define STATE_GPS_FOUND 0x4 #define STATE_GPS_READY 0x8 #define STATE_ACC_READY 0x10 #define STATE_SLEEPING 0x20 -#ifdef USE_GPS +#define MODE_LOGGER 0 +#define MODE_TIMER 1 + +#if USE_GPS // GPS logging can only be enabled when there is additional hardware serial UART #if defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__) #define GPSUART Serial2 @@ -79,14 +54,31 @@ static uint32_t lastFileSize = 0; //static uint32_t lastDataTime; static uint32_t lastGPSDataTime = 0; static uint16_t lastSpeed = -1; +static uint32_t lastSpeedTime = 0; static uint16_t speed = 0; +static uint16_t speedGPS = 0; static int startDistance = 0; static uint16_t fileIndex = 0; static uint32_t startTime = 0; +static long lastLat = 0; +static long lastLon = 0; +static long curLat = 0; +static long curLon = 0; +static uint16_t distance = 0; + +#define STAGE_IDLE 0 +#define STAGE_WAIT_START 1 +#define STAGE_MEASURING 2 + +static byte mode = MODE_DEFAULT; +static byte stage = STAGE_IDLE; -// cached data to be displayed -static byte lastPID = 0; -static int lastData; +#define SPEED_THRESHOLD_1 60 /* kph */ +#define SPEED_THRESHOLD_2 100 /* kph */ +#define SPEED_THRESHOLD_3 200 /* kph */ +#define DISTANCE_THRESHOLD 400 /* meters */ + +static uint16_t times[4] = {0}; static byte pollPattern[]= { PID_RPM, PID_SPEED, PID_ENGINE_LOAD, PID_RPM, PID_SPEED, PID_THROTTLE, PID_RPM, PID_SPEED, PID_ENGINE_LOAD, PID_RPM, PID_SPEED, PID_THROTTLE, @@ -118,11 +110,14 @@ public: #ifdef GPSUART unsigned long t = millis(); do { - if (GPSUART.available() && GPSUART.read() == '\r') { - state |= STATE_GPS_CONNECTED; - break; + if (GPSUART.available()) { + char c = GPSUART.read(); + if (c == '\r') { + state |= STATE_GPS_FOUND; + break; + } } - } while (millis() - t <= 2000); + } while (millis() - t <= 5000); #endif do { @@ -134,7 +129,7 @@ public: showStates(); uint16_t flags = FLAG_CAR | FLAG_OBD; - if (state & STATE_GPS_CONNECTED) flags |= FLAG_GPS; + if (state & STATE_GPS_FOUND) flags |= FLAG_GPS; if (state & STATE_ACC_READY) flags |= FLAG_ACC; #if ENABLE_DATA_LOG uint16_t index = openFile(LOG_TYPE_DEFAULT, flags); @@ -149,12 +144,12 @@ public: } else { lcd.print("NO LOG"); } - delay(1000); + delay(100); #endif #ifndef MEMORY_SAVING - showECUCap(); - delay(3000); + //showECUCap(); + //delay(1000); #endif readSensor(PID_DISTANCE, startDistance); @@ -169,7 +164,7 @@ public: } #endif - initLoggerScreen(); + initScreen(); } void loop() { @@ -187,28 +182,49 @@ public: } #endif - logOBDData(pollPattern[index]); - index = (index + 1) % PATTERN_NUM; - if (index == 0) { - if (isValidPID(PID_INTAKE_MAP)) - logOBDData(PID_INTAKE_MAP); - else if (isValidPID(PID_MAF_FLOW)) - logOBDData(PID_MAF_FLOW); - } + if (mode == MODE_TIMER) { + timerLoop(); + } else { + logOBDData(pollPattern[index]); + index = (index + 1) % PATTERN_NUM; + + if (index == 0) { + if (isValidPID(PID_INTAKE_MAP)) + logOBDData(PID_INTAKE_MAP); + else if (isValidPID(PID_MAF_FLOW)) + logOBDData(PID_MAF_FLOW); + } - if (millis() - lastTime > POLL_INTERVAL) { - byte pid = pollPattern2[index2]; - if (isValidPID(pid)) { - lastTime = millis(); - logOBDData(pid); - index2 = (index2 + 1) % PATTERN_NUM2; + if (millis() - lastTime > POLL_INTERVAL) { + byte pid = pollPattern2[index2]; + if (isValidPID(pid)) { + lastTime = millis(); + logOBDData(pid); + index2 = (index2 + 1) % PATTERN_NUM2; + } } - } #if USE_MPU6050 - if (state & STATE_ACC_READY) { - processAccelerometer(); + if (state & STATE_ACC_READY) { + processAccelerometer(); + } +#endif + } + +#if ENABLE_DATA_LOG + // flush SD data every 1KB + if (dataSize - lastFileSize >= 1024 && stage != STAGE_MEASURING) { + flushFile(); + lastFileSize = dataSize; + // display logged data size + if (mode == MODE_LOGGER) { + char buf[7]; + sprintf(buf, "%4uKB", (int)(dataSize >> 10)); + lcd.setFont(FONT_SIZE_SMALL); + lcd.setCursor(92, 7); + lcd.print(buf); + } } #endif @@ -275,6 +291,13 @@ public: return true; } #endif + void initScreen() + { + if (mode == MODE_LOGGER) + initLoggerScreen(); + else + initTimerScreen(); + } private: void dataIdleLoop() { @@ -347,8 +370,9 @@ private: dataTime = millis(); - uint32_t speed = gps.speed() * 1852 / 100; - logData(PID_GPS_SPEED, speed); + speedGPS = (uint16_t)(gps.speed() * 1852 / 100); + if (speedGPS > 1000) speedGPS = 0; + logData(PID_GPS_SPEED, speedGPS); // 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 @@ -357,9 +381,16 @@ private: // lastSpeed will be updated //ShowSensorData(PID_SPEED, speed); - long lat, lon; - gps.get_position(&lat, &lon, 0); - logData(PID_GPS_COORDINATES, (float)lat / 100000, (float)lon / 100000); + gps.get_position(&curLat, &curLon, 0); + + // calclate distance + if (lastLat) { + int16_t latDiff = curLat - lastLat; + int16_t lonDiff = curLon - lastLon; + distance = sqrt(latDiff * latDiff + lonDiff * lonDiff); + } + + logData(PID_GPS_COORDINATES, (float)curLat / 100000, (float)curLon / 100000); if (dataTime - lastAltTime > 10000) { uint32_t time; @@ -369,25 +400,27 @@ private: logData(PID_GPS_ALTITUDE, (float)gps.altitude()); } - lcd.setFont(FONT_SIZE_SMALL); - if (((unsigned int)dataTime >> 11) & 1) { - char buf[16]; - sprintf(buf, "LAT:%d.%05ld ", (int)(lat / 100000), lat % 100000); - lcd.setCursor(0, 6); - lcd.print(buf); - sprintf(buf, "LON:%d.%05ld ", (int)(lon / 100000), lon % 100000); - lcd.setCursor(0, 7); - lcd.print(buf); - } else { - char buf[16]; - lcd.setCursor(0, 6); - sprintf(buf, "SAT:%u ", (unsigned int)sat); - lcd.print(buf); - lcd.setCursor(0, 7); - uint32_t time; - gps.get_datetime(0, &time, 0); - sprintf(buf, "TIME:%08ld ", time); - lcd.print(buf); + if (mode == MODE_LOGGER) { + lcd.setFont(FONT_SIZE_SMALL); + if (((unsigned int)dataTime >> 11) & 1) { + char buf[16]; + sprintf(buf, "LAT:%d.%05ld ", (int)(curLat / 100000), curLat % 100000); + lcd.setCursor(0, 6); + lcd.print(buf); + sprintf(buf, "LON:%d.%05ld ", (int)(curLon / 100000), curLon % 100000); + lcd.setCursor(0, 7); + lcd.print(buf); + } else { + char buf[16]; + lcd.setCursor(0, 6); + sprintf(buf, "SAT:%u ", (unsigned int)sat); + lcd.print(buf); + lcd.setCursor(0, 7); + uint32_t time; + gps.get_datetime(0, &time, 0); + sprintf(buf, "TIME:%08ld ", time); + lcd.print(buf); + } } } lastGPSDataTime = dataTime; @@ -408,67 +441,134 @@ private: #endif void logOBDData(byte pid) { - char buffer[OBD_RECV_BUF_SIZE]; int value; +#ifdef OBD_MIN_INTERVAL uint32_t start = millis(); +#endif // send a query to OBD adapter for specified OBD-II pid - sendQuery(pid); - - // display data while waiting for OBD response - showSensorData(lastPID, lastData); + if (readSensor(pid, value)) { + dataTime = millis(); + showLoggerData(pid, value); + // log data to SD card + logData(0x100 | pid, value); + } - // wait for reponse - bool hasData; - do { + // 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(); - } while (!(hasData = available()) && millis() - start < OBD_TIMEOUT_SHORT); - // no need to continue if no data available - if (!hasData) { - errors++; - return; } +#endif + } + void timerLoop() + { + uint32_t elapsed = millis() - startTime; + uint16_t n; - // get response from OBD adapter - pid = 0; - char* data = getResponse(pid, buffer); - if (!data) { - // try recover next time - write('\r'); + int speed; + if (!readSensor(PID_SPEED, speed)) return; - } - // keep data timestamp of returned data as soon as possible + dataTime = millis(); - // convert raw data to normal value - value = normalizeData(pid, data); + lcd.setFont(FONT_SIZE_XLARGE); + if (lastSpeed != speed) { + lcd.setCursor(0, 4); + lcd.printInt((unsigned int)speed % 1000, 3); + lastSpeed = speed; + } + + if (!(state & STATE_GPS_READY)) { + // estimate distance + distance += (uint32_t)(speed + lastSpeed) * (dataTime - lastSpeedTime) / 2 / 3600; + } + lastSpeedTime = dataTime; - // log data to SD card - logData(0x100 | pid, value); + if (stage == STAGE_WAIT_START) { + if (speed > 0) { + stage = STAGE_MEASURING; + startTime = lastSpeedTime; - lastPID = pid; - lastData = value; + uint32_t t = dataTime; + dataTime = lastSpeedTime; + logData(0x100 | PID_SPEED, lastSpeed); + dataTime = t; + logData(0x100 | PID_SPEED, speed); -#if ENABLE_DATA_LOG - // flush SD data every 1KB - if (dataSize - lastFileSize >= 1024) { - flushFile(); - // display logged data size - char buf[7]; - sprintf(buf, "%4uKB", (int)(dataSize >> 10)); - lcd.setFont(FONT_SIZE_SMALL); - lcd.setCursor(92, 7); - lcd.print(buf); - lastFileSize = dataSize; - } -#endif + lastLat = curLat; + lastLon = curLon; + lastSpeed = 0; + distance = 0; - // 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(); + memset(times, 0, sizeof(times)); + + initTimerScreen(); + } + } else if (stage == STAGE_MEASURING) { + // display elapsed time (mm:ss:mm) + n = elapsed / 1000; + if (n < 100) { + lcd.setCursor(0, 0); + lcd.printInt(n, 2); + n = (elapsed % 1000) / 100; + lcd.setFont(FONT_SIZE_MEDIUM); + lcd.setCursor(32, 1); + lcd.write('.'); + lcd.write('0' + n); + } + if (times[2] == 0 && (speedGPS >= SPEED_THRESHOLD_3 || speed >= SPEED_THRESHOLD_3)) { + times[2] = elapsed / 100; + stage = STAGE_IDLE; + lcd.clearLine(0); + lcd.clearLine(1); + lcd.clearLine(2); + showTimerResults(); + lcd.setFont(FONT_SIZE_MEDIUM); + lcd.setCursor(0, 0); + lcd.print("DONE!"); + } else if (times[1] == 0 && (speedGPS >= SPEED_THRESHOLD_2 || speed >= SPEED_THRESHOLD_2)) { + times[1] = elapsed / 100; + showTimerResults(); + } else if (times[0] == 0 && (speedGPS >= SPEED_THRESHOLD_1 || speed >= SPEED_THRESHOLD_1)) { + times[0] = elapsed / 100; + showTimerResults(); + } else if (speed == 0) { + // speed go back to 0 + stage = STAGE_IDLE; + } + if (distance > 0) { + lcd.setFont(FONT_SIZE_SMALL); + lcd.setCursor(62, 6); + if (distance >= 400) { + lcd.printInt(400, 3); + if (!times[3]) { + times[3] = elapsed / 100; + showTimerResults(); + } + } else { + lcd.printInt(distance, 3); + } + } + // log speed data + logData(0x100 | PID_SPEED, speed); + // log additional data + int rpm; + if (readSensor(PID_RPM, rpm)) { + dataTime = millis(); + logData(0x100 | PID_RPM, rpm); + } + } else { + if (speed == 0) { + stage = STAGE_WAIT_START; + initTimerScreen(); + lcd.setFont(FONT_SIZE_MEDIUM); + lcd.setCursor(0, 0); + lcd.println(" GET"); + lcd.println("READY"); + delay(500); + } } -#endif } #ifndef MEMORY_SAVING void showECUCap() @@ -526,10 +626,10 @@ private: lcd.setCursor(0, 6); if (!(state & STATE_GPS_READY)) { lcd.print("GPS"); - lcd.draw((state & STATE_GPS_CONNECTED) ? tick : cross, 32, 48, 16, 16); + lcd.draw((state & STATE_GPS_FOUND) ? tick : cross, 32, 48, 16, 16); } } - virtual void showSensorData(byte pid, int value) + void showLoggerData(byte pid, int value) { char buf[8]; switch (pid) { @@ -568,7 +668,7 @@ private: break; } } - virtual void showGForce(int g) + void showGForce(int g) { byte n; /* 0~1.5g -> 0~8 */ @@ -595,7 +695,7 @@ private: } } } - virtual void initLoggerScreen() + void initLoggerScreen() { lcd.clear(); lcd.backlight(true); @@ -609,6 +709,52 @@ private: lcd.setCursor(80, 5); lcd.print("AIR: C"); } + void showTimerResults() + { + lcd.setFont(FONT_SIZE_SMALL); + lcd.setCursor(56, 0); + lcd.print(" 0~60: --"); + lcd.setCursor(56, 2); + lcd.print("0~100: --"); + lcd.setCursor(56, 4); + lcd.print("0~200: --"); + lcd.setCursor(56, 6); + lcd.print(" 400m: --"); + lcd.setFont(FONT_SIZE_MEDIUM); + char buf[8]; + if (times[0]) { + sprintf(buf, "%2d.%1d", times[0] / 10, times[0] % 10); + Serial.println(times[0]); + lcd.setCursor(92, 0); + lcd.print(buf); + } + if (times[1]) { + sprintf(buf, "%2d.%1d", times[1] / 10, times[1] % 10); + Serial.println(buf); + lcd.setCursor(92, 2); + lcd.print(buf); + } + if (times[2]) { + sprintf(buf, "%2d.%1d", times[2] / 10, times[2] % 10); + Serial.println(buf); + lcd.setCursor(92, 4); + lcd.print(buf); + } + if (times[3]) { + sprintf(buf, "%2d.%1d", times[3] / 10, times[3] % 10); + Serial.println(buf); + lcd.setCursor(92, 6); + lcd.print(buf); + } + } + void initTimerScreen() + { + lcd.clear(); + showTimerResults(); + lcd.setFont(FONT_SIZE_SMALL); + lcd.setCursor(24, 7); + lcd.print("km/h"); + } }; static COBDLogger logger; @@ -622,7 +768,7 @@ void setup() lcd.begin(); lcd.backlight(true); lcd.setFont(FONT_SIZE_MEDIUM); - lcd.println("OBD/GPS Logger"); + lcd.println("OBD Logger"); lcd.println("Initializing"); logger.begin(); @@ -641,7 +787,9 @@ void setup() GPSUART.println(PMTK_SET_NMEA_UPDATE_10HZ); #endif - delay(500); +#ifdef MODE_SWITCH_PIN + pinMode(MODE_SWITCH_PIN, INPUT); +#endif #if ENABLE_DATA_LOG logger.checkSD(); @@ -649,6 +797,17 @@ void setup() lcd.clear(); #endif logger.setup(); + +#ifdef MODE_SWITCH_PIN + if (digitalRead(MODE_SWITCH_PIN) == 0) { + delay(500); + if (digitalRead(MODE_SWITCH_PIN) == 0) { + mode = 1 - mode; + logger.initScreen(); + while (digitalRead(MODE_SWITCH_PIN) == 0); + } + } +#endif } void loop() -- cgit v1.2.3