ODB-II Adapter with Arduino Serial Monitor
Posted: Mon Apr 10, 2017 4:46 am
Hello Everyone,
I recently purchased a Freematics ONE (OBD-II) Adapter that connects to serial TX1/RX1 of the Arduino Mega.
I'm trying to make the code work with the Arduino Serial monitor because I do not have an LCD. I'd like to simply
use my laptop as the dispLAY.
The following is my code and the output generated. I'm not very good at programming as you will see, but I know a tiny
bit. Please help explain my errors. Thank you.
[quote]
/*************************************************************************
* Tester sketch for Freematics OBD-II Adapter for Arduino
* Visit http://freematics.com for more information
* Distributed under BSD license
* Written by Stanley Huang <support@freematics.com.au>
*************************************************************************/
#include <Arduino.h>
#include <OBD.h>
#include <SPI.h>
#include <Wire.h>
//#include "MultiLCD.h"
#include "config.h"
#if ENABLE_DATA_LOG
#include <SD.h>
#endif
#include "datalogger.h"
#define OBD_MODEL_UART 0
#define OBD_MODEL_I2C 1
#define STATE_MEMS_READY 1
#define STATE_INIT_DONE 2
typedef struct {
uint16_t left;
uint16_t right;
uint16_t bottom;
uint16_t height;
uint16_t pos;
} CHART_DATA;
CHART_DATA chartRPM = {24, 319, 239, 100, 24};
void chartUpdate(CHART_DATA* chart, int value);
void(* resetFunc) (void) = 0; //declare reset function at address 0
static uint32_t lastFileSize = 0;
static int speed = 0;
static uint32_t distance = 0;
static uint16_t fileIndex = 0;
static uint32_t startTime = 0;
static uint16_t elapsed = 0;
static uint8_t lastPid = 0;
static int lastValue = 0;
#if OBD_MODEL == OBD_MODEL_UART
class COBDDevice : public COBD, public CDataLogger
#else
class COBDDevice : public COBDI2C, public CDataLogger
#endif
{
public:
COBDDevice():state(0) {}
void setup()
{
#if ENABLE_DATA_LOG
lcd.setFontSize(FONT_SIZE_SMALL);
lcd.setColor(RGB16_WHITE);
lcd.setCursor(0, 3);
checkSD();
#endif
#ifdef OBD_ADAPTER_I2C
Wire.begin();
#endif
if (memsInit())
state |= STATE_MEMS_READY;
testOut();
while (!init());
showVIN();
showDTC();
delay(3000);
initScreen();
state |= STATE_INIT_DONE;
}
void testOut()
{
static const char PROGMEM cmds[][6] = {"ATZ\r", "ATH1\r", "ATRV\r", "0100\r", "010C\r", "0902\r"};
char buf[128];
// recover from possible previous incomplete communication
recover();
for (byte i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) {
char cmd[6];
memcpy_P(cmd, cmds[i], sizeof(cmd));
Serial.print("Sending ");
Serial.println(cmd);
if (sendCommand(cmd, buf, sizeof(buf))) {
char *p = strstr(buf, cmd);
if (p)
p += strlen(cmd);
else
p = buf;
while (*p == '\r') p++;
while (*p) {
Serial.write(*p);
if (*p == '\r')
Serial.write('\n');
p++;
}
Serial.println();
} else {
Serial.println("Timeout");
}
delay(500);
}
Serial.println();
}
void showVIN()
{
char buf[255];
if (getVIN(buf, sizeof(buf))) {
Serial.print("VIN:");
Serial.println(buf);
}
}
void showDTC()
{
uint16_t dtc[6];
int num = readDTC(dtc, sizeof(dtc) / sizeof(dtc[0]));
Serial.print(num);
Serial.println(" DTC found");
if (num > 0) {
for (byte i = 0; i < num; i++) {
Serial.print(dtc[i], HEX);
Serial.print(' ');
}
}
}
void loop()
{
static byte index2 = 0;
const byte pids[]= {PID_RPM, PID_SPEED, PID_THROTTLE, PID_ENGINE_LOAD, PID_COOLANT_TEMP, PID_INTAKE_TEMP, PID_AMBIENT_TEMP, PID_DISTANCE};
//const byte pids[]= {PID_RPM, PID_SPEED, PID_THROTTLE, PID_ENGINE_LOAD};
int values[sizeof(pids)];
// read multiple OBD-II PIDs
if (readPID(pids, sizeof(pids), values) == sizeof(pids)) {
dataTime = millis();
for (byte n = 0; n < sizeof(pids); n++) {
logData((uint16_t)pids[n] | 0x100, values[n]);
showData(pids[n], values[n]);
}
}
static byte lastSec = 0;
const byte pids2[] = {PID_COOLANT_TEMP, PID_INTAKE_TEMP, PID_AMBIENT_TEMP, PID_DISTANCE};
byte sec = (uint8_t)(millis() >> 10);
if (sec != lastSec) {
// goes in every other second
int value;
byte pid = pids2[index2 = (index2 + 1) % (sizeof(pids2))];
// read single OBD-II PID
if (isValidPID(pid) && readPID(pid, value)) {
dataTime = millis();
logData((uint16_t)pid | 0x100, value);
showData(pid, value);
lastSec = sec;
}
}
if (errors >= 5) {
reconnect();
}
if (state & STATE_MEMS_READY) {
processMEMS();
}
}
void processMEMS()
{
int acc[3];
int gyro[3];
int temp;
if (!memsRead(acc, gyro, 0, &temp)) return;
dataTime = millis();
acc[0] /= ACC_DATA_RATIO;
acc[1] /= ACC_DATA_RATIO;
acc[2] /= ACC_DATA_RATIO;
gyro[0] /= GYRO_DATA_RATIO;
gyro[1] /= GYRO_DATA_RATIO;
gyro[2] /= GYRO_DATA_RATIO;
Serial.print("ACCELEROMTER: ");
Serial.print(acc[0]);
Serial.print('/');
Serial.print(acc[1]);
Serial.print('/');
Serial.print(acc[2]);
Serial.println(' ');
Serial.print("GYRO: ");
Serial.print(gyro[0]);
Serial.print('/');
Serial.print(gyro[1]);
Serial.print('/');
Serial.print(gyro[2]);
Serial.print(' ');
Serial.println(' ');
// log x/y/z of accelerometer
logData(PID_ACC, acc[0], acc[1], acc[2]);
// log x/y/z of gyro meter
logData(PID_GYRO, gyro[0], gyro[1], gyro[2]);
}
void reconnect()
{
Serial.print("Reconnecting");
startTime = millis();
//digitalWrite(SD_CS_PIN, LOW);
for (uint16_t i = 0; ; i++) {
if (i == 5) {
Serial.print("Clear");
}
if (init()) {
Serial.print("Reseting...");
// reset Arduino
resetFunc();
}
}
}
//NOTES:
//COMPARE program value with Serial.print(value) vs. my println(value)
void showData(byte pid, int value)
{
switch (pid) {
case PID_RPM:
Serial.print("Freematics RPM: ");
Serial.println((unsigned int)value % 10000, 4);
showChart(value);
Serial.print("My RPM VALUE: ");
Serial.println(value);
break;
case PID_SPEED:
Serial.print("Freematics Speed: ");
Serial.println((unsigned int)value % 1000, 3);
Serial.print("My Speed VALUE: ");
Serial.println(value);
break;
case PID_ENGINE_LOAD:
Serial.print("Freematics ENG. LOAD: ");
Serial.println(value % 100, 3);
Serial.print("My Engine Load VALUE: ");
Serial.println(value);
break;
case PID_INTAKE_TEMP:
if (value < 0) value = 0;
Serial.print("Freematics IAT: ");
Serial.println(value, 3);
Serial.print("My IAT VALUE: ");
Serial.println(value, 3);
break;
case PID_INTAKE_MAP:
Serial.print("Freematics MAP: "); //change to Println from print
Serial.println((uint16_t)value % 1000, 3); //change to Println from print
Serial.print("My MAP VALUE: ");
Serial.println(value);
break;
case PID_COOLANT_TEMP:
Serial.print("Freematics ECT: ");
Serial.println((uint16_t)value % 1000, 3);
Serial.print("My ECT VALUE: ");
Serial.println(value);
break;
case PID_DISTANCE:
Serial.print("Freematics DISTANCE: ");
Serial.println((uint16_t)value % 1000, 3);
Serial.print("My DISTANCE VALUE: ");
Serial.println(value);
break;
}
}
void ShowVoltage(float v)
{
Serial.print("Freematics Voltage: ");
Serial.println(v);
Serial.print("My Voltage: ");
Serial.println(v);
}
void showChart(int value)
{
uint16_t height;
if (value >= 560) {
height = (value - 500) / 60;
} else {
height = 1;
}
chartUpdate(&chartRPM, height);
}
void initScreen()
{
Serial.print("ENGINE RPM");
Serial.print("SPEED");
Serial.print("ENGINE LOAD");
Serial.print("INTAKE TEMP");
Serial.print("COOLANT TEMP");
Serial.print("DISTANCE");
Serial.print("INTAKE MAP");
Serial.print("BATTERY");
Serial.print("ACC");
Serial.print("GYRO");
Serial.print("rpm");
Serial.print("km/h");
Serial.print("C");
Serial.print("C");
Serial.print("km");
Serial.print("kpa");
Serial.print("V");
}
byte state;
};
COBDDevice myOBD;
void setup()
{
myOBD.begin();
myOBD.initSender();
myOBD.setup();
}
void loop()
{
myOBD.loop();
}
I recently purchased a Freematics ONE (OBD-II) Adapter that connects to serial TX1/RX1 of the Arduino Mega.
I'm trying to make the code work with the Arduino Serial monitor because I do not have an LCD. I'd like to simply
use my laptop as the dispLAY.
The following is my code and the output generated. I'm not very good at programming as you will see, but I know a tiny
bit. Please help explain my errors. Thank you.
[quote]
/*************************************************************************
* Tester sketch for Freematics OBD-II Adapter for Arduino
* Visit http://freematics.com for more information
* Distributed under BSD license
* Written by Stanley Huang <support@freematics.com.au>
*************************************************************************/
#include <Arduino.h>
#include <OBD.h>
#include <SPI.h>
#include <Wire.h>
//#include "MultiLCD.h"
#include "config.h"
#if ENABLE_DATA_LOG
#include <SD.h>
#endif
#include "datalogger.h"
#define OBD_MODEL_UART 0
#define OBD_MODEL_I2C 1
#define STATE_MEMS_READY 1
#define STATE_INIT_DONE 2
typedef struct {
uint16_t left;
uint16_t right;
uint16_t bottom;
uint16_t height;
uint16_t pos;
} CHART_DATA;
CHART_DATA chartRPM = {24, 319, 239, 100, 24};
void chartUpdate(CHART_DATA* chart, int value);
void(* resetFunc) (void) = 0; //declare reset function at address 0
static uint32_t lastFileSize = 0;
static int speed = 0;
static uint32_t distance = 0;
static uint16_t fileIndex = 0;
static uint32_t startTime = 0;
static uint16_t elapsed = 0;
static uint8_t lastPid = 0;
static int lastValue = 0;
#if OBD_MODEL == OBD_MODEL_UART
class COBDDevice : public COBD, public CDataLogger
#else
class COBDDevice : public COBDI2C, public CDataLogger
#endif
{
public:
COBDDevice():state(0) {}
void setup()
{
#if ENABLE_DATA_LOG
lcd.setFontSize(FONT_SIZE_SMALL);
lcd.setColor(RGB16_WHITE);
lcd.setCursor(0, 3);
checkSD();
#endif
#ifdef OBD_ADAPTER_I2C
Wire.begin();
#endif
if (memsInit())
state |= STATE_MEMS_READY;
testOut();
while (!init());
showVIN();
showDTC();
delay(3000);
initScreen();
state |= STATE_INIT_DONE;
}
void testOut()
{
static const char PROGMEM cmds[][6] = {"ATZ\r", "ATH1\r", "ATRV\r", "0100\r", "010C\r", "0902\r"};
char buf[128];
// recover from possible previous incomplete communication
recover();
for (byte i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) {
char cmd[6];
memcpy_P(cmd, cmds[i], sizeof(cmd));
Serial.print("Sending ");
Serial.println(cmd);
if (sendCommand(cmd, buf, sizeof(buf))) {
char *p = strstr(buf, cmd);
if (p)
p += strlen(cmd);
else
p = buf;
while (*p == '\r') p++;
while (*p) {
Serial.write(*p);
if (*p == '\r')
Serial.write('\n');
p++;
}
Serial.println();
} else {
Serial.println("Timeout");
}
delay(500);
}
Serial.println();
}
void showVIN()
{
char buf[255];
if (getVIN(buf, sizeof(buf))) {
Serial.print("VIN:");
Serial.println(buf);
}
}
void showDTC()
{
uint16_t dtc[6];
int num = readDTC(dtc, sizeof(dtc) / sizeof(dtc[0]));
Serial.print(num);
Serial.println(" DTC found");
if (num > 0) {
for (byte i = 0; i < num; i++) {
Serial.print(dtc[i], HEX);
Serial.print(' ');
}
}
}
void loop()
{
static byte index2 = 0;
const byte pids[]= {PID_RPM, PID_SPEED, PID_THROTTLE, PID_ENGINE_LOAD, PID_COOLANT_TEMP, PID_INTAKE_TEMP, PID_AMBIENT_TEMP, PID_DISTANCE};
//const byte pids[]= {PID_RPM, PID_SPEED, PID_THROTTLE, PID_ENGINE_LOAD};
int values[sizeof(pids)];
// read multiple OBD-II PIDs
if (readPID(pids, sizeof(pids), values) == sizeof(pids)) {
dataTime = millis();
for (byte n = 0; n < sizeof(pids); n++) {
logData((uint16_t)pids[n] | 0x100, values[n]);
showData(pids[n], values[n]);
}
}
static byte lastSec = 0;
const byte pids2[] = {PID_COOLANT_TEMP, PID_INTAKE_TEMP, PID_AMBIENT_TEMP, PID_DISTANCE};
byte sec = (uint8_t)(millis() >> 10);
if (sec != lastSec) {
// goes in every other second
int value;
byte pid = pids2[index2 = (index2 + 1) % (sizeof(pids2))];
// read single OBD-II PID
if (isValidPID(pid) && readPID(pid, value)) {
dataTime = millis();
logData((uint16_t)pid | 0x100, value);
showData(pid, value);
lastSec = sec;
}
}
if (errors >= 5) {
reconnect();
}
if (state & STATE_MEMS_READY) {
processMEMS();
}
}
void processMEMS()
{
int acc[3];
int gyro[3];
int temp;
if (!memsRead(acc, gyro, 0, &temp)) return;
dataTime = millis();
acc[0] /= ACC_DATA_RATIO;
acc[1] /= ACC_DATA_RATIO;
acc[2] /= ACC_DATA_RATIO;
gyro[0] /= GYRO_DATA_RATIO;
gyro[1] /= GYRO_DATA_RATIO;
gyro[2] /= GYRO_DATA_RATIO;
Serial.print("ACCELEROMTER: ");
Serial.print(acc[0]);
Serial.print('/');
Serial.print(acc[1]);
Serial.print('/');
Serial.print(acc[2]);
Serial.println(' ');
Serial.print("GYRO: ");
Serial.print(gyro[0]);
Serial.print('/');
Serial.print(gyro[1]);
Serial.print('/');
Serial.print(gyro[2]);
Serial.print(' ');
Serial.println(' ');
// log x/y/z of accelerometer
logData(PID_ACC, acc[0], acc[1], acc[2]);
// log x/y/z of gyro meter
logData(PID_GYRO, gyro[0], gyro[1], gyro[2]);
}
void reconnect()
{
Serial.print("Reconnecting");
startTime = millis();
//digitalWrite(SD_CS_PIN, LOW);
for (uint16_t i = 0; ; i++) {
if (i == 5) {
Serial.print("Clear");
}
if (init()) {
Serial.print("Reseting...");
// reset Arduino
resetFunc();
}
}
}
//NOTES:
//COMPARE program value with Serial.print(value) vs. my println(value)
void showData(byte pid, int value)
{
switch (pid) {
case PID_RPM:
Serial.print("Freematics RPM: ");
Serial.println((unsigned int)value % 10000, 4);
showChart(value);
Serial.print("My RPM VALUE: ");
Serial.println(value);
break;
case PID_SPEED:
Serial.print("Freematics Speed: ");
Serial.println((unsigned int)value % 1000, 3);
Serial.print("My Speed VALUE: ");
Serial.println(value);
break;
case PID_ENGINE_LOAD:
Serial.print("Freematics ENG. LOAD: ");
Serial.println(value % 100, 3);
Serial.print("My Engine Load VALUE: ");
Serial.println(value);
break;
case PID_INTAKE_TEMP:
if (value < 0) value = 0;
Serial.print("Freematics IAT: ");
Serial.println(value, 3);
Serial.print("My IAT VALUE: ");
Serial.println(value, 3);
break;
case PID_INTAKE_MAP:
Serial.print("Freematics MAP: "); //change to Println from print
Serial.println((uint16_t)value % 1000, 3); //change to Println from print
Serial.print("My MAP VALUE: ");
Serial.println(value);
break;
case PID_COOLANT_TEMP:
Serial.print("Freematics ECT: ");
Serial.println((uint16_t)value % 1000, 3);
Serial.print("My ECT VALUE: ");
Serial.println(value);
break;
case PID_DISTANCE:
Serial.print("Freematics DISTANCE: ");
Serial.println((uint16_t)value % 1000, 3);
Serial.print("My DISTANCE VALUE: ");
Serial.println(value);
break;
}
}
void ShowVoltage(float v)
{
Serial.print("Freematics Voltage: ");
Serial.println(v);
Serial.print("My Voltage: ");
Serial.println(v);
}
void showChart(int value)
{
uint16_t height;
if (value >= 560) {
height = (value - 500) / 60;
} else {
height = 1;
}
chartUpdate(&chartRPM, height);
}
void initScreen()
{
Serial.print("ENGINE RPM");
Serial.print("SPEED");
Serial.print("ENGINE LOAD");
Serial.print("INTAKE TEMP");
Serial.print("COOLANT TEMP");
Serial.print("DISTANCE");
Serial.print("INTAKE MAP");
Serial.print("BATTERY");
Serial.print("ACC");
Serial.print("GYRO");
Serial.print("rpm");
Serial.print("km/h");
Serial.print("C");
Serial.print("C");
Serial.print("km");
Serial.print("kpa");
Serial.print("V");
}
byte state;
};
COBDDevice myOBD;
void setup()
{
myOBD.begin();
myOBD.initSender();
myOBD.setup();
}
void loop()
{
myOBD.loop();
}