summaryrefslogtreecommitdiff
path: root/samples/test_obd_uart/test_obd_uart.ino
diff options
context:
space:
mode:
Diffstat (limited to 'samples/test_obd_uart/test_obd_uart.ino')
-rw-r--r--samples/test_obd_uart/test_obd_uart.ino382
1 files changed, 382 insertions, 0 deletions
diff --git a/samples/test_obd_uart/test_obd_uart.ino b/samples/test_obd_uart/test_obd_uart.ino
new file mode 100644
index 0000000..ba7ad62
--- /dev/null
+++ b/samples/test_obd_uart/test_obd_uart.ino
@@ -0,0 +1,382 @@
+#include <Arduino.h>
+#include <Wire.h>
+#include <SPI.h>
+#include <MultiLCD.h>
+#include <TinyGPS.h>
+#include <OBD.h>
+#include <MPU6050.h>
+
+#define INIT_CMD_COUNT 4
+#define MAX_CMD_LEN 6
+
+// GPS logging can only be enabled when there is additional hardware serial UART
+#if defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__)
+#define GPSUART Serial3
+#elif defined(__AVR_ATmega644P__)
+#define GPSUART Serial1
+#endif
+
+#define GPS_BAUDRATE 38400 /* bps */
+
+#ifdef GPSUART
+TinyGPS gps;
+#endif // GPSUART
+
+int MPU6050_read(int start, uint8_t *buffer, int size);
+
+char initcmd[INIT_CMD_COUNT][MAX_CMD_LEN] = {"ATZ\r","ATE0\r","ATL1\r","0902\r"};
+
+//SoftwareSerial softSerial(2, 3); // RX, TX
+
+unsigned int adc_key_val[5] ={30, 150, 360, 535, 760 };
+int NUM_KEYS = 5;
+int adc_key_in;
+char key=-1;
+char oldkey=-1;
+
+byte index = 0;
+uint16_t pid = 0x0111;
+
+bool hasMPU6050 = false;
+
+//create object to control an LCD.
+//LCD_SSD1306 lcd;
+//LCD_PCD8544 lcd;
+//LCD_ILI9325D lcd;
+LCD_ILI9341 lcd;
+
+#ifdef GPSUART
+void ShowGPSData()
+{
+ // parsed GPS data is ready
+ char buf[32];
+ unsigned long fix_age;
+
+ unsigned long date, time;
+ gps.get_datetime(&date, &time, &fix_age);
+ sprintf(buf, "TIME: %08ld", time);
+ lcd.setCursor(0, 6);
+ lcd.print(buf);
+
+ long lat, lon;
+ gps.get_position(&lat, &lon, &fix_age);
+ // display LAT/LON if screen is big enough
+ lcd.setCursor(0, 7);
+ if (((unsigned int)millis() / 1000) & 1)
+ sprintf(buf, "LAT: %d.%5ld ", (int)(lat / 100000), lat % 100000);
+ else
+ sprintf(buf, "LON: %d.%5ld ", (int)(lon / 100000), lon % 100000);
+ lcd.print(buf);
+}
+#endif
+
+class COBDTester : public COBD
+{
+public:
+ bool Init(bool passive = false)
+ {
+ unsigned long currentMillis;
+ unsigned char n;
+ char prompted;
+ char buffer[128];
+
+ for (unsigned char i = 0; i < INIT_CMD_COUNT; i++) {
+ write(initcmd[i]);
+ n = 0;
+ prompted = 0;
+ currentMillis = millis();
+ for (;;) {
+ if (available()) {
+ char c = read();
+ if (c == '>') {
+ buffer[n] = 0;
+ prompted++;
+ } else if (n < sizeof(buffer) - 1) {
+ buffer[n++] = c;
+ lcd.write(c);
+ }
+ } else if (prompted) {
+ break;
+ } else {
+ unsigned long elapsed = millis() - currentMillis;
+ if (elapsed > OBD_TIMEOUT_SHORT) {
+ // init timeout
+ //WriteData("\r");
+ lcd.println("Timeout!");
+ if (i == 0) return false;
+ i--;
+ break;
+ }
+ }
+ }
+ delay(500);
+ }
+
+ //while (digitalRead(8) != 0);
+ lcd.clear();
+ lcd.println("VIN:");
+
+ // parse VIN
+ char *p;
+ lcd.println(buffer);
+ if (p = strchr(buffer, ':')) {;
+ byte *q = vin;
+ p += 10;
+ memset(vin, '-', sizeof(vin));
+ while (*p == ' ') {
+ p++;
+ if (*(p + 1) == ':') {
+ p += 2;
+ continue;
+ }
+ *(q++) = hex2uint8(p);
+ p += 2;
+ }
+ }
+ for (byte i = 0; i < sizeof(vin); i++) {
+ lcd.write(vin[i]);
+ }
+ delay(5000);
+
+ char* data;
+ memset(pidmap, 0, sizeof(pidmap));
+ lcd.clear();
+ for (byte i = 0; i < 4; i++) {
+ sprintf(buffer, "PIDs [%02x-%02x]", i * 0x20 + 1, i * 0x20 + 0x20);
+ lcd.println(buffer);
+ byte pid = i * 0x20;
+ sendQuery(pid);
+ data = getResponse(pid, buffer);
+ if (!data) break;
+ lcd.println(buffer);
+ delay(500);
+ data--;
+ for (byte n = 0; n < 4; n++) {
+ if (data[n * 3] != ' ')
+ break;
+ pidmap[i * 4 + n] = hex2uint8(data + n * 3 + 1);
+ }
+ }
+ delay(2000);
+
+ errors = 0;
+ return true;
+ }
+ void SendQuery()
+ {
+ char buf[17];
+ switch (index) {
+ case 0:
+ sprintf(buf, "[%04X]", pid);
+ break;
+ case 1:
+ sprintf(buf, "%03X[%01X]", pid >> 4, pid & 0xf);
+ break;
+ case 2:
+ sprintf(buf, "%02X[%01X]%01X", pid >> 8, (pid >> 4) & 0xf, pid & 0xf);
+ break;
+ case 3:
+ sprintf(buf, "%01X[%01X]%02X", pid >> 12, (pid >> 8) & 0xf, pid & 0xff);
+ break;
+ case 4:
+ sprintf(buf, "[%01X]%03X", pid >> 12, pid & 0xfff);
+ break;
+ }
+
+ lcd.setCursor(0, 0);
+ lcd.print(buf);
+
+ dataMode = (byte)(pid >> 8);
+ sendQuery((byte)pid);
+ }
+ void Recover()
+ {
+ write('\r');
+ }
+ void Loop()
+ {
+ int value;
+ char buffer[OBD_RECV_BUF_SIZE];
+ bool gpsReady = false;
+
+ // issue a query for specified OBD-II pid
+ SendQuery();
+
+ do {
+#ifdef GPSUART
+ // while waiting for response, test GPS
+ unsigned long start = millis();
+ while (GPSUART.available() && millis() - start < 100) {
+ if (gps.encode(GPSUART.read())) {
+ gpsReady = true;
+ }
+ }
+#endif
+ } while (!available());
+
+#ifdef GPSUART
+ if (gpsReady)
+ ShowGPSData();
+#endif
+
+ // check OBD response
+ buffer[0] = 0;
+ byte curpid = (byte)pid;
+ char* data = getResponse(curpid, buffer);
+ lcd.setCursor(6, 0);
+ if (!data) {
+ lcd.setCursor(0, 2);
+ lcd.print("Error");
+ // try recover next time
+ Recover();
+ } else {
+ char *p = buffer;
+ while (*p && *p < ' ') p++;
+ for (char *q = p; *q; q++) {
+ if (*q < ' ') *q = ' ';
+ }
+ lcd.setCursor(0, 2);
+ lcd.print(p);
+ lcd.setCursor(7 * 9, 0);
+ sprintf(buffer, "%d", normalizeData(curpid, data));
+ lcd.print(buffer);
+ }
+ }
+};
+
+COBDTester obd;
+
+// Convert ADC value to key number
+char get_key(unsigned int input)
+{
+ char k;
+ for (k = 0; k < NUM_KEYS; k++) {
+ if (input < adc_key_val[k])
+ return k;
+ }
+ return -1;
+}
+
+void testMPU6050()
+{
+ int error;
+ float dT;
+ accel_t_gyro_union accel_t_gyro;
+
+ // Read the raw values.
+ // Read 14 bytes at once,
+ // containing acceleration, temperature and gyro.
+ // With the default settings of the MPU-6050,
+ // there is no filter enabled, and the values
+ // are not very stable.
+
+ error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) &accel_t_gyro, sizeof(accel_t_gyro));
+ if (error != 0) {
+ lcd.setCursor(0, 4);
+ lcd.print("MPU6050 N/A");
+ return;
+ }
+
+
+ // Swap all high and low bytes.
+ // After this, the registers values are swapped,
+ // so the structure name like x_accel_l does no
+ // longer contain the lower byte.
+ uint8_t swap;
+ #define SWAP(x,y) swap = x; x = y; y = swap
+
+ SWAP (accel_t_gyro.reg.x_accel_h, accel_t_gyro.reg.x_accel_l);
+ SWAP (accel_t_gyro.reg.y_accel_h, accel_t_gyro.reg.y_accel_l);
+ SWAP (accel_t_gyro.reg.z_accel_h, accel_t_gyro.reg.z_accel_l);
+ SWAP (accel_t_gyro.reg.t_h, accel_t_gyro.reg.t_l);
+ SWAP (accel_t_gyro.reg.x_gyro_h, accel_t_gyro.reg.x_gyro_l);
+ SWAP (accel_t_gyro.reg.y_gyro_h, accel_t_gyro.reg.y_gyro_l);
+ SWAP (accel_t_gyro.reg.z_gyro_h, accel_t_gyro.reg.z_gyro_l);
+
+
+ // Print the raw acceleration values
+
+ char buf[20];
+ dT = ( (float) accel_t_gyro.value.temperature + 12412.0) / 340.0;
+ sprintf(buf, "%d %d %d %d ",
+ (int)dT,
+ accel_t_gyro.value.x_accel / 128,
+ accel_t_gyro.value.y_accel / 128,
+ accel_t_gyro.value.z_accel / 128);
+ //Serial.println(buf);
+ lcd.setCursor(0, 4);
+ lcd.print(buf);
+}
+
+void ShowECUCap()
+{
+ char buffer[24];
+ 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[] = {"RPM", "SPEED", "THROTTLE", "ENG.LOAD", "MAF", "MAP", "FUEL LV.", "FUEL PRE.", "COOLANT", "INTAKE","AMBIENT", "IGNITION", "BARO"};
+ byte i = 0;
+ lcd.clear();
+ for (; i < sizeof(pidlist) / sizeof(pidlist[0]) / 2; i++) {
+ lcd.setCursor(0, i);
+ sprintf(buffer, "%s:%c", namelist[i], obd.isValidPID(pidlist[i]) ? 'Y' : 'N');
+ lcd.print(buffer);
+ }
+ for (byte row = 0; i < sizeof(pidlist) / sizeof(pidlist[0]); i++, row++) {
+ lcd.setCursor(64, row);
+ sprintf(buffer, "%s:%c", namelist[i], obd.isValidPID(pidlist[i]) ? 'Y' : 'N');
+ lcd.print(buffer);
+ }
+}
+
+void setup()
+{
+ Wire.begin();
+ lcd.begin();
+#ifdef GPSUART
+ GPSUART.begin(GPS_BAUDRATE);
+#endif
+
+ obd.begin();
+
+ pinMode(8, INPUT);
+
+ do {
+ lcd.setCursor(0, 0);
+ lcd.println("Init MPU6050...");
+
+ hasMPU6050 = MPU6050_init() == 0;
+ if (hasMPU6050) {
+ unsigned long t = millis();
+ do {
+ testMPU6050();
+ delay(100);
+ } while (millis() - t <= 1000);
+ }
+ delay(1000);
+
+#ifdef GPSUART
+ if (GPSUART.available()) {
+ lcd.println("Init GPS... ");
+ delay(1000);
+ }
+#endif
+ lcd.println("Init OBD... ");
+ if (hasMPU6050) {
+ testMPU6050();
+ }
+ delay(500);
+ } while(!obd.Init());
+
+ ShowECUCap();
+ delay(3000);
+ lcd.clear();
+}
+
+void loop()
+{
+ obd.Loop();
+
+ // test MPU6050
+ if (hasMPU6050) {
+ testMPU6050();
+ }
+}