Emerson Garland
Published © GPL3+

Visualize Car Data With Carloop And Blynk

Visualize car data with a free Blynk account, particle electron and Carloop.

IntermediateFull instructions provided3 hours12,892
Visualize Car Data With Carloop And Blynk

Things used in this project

Hardware components

Electron
Particle Electron
×1
Carloop
Carloop
×1

Software apps and online services

Blynk
Blynk

Story

Read more

Schematics

High Level Diagram

General Overview of Data Flow

Code

Mode 1 PIDs to Blynk

Arduino
Use this code to publish your chosen PIDs to Blynk
/*
 * Copyright 2016 Emerson Garland
 * Free to modify, share and do whatever, just give me credit if you like it!
 * This code will publish chosen obdii compliant messages to blynk for data visualization.
 */

//#include "carloop.h"
// include carloop.h using the ide add library function.
#include "base85.h"
// include base85.h by copy and pasting base85.h located in this repository into the web ide
//#include "blynk/blynk.h"
// include blynk/blynk.h using the ide add library function.

SYSTEM_MODE(SEMI_AUTOMATIC);
SYSTEM_THREAD(ENABLED);

void sendObdRequest();
void waitForObdResponse();
void delayUntilNextRequest();
void printValuesAtInterval();
void publishValuesAtInterval();
void printValues();
void getEngineLoad();
void receiveObdRequestVIN();
void sendObdRequestVIN();

//PLACE YOUR BLYNK AUTHENTICATION KEY IN BELOW AS SHOWN IN EXAMPLE BELOW:
//char auth[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";


char auth[] = "Your key here";

String dumpMessage(const CANMessage &message);
bool byteArray8Equal(uint8_t a1[8], uint8_t a2[8]);

Carloop<CarloopRevision2> carloop;

int canMessageCount = 0;


/////////////////////////////////////////////////////////////////////////
//GLOBAL FLOATS FOR USE IN PRINTING AND PUBLISHING TO EXTERNAL SERVICES//
/////////////////////////////////////////////////////////////////////////

//ACRONYM DEFINITIONS:
//O2_V_1 = OXYGEN SENSOR 1 VOLTAGE
//O2_T_1 = OXYGEN SENSOR 1 FUEL TRIM
//O2_F_A_E_R_V_1_FUEL = OXYGEN SENSOR 1 FUEL TO AIR EQUIVILANCE RATIO AND VOLTAGE FUEL BYTE
//O2_F_A_E_R_V_1_VOLTAGE = OXYGEN SENSOR 1 FUEL TO AIR EQUIVILANCE RATIO AND VOLTAGE VOLTAGE BYTE
//O2_F_A_E_R_C_1_CURRENT = OXYGEN SENSOR 1 FUEL TO AIR EQUIVILANCE RATIO AND CURRENT CURRENTE BYTE

float MIL_STATUS;
float FUEL_SYSTEM_STATUS;
float ENGINE_LOAD;
float COOLANT_TEMPERATURE;
float SHORT_TERM_FUEL_TRIM_BANK_1;
float LONG_TERM_FUEL_TRIM_BANK_1;
float SHORT_TERM_FUEL_TRIM_BANK_2;
float LONG_TERM_FUEL_TRIM_BANK_2;
float FUEL_PRESSURE;
float INTAKE_MANIFOLD_PRESSURE;
float ENGINE_RPM;
float VEHICLE_SPEED;
float TIMING_ADVANCE;
float INTAKE_AIR_TEMPERATURE;
float MAF_AIR_FLOW_RATE;
float THROTTLE;
float COMMANDED_SECONDARY_AIR_STATUS;
float O2_SENSORS_PRESENT;
float O2_V_1;
float O2_T_1;
float O2_V_2;
float O2_T_2;
float O2_V_3;
float O2_T_3;
float O2_V_4;
float O2_T_4;
float O2_V_5;
float O2_T_5;
float O2_V_6;
float O2_T_6;
float O2_V_7;
float O2_T_7;
float O2_V_8;
float O2_T_8;
float OBD_STANDARDS;
float ENGINE_RUN_TIME;
float SUPPORTED_PIDS_21_40;
float DISTANCE_TRAVELED_WITH_MIL_ON;
float FUEL_RAIL_PRESSURE;
float FUEL_RAIL_GAUGE_PRESSURE;
float O2_F_A_E_R_V_1_FUEL;
float O2_F_A_E_R_V_1_VOLTAGE;
float O2_F_A_E_R_V_2_FUEL;
float O2_F_A_E_R_V_2_VOLTAGE;
float O2_F_A_E_R_V_3_FUEL;
float O2_F_A_E_R_V_3_VOLTAGE;
float O2_F_A_E_R_V_4_FUEL;
float O2_F_A_E_R_V_4_VOLTAGE;
float O2_F_A_E_R_V_5_FUEL;
float O2_F_A_E_R_V_5_VOLTAGE;
float O2_F_A_E_R_V_6_FUEL;
float O2_F_A_E_R_V_6_VOLTAGE;
float O2_F_A_E_R_V_7_FUEL;
float O2_F_A_E_R_V_7_VOLTAGE;
float O2_F_A_E_R_V_8_FUEL;
float O2_F_A_E_R_V_8_VOLTAGE;
float COMMANDED_EGR;
float EGR_ERROR;
float COMMANDED_EVAPORATIVE_PURGE;
float FUEL_TANK_LEVEL_INPUT;
float WARM_UPS_SINCE_CODES_CLEARED;
float DISTANCE_TRAVELED_SINCE_CODES_CLEARED;
float EVAPORATOR_SYSTEM_PRESSURE;
float ABSOLUTE_BAROMETRIC_PRESSURE;
float O2_F_A_E_R_C_1_FUEL;
float O2_F_A_E_R_C_1_CURRENT;
float O2_F_A_E_R_C_2_FUEL;
float O2_F_A_E_R_C_2_CURRENT;
float O2_F_A_E_R_C_3_FUEL;
float O2_F_A_E_R_C_3_CURRENT;
float O2_F_A_E_R_C_4_FUEL;
float O2_F_A_E_R_C_4_CURRENT;
float O2_F_A_E_R_C_5_FUEL;
float O2_F_A_E_R_C_5_CURRENT;
float O2_F_A_E_R_C_6_FUEL;
float O2_F_A_E_R_C_6_CURRENT;
float O2_F_A_E_R_C_7_FUEL;
float O2_F_A_E_R_C_7_CURRENT;
float O2_F_A_E_R_C_8_FUEL;
float O2_F_A_E_R_C_8_CURRENT;
float CATALYST_TEMPERATURE_BANK1_SENSOR1;
float CATALYST_TEMPERATURE_BANK2_SENSOR1;
float CATALYST_TEMPERATURE_BANK1_SENSOR2;
float CATALYST_TEMPERATURE_BANK2_SENSOR2;
float SUPPORTED_PIDS_41_60;
float MONITOR_STATUS;
float CONTROL_MODULE_VOLTAGE;
float ABSOLUTE_LOAD_VALUE;
float FUEL_AIR_COMMANDED_EQUIV_RATIO;
float RELATIVE_THROTTLE_POSITION;
float AMBIENT_AIR_TEMPERATURE;
float ABSOLUTE_THROTTLE_B;
float ABSOLUTE_THROTTLE_C;
float ACCELERATOR_PEDAL_POSITION_D;
float ACCELERATOR_PEDAL_POSITION_E;
float ACCELERATOR_PEDAL_POSITION_F;
float COMMANDED_THROTTLE_ACTUATOR;
float TIME_RUN_WITH_MIL_ON;
float TIME_SINCE_TROUBLE_CODES_CLEARED;
float MAX_VALUES;
float MAX_VALUES_2;
float FUEL_TYPE;
float ETHANOL_FUEL_PERCENT;
float ABSOLUTE_EVAP_SYS_VAPOR_PRESSURE;
float EVAP_SYSTEM_VAPOR_PRESSURE;
float SHORT_TERM_SECONDARY_O2_TRIM_BANK_1_3;
float LONG_TERM_SECONDARY_O2_TRIM_BANK_1_3;
float SHORT_TERM_SECONDARY_O2_TRIM_BANK_2_4;
float LONG_TERM_SECONDARY_O2_TRIM_BANK_2_4;
float FUEL_RAIL_ABSOLUTE_PRESSURE;
float RELATIVE_ACCELERATOR_PEDAL_POSITION;
float HYBRID_BATTERY_PACK_REMAINING_LIFE;
float ENGINE_OIL_TEMPERATURE;
float FUEL_INJECTION_TIMING;
float ENGINE_FUEL_RATE;
float EMISSION_REQUIREMENTS;
float SUPPORTED_PIDS_61_80;
float DEMAND_PERCENT_TORQUE;
float ACTUAL_PERCENT_TORQUE;
float ENGINE_REFERENCE_TORQUE;
float ENGINE_PERCENT_TORQUE_DATA;
float AUXILLARY_IO_SUPPORTED;
float MASS_AIR_FLOW_SENSOR;
float ENGINE_COOLANT_TEMPERATURE;
float INTAKE_AIR_TEMPERATURE_SENSOR;

///////////////////////////////////////////////////////////////////////////
//GLOBAL INTEGERS FOR USE IN PERFORMING MATH AND EXTRACTION OF OBDII DATA//
///////////////////////////////////////////////////////////////////////////
int data0;
int data1;
int data2;
int data3;
int data4;
int data5;
int data6;
int data7;


// OBD CAN MESSAGE IDs
const auto OBD_CAN_BROADCAST_ID    = 0X7DF;
const auto OBD_CAN_REQUEST_ID      = 0x7E0;
const auto OBD_CAN_REPLY_ID_MIN    = 0x7E8;
const auto OBD_CAN_REPLY_ID_MAX    = 0x7EF;

const String key = "YN8B4S3KMEFDM0FT";

// OBD MODES
const auto OBD_MODE_CURRENT_DATA = 0x01;

//const auto OBD_MODE_REQUEST_VEHICLE_DATA = 0x09;

///////////////////////////////////////////////////////////////////////////////////////////////////////
//LIST OF ALL (Almost) MODE 1 PIDS THAT YOU ARE CAPABLE OF POLLING. NOT ALL WILL BE AVAILABLE TO YOU.//
///////////////////////////////////////////////////////////////////////////////////////////////////////

const auto OBD_PID_SUPPORTED_PIDS_01_20                  = 0x00;
const auto OBD_PID_MIL_STATUS                            = 0x01;
const auto OBD_PID_FUEL_SYSTEM_STATUS                    = 0x03;
const auto OBD_PID_ENGINE_LOAD                           = 0x04;
const auto OBD_PID_COOLANT_TEMPERATURE                   = 0x05;
const auto OBD_PID_SHORT_TERM_FUEL_TRIM_BANK_1           = 0x06;
const auto OBD_PID_LONG_TERM_FUEL_TRIM_BANK_1            = 0x07;
const auto OBD_PID_SHORT_TERM_FUEL_TRIM_BANK_2           = 0x08;
const auto OBD_PID_LONG_TERM_FUEL_TRIM_BANK_2            = 0x09;
const auto OBD_PID_FUEL_PRESSURE                         = 0x0a;
const auto OBD_PID_INTAKE_MANIFOLD_PRESSURE              = 0x0b;
const auto OBD_PID_ENGINE_RPM                            = 0x0c;
const auto OBD_PID_VEHICLE_SPEED                         = 0x0d;
const auto OBD_PID_TIMING_ADVANCE                        = 0x0e;
const auto OBD_PID_INTAKE_AIR_TEMPERATURE                = 0x0f;
const auto OBD_PID_MAF_AIR_FLOW_RATE                     = 0x10;
const auto OBD_PID_THROTTLE    	                         = 0x11;
const auto OBD_PID_COMMANDED_SECONDARY_AIR_STATUS        = 0x12;
const auto OBD_PID_O2_SENSORS_PRESENT                    = 0x13;
const auto OBD_PID_O2_V_F_T_1                            = 0x14;
const auto OBD_PID_O2_V_F_T_2                            = 0x15;
const auto OBD_PID_O2_V_F_T_3                            = 0x16;
const auto OBD_PID_O2_V_F_T_4                            = 0x17;
const auto OBD_PID_O2_V_F_T_5                            = 0x18;
const auto OBD_PID_O2_V_F_T_6                            = 0x19;
const auto OBD_PID_O2_V_F_T_7                            = 0x1a;
const auto OBD_PID_O2_V_F_T_8                            = 0x1b;
const auto OBD_PID_OBD_STANDARDS                         = 0x1c;
const auto OBD_PID_ENGINE_RUN_TIME                       = 0x1f;
const auto OBD_PID_SUPPORTED_PIDS_21_40                  = 0x20;
const auto OBD_PID_DISTANCE_TRAVELED_WITH_MIL_ON         = 0x21;
const auto OBD_PID_FUEL_RAIL_PRESSURE                    = 0x22;
const auto OBD_PID_FUEL_RAIL_GAUGE_PRESSURE              = 0x23;
const auto OBD_PID_O2_F_A_E_R_V_1                        = 0x24;
const auto OBD_PID_O2_F_A_E_R_V_2                        = 0x25;
const auto OBD_PID_O2_F_A_E_R_V_3                        = 0x26;
const auto OBD_PID_O2_F_A_E_R_V_4                        = 0x27;
const auto OBD_PID_O2_F_A_E_R_V_5                        = 0x28;
const auto OBD_PID_O2_F_A_E_R_V_6                        = 0x29;
const auto OBD_PID_O2_F_A_E_R_V_7                        = 0x2a;
const auto OBD_PID_O2_F_A_E_R_V_8                        = 0x2b;
const auto OBD_PID_COMMANDED_EGR                         = 0x2c;
const auto OBD_PID_EGR_ERROR                             = 0x2d;
const auto OBD_PID_COMMANDED_EVAPORATIVE_PURGE           = 0x2e;
const auto OBD_PID_FUEL_TANK_LEVEL_INPUT                 = 0x2f;
const auto OBD_PID_WARM_UPS_SINCE_CODES_CLEARED          = 0x30;
const auto OBD_PID_DISTANCE_TRAVELED_SINCE_CODES_CLEARED = 0x31;
const auto OBD_PID_EVAPORATOR_SYSTEM_PRESSURE            = 0x32;
const auto OBD_PID_ABSOLUTE_BAROMETRIC_PRESSURE          = 0x33;
const auto OBD_PID_O2_F_A_E_R_1_C                        = 0x34;
const auto OBD_PID_O2_F_A_E_R_2_C                        = 0x35;
const auto OBD_PID_O2_F_A_E_R_3_C                        = 0x36;
const auto OBD_PID_O2_F_A_E_R_4_C                        = 0x37;
const auto OBD_PID_O2_F_A_E_R_5_C                        = 0x38;
const auto OBD_PID_O2_F_A_E_R_6_C                        = 0x39;
const auto OBD_PID_O2_F_A_E_R_7_C                        = 0x3a;
const auto OBD_PID_O2_F_A_E_R_8_C                        = 0x3b;
const auto OBD_PID_CATALYST_TEMPERATURE_BANK1_SENSOR1    = 0x3c;
const auto OBD_PID_CATALYST_TEMPERATURE_BANK2_SENSOR1    = 0x3d;
const auto OBD_PID_CATALYST_TEMPERATURE_BANK1_SENSOR2    = 0x3e;
const auto OBD_PID_CATALYST_TEMPERATURE_BANK2_SENSOR2    = 0x3f;
const auto OBD_PID_SUPPORTED_PIDS_41_60                  = 0x40;
const auto OBD_PID_MONITOR_STATUS                        = 0x41;
const auto OBD_PID_CONTROL_MODULE_VOLTAGE                = 0x42;
const auto OBD_PID_ABSOLUTE_LOAD_VALUE                   = 0x43;
const auto OBD_PID_FUEL_AIR_COMMANDED_EQUIV_RATIO        = 0x44;
const auto OBD_PID_RELATIVE_THROTTLE_POSITION            = 0x45;
const auto OBD_PID_AMBIENT_AIR_TEMPERATURE               = 0x46;
const auto OBD_PID_ABSOLUTE_THROTTLE_B                   = 0x47;
const auto OBD_PID_ABSOLUTE_THROTTLE_C                   = 0x48;
const auto OBD_PID_ACCELERATOR_PEDAL_POSITION_D          = 0x49;
const auto OBD_PID_ACCELERATOR_PEDAL_POSITION_E          = 0x4a;
const auto OBD_PID_ACCELERATOR_PEDAL_POSITION_F          = 0x4b;
const auto OBD_PID_COMMANDED_THROTTLE_ACTUATOR           = 0x4c;
const auto OBD_PID_TIME_RUN_WITH_MIL_ON                  = 0x4d;
const auto OBD_PID_TIME_SINCE_TROUBLE_CODES_CLEARED      = 0x4e;
const auto OBD_PID_MAX_VALUES                            = 0x4f;
const auto OBD_PID_MAX_VALUES_2                          = 0x50;
const auto OBD_PID_FUEL_TYPE                             = 0x51;
const auto OBD_PID_ETHANOL_FUEL_PERCENT                  = 0x52;
const auto OBD_PID_ABSOLUTE_EVAP_SYS_VAPOR_PRESSURE      = 0x53;
const auto OBD_PID_EVAP_SYSTEM_VAPOR_PRESSURE            = 0x54;
const auto OBD_PID_SHORT_TERM_SECONDARY_O2_TRIM_BANK_1_3 = 0x55;
const auto OBD_PID_LONG_TERM_SECONDARY_O2_TRIM_BANK_1_3  = 0x56;
const auto OBD_PID_SHORT_TERM_SECONDARY_O2_TRIM_BANK_2_4 = 0x57;
const auto OBD_PID_LONG_TERM_SECONDARY_O2_TRIM_BANK_2_4  = 0x58;
const auto OBD_PID_FUEL_RAIL_ABSOLUTE_PRESSURE           = 0x59;
const auto OBD_PID_RELATIVE_ACCELERATOR_PEDAL_POSITION   = 0x5a;
const auto OBD_PID_HYBRID_BATTERY_PACK_REMAINING_LIFE    = 0x5b;
const auto OBD_PID_ENGINE_OIL_TEMPERATURE                = 0x5c;
const auto OBD_PID_FUEL_INJECTION_TIMING                 = 0x5d;
const auto OBD_PID_ENGINE_FUEL_RATE                      = 0x5e;
const auto OBD_PID_EMISSION_REQUIREMENTS                 = 0x5f;
const auto OBD_PID_SUPPORTED_PIDS_61_80                  = 0x60;
const auto OBD_PID_DEMAND_PERCENT_TORQUE                 = 0x61;
const auto OBD_PID_ACTUAL_PERCENT_TORQUE                 = 0x62;
const auto OBD_PID_ENGINE_REFERENCE_TORQUE               = 0x63;
const auto OBD_PID_ENGINE_PERCENT_TORQUE_DATA            = 0x64;
const auto OBD_PID_AUXILLARY_IO_SUPPORTED                = 0x65;
const auto OBD_PID_MASS_AIR_FLOW_SENSOR                  = 0x66;
const auto OBD_PID_ENGINE_COOLANT_TEMPERATURE            = 0x67;
const auto OBD_PID_INTAKE_AIR_TEMPERATURE_SENSOR         = 0x68;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//SUM THE TOTAL AMOUNT OF PIDS YOU WOULD LIKE TO REQUEST AND PLACE THAT IN const size_t NUM_PIDS_TO_REQUEST// 
/////////////////////////////////////////////////////////////////////////////////////////////////////////////

const size_t NUM_PIDS_TO_REQUEST = 102;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//COMMENT OUT OR REMOVE THE PIDS THAT YOU DO NOT HAVE TO INCREASE EFFECIENCY BUT BE SURE TO UPDATE THE ABOVE CONSTANT//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

const uint8_t pidsToRequest[NUM_PIDS_TO_REQUEST] = {
    
OBD_PID_SUPPORTED_PIDS_01_20,
OBD_PID_MIL_STATUS,
OBD_PID_FUEL_SYSTEM_STATUS,
OBD_PID_ENGINE_LOAD,
OBD_PID_COOLANT_TEMPERATURE,
OBD_PID_SHORT_TERM_FUEL_TRIM_BANK_1,
OBD_PID_LONG_TERM_FUEL_TRIM_BANK_1,
OBD_PID_SHORT_TERM_FUEL_TRIM_BANK_2,
OBD_PID_LONG_TERM_FUEL_TRIM_BANK_2,
OBD_PID_FUEL_PRESSURE,
OBD_PID_INTAKE_MANIFOLD_PRESSURE,
OBD_PID_ENGINE_RPM,
OBD_PID_VEHICLE_SPEED,
OBD_PID_TIMING_ADVANCE,
OBD_PID_INTAKE_AIR_TEMPERATURE,
OBD_PID_MAF_AIR_FLOW_RATE,
OBD_PID_THROTTLE,
OBD_PID_COMMANDED_SECONDARY_AIR_STATUS,
OBD_PID_O2_SENSORS_PRESENT,
OBD_PID_O2_V_F_T_1,
OBD_PID_O2_V_F_T_2,
OBD_PID_O2_V_F_T_3,
OBD_PID_O2_V_F_T_4,
OBD_PID_O2_V_F_T_5,
OBD_PID_O2_V_F_T_6,
OBD_PID_O2_V_F_T_7,
OBD_PID_O2_V_F_T_8,
OBD_PID_OBD_STANDARDS,
OBD_PID_ENGINE_RUN_TIME,
OBD_PID_SUPPORTED_PIDS_21_40,
OBD_PID_DISTANCE_TRAVELED_WITH_MIL_ON,
OBD_PID_FUEL_RAIL_PRESSURE,
OBD_PID_FUEL_RAIL_GAUGE_PRESSURE,
OBD_PID_O2_F_A_E_R_V_1,
OBD_PID_O2_F_A_E_R_V_2,
OBD_PID_O2_F_A_E_R_V_3,
OBD_PID_O2_F_A_E_R_V_4,
OBD_PID_O2_F_A_E_R_V_5,
OBD_PID_O2_F_A_E_R_V_6,
OBD_PID_O2_F_A_E_R_V_7,
OBD_PID_O2_F_A_E_R_V_8,
OBD_PID_COMMANDED_EGR,
OBD_PID_EGR_ERROR,
OBD_PID_COMMANDED_EVAPORATIVE_PURGE,
OBD_PID_FUEL_TANK_LEVEL_INPUT,
OBD_PID_WARM_UPS_SINCE_CODES_CLEARED,
OBD_PID_DISTANCE_TRAVELED_SINCE_CODES_CLEARED,
OBD_PID_EVAPORATOR_SYSTEM_PRESSURE,
OBD_PID_ABSOLUTE_BAROMETRIC_PRESSURE,
OBD_PID_O2_F_A_E_R_1_C,
OBD_PID_O2_F_A_E_R_2_C,
OBD_PID_O2_F_A_E_R_3_C,
OBD_PID_O2_F_A_E_R_4_C,
OBD_PID_O2_F_A_E_R_5_C,
OBD_PID_O2_F_A_E_R_6_C,
OBD_PID_O2_F_A_E_R_7_C,
OBD_PID_O2_F_A_E_R_8_C,
OBD_PID_CATALYST_TEMPERATURE_BANK1_SENSOR1,
OBD_PID_CATALYST_TEMPERATURE_BANK2_SENSOR1,
OBD_PID_CATALYST_TEMPERATURE_BANK1_SENSOR2,
OBD_PID_CATALYST_TEMPERATURE_BANK2_SENSOR2,
OBD_PID_SUPPORTED_PIDS_41_60,
OBD_PID_MONITOR_STATUS,
OBD_PID_CONTROL_MODULE_VOLTAGE,
OBD_PID_ABSOLUTE_LOAD_VALUE,
OBD_PID_FUEL_AIR_COMMANDED_EQUIV_RATIO,
OBD_PID_RELATIVE_THROTTLE_POSITION,
OBD_PID_AMBIENT_AIR_TEMPERATURE,
OBD_PID_ABSOLUTE_THROTTLE_B,
OBD_PID_ABSOLUTE_THROTTLE_C,
OBD_PID_ACCELERATOR_PEDAL_POSITION_D,
OBD_PID_ACCELERATOR_PEDAL_POSITION_E,
OBD_PID_ACCELERATOR_PEDAL_POSITION_F,
OBD_PID_COMMANDED_THROTTLE_ACTUATOR,
OBD_PID_TIME_RUN_WITH_MIL_ON,
OBD_PID_TIME_SINCE_TROUBLE_CODES_CLEARED,
OBD_PID_MAX_VALUES,
OBD_PID_MAX_VALUES_2,
OBD_PID_FUEL_TYPE,
OBD_PID_ETHANOL_FUEL_PERCENT,
OBD_PID_ABSOLUTE_EVAP_SYS_VAPOR_PRESSURE,
OBD_PID_EVAP_SYSTEM_VAPOR_PRESSURE,
OBD_PID_SHORT_TERM_SECONDARY_O2_TRIM_BANK_1_3,
OBD_PID_LONG_TERM_SECONDARY_O2_TRIM_BANK_1_3,
OBD_PID_SHORT_TERM_SECONDARY_O2_TRIM_BANK_2_4,
OBD_PID_LONG_TERM_SECONDARY_O2_TRIM_BANK_2_4,
OBD_PID_FUEL_RAIL_ABSOLUTE_PRESSURE,
OBD_PID_RELATIVE_ACCELERATOR_PEDAL_POSITION,
OBD_PID_HYBRID_BATTERY_PACK_REMAINING_LIFE,
OBD_PID_ENGINE_OIL_TEMPERATURE,
OBD_PID_FUEL_INJECTION_TIMING,
OBD_PID_ENGINE_FUEL_RATE,
OBD_PID_EMISSION_REQUIREMENTS,
OBD_PID_SUPPORTED_PIDS_61_80,
OBD_PID_DEMAND_PERCENT_TORQUE,
OBD_PID_ACTUAL_PERCENT_TORQUE,
OBD_PID_ENGINE_REFERENCE_TORQUE,
OBD_PID_ENGINE_PERCENT_TORQUE_DATA,
OBD_PID_AUXILLARY_IO_SUPPORTED,
OBD_PID_MASS_AIR_FLOW_SENSOR,
OBD_PID_ENGINE_COOLANT_TEMPERATURE,
OBD_PID_INTAKE_AIR_TEMPERATURE_SENSOR

};
    
    
uint8_t pidIndex = NUM_PIDS_TO_REQUEST - 1;

String dumpForPublish;

auto *obdLoopFunction = sendObdRequest;
unsigned long transitionTime = 0;
uint8_t lastMessageData[8];

void setup() {
    Blynk.begin(auth);
	Serial.begin(115200);
	carloop.begin();
	Particle.connect();
	transitionTime = millis();
}



void loop() {
	
	carloop.update();
	printValuesAtInterval();
	publishValuesAtInterval();
	obdLoopFunction();
	waitForObdResponse();
        math();

}


/*************** Begin: OBD Loop Functions ****************/

/* For help understanding the OBD Query format over CAN bus,
 * see: https://en.wikipedia.org/wiki/OBD-II_PIDs#Query
 *
 * For help understanding why the first data byte is 0x02,
 * see: http://hackaday.com/2013/10/29/can-hacking-protocols/
 *
 * For help understanding modes and PIDs,
 * see: https://en.wikipedia.org/wiki/OBD-II_PIDs#Modes
 * and: https://en.wikipedia.org/wiki/OBD-II_PIDs#Standard_PIDs
 */
void sendObdRequest() {
	pidIndex = (pidIndex + 1) % NUM_PIDS_TO_REQUEST;

	CANMessage message;
	message.id = OBD_CAN_BROADCAST_ID;
	message.len = 8; // just always use 8
	message.data[0] = 0x02; // 0 = single-frame format, 2  = num data bytes
	message.data[1] = OBD_MODE_CURRENT_DATA; // OBD MODE
	message.data[2] = pidsToRequest[pidIndex]; // OBD PID

	carloop.can().transmit(message);

	obdLoopFunction = waitForObdResponse;
	transitionTime = millis();
}

void waitForObdResponse() {
	if (millis() - transitionTime >= 10) {
		obdLoopFunction = delayUntilNextRequest;
		transitionTime = millis();
		return;
	}
    bool responseReceived = false;
	String dump;
	CANMessage message;
	while (carloop.can().receive(message)) {
		canMessageCount++;
		if (message.id == 0x130) {
			if (!byteArray8Equal(message.data, lastMessageData)) {
				memcpy(lastMessageData, message.data, 8);
			}
		} else {
			if (message.id >= OBD_CAN_REPLY_ID_MIN &&
					message.id <= OBD_CAN_REPLY_ID_MAX &&
					message.data[2] == pidsToRequest[pidIndex]) {
				    responseReceived = true;
                    data0 = message.data[0];
                    data1 = message.data[1];
			        data2 = message.data[2];
                    data3 = message.data[3];
                    data4 = message.data[4];
                    data5 = message.data[5];
                    data6 = message.data[6];
                    data7 = message.data[7];
                    return;
					}
		return;
		}
	return;
	}
}


void delayUntilNextRequest() {
	if (millis() - transitionTime >= 8) {
		obdLoopFunction = sendObdRequest;
		transitionTime = millis();
	}
}

/*************** End: OBD Loop Functions ****************/


void printValuesAtInterval() {
	static const unsigned long interval = 500;
	static unsigned long lastDisplay = 0;
	if (millis() - lastDisplay < interval) {
		return;
	}
	lastDisplay = millis();
	printValues();
}

void printValues() {

/////////////////////////////
//PRINT VALUES FOR DEBUGING//
/////////////////////////////

//    Serial.print("Engine Load: ");
//    Serial.println(ENGINE_LOAD);
    
 
}

void publishValuesAtInterval() {
    static const unsigned long interval2 = 10000;
	static unsigned long lastDisplay2 = 0;
    if(millis() - lastDisplay2 < interval2) {
        return;
    }
    lastDisplay2 = millis();
    publishValues();
    blynkValues();
}


///////////////////////////////////////////////////
//FUNCTION TO SEND DATA TO BYNK FOR VISUALIZATION//
//THESE PARAMETERS ARE HERE AS AN EXAMPLE AND ARE//
//AVAILABLE ON MY 2016 MIATA///////////////////////

void blynkValues() {
    //TODO: ONLY SEND DATA WHEN THE ENGINE IS ON
            Blynk.run();
            String StringMIL_STATUS                             = String(MIL_STATUS);
            String StringFUEL_SYSTEM_STATUS                     = String(FUEL_SYSTEM_STATUS);
	    String StringENGINE_LOAD                            = String(ENGINE_LOAD);
	    String StringENGINE_COOLANT_TEMPERATURE             = String(ENGINE_COOLANT_TEMPERATURE);
	    String StringSHORT_TERM_FUEL_TRIM_BANK_1            = String(SHORT_TERM_FUEL_TRIM_BANK_1);
	    String StringLONG_TERM_FUEL_TRIM_BANK_1             = String(LONG_TERM_FUEL_TRIM_BANK_1);
	    String StringINTAKE_MANIFOLD_PRESSURE               = String(INTAKE_MANIFOLD_PRESSURE);
	    String StringENGINE_RPM                             = String(ENGINE_RPM);
	    String StringVEHICLE_SPEED                          = String(VEHICLE_SPEED);
	    String StringTIMING_ADVANCE                         = String(TIMING_ADVANCE);
	    String StringINTAKE_AIR_TEMPERATURE                 = String(INTAKE_AIR_TEMPERATURE);
	    String StringMAF_AIR_FLOW_RATE                      = String(MAF_AIR_FLOW_RATE);
	    String StringTHROTTLE                               = String(THROTTLE);
	    String StringO2_V_6                                 = String(O2_V_6);
	    String StringO2_T_6                                 = String(O2_T_6);
	    String StringDISTANCE_TRAVELED_WITH_MIL_ON          = String(DISTANCE_TRAVELED_WITH_MIL_ON);
	    String StringCOMMANDED_EVAPORATIVE_PURGE            = String(COMMANDED_EVAPORATIVE_PURGE);
	    String StringFUEL_TANK_LEVEL_INPUT                  = String(FUEL_TANK_LEVEL_INPUT);
	    String StringWARM_UPS_SINCE_CODES_CLEARED           = String(WARM_UPS_SINCE_CODES_CLEARED);
	    String StringDISTANCE_TRAVELED_SINCE_CODES_CLEARED  = String(DISTANCE_TRAVELED_SINCE_CODES_CLEARED);
	    String StringEVAPORATOR_SYSTEM_PRESSURE             = String(EVAPORATOR_SYSTEM_PRESSURE);
	    String StringABSOLUTE_BAROMETRIC_PRESSURE           = String(ABSOLUTE_BAROMETRIC_PRESSURE);
	    String StringO2_F_A_E_R_C_1_FUEL                    = String(O2_F_A_E_R_C_1_FUEL);
	    String StringCATALYST_TEMPERATURE_BANK1_SENSOR1     = String(CATALYST_TEMPERATURE_BANK1_SENSOR1);
	    String StringCONTROL_MODULE_VOLTAGE                 = String(CONTROL_MODULE_VOLTAGE);
	    String StringABSOLUTE_LOAD_VALUE                    = String(ABSOLUTE_LOAD_VALUE);
	    String StringFUEL_AIR_COMMANDED_EQUIV_RATIO         = String(FUEL_AIR_COMMANDED_EQUIV_RATIO);
	    String StringRELATIVE_THROTTLE_POSITION             = String(RELATIVE_THROTTLE_POSITION);
	    String StringAMBIENT_AIR_TEMPERATURE                = String(AMBIENT_AIR_TEMPERATURE);
	    String StringABSOLUTE_THROTTLE_B                    = String(ABSOLUTE_THROTTLE_B);
	    String StringACCELERATOR_PEDAL_POSITION_D           = String(ACCELERATOR_PEDAL_POSITION_D);
	    String StringACCELERATOR_PEDAL_POSITION_E           = String(ACCELERATOR_PEDAL_POSITION_E);
	    String StringFUEL_TYPE                              = String(FUEL_TYPE);
	    String StringFUEL_RAIL_ABSOLUTE_PRESSURE            = String(FUEL_RAIL_ABSOLUTE_PRESSURE);
	    
	    ////////////////////////////
	    //PUBLISH STRINGS TO BLYNK//
	    ////////////////////////////
	    Blynk.virtualWrite(V0, StringMIL_STATUS);
	    Blynk.virtualWrite(V1, StringFUEL_SYSTEM_STATUS);
	    Blynk.virtualWrite(V2, StringENGINE_LOAD);
	    Blynk.virtualWrite(V3, StringENGINE_COOLANT_TEMPERATURE);
	    Blynk.virtualWrite(V4, StringSHORT_TERM_FUEL_TRIM_BANK_1);
	    Blynk.virtualWrite(V5, StringLONG_TERM_FUEL_TRIM_BANK_1);
	    Blynk.virtualWrite(V6, StringINTAKE_MANIFOLD_PRESSURE);
	    Blynk.virtualWrite(V7, StringENGINE_RPM);
	    Blynk.virtualWrite(V8, StringVEHICLE_SPEED);
	    Blynk.virtualWrite(V9, StringTIMING_ADVANCE);
	    Blynk.virtualWrite(V10, StringINTAKE_AIR_TEMPERATURE);
	    Blynk.virtualWrite(V11, StringMAF_AIR_FLOW_RATE);
	    Blynk.virtualWrite(V12, StringTHROTTLE);
	    Blynk.virtualWrite(V13, StringO2_V_6);
	    Blynk.virtualWrite(V14, StringO2_T_6);
	    Blynk.virtualWrite(V15, StringDISTANCE_TRAVELED_WITH_MIL_ON);
	    Blynk.virtualWrite(V16, StringCOMMANDED_EVAPORATIVE_PURGE);
	    Blynk.virtualWrite(V17, StringFUEL_TANK_LEVEL_INPUT);
	    Blynk.virtualWrite(V18, StringWARM_UPS_SINCE_CODES_CLEARED);
	    Blynk.virtualWrite(V19, StringDISTANCE_TRAVELED_SINCE_CODES_CLEARED);
	    Blynk.virtualWrite(V20, StringEVAPORATOR_SYSTEM_PRESSURE);
	    Blynk.virtualWrite(V21, StringABSOLUTE_BAROMETRIC_PRESSURE);
	    Blynk.virtualWrite(V22, StringO2_F_A_E_R_C_1_FUEL);
	    Blynk.virtualWrite(V23, StringCATALYST_TEMPERATURE_BANK1_SENSOR1);
	    Blynk.virtualWrite(V24, StringCONTROL_MODULE_VOLTAGE);
	    Blynk.virtualWrite(V25, StringABSOLUTE_LOAD_VALUE);
	    Blynk.virtualWrite(V26, StringFUEL_AIR_COMMANDED_EQUIV_RATIO);
	    Blynk.virtualWrite(V27, StringRELATIVE_THROTTLE_POSITION);
	    Blynk.virtualWrite(V28, StringAMBIENT_AIR_TEMPERATURE);
	    Blynk.virtualWrite(V29, StringABSOLUTE_THROTTLE_B);
	    Blynk.virtualWrite(V30, StringACCELERATOR_PEDAL_POSITION_D);
	    Blynk.virtualWrite(V31, StringACCELERATOR_PEDAL_POSITION_E);
	    Blynk.virtualWrite(V32, StringFUEL_TYPE);
	    Blynk.virtualWrite(V33, StringFUEL_RAIL_ABSOLUTE_PRESSURE);

}

//////////////////////////////////////
//ALMOST EVERY MODE 1 OBDII PID MATH//
//////////////////////////////////////

void math() {

//void mathMIL_STATUS() {
    
    if (data2 == 2) {
        float MILStatus;
        MILStatus = (data3>>7) & 1;
        MIL_STATUS = MILStatus;
    }
//}

//void mathFUEL_SYSTEM_STATUS() {
    
    if (data2 == 3) {
        float fuelSystemStatus;
        fuelSystemStatus = data3;
        FUEL_SYSTEM_STATUS = fuelSystemStatus;
    }
//}

//void mathENGINE_LOAD() {
    
    if (data2 == 4) {
        float load;
        load = (data3)/2.55;
        ENGINE_LOAD = load;
    }
//}

//void mathENGINE_COOLANT_TEMPERATURE() {
    
    if (data2 == 5) {
        float coolantTemp;
        coolantTemp = (data3)-40;
        ENGINE_COOLANT_TEMPERATURE = coolantTemp;
    }
//}

//void mathSHORT_TERM_FUEL_TRIM_BANK_1() {
    
    if (data2 == 6) {
        float stFuelTrimBank1;
        stFuelTrimBank1 = (data3/1.28 - 100);
        SHORT_TERM_FUEL_TRIM_BANK_1 = stFuelTrimBank1;
    }
//}

//void mathLONG_TERM_FUEL_TRIM_BANK_1() {
    
    if (data2 == 7) {
        float ltFuelTrimBank1;
        ltFuelTrimBank1 = (data3/1.28 - 100);
        LONG_TERM_FUEL_TRIM_BANK_1 = ltFuelTrimBank1;
    }
//}

//void mathSHORT_TERM_FUEL_TRIM_BANK_2() {
    
    if (data2 == 8) {
        float stFuelTrimBank2;
        stFuelTrimBank2 = (data3/1.28 - 100);
        SHORT_TERM_FUEL_TRIM_BANK_2 = stFuelTrimBank2;
    }
//}

//void mathLONG_TERM_FUEL_TRIM_BANK_2() {
    
    if (data2 == 9) {
        float ltFuelTrimBank2;
        ltFuelTrimBank2 = (data3/1.28 - 100);
        LONG_TERM_FUEL_TRIM_BANK_2 = ltFuelTrimBank2;
    }
//}

//void mathFUEL_PRESSURE() {
    
    if (data2 == 10) {
        float fuelPressure;
        fuelPressure = (data3*3);
        FUEL_PRESSURE = fuelPressure;
    }
//}

//void mathINTAKE_MANIFOLD_PRESSURE() {
    
    if (data2 == 11) {
        float intakeManifoldPressure;
        intakeManifoldPressure = (data3);
        INTAKE_MANIFOLD_PRESSURE = intakeManifoldPressure;
    }
//}

//void mathENGINE_RPM() {


    if (data2 == 12) {
        float RPM1;
        float RPM2;
        RPM1 = data3;
        RPM2 = data4;
        ENGINE_RPM = ((RPM1*256)+RPM2)/4;
    }
//}

//void mathVEHICLE_SPEED() {
    
    if (data2 == 13) {
        float vehicleSpeed;
        vehicleSpeed = (data3);
        VEHICLE_SPEED = vehicleSpeed;
    }
//}

//void mathTIMING_ADVANCE() {
	
	if (data2 == 14) {
	    float timingAdvance;
		timingAdvance = (data3/2 - 64);
		TIMING_ADVANCE = timingAdvance;
	}
//}

//void mathINTAKE_AIR_TEMPERATURE() {
	
	if (data2 == 15) {
	    float intakeAirTemperature;
		intakeAirTemperature = (data3 - 40);
		INTAKE_AIR_TEMPERATURE = intakeAirTemperature;
	}
//}

//void mathMAF_AIR_FLOW_RATE() {
	
	if (data2 == 16) {
	    float MAFAirFlowRate1;
	    float MAFAirFlowRate2;
		MAFAirFlowRate1 = data3;
		MAFAirFlowRate2 = data4;
		MAF_AIR_FLOW_RATE = ((MAFAirFlowRate1*256)+MAFAirFlowRate2)/4;
	}
//}

//void mathTHROTTLE() {
    
    if (data2 == 17) {
        float throttle;
        throttle = (data3)/2.55;
        THROTTLE = throttle;
    }
//}

//void mathCOMMANDED_SECONDARY_AIR_STATUS() {
    
    if (data2 == 18) {
        float commandedSecondaryAirStatus;
        commandedSecondaryAirStatus = (data3);
        COMMANDED_SECONDARY_AIR_STATUS = commandedSecondaryAirStatus;
    }
//}

//void mathO2_V_T_1(){
    
    if (data2 == 20) {
        float o2Voltage1;
        float o2Trim1;
        o2Voltage1 = data3/200;
        o2Trim1 = data4/1.28-100;
        O2_V_1 = o2Voltage1;
        O2_T_1 = o2Trim1;
    }
//}

//void mathO2_V_T_2(){
    
    if (data2 == 21) {
        float o2Voltage1;
        float o2Trim1;
        o2Voltage1 = data3/200;
        o2Trim1 = data4/1.28-100;
        O2_V_2 = o2Voltage1;
        O2_T_2 = o2Trim1;
    }
//}

//void mathO2_V_T_3(){
    
    if (data2 == 22) {
        float o2Voltage1;
        float o2Trim1;
        o2Voltage1 = data3/200;
        o2Trim1 = data4/1.28-100;
        O2_V_3 = o2Voltage1;
        O2_T_3 = o2Trim1;
    }
//}

//void mathO2_V_T_4(){
    
    if (data2 == 23) {
        float o2Voltage1;
        float o2Trim1;
        o2Voltage1 = data3/200;
        o2Trim1 = data4/1.28-100;
        O2_V_4 = o2Voltage1;
        O2_T_4 = o2Trim1;
    }
//}

//void mathO2_V_T_5(){

    if (data2 == 24) {
        float o2Voltage1;
        float o2Trim1;
        o2Voltage1 = data3/200;
        o2Trim1 = data4/1.28-100;
        O2_V_5 = o2Voltage1;
        O2_T_5 = o2Trim1;
    }
//}

//void mathO2_V_T_6(){
    
    if (data2 == 25) {
        float o2Voltage1;
        float o2Trim1;
        o2Voltage1 = data3/200;
        o2Trim1 = data4/1.28-100;
        O2_V_6 = o2Voltage1;
        O2_T_6 = o2Trim1;
    }
//}

//void mathO2_V_T_7(){
    
    if (data2 == 26) {
        float o2Voltage1;
        float o2Trim1;
        o2Voltage1 = data3/200;
        o2Trim1 = data4/1.28-100;
        O2_V_7 = o2Voltage1;
        O2_T_7 = o2Trim1;
    }
//}

//void mathO2_V_T_8(){
    
    if (data2 == 27) {
        float o2Voltage1;
        float o2Trim1;
        o2Voltage1 = data3/200;
        o2Trim1 = data4/1.28-100;
        O2_V_8 = o2Voltage1;
        O2_T_8 = o2Trim1;
    }
//}

//void mathENGINE_RUN_TIME() {
    
    if (data2 == 31) {
        float engineRunTime1;
        float engineRunTime2;
        engineRunTime1 = data3;
        engineRunTime2 = data4;
        ENGINE_RUN_TIME = (engineRunTime1*256+engineRunTime2);
    }
//}

//void mathDISTANCE_TRAVELED_WITH_MIL_ON() {
    
    if (data2 == 33) {
        float distanceTraveledWithMILOn1;
        float distanceTraveledWithMILOn2;
        distanceTraveledWithMILOn1 = data3;
        distanceTraveledWithMILOn2 = data4;
        DISTANCE_TRAVELED_WITH_MIL_ON = (distanceTraveledWithMILOn1*256+distanceTraveledWithMILOn2);
    }
//}

//void mathFUEL_RAIL_PRESSURE() {
    
    if (data2 == 34) {
        float fuelRailPressureA;
        float fuelRailPressureB;
        fuelRailPressureA = data3;
        fuelRailPressureB = data4;
        FUEL_RAIL_PRESSURE = 0.079*(256*fuelRailPressureA+fuelRailPressureB);
    }
//}

//void mathFUEL_RAIL_GAUGE_PRESSURE() {
    
    if (data2 == 35) {
        float fuelRailGaugePressureA;
        float fuelRailGaugePressureB;
        fuelRailGaugePressureA = data3;
        fuelRailGaugePressureB = data4;
        FUEL_RAIL_GAUGE_PRESSURE = 10*(256*fuelRailGaugePressureA+fuelRailGaugePressureB);
    }
//}

//void mathOBD_PID_O2_F_A_E_R_V_1() {
    
    if (data2 == 36) {
        float fuelAirRatioA;
        float fuelAirRatioB;
        float voltageC;
        float voltageD;
        fuelAirRatioA = data3;
        fuelAirRatioB = data4;
        voltageC = data5;
        voltageD = data6;
        O2_F_A_E_R_V_1_FUEL = (2/65536)*(256*fuelAirRatioA+fuelAirRatioB);
        O2_F_A_E_R_V_1_VOLTAGE = (8/65536)*(256*voltageC+voltageD);
        
    }
//}

//void mathOBD_PID_O2_F_A_E_R_V_2() {
    
    if (data2 == 37) {
        float fuelAirRatioA;
        float fuelAirRatioB;
        float voltageC;
        float voltageD;
        fuelAirRatioA = data3;
        fuelAirRatioB = data4;
        voltageC = data5;
        voltageD = data6;
        O2_F_A_E_R_V_2_FUEL = (2/65536)*(256*fuelAirRatioA+fuelAirRatioB);
        O2_F_A_E_R_V_2_VOLTAGE = (8/65536)*(256*voltageC+voltageD);
        
    }
//}

//void mathOBD_PID_O2_F_A_E_R_V_3() {
    
    if (data2 == 38) {
        float fuelAirRatioA;
        float fuelAirRatioB;
        float voltageC;
        float voltageD;
        fuelAirRatioA = data3;
        fuelAirRatioB = data4;
        voltageC = data5;
        voltageD = data6;
        O2_F_A_E_R_V_3_FUEL = (2/65536)*(256*fuelAirRatioA+fuelAirRatioB);
...

This file has been truncated, please download it to see its full contents.

Available Mode 1 PIDs

Arduino
Use this code to print out available PIDs
/*
 * Copyright 2016 Emerson Garland
 * Free to modify, share and do whatever, just give me credit if you like it!
 *
 * This code will loop over requesting PID availablility and print all parameters available.
 * Monitor you com port (ensure you've installed necessary drivers!) using your favorite tool, program below is set to 115200 baud.
 * Reference https://en.wikipedia.org/wiki/OBD-II_PIDs#Mode_1_PID_00 for pid info.
 *
 *
 * Be sure to include carloop library via the web ide. Libraries>(search Carloop)>add to existing app.
 *
 *
 * Make sure to include base85.h in the ide.
 */




//#include "carloop.h"
#include "base85.h"


SYSTEM_MODE(SEMI_AUTOMATIC);
SYSTEM_THREAD(ENABLED);

void sendObdRequest();
void waitForObdResponse();
void delayUntilNextRequest();
void printValuesAtInterval();
void publishValuesAtInterval();
void printValues();


String dumpMessage(const CANMessage &message);
bool byteArray8Equal(uint8_t a1[8], uint8_t a2[8]);

Carloop<CarloopRevision2> carloop;

int canMessageCount = 0;

///////////////////////////////////////////////////////////////////////////
//GLOBAL INTEGERS FOR USE IN PERFORMING MATH AND EXTRACTION OF OBDII DATA//
///////////////////////////////////////////////////////////////////////////
int data0;
int data1;
int data2;
int data3;
int data4;
int data5;
int data6;
int data7;

int PID_Array[] = {data3, data4, data5, data6};


int AvailablePID_1_20[32];
int AvailablePID_21_40[32];
int AvailablePID_41_60[32];
int AvailablePID_61_80[32];

// OBD CAN MESSAGE IDs
const auto OBD_CAN_BROADCAST_ID    = 0X7DF;
const auto OBD_CAN_REQUEST_ID      = 0x7E0;
const auto OBD_CAN_REPLY_ID_MIN    = 0x7E8;
const auto OBD_CAN_REPLY_ID_MAX    = 0x7EF;

// OBD MODES
const auto OBD_MODE_CURRENT_DATA = 0x01;


///////////////////////////////////////////////////////////////////////////////
//LIST OF ALL MODE 1 AVAILABLE PIDS POLLING. NOT ALL MAY BE AVAILABLE TO YOU.//
///////////////////////////////////////////////////////////////////////////////

const auto OBD_PID_SUPPORTED_PIDS_01_20                  = 0x00;
const auto OBD_PID_SUPPORTED_PIDS_21_40                  = 0x20;
const auto OBD_PID_SUPPORTED_PIDS_41_60                  = 0x40;
const auto OBD_PID_SUPPORTED_PIDS_61_80                  = 0x60;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//SUM THE TOTAL AMOUNT OF PIDS YOU WOULD LIKE TO REQUEST AND PLACE THAT IN const size_t NUM_PIDS_TO_REQUEST// 
/////////////////////////////////////////////////////////////////////////////////////////////////////////////

const size_t NUM_PIDS_TO_REQUEST = 4;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//COMMENT OUT OR REMOVE THE PIDS THAT YOU DO NOT HAVE TO INCREASE EFFECIENCY BUT BE SURE TO UPDATE THE ABOVE CONSTANT//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

const uint8_t pidsToRequest[NUM_PIDS_TO_REQUEST] = {
    
OBD_PID_SUPPORTED_PIDS_01_20,
OBD_PID_SUPPORTED_PIDS_21_40,
OBD_PID_SUPPORTED_PIDS_41_60,
OBD_PID_SUPPORTED_PIDS_61_80

};
    
    
uint8_t pidIndex = NUM_PIDS_TO_REQUEST - 1;

String dumpForPublish;

auto *obdLoopFunction = sendObdRequest;
unsigned long transitionTime = 0;
uint8_t lastMessageData[8];

void setup() {

	Serial.begin(115200);
	carloop.begin();
	Particle.connect();
	transitionTime = millis();
}



void loop() {
	
	carloop.update();
	printValuesAtInterval();
	obdLoopFunction();
	waitForObdResponse();
    math();
    
}


/*************** Begin: OBD Loop Functions ****************/

void sendObdRequest() {
	pidIndex = (pidIndex + 1) % NUM_PIDS_TO_REQUEST;

	CANMessage message;
	message.id = OBD_CAN_BROADCAST_ID;
	message.len = 8; // just always use 8
	message.data[0] = 0x02; // 0 = single-frame format, 2  = num data bytes
	message.data[1] = OBD_MODE_CURRENT_DATA; // OBD MODE
	message.data[2] = pidsToRequest[pidIndex]; // OBD PID

	carloop.can().transmit(message);

	obdLoopFunction = waitForObdResponse;
	transitionTime = millis();
}

void waitForObdResponse() {
	if (millis() - transitionTime >= 10) {
		obdLoopFunction = delayUntilNextRequest;
		transitionTime = millis();
		return;
	}
    bool responseReceived = false;
	String dump;
	CANMessage message;
	while (carloop.can().receive(message)) {
		canMessageCount++;
		if (message.id == 0x130) {
			if (!byteArray8Equal(message.data, lastMessageData)) {
				memcpy(lastMessageData, message.data, 8);
			}
		} else {
			if (message.id >= OBD_CAN_REPLY_ID_MIN &&
					message.id <= OBD_CAN_REPLY_ID_MAX &&
					message.data[2] == pidsToRequest[pidIndex]) {
				    responseReceived = true;
				    //Serial.println("response recieved");
                    data0 = message.data[0];
                    data1 = message.data[1];
			        data2 = message.data[2];
                    data3 = message.data[3];
                    data4 = message.data[4];
                    data5 = message.data[5];
                    data6 = message.data[6];
                    data7 = message.data[7];
                    
                    PID_Array[0] = message.data[3];
                    PID_Array[1] = message.data[4];
                    PID_Array[2] = message.data[5];
                    PID_Array[3] = message.data[6];
                    
                    return;
					}
		return;
		}
	return;
	}
}


void delayUntilNextRequest() {
	if (millis() - transitionTime >= 8) {
		obdLoopFunction = sendObdRequest;
		transitionTime = millis();
	}
}

/*************** End: OBD Loop Functions ****************/


void printValuesAtInterval() {
	static const unsigned long interval = 10000;
	static unsigned long lastDisplay = 0;
	if (millis() - lastDisplay < interval) {
		return;
	}
	lastDisplay = millis();
	printValues();
}

void printValues() {

    //PIDs 1-20 in HEX
    Serial.println("**************Printing PIDs 0-20 (HEXIDECIMAL)**************");
    if (AvailablePID_1_20[7] == true) {
        Serial.println("Monitor status since DTCs cleared");
    }
    if (AvailablePID_1_20[6] == true) {
        Serial.println("Freeze DTC");
    }
    if (AvailablePID_1_20[5] == true) {
        Serial.println("Fuel system status");
    }
    if (AvailablePID_1_20[4] == true) {
        Serial.println("Calculated engine load");
    }
    if (AvailablePID_1_20[3] == true) {
        Serial.println("Engine coolant temperature");
    }
    if (AvailablePID_1_20[2] == true) {
        Serial.println("Short term fuel trim Bank 1");
    }
    if (AvailablePID_1_20[1] == true) {
        Serial.println("Long term fuel trim Bank 1");
    }
    if (AvailablePID_1_20[0] == true) {
        Serial.println("Short term fuel trim Bank 2");
    }
    if (AvailablePID_1_20[15] == true) {
        Serial.println("Long term fuel trim Bank 2");
    }
    if (AvailablePID_1_20[14] == true) {
        Serial.println("Fuel pressure");
    }
    if (AvailablePID_1_20[13] == true) {
        Serial.println("Intake manifold absolute pressure");
    }
    if (AvailablePID_1_20[12] == true) {
        Serial.println("Engine RPM");
    }
    if (AvailablePID_1_20[11] == true) {
        Serial.println("Vehicle speed");
    }
    if (AvailablePID_1_20[10] == true) {
        Serial.println("Timing advance");
    }
    if (AvailablePID_1_20[9] == true) {
        Serial.println("Intake air temperature");
    }
    if (AvailablePID_1_20[8] == true) {
        Serial.println("MAF air flow rate");
    }
    if (AvailablePID_1_20[23] == true) {
        Serial.println("Throttle position");
    }
    if (AvailablePID_1_20[22] == true) {
        Serial.println("Commanded secondary air status");
    }
    if (AvailablePID_1_20[21] == true) {
        Serial.println("Oxygen sensors present (in 2 banks)");
    }
    if (AvailablePID_1_20[20] == true) {
        Serial.println("Oxygen Sensor 1 A:Voltage B:Short term fuel trim");
    }
    if (AvailablePID_1_20[19] == true) {
        Serial.println("Oxygen Sensor 2 A:Voltage B:Short term fuel trim");
    }
    if (AvailablePID_1_20[18] == true) {
        Serial.println("Oxygen Sensor 3 A:Voltage B:Short term fuel trim");
    }
    if (AvailablePID_1_20[17] == true) {
        Serial.println("Oxygen Sensor 4 A:Voltage B:Short term fuel trim");
    }
    if (AvailablePID_1_20[16] == true) {
        Serial.println("Oxygen Sensor 5 A:Voltage B:Short term fuel trim");
    }
    if (AvailablePID_1_20[31] == true) {
        Serial.println("Oxygen Sensor 6 A:Voltage B:Short term fuel trim");
    }
    if (AvailablePID_1_20[30] == true) {
        Serial.println("Oxygen Sensor 7 A:Voltage B:Short term fuel trim");
    }
    if (AvailablePID_1_20[29] == true) {
        Serial.println("Oxygen Sensor 8 A:Voltage B:Short term fuel trim");
    }
    if (AvailablePID_1_20[28] == true) {
        Serial.println("OBD standards this vehicle conforms to");
    }
    if (AvailablePID_1_20[27] == true) {
        Serial.println("Oxygen sensors present (in 4 banks)");
    }
    if (AvailablePID_1_20[26] == true) {
        Serial.println("Auxiliary input status");
    }
    if (AvailablePID_1_20[25] == true) {
        Serial.println("Run time since engine start");
    }
    if (AvailablePID_1_20[24] == true) {
        Serial.println("PIDs supported [21 - 40]");
    }
    
    //PIDs 21-40 in HEX
    Serial.println("**************Printing PIDs 21-40 (HEXIDECIMAL)**************");
    if (AvailablePID_21_40[7] == true) {
        Serial.println("Distance traveled with malfunction indicator lamp (MIL) on");
    }
    if (AvailablePID_21_40[6] == true) {
        Serial.println("Fuel Rail Pressure (relative to manifold vacuum)");
    }
    if (AvailablePID_21_40[5] == true) {
        Serial.println("Fuel Rail Gauge Pressure (diesel, or gasoline direct injection)");
    }
    if (AvailablePID_21_40[4] == true) {
        Serial.println("Oxygen Sensor 1 AB: Fuel Air Equivalence Ratio CD: Voltage");
    }
    if (AvailablePID_21_40[3] == true) {
        Serial.println("Oxygen Sensor 2 AB: Fuel Air Equivalence Ratio CD: Voltage");
    }
    if (AvailablePID_21_40[2] == true) {
        Serial.println("Oxygen Sensor 3 AB: Fuel Air Equivalence Ratio CD: Voltage");
    }
    if (AvailablePID_21_40[1] == true) {
        Serial.println("Oxygen Sensor 4 AB: Fuel Air Equivalence Ratio CD: Voltage");
    }
    if (AvailablePID_21_40[0] == true) {
        Serial.println("Oxygen Sensor 5 AB: Fuel Air Equivalence Ratio CD: Voltage");
    }
    if (AvailablePID_21_40[15] == true) {
        Serial.println("Oxygen Sensor 6 AB: Fuel Air Equivalence Ratio CD: Voltage");
    }
    if (AvailablePID_21_40[14] == true) {
        Serial.println("Oxygen Sensor 7 AB: Fuel Air Equivalence Ratio CD: Voltage");
    }
    if (AvailablePID_21_40[13] == true) {
        Serial.println("Oxygen Sensor 8 AB: Fuel Air Equivalence Ratio CD: Voltage");
    }
    if (AvailablePID_21_40[12] == true) {
        Serial.println("Commanded EGR");
    }
    if (AvailablePID_21_40[11] == true) {
        Serial.println("EGR Error");
    }
    if (AvailablePID_21_40[10] == true) {
        Serial.println("Commanded evaporative purge");
    }
    if (AvailablePID_21_40[9] == true) {
        Serial.println("Fuel Tank Level Input");
    }
    if (AvailablePID_21_40[8] == true) {
        Serial.println("Warm-ups since codes cleared");
    }
    if (AvailablePID_21_40[23] == true) {
        Serial.println("Distance traveled since codes cleared");
    }
    if (AvailablePID_21_40[22] == true) {
        Serial.println("Evap. System Vapor Pressure");
    }
    if (AvailablePID_21_40[21] == true) {
        Serial.println("Absolute Barometric Pressure");
    }
    if (AvailablePID_21_40[20] == true) {
        Serial.println("Oxygen Sensor 1 AB: Fuel Air Equivalence Ratio CD: Current");
    }
    if (AvailablePID_21_40[19] == true) {
        Serial.println("Oxygen Sensor 2 AB: Fuel Air Equivalence Ratio CD: Current");
    }
    if (AvailablePID_21_40[18] == true) {
        Serial.println("Oxygen Sensor 3 AB: Fuel Air Equivalence Ratio CD: Current");
    }
    if (AvailablePID_21_40[17] == true) {
        Serial.println("Oxygen Sensor 4 AB: Fuel Air Equivalence Ratio CD: Current");
    }
    if (AvailablePID_21_40[16] == true) {
        Serial.println("Oxygen Sensor 5 AB: Fuel Air Equivalence Ratio CD: Current");
    }
    if (AvailablePID_21_40[31] == true) {
        Serial.println("Oxygen Sensor 6 AB: Fuel Air Equivalence Ratio CD: Current");
    }
    if (AvailablePID_21_40[30] == true) {
        Serial.println("Oxygen Sensor 7 AB: Fuel Air Equivalence Ratio CD: Current");
    }
    if (AvailablePID_21_40[29] == true) {
        Serial.println("Oxygen Sensor 8 AB: Fuel Air Equivalence Ratio CD: Current");
    }
    if (AvailablePID_21_40[28] == true) {
        Serial.println("Catalyst Temperature: Bank 1, Sensor 1");
    }
    if (AvailablePID_21_40[27] == true) {
        Serial.println("Catalyst Temperature: Bank 2, Sensor 1");
    }
    if (AvailablePID_21_40[26] == true) {
        Serial.println("Catalyst Temperature: Bank 1, Sensor 2");
    }
    if (AvailablePID_21_40[25] == true) {
        Serial.println("Catalyst Temperature: Bank 2, Sensor 2");
    }
    if (AvailablePID_21_40[24] == true) {
        Serial.println("PIDs supported [41 - 60]");
    }
    
    //PIDs41-60 in HEX
    Serial.println("**************Printing PIDs 41-60 (HEXIDECIMAL)**************");
    if (AvailablePID_41_60[7] == true) {
        Serial.println("Monitor status this drive cycle");
    }
    if (AvailablePID_41_60[6] == true) {
        Serial.println("Control module voltage");
    }
    if (AvailablePID_41_60[5] == true) {
        Serial.println("Absolute load value");
    }
    if (AvailablePID_41_60[4] == true) {
        Serial.println("Fuel Air commanded equivalence ratio");
    }
    if (AvailablePID_41_60[3] == true) {
        Serial.println("Relative throttle position");
    }
    if (AvailablePID_41_60[2] == true) {
        Serial.println("Ambient air temperature");
    }
    if (AvailablePID_41_60[1] == true) {
        Serial.println("Absolute throttle position B");
    }
    if (AvailablePID_41_60[0] == true) {
        Serial.println("Absolute throttle position C");
    }
    if (AvailablePID_41_60[15] == true) {
        Serial.println("Accelerator pedal position D");
    }
    if (AvailablePID_41_60[14] == true) {
        Serial.println("Accelerator pedal position E");
    }
    if (AvailablePID_41_60[13] == true) {
        Serial.println("Accelerator pedal position F");
    }
    if (AvailablePID_41_60[12] == true) {
        Serial.println("Commanded throttle actuator");
    }
    if (AvailablePID_41_60[11] == true) {
        Serial.println("Time run with MIL on");
    }
    if (AvailablePID_41_60[10] == true) {
        Serial.println("Time since trouble codes cleared");
    }
    if (AvailablePID_41_60[9] == true) {
        Serial.println("Maximum value for Fuel–Air equivalence ratio, oxygen sensor voltage, oxygen sensor current, and intake manifold absolute pressure");
    }
    if (AvailablePID_41_60[8] == true) {
        Serial.println("Maximum value for air flow rate from mass air flow sensor");
    }
    if (AvailablePID_41_60[23] == true) {
        Serial.println("Fuel Type");
    }
    if (AvailablePID_41_60[22] == true) {
        Serial.println("Ethanol fuel %");
    }
    if (AvailablePID_41_60[21] == true) {
        Serial.println("Absolute Evap system Vapor Pressure");
    }
    if (AvailablePID_41_60[20] == true) {
        Serial.println("Evap system vapor pressure");
    }
    if (AvailablePID_41_60[19] == true) {
        Serial.println("Short term secondary oxygen sensor trim, A: bank 1, B: bank 3");
    }
    if (AvailablePID_41_60[18] == true) {
        Serial.println("Long term secondary oxygen sensor trim, A: bank 1, B: bank 3");
    }
    if (AvailablePID_41_60[17] == true) {
        Serial.println("Short term secondary oxygen sensor trim, A: bank 2, B: bank 4");
    }
    if (AvailablePID_41_60[16] == true) {
        Serial.println("Long term secondary oxygen sensor trim, A: bank 2, B: bank 4");
    }
    if (AvailablePID_41_60[31] == true) {
        Serial.println("Fuel rail absolute pressure");
    }
    if (AvailablePID_41_60[30] == true) {
        Serial.println("Relative accelerator pedal position");
    }
    if (AvailablePID_41_60[29] == true) {
        Serial.println("Hybrid battery pack remaining life");
    }
    if (AvailablePID_41_60[28] == true) {
        Serial.println("Engine oil temperature");
    }
    if (AvailablePID_41_60[27] == true) {
        Serial.println("Fuel injection timing");
    }
    if (AvailablePID_41_60[26] == true) {
        Serial.println("Engine fuel rate");
    }
    if (AvailablePID_41_60[25] == true) {
        Serial.println("Emission requirements to which vehicle is designed");
    }
    if (AvailablePID_41_60[24] == true) {
        Serial.println("PIDs supported [61 - 80]");
    }
    
    Serial.println("**************Printing PIDs 61-80 (HEXIDECIMAL)**************");
    if (AvailablePID_61_80[7] == true) {
        Serial.println("Driver's demand engine - percent torque");
    }
    if (AvailablePID_61_80[6] == true) {
        Serial.println("Actual engine - percent torque");
    }
    if (AvailablePID_61_80[5] == true) {
        Serial.println("Engine reference torque");
    }
    if (AvailablePID_61_80[4] == true) {
        Serial.println("Engine percent torque data");
    }
    if (AvailablePID_61_80[3] == true) {
        Serial.println("Auxiliary input / output supported");
    }
    if (AvailablePID_61_80[2] == true) {
        Serial.println("Mass air flow sensor");
    }
    if (AvailablePID_61_80[1] == true) {
        Serial.println("Engine coolant temperature");
    }
    if (AvailablePID_61_80[0] == true) {
        Serial.println("Intake air temperature sensor");
    }
    if (AvailablePID_61_80[15] == true) {
        Serial.println("Commanded EGR and EGR Error");
    }
    if (AvailablePID_61_80[14] == true) {
        Serial.println("Commanded Diesel intake air flow control and relative intake air flow position");
    }
    if (AvailablePID_61_80[13] == true) {
        Serial.println("Exhaust gas recirculation temperature");
    }
    if (AvailablePID_61_80[12] == true) {
        Serial.println("Commanded throttle actuator control and relative throttle position");
    }
    if (AvailablePID_61_80[11] == true) {
        Serial.println("Fuel pressure control system");
    }
    if (AvailablePID_61_80[10] == true) {
        Serial.println("Injection pressure control system");
    }
    if (AvailablePID_61_80[9] == true) {
        Serial.println("Turbocharger compressor inlet pressure");
    }
    if (AvailablePID_61_80[8] == true) {
        Serial.println("Boost pressure control");
    }
    if (AvailablePID_61_80[23] == true) {
        Serial.println("Variable Geometry turbo (VGT) control");
    }
    if (AvailablePID_61_80[22] == true) {
        Serial.println("Wastegate control");
    }
    if (AvailablePID_61_80[21] == true) {
        Serial.println("Exhaust pressure");
    }
    if (AvailablePID_61_80[20] == true) {
        Serial.println("Turbocharger RPM");
    }
    if (AvailablePID_61_80[19] == true) {
        Serial.println("Turbocharger temperature");
    }
    if (AvailablePID_61_80[18] == true) {
        Serial.println("Turbocharger temperature");
    }
    if (AvailablePID_61_80[17] == true) {
        Serial.println("Charge air cooler temperature (CACT)");
    }
    if (AvailablePID_61_80[16] == true) {
        Serial.println("Exhaust Gas temperature (EGT) Bank 1");
    }
    if (AvailablePID_61_80[31] == true) {
        Serial.println("Exhaust Gas temperature (EGT) Bank 2");
    }
    if (AvailablePID_61_80[30] == true) {
        Serial.println("Diesel particulate filter (DPF)");
    }
    if (AvailablePID_61_80[29] == true) {
        Serial.println("Diesel particulate filter (DPF)");
    }
    if (AvailablePID_61_80[28] == true) {
        Serial.println("Diesel Particulate filter (DPF) temperature");
    }
    if (AvailablePID_61_80[27] == true) {
        Serial.println("NOx NTE control area status");
    }
    if (AvailablePID_61_80[26] == true) {
        Serial.println("PM NTE control area status");
    }
    if (AvailablePID_61_80[25] == true) {
        Serial.println("Engine run time");
    }
    if (AvailablePID_61_80[24] == true) {
        Serial.println("PIDs supported [81 - A0]");
    }
    
}

///////////////////////////////////////
//MATH FOR DETERMINING AVAILABLE PIDS//
///////////////////////////////////////

void math() {
    if (data2 == 0) {
      int n = 0;
      int arrayPosition = 0;
      int arrayPlaceHolder = 0;

      int a = 0;
      for (int i = 0; i <= 31; i++) {
        int x;

        AvailablePID_1_20[i] = (PID_Array[arrayPosition] >> n) & 1;
        n = n + 1;
        arrayPlaceHolder = i;
        x = arrayPlaceHolder;
        if (x == 7 || x == 15 || x == 23) {
          arrayPosition = arrayPosition + 1;
          n = 0;
        }
      }
    }

    if (data2 == 32) {
      int n = 0;
      int arrayPosition = 0;
      int arrayPlaceHolder = 0;
      
      for (int i = 0; i <= 31; i++) {
        int x;
  
        AvailablePID_21_40[i] = (PID_Array[arrayPosition] >> n) & 1;
        n = n+1;

        arrayPlaceHolder = i;
        x = arrayPlaceHolder;
        if (x == 7 || x == 15 || x == 23) {
          arrayPosition = arrayPosition + 1;
          n = 0;
        }
      }
    }
    
    
    if (data2 == 64) {
      int n = 0;
      int arrayPosition = 0;
      int arrayPlaceHolder = 0;
      
      for (int i = 0; i <= 31; i++) {
        int x;
  
        AvailablePID_41_60[i] = (PID_Array[arrayPosition] >> n) & 1;
        n = n+1;

        arrayPlaceHolder = i;
        x = arrayPlaceHolder;
        if (x == 7 || x == 15 || x == 23) {
          arrayPosition = arrayPosition + 1;
          n = 0;
        }
      }
    }
    
    
     if (data2 == 96) {
      int n = 0;
      int arrayPosition = 0;
      int arrayPlaceHolder = 0;
      
      for (int i = 0; i <= 31; i++) {
        int x;
  
        AvailablePID_61_80[i] = (PID_Array[arrayPosition] >> n) & 1;
        n = n+1;

        arrayPlaceHolder = i;
        x = arrayPlaceHolder;
        if (x == 7 || x == 15 || x == 23) {
          arrayPosition = arrayPosition + 1;
          n = 0;
        }
      }
    }

}

bool byteArray8Equal(uint8_t a1[8], uint8_t a2[8]) {
	for (int i = 0; i < 8; i++) {
		if (a1[i] != a2[i]) return false;
	}
	return true;
}

Carloop Repository

Credits

Emerson Garland

Emerson Garland

1 project • 13 followers
Engineer

Comments