Hi all!
I have an Arduino running that does two things;
- It operates as a trip computer for my car, displaying information on a tiny OLED screen
- It operates as an OBD-II CAN Bus interface with my car engine ECU.
It all works ok and I’m now trying to optimise and simplify the code where I can and there is one bit that I’m struggling with.
This relates to the OLED screen. It takes a long time in Arduino terms to update the screen, and it blocks other operations (like serial and CAN interfaces) so I would rather only update the screen when it needs to.
There are two conditions when it would need to be updated:
- If some data has changed
- If I want to change the page (there are 15 menu pages or so)
At the moment, I’ve got a separate function for each menu page to clear the screen, then format and add data as necessary. I’ve got a variable for each piece of data and another variable for what the data was last time the screen was updated. As such, before updating the OLED for each function, I check whether any data for that page has changed, or whether I’m looking to change the menu page. As a fall back, I update the screen periodically just in case I missed something.
This works fine, but there are a lot of “PREV” variables used for comparing old vs new data and it looks inelegant to me, but I can’t think of a better way to do it. I’m sure there are a lot smarter people on here than me though so hopefully someone can help me understand how to approach this better?
//CAN Enabled Dash Software - Last Updated 20 Apr 2021 - Nick Simpson
//This version uses the Test Board Menu Button Input!!
#include <EEPROM.h>
#include <Bounce2.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>
#include <FlexCAN.h> //Can Bus
#include <AnalogSmooth.h>
//=======================================================================START GLOBAL VARIABLES
//--------------------------------------------------------Global Variables
//Used by CAN
int RPM;
int SPEED;
int OIL_TEMP;
int COOLANT_TEMP;
int AMBIENT_TEMP;
int INTAKE_TEMP;
int BATT_VOLTAGE; //float BATT_VOLTAGE = 0;
int FUEL_PRESSURE;
int FUEL_RATE; //float FUEL_RATE;
int THROTTLE_POS;
//Analogue Only
float FUEL_LEVEL = 0;
int OIL_PRESS = 0;
//REMOVE THESE
float SPEED_KPH;
int SPEED_MPH = 0;
//Pins
const int MenuPin = 20; // the pin number of the Menu button
int ShutDownPin = 11; // read analogue voltage on pin A0 into Shutdown
int MWarnPin = A0; //SUPPOSED TO BE ECU ON pin but no reading
int OilP_Pin = 21;
int Gear_Pin = 15;
int AirT_Pin = 16;
//Modes
int ShutDown = 0;
int DarkMode = 0;
//Menus
int timerstart; //0-60
int timerstop; //0-60
char flash;
char textflashoil;
char textflashwater;
char textflashoilp;
char textflashfuel;
int menuincrement;
int OIL_TEMP_TEXT;
int WATER_TEXT;
int RPM_TEXT;
int INTAKE_TEXT;
int distance_since_service;
int service_interval = 6000;
int distance_to_service;
//Gear Position
int GEAR_POS; //was float
String GPrev;
int GearChange = 0;
int GearSetupMode = 0;
unsigned long GearTime;
unsigned long GearShowTime = 499; //Time in milliseconds to show gear on shift
int SetGear = 0;
int GearWindow = 6; //was 6 0-255 +- Gear position capture
int lastmenu;
String GEAR = "N";
//----
//Send Receive Timer
unsigned long Last_Send_Receive = 10;
unsigned long Serial_Interval = 5;
unsigned long Send_Receive_Timer = 0;
//Time Variables------------
float distm;
float meterssubtotal;
unsigned long kphspeed;
float SPEED_MPS;
unsigned long currentMillis = 0;
unsigned long ODOmillis;
unsigned long Fuelmillis;
unsigned long Startmillis;
unsigned long flashmillis;
unsigned long Finishmillis;
unsigned long DTCmillis;
unsigned long DTCclearmillis;
unsigned long timeto60;
unsigned long DoneTime;
float timeseconds;
//----
//MENU------------------------
int Menubutton = 0; // int for reading pushbutton state
int buttonPressedMillis;
int buttonPressedDuration;
String servicetext;
int BlinkState = LOW;
int menupressed = 0;
int SPEED_DISPLAY = 0;
float SPEED_MULTIPLIER = 1;
boolean ResetSteppers = 0;
boolean Done = 0;
// Instantiate a Bounce object :
Bounce menubutton = Bounce();
unsigned long buttonPressTimeStamp;
int menu = 1;
int ChangeSource = 0;
int CheckEngineOn = 0;
//=======================================================================END GLOBAL VARIABLES
//=======================================================================START EEPROM RELATED VARIABLES
// start reading from the first byte (address 0) of the EEPROM
unsigned int address = 0;
byte value;
int starteeprom;
int EEPROMAddress; //S1
int EEPROMWriteCount; //S2
int tripdisthundredm; //S3
int tripdistkm; //S4
int tripdisthundredkm; //S5
int tripdistthousandkm; //S6
int disthundredm; //S7
int distkm; //S8
int distenkm; //S9
int disthundredkm; //S10
int disthousandkm; //S11
int disttenthousandkm; //S12
int disthundredthousandkm; //S13
float Best060; //S14
float PrevMPG; //S15
int MaxRPM; //S16
int MaxSpeed; //S17
int MaxTemp; //S18
float MaxOil; //S19
int servicedisthundredm; //S20
int servicedistkm; //S21
int servicedisthundredkm; //S22
int servicedistthousandkm; //S23
int MenuMem; //S24
int Neutralp; //S25
int Gear1p; //S26
int Gear2p; //S27
int Gear3p; //S28
int Gear4p; //S29
int Gear5p; //S30
int Gear6p; //S31
int Reversep; //S32
int MODE_SPEED; //S33 1 is serial mode, 2 is CAN mode
int MODE_RPM; //S34 1 is serial mode, 2 is CAN mode
int MODE_COOLANT_TEMP; //S35 1 is serial mode, 2 is CAN mode
int MODE_OIL_TEMP; //S36 1 is serial mode, 2 is CAN mode
int MODE_AMBIENT_TEMP; //S37 1 is serial mode, 2 is CAN mode
int MODE_INTAKE_TEMP = 2; //not currently saved in EEPROM (no need)
int MODE_THROTTLE_POS = 2; //not currently saved in EEPROM (no need)
int MODE_FUEL_PRESSURE = 2; //not currently saved in EEPROM (no need)
int MODE_FUEL_RATE = 2; //not currently saved in EEPROM (no need)
int MODE_BATT_VOLTAGE = 2; //not currently saved in EEPROM (no need)
int MODE_numDTC = 2; //not currently saved in EEPROM (no need)
// set the epprom addresses for the settings that we are keeping
#define E_INIT 1023
// the setting array size must match the settings number
uint32_t settings[23];
// settings addresses
#define S1 1020
#define S2 3
#define S3 6
#define S4 9
#define S5 12
#define S6 15
#define S7 18
#define S8 21
#define S9 24
#define S10 27
#define S11 30
#define S12 33
#define S13 36
#define S14 39
#define S15 42
#define S16 45
#define S17 48
#define S18 51
#define S19 54
#define S20 57
#define S21 60
#define S22 63
#define S23 66
#define S24 69
#define S25 72
#define S26 75
#define S27 78
#define S28 81
#define S29 84
#define S30 87
#define S31 90
#define S32 93
#define S33 96
#define S34 99
#define S35 102
#define S36 105
#define S37 108
#define S38 111
int EEPROM_OFFSET = 114;
//=======================================================================END EEPROM RELATED VARIABLES
//=======================================================================START CAN BUS RELATED VARIABLES
//------------CAN PIDs------------
/* Details from http://en.wikipedia.org/wiki/OBD-II_PIDs */
#define MODE1 0x01 //Show current data
#define MODE2 0x02 //Show freeze frame data
#define MODE3 0x03 //Show stored Diagnostic Trouble Codes
#define MODE4 0x04 //Clear Diagnostic Trouble Codes and stored values
#define PID_SUPPORTED 0x00
#define PID_MONITOR_STATUS 0x01
#define PID_SPEED 0x0D
#define PID_RPM 0x0C
#define PID_OIL_TEMP 0x5C
#define PID_COOLANT_TEMP 0x05
#define PID_INTAKE_TEMP 0x0F
#define PID_AMBIENT_TEMP 0x46
#define PID_BATT_VOLTAGE 0x42
#define O2_VOLTAGE_1 0x24
#define O2_VOLTAGE_2 0x25
#define PID_FUEL_PRESSURE 0x0A
#define PID_FUEL_RATE 0x5E
#define PID_THROTTLE_POS 0x11
#define MODE1_RESPONSE 0x41
#define MODE3_RESPONSE 0x43
#define MODE4_RESPONSE 0x44
#define PID_REQUEST 0x7DF
#define PID_REPLY 0x7E8
#define DTC_PID 0x00
//------------DIAGNOSTIC SERIAL DUMP------------
static uint8_t hex[17] = "0123456789abcdef";
static void hexDump(uint8_t dumpLen, uint8_t *bytePtr)
{
uint8_t working;
while ( dumpLen-- ) {
working = *bytePtr++;
Serial.write( hex[ working >> 4 ] );
Serial.write( hex[ working & 15 ] );
}
Serial.write('\r');
Serial.write('\n');
}
//------------CAN Variables------------
byte PID_CALL;
byte PID;
byte MODE;
byte PID_RESPONSE;
CAN_message_t can_MsgRx, can_MsgTx;
bool CANWaiting = false;
int CAN_Retry = 0;
//------------Structure Arrray Initialisation------------
struct OBD {
String Name;
word PID;
int* Active;
word MODE;
int* Data;
int NoReply;
};
//------------DTC Variables------------
int DTC = 2;
int numDTC;
int DTC1Raw;
int DTC2Raw;
char DTC1 [5];
char DTC2 [5];
int SeenDTC = 0;
int DTCp1;
int DTCp2;
int DTC_CLEARED = 0;
//------------CAN Time Variables------------
//For Serial/CAN
unsigned long CAN_Request_Millis = 10;
unsigned long CAN_Timeout = 100; //CHANGE TO 100
unsigned long CAN_Wait_Duration = 0;
//------------Set Up Structure Array------------
int Row = 0;
// *******************************************************************************************************************************************************SET UP REQUIRED PIDS (currently all)
OBD OBDArray[] = {{"RPM", PID_RPM, &MODE_RPM, MODE1, &RPM, 0}, // Overwritten by EEPROM saved state
{"SPEED", PID_SPEED, &MODE_SPEED, MODE1, &SPEED, 0}, // Overwritten by EEPROM saved state
{"COOLANT_TEMP", PID_COOLANT_TEMP, &MODE_COOLANT_TEMP, MODE1, &COOLANT_TEMP, 0}, // Overwritten by EEPROM saved state
{"OIL_TEMP", PID_OIL_TEMP, &MODE_OIL_TEMP, MODE1, &OIL_TEMP, 0}, // Overwritten by EEPROM saved state
{"AMBIENT_TEMP", PID_AMBIENT_TEMP, &MODE_AMBIENT_TEMP, MODE1, &AMBIENT_TEMP, 0}, // Overwritten by EEPROM saved state
{"INTAKE_TEMP", PID_INTAKE_TEMP, &MODE_INTAKE_TEMP, MODE1, &INTAKE_TEMP, 0},
{"THROTTLE_POS", PID_THROTTLE_POS, &MODE_THROTTLE_POS, MODE1, &THROTTLE_POS, 0},
{"FUEL_PRESSURE", PID_FUEL_PRESSURE, &MODE_FUEL_PRESSURE, MODE1, &FUEL_PRESSURE, 0},
{"FUEL_RATE", PID_FUEL_RATE, &MODE_FUEL_RATE, MODE1, &FUEL_RATE, 0},
{"BATT_VOLTAGE", PID_BATT_VOLTAGE, &MODE_BATT_VOLTAGE, MODE1, &BATT_VOLTAGE, 0},
{"numDTC", DTC_PID, &MODE_numDTC, MODE3, &numDTC, 0}
};
byte Arraysize = sizeof(OBDArray) / sizeof(OBDArray[0]);
//=======================================================================END CAN BUS RELATED VARIABLES
//=======================================================================START SERIAL RELATED VARIABLES
unsigned long Serial1millis;
unsigned long Serial2millis;
//Serial
int SPEED_SEND;
int RPM_SEND;
int CT_SEND;
int FL_SEND;
int DarkMode_SEND = 0;
int ShutDown_SEND = 0;
int CAN_MODES_SEND;
int UpdateSerial1 = 0;
int UpdateSerial2 = 0;
int LightsOn = 0;
//Serial1 Receive--------------------------------
const byte S1numChars = 32;
char S1receivedChars[S1numChars];
char S1tempChars[S1numChars]; // temporary array for use when parsing
static boolean S1recvInProgress = false;
static byte S1ndx = 0;
char S1startMarker = '<';
char S1endMarker = '>';
char S1Received;
boolean S1newData = false;
//Serial2 Receive--------------------------------
const byte S2numChars = 32;
char S2receivedChars[S2numChars];
char S2tempChars[S2numChars]; // temporary array for use when parsing
static boolean S2recvInProgress = false;
static byte S2ndx = 0;
char S2startMarker = '<';
char S2endMarker = '>';
char S2Received;
boolean S2newData = false;
//=======================================================================END SERIAL RELATED VARIABLES
//=======================================================================START ANALOGSMOOTH RELATED VARIABLES
float damping_coefficient = 0.01;
float Hz = 0;
int i = 1;
// Defaults to window size 10
//AnalogSmooth as = AnalogSmooth();
// Window size can range from 1 - 100
AnalogSmooth as100 = AnalogSmooth(100);
AnalogSmooth as101 = AnalogSmooth(100);
AnalogSmooth as102 = AnalogSmooth(100);
AnalogSmooth as50 = AnalogSmooth(5);
AnalogSmooth asQ = AnalogSmooth(5);
//=======================================================================END ANALOGSMOOTH RELATED VARIABLES
//=======================================================================START OLED SCREEN RELATED VARIABLES
#define OLED_RESET -1
Adafruit_SSD1306 display(128, 32, &Wire, OLED_RESET);
//=======================================================================END OLED SCREEN RELATED VARIABLES
//=======================================================================START SPLASH SCREEN RELATED VARIABLES
unsigned int ShowServiceTime = 5000;
unsigned int ShowODOTime = 8000;
unsigned int ShowMenuMem = 9000;
#define LOGO_HEIGHT 27
#define LOGO_WIDTH 77
static const unsigned char PROGMEM logo_bmp[] =
{ 0x3F, 0xFF, 0xFF, 0xFF, 0x80, 0x1F, 0xFF, 0xFF, 0xF0, 0x00, // ############################### #########################
0x3F, 0xFF, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFF, 0xF8, 0x00, // ############################### ###########################
0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFF, 0xFE, 0x00, // ################################ #############################
0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0x7F, 0xFF, 0xFF, 0xFE, 0x00, // ################################ ##############################
0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0x7F, 0xFF, 0xFF, 0xFF, 0x00, // ################################ ###############################
0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, // ################################ ################################
0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, // ################################# #################################
0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, // ################################# #################################
0x00, 0x00, 0x00, 0xFF, 0xC1, 0xFF, 0xC0, 0x01, 0xFF, 0x80, // ########## ########### ##########
0x00, 0x00, 0x00, 0xFF, 0xC1, 0xFF, 0x80, 0x01, 0xFF, 0x80, // ########## ########## ##########
0x00, 0xFF, 0xC0, 0xFF, 0xC3, 0xFF, 0x80, 0x03, 0xFF, 0x80, // ########## ########## ########### ###########
0x00, 0xFF, 0x80, 0xFF, 0xC3, 0xFF, 0x07, 0xFF, 0xFF, 0x80, // ######### ########## ########## ####################
0x00, 0xFF, 0x80, 0x7F, 0xC7, 0xFF, 0x0F, 0xFF, 0xFF, 0x00, // ######### ######### ########### ####################
0x01, 0xFF, 0x80, 0x7F, 0xC7, 0xFE, 0x0F, 0xFF, 0xFF, 0x00, // ########## ######### ########## ####################
0x01, 0xFF, 0x80, 0x7F, 0xCF, 0xFE, 0x0F, 0xFF, 0xFE, 0x00, // ########## ######### ########### ###################
0x01, 0xFF, 0x00, 0x7F, 0xCF, 0xFC, 0x0F, 0xFF, 0xFC, 0x00, // ######### ######### ########## ##################
0x01, 0xFF, 0x00, 0x7F, 0xDF, 0xFC, 0x0F, 0xFF, 0xF8, 0x00, // ######### ######### ########### #################
0x03, 0xFF, 0x00, 0x7F, 0xFF, 0xF8, 0x0F, 0xFF, 0xE0, 0x00, // ########## #################### ###############
0x03, 0xFF, 0x00, 0x7F, 0xFF, 0xF8, 0x07, 0xFF, 0x00, 0x00, // ########## #################### ###########
0x03, 0xFE, 0x00, 0x7F, 0xFF, 0xF0, 0x07, 0xFF, 0x00, 0x00, // ######### ################### ###########
0x03, 0xFE, 0x00, 0x7F, 0xFF, 0xF0, 0x03, 0xFF, 0x80, 0x00, // ######### ################### ###########
0x07, 0xFE, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xC0, 0x00, // ########## ################## ###########
0x07, 0xFE, 0x00, 0x3F, 0xFF, 0xE0, 0x01, 0xFF, 0xC0, 0x00, // ########## ################# ###########
0x07, 0xFC, 0x00, 0x3F, 0xFF, 0xC0, 0x00, 0xFF, 0xE0, 0x00, // ######### ################ ###########
0x07, 0xFC, 0x00, 0x3F, 0xFF, 0xC0, 0x00, 0xFF, 0xE0, 0x00, // ######### ################ ###########
0x0F, 0xFC, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x7F, 0xF0, 0x00, // ########## ############### ###########
0x0F, 0xF8, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x7F, 0xF0, 0x00, // ######### ############### ###########
};
//=======================================================================END SPLASH SCREEN RELATED VARIABLES
// *******************************************************************************************************************************************************CHECK THE CODE FOR WHERE THESE ARE USED AND REWRITE SO THEY AREN'T NEEDED (USING ARRAY?)
int RPM_CAN;
int SPEED_MPH_CAN;
int OIL_TEMP_CAN;
int COOLANT_TEMP_CAN;
int AMBIENT_TEMP_CAN;
int INTAKE_TEMP_CAN;
float BATT_VOLTAGE_CAN;
int FUEL_PRESSURE_CAN;
float FUEL_RATE_CAN;
int THROTTLE_POS_CAN;
byte MONITOR_STATUS;
byte MONITOR_STATUS_CAN;
int RPM_SER;
int SPEED_SER;
int OIL_TEMP_SER;
int COOLANT_TEMP_SER;
int COOLANT_TEMP_D;
int FUEL_LEVEL_SER;
int FUEL_LEVEL_D;
int AMBIENT_TEMP_SER;
int OIL_PRESS_SER;
//------------------------------------------------
// *******************************************************************************************************************************************************IS THERE A SMARTER WAY TO ONLY UPDATE THE OLED WHEN NEEDED?
//PREVS
int SPEED_MPH_PREV;
int RPM_PREV;
int distkm_PREV;
int tripdisthundredm_PREV;
int AMBIENT_TEMP_PREV;
String GEAR_PREV;
int INTAKE_TEMP_PREV;
int OIL_TEMP_PREV;
int ChangeSourceTo_PREV;
int OIL_TEMP_TEXT_PREV;
int WATER_TEXT_PREV;
int RPM_TEXT_PREV;
int INTAKE_TEXT_PREV;
int SetGear_PREV;
int COOLANT_TEMP_PREV;
int OIL_PRESS_PREV;
int FUEL_PRESSURE_PREV;
int textflashoilp_PREV;
float FUEL_LEVEL_PREV;
float FUEL_RATE_PREV;
float BATT_VOLTAGE_PREV;
int numDTC_PREV;
int DTC_PREV;
int MaxSpeed_PREV;
int MaxRPM_PREV;
int MaxTemp_PREV;
int MaxOil_PREV;
int distance_to_service_PREV;
int mode060_PREV;
int mode060;
int menu_PREV;
int DarkMode_PREV;
boolean Done_PREV = 0;
int BlinkState_PREV = 0;
//=======================================================================END SET UP VARIABLES
void setup(void) {//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++START SETUP
Serial.begin(9600);
Serial1.begin(250000);
Serial2.begin(250000);
Can0.begin(500000);
Wire.setClock(3400000);
loadEEPROMSettings();
//----------------------------------------------------------------------MENU BUTTON
pinMode( MenuPin, INPUT_PULLUP );
// After setting up the button, setup the Bounce instance :
menubutton.attach(MenuPin, INPUT_PULLUP) ;
menubutton.interval(60); // De-bounce time of x milliseconds
menu = 1; // set default menu display for oled
//----------------------------------------------------------------------MISC
timerstart = 0;
timerstop = 0;
starteeprom = 0;
pinMode(ShutDownPin, INPUT_PULLUP);
pinMode(MWarnPin, INPUT_PULLUP);
pinMode(Gear_Pin, INPUT_PULLDOWN);
pinMode(AirT_Pin, INPUT_PULLDOWN);
//----------------------------------------------------------------------INITIATE SCREEN
Serial.println("Starting OLED");
display.begin(SSD1306_SWITCHCAPVCC);
display.clearDisplay();
drawTVR();
delay(2500); //Show TVR Splash screen
//----------------------------------------------------------------------INITIATE SERIVCE INTERVAL
distance_since_service = (servicedistthousandkm * 1000) + (servicedisthundredkm * 100) + (servicedistkm * 10) + servicedisthundredm ;
distance_to_service = service_interval - distance_since_service;
if (distance_since_service <= service_interval) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(10, 25);
display.println("T O S E R V I C E");
display.setTextSize(2);
display.setCursor(42, 3);
display.println(distance_to_service);
display.display();
}
if (distance_since_service > service_interval) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(5, 25);
display.println("S E R V I C E D U E"); //THIS LOOKS LIKE IT WONT FIT
display.setTextSize(2);
display.setCursor(35, 3);
display.println(distance_to_service);
display.setTextSize(2);
display.setCursor(0, 0);
display.println("**");
display.setCursor(98, 0);
display.println("**");
display.display();
}
ODOmillis = (0);
Fuelmillis = (0);
}//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++END SETUP
void loop(void) {//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++START LOOP
currentMillis = millis();
Send_Receive_Timer = currentMillis - Last_Send_Receive;
// *******************************************************************************************************************************************************THIS TIMER PROBABLY DOESN'T NEED TO APPLY TO THE CAN FUNCTION
if (Send_Receive_Timer > Serial_Interval)
{
//===========SERIAL OR CAN SET BASED ON MODES=======================
//----------------------------------------------------------------------READ SERIAL MONITOR (menu control)
if (Serial.available()) keyboard();
//----------------------------------------------------------------------READ SERIAL1
Serial1Receive();
if (S1newData == true) {
strcpy(S1tempChars, S1receivedChars);
Serial1Parse();
//showParsedData(); //DIAGNOSTICS ONLY
S1newData = false;
}
//----------------------------------------------------------------------READ SERIAL2
Serial2Receive();
if (S2newData == true) {
strcpy(S2tempChars, S2receivedChars);
Serial2Parse();
S2newData = false;
}
}
//----------------------------------------------------------------------READ CAN BUS
Get_CAN_Data();
//Print_CAN_Data();//--------------------------Diagnostic only
if (Send_Receive_Timer > Serial_Interval)
{
//----------------------------------------------------------------------Write SERIAL
Send_Serial1_Data();
Send_Serial2_Data();
Last_Send_Receive = currentMillis;
}
//----------------------------------------------------------------------READ ANALOGUE INPUTS
//-------------------------------------------READ FUEL LEVEL
// *******************************************************************************************************************************************************NEED TO WRITE THIS
//---------------------------------------------
//----------------------------------------------------------------------ECM Check Engine Light Warning
if (digitalRead(MWarnPin) == HIGH)CheckEngineOn = 1;
if (digitalRead(MWarnPin) == HIGH)CheckEngineOn = 0;
//----------------------------------------------------------------------Gear Position
GEAR_POS = as50.analogReadSmooth(Gear_Pin); //constrain(as50.analogReadSmooth(Gear_Pin), 15, 1000);
//GEAR_POS = constrain(asQ.analogReadSmooth(Gear_Pin), 15, 1000);
GEAR_POS = map(GEAR_POS, 15, 1000, 0, 255);
// Serial.print("Current = ");
// Serial.println(GEAR_POS);
// Serial.print("Neutral = ");
// Serial.println(Neutralp);
// Serial.print("Gear1 = ");
// Serial.println(Gear1p);
// Serial.print("Gear2 = ");
// Serial.println(Gear2p);
// Serial.print("Gear3 = ");
// Serial.println(Gear3p);
// Serial.print("Gear4 = ");
// Serial.println(Gear4p);
// Serial.print("Gear5 = ");
// Serial.println(Gear5p);
// Serial.print("Gear6 = ");
// Serial.println(Gear6p);
// Serial.print("GearR = ");
// Serial.println(Reversep);
// if (ChangeSource == 1) ChangeSourceFunc();
if (GearSetupMode == 1) Gear_Setup();
if (GearSetupMode == 0 && millis() - GearTime > 100) GEARS();
//----------------------------------------------------------------------Oil Pressure
OIL_PRESS_SER = as100.analogReadSmooth(OilP_Pin) * 1.5; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ THIS COMES OUT WHEN NEW BOARD ARRIVES (FUEL ON OTHER BOARD)
OIL_PRESS_SER = constrain(map(OIL_PRESS_SER, 120, 830, 60, 0), 0, 60); // map
OIL_PRESS += 0.1 * (OIL_PRESS_SER - OIL_PRESS);
//Serial.println(OIL_PRESS_SER);
//----------------------------------------------------------------------Ambient Temperature
if (MODE_AMBIENT_TEMP == 1) {
AMBIENT_TEMP_SER = as101.analogReadSmooth(AirT_Pin) * 1.5;
AMBIENT_TEMP_SER = map(AMBIENT_TEMP_SER, 80, 1370, 130, 0); // map
AMBIENT_TEMP += 0.1 * (AMBIENT_TEMP_SER - AMBIENT_TEMP); //FILTER (smaller filter value (0.1) means more filtering, 1 is no filter)
}
//----------------------------------------------------------------------READ MENU PIN
// Update the Bounce instance :
menubutton.update();
//Button Handling
if (menubutton.fell()) buttonPressedMillis = millis();
if (menubutton.rose()) buttonPressedDuration = millis() - buttonPressedMillis;
//Button Action
if (buttonPressedDuration) {
//----------------------------------------------------------------------BUTTON CLICK FUNCTIONS
if (buttonPressedDuration < 1000 && GearSetupMode == 0 && DarkMode == 1) DarkMode = 0;
else if (buttonPressedDuration < 1000 && GearSetupMode == 0) {
menupressed = 1;
menu++;
}
else if (buttonPressedDuration < 1000 && GearSetupMode == 1) {
if (SetGear == 1) Neutralp = GEAR_POS;
if (SetGear == 2) Gear1p = GEAR_POS;
if (SetGear == 3) Gear2p = GEAR_POS;
if (SetGear == 4) Gear3p = GEAR_POS;
if (SetGear == 5) Gear4p = GEAR_POS;
if (SetGear == 6) Gear5p = GEAR_POS;
if (SetGear == 7) Gear6p = GEAR_POS;
if (SetGear == 8) Reversep = GEAR_POS;
if (SetGear == 9) GearSetupMode = 0;
SetGear ++;
}
//+++++++++++++++++++++++++++++++ SHORT BUTTON HOLD FUNCTIONS +++++++++++++++++++++++++++++++
else if (buttonPressedDuration < 5000) {
//---------- Normal Menu ----------
if (menu == 1) cleartrip();
//if (menu == 4) ; //RESET MPG
else if (menu == 5) DarkMode = 1;
else if (menu == 8) clearstats();
else if (menu == 9) Best060 = 0;
else if (menu == 14) {
CAN_Request(MODE4, 0); //Clear Trouble Codes
DTCclearmillis = millis();
DTC_CLEARED = 1;
}
else if (menu == 15) menu = 21; //Enter setup sub-menu
//---------- Setup Sub-Menu ----------
else if (menu == 21) { // Speed
if (SPEED_DISPLAY == 2) {
SPEED_DISPLAY = 1;
SPEED_MULTIPLIER = 1; //MPH currently set to *1 (* 0.621371 for KPH to MPH)
}
else if (SPEED_DISPLAY == 1) {
SPEED_DISPLAY = 2;
SPEED_MULTIPLIER = 1.60934; //KPH currently set to *1.60934
}
ChangeSource = 1;
}
//-----Source Change-----
else if (menu == 22) { // Speed
if (MODE_SPEED == 2) MODE_SPEED = 1;
else if (MODE_SPEED == 1) MODE_SPEED = 2;
ChangeSource = 1;
}
else if (menu == 23) { // RPM
if (MODE_RPM == 2) MODE_RPM = 1;
else if (MODE_RPM == 1) MODE_RPM = 2;
ChangeSource = 1;
}
else if (menu == 24) { //Coolant temp
if (MODE_COOLANT_TEMP == 2) MODE_COOLANT_TEMP = 1;
else if (MODE_COOLANT_TEMP == 1) MODE_COOLANT_TEMP = 2;
ChangeSource = 1;
}
else if (menu == 25) {
if (MODE_AMBIENT_TEMP == 2) MODE_AMBIENT_TEMP = 1;
else if (MODE_AMBIENT_TEMP == 1) MODE_AMBIENT_TEMP = 2;
ChangeSource = 1;
}
else if (menu == 26) { //Oil temp
if (MODE_OIL_TEMP == 2) MODE_OIL_TEMP = 1;
else if (MODE_OIL_TEMP == 1) MODE_OIL_TEMP = 2;
ChangeSource = 1;
}
else if (menu == 27) ResetSteppers = 1;
else if (menu == 31) menu = 15;
}
//+++++++++++++++++++++++++++++++ LONG BUTTON HOLD FUNCTIONS +++++++++++++++++++++++++++++++
else {
//---------- Normal Menu ----------
if (menu == 12) clearservice();
//---------- Setup Sub-Menu ----------
else if (menu == 27) {
ResetSteppers = 1;
DoneTime = millis();
Done = 1;
}
else if (menu == 28) {
GearSetupMode = 1;
SetGear = 1;
}
else if (menu == 29) {
clearODO();
DoneTime = millis();
Done = 1;
}
else if (menu == 30) menu = 35; //Alignment Box
}
//reset duration to only trigger once!
buttonPressedDuration = 0;
}
//Show Odometer on startup
if (ODOmillis < ShowODOTime) menu = 1;
//Show memory page after startup
if (ODOmillis > ShowODOTime && ODOmillis < ShowMenuMem && menupressed == 0) menu = MenuMem;
//Menu Loop Normal
if (menu == 16) menu = 1;
//Menu Loop Setup
if (menu == 32) menu = 21;
//Alignment Box
if (menu == 36) menu = 30;
//Gearchange
if (GearChange == 1 && millis() - GearTime < GearShowTime) menu = 3;
if (GearChange == 1 && millis() - GearTime > GearShowTime) {
menu = lastmenu;
GearChange = 0;
}
// //Change Sensor Source
// if (ChangeSource == 1 && millis() - ChangeSourceTime > ChangeSourceShowTime) ChangeSource = 0;
//----------------------------------------------------------------------Update Odometer Counter and Display
//
if (millis() - ODOmillis >= 10) { //Update every 0.1s.
if (millis() - ODOmillis >= 1000) { //Update every 1s
SPEED_MPS = SPEED_MPH * 0.44704; //convert to distance meters per second
distm = SPEED_MPS / 1 ; // spare conversion factor
meterssubtotal += distm; // add meters traveled to a total called meters
updateodometer(); //add the meters traveled to the meters counter
// Update lasmillis
ODOmillis = millis();
}
if (ODOmillis > ShowServiceTime) { //Service timer display
if (ShutDown != 1 && GearSetupMode != 1) { // && ChangeSource != 1
checkdisplay(); // update lcd readings
}
}
}
//----------------------------------------------------------------------Update Max Stats
if (SPEED_MPH > MaxSpeed) {
MaxSpeed = SPEED_MPH;
}
if (RPM > MaxRPM) {
MaxRPM = RPM;
}
if (COOLANT_TEMP > MaxTemp) {
MaxTemp = COOLANT_TEMP;
}
if (OIL_TEMP > MaxOil) {
MaxOil = OIL_TEMP;
}
//----------------------------------------------------------------------START EEPROM UPDATE (if igniton is killed)
//BATT_VOLTAGE = asQ.analogReadSmooth(ShutDownPin);
//Serial.println(BATT_VOLTAGE); //*15.699
if (digitalRead(ShutDownPin) == LOW)starteeprom = 1;
if (digitalRead(ShutDownPin) == HIGH && starteeprom == 1) {
ShutDown = 1;
updateeeprom();
starteeprom = 0;
drawTVR();
display.clearDisplay();
}
//----------------------------------------------------------------------START DTC CYCLE TEXT WARNING
// *******************************************************************************************************************************************************CAN DTC HANDLE MORE THAN 2 CODES?
if (millis() - DTCmillis > 1000) { //Update every one second.
DTCmillis = millis(); // Update lasmillis
if (DTC_CLEARED == 1 && (millis() - DTCclearmillis < 5000)) {
DTC = 4;
}
else if (DTC_CLEARED == 1 && (millis() - DTCclearmillis > 5000)) {
DTC = 1;
DTC_CLEARED = 0;
}
else if (DTC == 1) DTC = 2;
else if (numDTC > 2) {
if (DTC == 3) DTC = 1;
if (DTC == 2) DTC = 3;
}
else if (DTC == 2) DTC = 1;
}
//----------------------------------------------------------------------START FLASH FUNCTION FOR TEXT WARNING----------------------------
if (millis() - flashmillis > 500) { //Update every half second.
flashmillis = millis(); // Update lasmillis
// if the LED is off turn it on and vice-versa:
if (BlinkState == LOW) BlinkState = HIGH;
else BlinkState = LOW;
}
if (BlinkState == 1)flash = BLACK;
if (BlinkState == 0)flash = WHITE;
//----------------------------------------------------------------------START ALARM CHANNELS==============================================================
//------------------------DTC-------------------------------------------
if (numDTC > 0 && SeenDTC == 0) {
SeenDTC = 1;
menu = 14;
}
else RPM_TEXT = WHITE;
//------------------------RPM-------------------------------------------
if (RPM >= 5500) {
RPM_TEXT = flash;
//MASTER WARNING LIGHT ON
}
else RPM_TEXT = WHITE;
//------------------------INTAKE TEMP-------------------------------------------
if (INTAKE_TEMP >= 50) {
INTAKE_TEXT = flash;
menu = 2;
//MASTER WARNING LIGHT ON
}
else INTAKE_TEXT = WHITE;
//------------------------OIL TEMP-------------------------------------------
if (OIL_TEMP >= 110) {
OIL_TEMP_TEXT = flash;
menu = 6;
//MASTER WARNING LIGHT ON
}
else OIL_TEMP_TEXT = WHITE;
//------------------------WATER TEMP-------------------------------------------
if (COOLANT_TEMP >= 100) {
WATER_TEXT = flash;
menu = 6;
//MASTER WARNING LIGHT ON
}
else WATER_TEXT = WHITE;
//------------------------OIL PRESS-------------------------------------------
if (OIL_PRESS > 0 && OIL_PRESS < 20 && RPM > 2000) {
textflashoilp = flash;
menu = 7;
}
else textflashoilp = WHITE;
if (OIL_PRESS > 0 && OIL_PRESS < 7) {
textflashoilp = flash;
menu = 7;
}
else textflashoilp = WHITE;
//------------------------FUEL LEVEL-------------------------------------------
if (millis() - Fuelmillis >= 500) { //Read temperatures every three seconds
if (FUEL_LEVEL > 0 && FUEL_LEVEL < 6) {
textflashfuel = flash;
menu = 4;
}
else textflashfuel = WHITE;
}
//----------------------------------------------------------------------???
if (millis() - DoneTime > 2000) {
Done = 0;
ResetSteppers = 0;
}
//----------------------------------------------------------------------Dim Display==================
if (LightsOn == 1) display.dim(true);
else display.dim(false);
}//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++END LOOP
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++START FUNCTIONS
//=====================================START CAN BUS FUNTIONS====================================================
//-------------GET CAN DATA-------------
void Get_CAN_Data() {
//Are we waiting for a response?
if (CANWaiting == true) { // IS IT THE RESPONSE WE'RE WAITING FOR?? IF SO, SAVE IT AND MOVE ON
if (Can0.available() > 0) {//Is a response waiting?
Can0.read(can_MsgRx);
if ((can_MsgRx.id == PID_REPLY) && ((can_MsgRx.buf[2] == OBDArray[Row].PID) || can_MsgRx.buf[1] == MODE3_RESPONSE)) //Is this message the response we're looking for?
{
//Yes
if (can_MsgRx.buf[1] == MODE3_RESPONSE) {//Is the message an error code?
//Serial.print("CAN ERROR RECEIVED: "); hexDump(8, can_MsgRx.buf); //Diagnostic - Dump message to Serial useful explanation: https://www.csselectronics.com/screen/page/simple-intro-obd2-explained/language/en
numDTC = CAN_ERR_Receive(can_MsgRx.buf[2], can_MsgRx.buf[3], can_MsgRx.buf[4], can_MsgRx.buf[5], can_MsgRx.buf[6]);
}
else {//Normal PID Received
//Serial.print("CAN RECEIVED: "); hexDump(8, can_MsgRx.buf); //Diagnostic - Dump message to Serial useful explanation: https://www.csselectronics.com/screen/page/simple-intro-obd2-explained/language/en
*(OBDArray[Row].Data) = CAN_Receive_Parse(can_MsgRx.buf[2], can_MsgRx.buf[3], can_MsgRx.buf[4]);
}
CANWaiting = false; //Reset waiting flag
NextPID();//Prepare next PID
}
}
else { //Still waiting - check for timeout
CAN_Wait_Duration = currentMillis - CAN_Request_Millis;
if (CAN_Wait_Duration > CAN_Timeout) //Waited too long
{
OBDArray[Row].NoReply ++; //Add to the no reply counter for this PID
if (OBDArray[Row].NoReply > 100) { //if >100 no replys then this PID is not available, so stop requesting it and show an error
//Switch off this PID Request
*(OBDArray[Row].Active) = 1;
//Show Error
Serial.print("OBD Error - ");
Serial.println(OBDArray[Row].Name);
//Try Next PID
NextPID();
CAN_Retry = 0;
CANWaiting = false;
}
//If it has just dropped a single packet then give it another try
if (CAN_Retry == 2) {
//Try Next PID
NextPID();
CAN_Retry = 0;
CANWaiting = false;
}
else {
CAN_Retry ++; //Retry this PID
}
}
}
}
if (CANWaiting == false) {
//Request next Data
CAN_Request(OBDArray[Row].MODE, OBDArray[Row].PID);
CAN_Request_Millis = currentMillis;
CANWaiting = true;
}
}
//-------------REQUEST CAN DATA-------------
void CAN_Request(byte CAN_MODE, byte PID_CALL) {
can_MsgTx.ext = 0;
can_MsgTx.id = PID_REQUEST;
can_MsgTx.len = 8;
can_MsgTx.buf[0] = 0x02; //Length in number of bytes of remaining data (2 bytes = 02, 3 bytes = 03 etc)
can_MsgTx.buf[1] = CAN_MODE;
can_MsgTx.buf[2] = PID_CALL;
can_MsgTx.buf[3] = 0;
can_MsgTx.buf[4] = 0;
can_MsgTx.buf[5] = 0;
can_MsgTx.buf[6] = 0;
can_MsgTx.buf[7] = 0;
can_MsgTx.flags.extended = 0;
can_MsgTx.flags.remote = 0;
//Serial.print("CAN SENT: "); hexDump(8, can_MsgTx.buf); //Diagnostic - Dump message to Serial//@@@@@@@@@@@@@@@@@@@@@@@@@@@CAN DIAGNOSTICS@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//Serial.println(currentMillis / 10);
Can0.write(can_MsgTx); //Send message
}
//-------------NEXT PID TO RUN-------------
void NextPID() {
//Start with next row unless at end of table, then start from 0
for (int i = 0; i < (Arraysize - 1); i++) {
if ((i + Row) == (Arraysize - 1)) Row = 0;
else Row = (Row + 1);
if (*(OBDArray[Row].Active) == 2) break;
}
}
//-------------SERIAL PRINT CAN DATA-------------
void Print_CAN_Data() {
Serial.print("RPM: ");
Serial.print(RPM);
Serial.print(" | SPEED: ");
Serial.print(SPEED);
Serial.print(" | COOLANT: ");
Serial.print(COOLANT_TEMP);
Serial.print(" | OIL: ");
Serial.print(OIL_TEMP);
Serial.print(" | AMBIENT: ");
Serial.print(AMBIENT_TEMP);
Serial.print(" | INTAKE: ");
Serial.print(INTAKE_TEMP);
Serial.print(" | TPS: ");
Serial.print(THROTTLE_POS);
Serial.print(" | FUEL P: ");
Serial.print(FUEL_PRESSURE);
Serial.print(" | FUEL R: ");
Serial.print(FUEL_RATE);
Serial.print(" | BATT: ");
Serial.print(BATT_VOLTAGE);
Serial.print(" | DTC: ");
Serial.println(numDTC);
}
//-------------PROCESS DTC INCOMING-------------
int CAN_ERR_Receive(byte pkt2, byte pkt3, byte pkt4, byte pkt5, byte pkt6) {
numDTC = pkt2;
if (numDTC > 0) {
DTCp1 = pkt3;
DTCp2 = pkt4;
if (DTCp1 < 10) DTC1Raw = (DTCp1 * 100) + DTCp2;
else DTC1Raw = (DTCp1 * 1000) + DTCp2;
sprintf (DTC1, "P%04u", DTC1Raw);
}
else sprintf (DTC1, "");
if (numDTC > 1) {
DTCp1 = pkt5;
DTCp2 = pkt6;
if (DTCp1 < 10) DTC2Raw = (DTCp1 * 100) + DTCp2;
else DTC2Raw = (DTCp1 * 1000) + DTCp2;
sprintf (DTC2, "P%04u", DTC2Raw);
}
else sprintf (DTC2, "");
return numDTC;
}
//-------------PROCESS NORMAL PID INCOMING-------------
int CAN_Receive_Parse(byte PID_Received, int Data_1, int Data_2) {
switch (PID_Received) //Switch means look at different cases
{ /* Details from http://en.wikipedia.org/wiki/OBD-II_PIDs */
case PID_SPEED: // A [km] int SPEED =
return Data_1 * 1; //CHECK SPEED IS IN KPH AND CONVERSION!!!!
break;
case PID_RPM: // ((A*256)+B)/4 [RPM]
return ((Data_1 * 256) + Data_2) / 4;
break;
case PID_OIL_TEMP: // A-40 [degree C]
return Data_1 - 40;
break;
case PID_COOLANT_TEMP: // A-40 [degree C]
return Data_1 - 40;
break;
case PID_INTAKE_TEMP: // A-40 [degree C]
return Data_1 - 40;
break;
case PID_AMBIENT_TEMP: // A-40 [degree C]
return Data_1 - 40;
break;
case PID_BATT_VOLTAGE: //
return ((Data_1 * 256) + Data_2);
break;
case PID_FUEL_PRESSURE: // [kPa]
return Data_1 * 3;
break;
case PID_FUEL_RATE: // [l/h]
return ((Data_1 * 256) + Data_2) / 2;
break;
case PID_THROTTLE_POS:
return int((Data_1 * 100) / 255);
break;
case PID_MONITOR_STATUS:
return Data_1;// & Data_2 & can_MsgRx.buf[5];
break;
}
}
//=========================================END CAN BUS FUNCTIONS====================================================
//=========================================START SERIAL FUNTIONS====================================================
void keyboard() {
switch (Serial.read())
{
case '1': menu = 1; break; //ODO
case '2': menu = 2; break; //Main
case '3': menu = 3; break; //GearOnly
case '4': menu = 4; break; //FuelR
case '5': menu = 5; break; //DarkMode
case '6': menu = 6; break; //Oil Water T
case '7': menu = 7; break; //Oil P Fuel P
case '8': menu = 8; break; // Stats
case '9': menu = 9; break; // 0-60
case 'A': menu = 10; break; // Speed
case 'B': menu = 11; break; // RPM
case 'C': menu = 12; break; // Batt
case 'D': menu = 13; break; // Service
case 'E': menu = 14; break; // DTC
case 'F': menu = 15; break; // Setup
case 'O': {
MODE_RPM = 2;
MODE_SPEED = 2;
MODE_COOLANT_TEMP = 2;
MODE_OIL_TEMP = 2;
MODE_AMBIENT_TEMP = 2;
break;
}
}
}
//----------------------SERIAL 1 Receive------------------------
void Serial1Receive() {
while (Serial1.available() > 0 && S1newData == false) {
S1Received = Serial1.read();
if (S1recvInProgress == true) {
if (S1Received != S1endMarker) {
S1receivedChars[S1ndx] = S1Received;
S1ndx++;
if (S1ndx >= S1numChars) {
S1ndx = S1numChars - 1;
}
}
else {
S1receivedChars[S1ndx] = '\0'; // terminate the string
S1recvInProgress = false;
S1ndx = 0;
S1newData = true;
}
}
else if (S1Received == S1startMarker) {
S1recvInProgress = true;
}
}
}
//----------------------SERIAL 1 PARSE------------------------
void Serial1Parse() { // split the data into its parts
//Check incoming datasteam:
//Serial.println(tempChars);
char *ptr;
ptr = strtok(S1tempChars, ",");
if (ptr == NULL)
{
//Serial.println("No comma found");
}
else
{
do
{
switch (ptr[0])
{
case 'S':
SPEED_SER = atoi(&ptr[1]);
break;
case 'R':
RPM_SER = atoi(&ptr[1]);
break;
case 'T':
COOLANT_TEMP_SER = atoi(&ptr[1]) / 10;
break;
case 'F':
FUEL_LEVEL_SER = atoi(&ptr[1]) / 10;
break;
}
ptr = strtok(NULL, ",");
} while (ptr != NULL);
}
if (MODE_SPEED == 1) SPEED_MPH = SPEED_SER;
if (MODE_RPM == 1) RPM = RPM_SER;
FUEL_LEVEL = FUEL_LEVEL_SER;
if (MODE_COOLANT_TEMP == 1) COOLANT_TEMP = COOLANT_TEMP_SER;
}
//============
void showParsedData() {
//FOR DIAGNOSIS ONLY
Serial.print("<");
Serial.print(SPEED_MPH);
Serial.print(", ");
Serial.print(RPM);
Serial.print(", ");
Serial.print(COOLANT_TEMP);
Serial.print(", ");
Serial.print(FUEL_LEVEL);
Serial.println(">");
}
//----------------------SERIAL 1 SEND------------------------
void Send_Serial1_Data() {
if (millis() - Serial1millis > 1000) { //Update every 1 seconds.
Serial1millis = millis(); // Update lasmillis
// time to update serial
UpdateSerial1 = 1;
}
//Serial.print(ShutDown);
if (ResetSteppers == 1 || UpdateSerial1 == 1 || ShutDown == 1 || MODE_SPEED + MODE_RPM + MODE_COOLANT_TEMP != CAN_MODES_SEND || RPM / 10 != RPM_SEND || COOLANT_TEMP != CT_SEND || SPEED_MPH != SPEED_SEND) {
Serial1.print('<');
if (UpdateSerial1 == 1 || ShutDown != ShutDown_SEND) {
ShutDown_SEND = ShutDown;
Serial1.print('S');
Serial1.print(ShutDown);
Serial1.print(',');
}
if (UpdateSerial1 == 1 || MODE_SPEED + MODE_RPM + MODE_COOLANT_TEMP != CAN_MODES_SEND) {
CAN_MODES_SEND = MODE_SPEED + MODE_RPM + MODE_COOLANT_TEMP;
Serial1.print('M');
Serial1.print(MODE_SPEED);
Serial1.print(MODE_RPM);
Serial1.print(MODE_COOLANT_TEMP);
Serial1.print(',');
}
if ((RPM) != RPM_SEND && MODE_RPM == 2) {
RPM_SEND = RPM;
//Serial1.print('<');
Serial1.print('R');
Serial1.print(RPM_SEND);
Serial1.print(',');
}
if (UpdateSerial1 == 1 || (COOLANT_TEMP != CT_SEND && MODE_COOLANT_TEMP == 2)) {
CT_SEND = COOLANT_TEMP;
Serial1.print('T');
Serial1.print(CT_SEND);
Serial1.print(',');
}
if (SPEED_MPH != SPEED_SEND && MODE_SPEED == 2) {
SPEED_SEND = SPEED_MPH;
Serial1.print('V');
Serial1.print(SPEED_SEND);
Serial1.print(',');
}
if (UpdateSerial1 == 1 || ResetSteppers == 1) {
Serial1.print('Z');
Serial1.print(ResetSteppers);
Serial1.print(',');
}
Serial1.print('>');
UpdateSerial1 = 0;
}
}
//----------------------SERIAL 1 RECEIVE------------------------
void Serial2Receive() {
while (Serial2.available() > 0 && S2newData == false) {
S2Received = Serial2.read();
if (S2recvInProgress == true) {
if (S2Received != S2endMarker) {
S2receivedChars[S2ndx] = S2Received;
S2ndx++;
if (S2ndx >= S2numChars) {
S2ndx = S2numChars - 1;
}
}
else {
S2receivedChars[S2ndx] = '\0'; // terminate the string
S2recvInProgress = false;
S2ndx = 0;
S2newData = true;
}
}
else if (S2Received == S2startMarker) {
S2recvInProgress = true;
}
}
}
//----------------------SERIAL 1 PARSE------------------------
void Serial2Parse() { // split the data into its parts
//Serial.println(tempChars); //diagnostic only: check incoming data
char *ptr2;
ptr2 = strtok(S2tempChars, ",");
if (ptr2 == NULL)
{
//Serial.println("No comma found");
}
else
{
do
{
switch (ptr2[0])
{
case 'L':
LightsOn = atoi(&ptr2[1]);
break;
}
ptr2 = strtok(NULL, ",");
} while (ptr2 != NULL);
}
}
//----------------------SERIAL 1 SEND------------------------
void Send_Serial2_Data() {
if (millis() - Serial2millis > 1000) { //Update every 1 seconds.
Serial2millis = millis(); // Update lasmillis
// time to update serial
UpdateSerial2 = 1;
}
if (DarkMode != DarkMode_SEND || ShutDown == 1 || UpdateSerial2 == 1) {
Serial2.print('<');
if ((DarkMode) != DarkMode_SEND || UpdateSerial2 == 1) {
DarkMode_SEND = DarkMode;
Serial2.print('D');
Serial2.print(DarkMode);
Serial2.print(',');
}
if (ShutDown == 1 || UpdateSerial2 == 1) {
ShutDown_SEND = ShutDown;
Serial2.print('S');
Serial2.print(ShutDown);
Serial2.print(',');
}
Serial2.print('>');
}
UpdateSerial2 = 0;
}
//=========================================END SERIAL FUNCTIONS====================================================
//=========================================START MISC FUNCTIONS====================================================
void GEARS() {
if (GEAR_POS > Neutralp - GearWindow && GEAR_POS < Neutralp + GearWindow && Neutralp > 0 && millis() - GearTime > 250) GEAR = "N";
if (GEAR_POS > Gear1p - GearWindow && GEAR_POS < Gear1p + GearWindow && Gear1p > 0 && millis() - GearTime > 250) GEAR = "1";
if (GEAR_POS > Gear2p - GearWindow && GEAR_POS < Gear2p + GearWindow && Gear2p > 0 && millis() - GearTime > 250) GEAR = "2";
if (GEAR_POS > Gear3p - GearWindow && GEAR_POS < Gear3p + GearWindow && Gear3p > 0 && millis() - GearTime > 250) GEAR = "3";
if (GEAR_POS > Gear4p - GearWindow && GEAR_POS < Gear4p + GearWindow && Gear4p > 0 && millis() - GearTime > 250) GEAR = "4";
if (GEAR_POS > Gear5p - GearWindow && GEAR_POS < Gear5p + GearWindow && Gear5p > 0 && millis() - GearTime > 250) GEAR = "5";
if (GEAR_POS > Gear6p - GearWindow && GEAR_POS < Gear6p + GearWindow && Gear6p > 0 && millis() - GearTime > 250) GEAR = "6";
if (GEAR_POS > Reversep - GearWindow && GEAR_POS < Reversep + GearWindow && Reversep > 0 && millis() - GearTime > 250) GEAR = "R";
if (GEAR != GPrev) {
if ( GearChange != 1) lastmenu = menu;
GearChange = 1;
GearTime = millis();
}
GPrev = GEAR;
}
void checkdisplay() {
//Serial.println("Display");
if (menu == 1) display_Odometer();
if (menu == 2) display_Main();
if (menu == 3) display_GearOnly();
if (menu == 4) display_FuelR();
if (menu == 5) display_DarkMode();
if (menu == 6) display_oil_water();
if (menu == 7) display_OilP_FuelP();
if (menu == 8) display_Stats();
if (menu == 9) display_Acceltimer();
if (menu == 10) display_speedmph();
if (menu == 11) display_RPM();
if (menu == 12) display_BattV();
if (menu == 13) display_servicedist();
if (menu == 14) display_troublecodes();
if (menu == 15) display_Setup();
if (menu == 21) setup_SpeedUnits();
if (menu == 22) setup_SpeedSource();
if (menu == 23) setup_RPMSource();
if (menu == 24) setup_CoolTSource();
if (menu == 25) setup_AirTSource();
if (menu == 26) setup_OilTSource();
if (menu == 27) setup_ZeroStep();
if (menu == 28) setup_Gears();
if (menu == 29) setup_ZeroODO();
if (menu == 30) setup_ShowAlignBox();
if (menu == 31) setup_ExitSubmenu();
if (menu == 35) AlignmentBox();
}
//-------------------------UPDATE ODO--------------------------------------------------------
void updateodometer() {
if (meterssubtotal > 99.99) {
++disthundredm;
++tripdisthundredm;
++servicedisthundredm;
meterssubtotal = 0;
}
if (disthundredm > 9) {
++distkm;
disthundredm = 0;
}
if (distkm > 9) {
++distenkm;
distkm = 0;
}
if (distenkm > 9) {
++disthundredkm;
distenkm = 0;
}
if (disthundredkm > 9) {
++disthousandkm;
disthundredkm = 0;
}
if (disthousandkm > 9) {
++disttenthousandkm;
disthousandkm = 0;
}
if (disttenthousandkm > 9) {
++disthundredthousandkm;
disttenthousandkm = 0;
}
//-----------------------UPDATE TRIP--------------------------------
if (tripdisthundredm > 9) {
++tripdistkm;
tripdisthundredm = 0;
}
if (tripdistkm > 9) {
++tripdisthundredkm;
tripdistkm = 0;
}
if (tripdisthundredkm > 9) {
++tripdistthousandkm;
tripdisthundredkm = 0;
}
if (tripdistthousandkm == 9 && tripdisthundredkm == 9 && tripdistkm == 9 && tripdisthundredm == 9) {
tripdisthundredm = 0;
tripdistkm = 0;
tripdisthundredkm = 0;
tripdistthousandkm = 0;
}
//---------------------UPDATE SERVICE------------------------------
if (servicedisthundredm > 9) {
++servicedistkm;
servicedisthundredm = 0;
}
if (servicedistkm > 9) {
++servicedisthundredkm;
servicedistkm = 0;
}
if (servicedisthundredkm > 9) {
++servicedistthousandkm;
servicedisthundredkm = 0;
}
if (servicedistthousandkm == 9 && servicedisthundredkm == 9 && servicedistkm == 9 && servicedisthundredm == 9) {
servicedisthundredm = 0;
servicedistkm = 0;
servicedisthundredkm = 0;
servicedistthousandkm = 0;
}
}
//-----------------------CLEAR MENUS--------------------------------------------------------
void cleartrip() {
menu = 1;
tripdisthundredm = 0;
tripdistkm = 0;
tripdisthundredkm = 0;
tripdistthousandkm = 0;
}
void clearstats() {
MaxSpeed = 0;
MaxRPM = 0;
MaxTemp = 0;
MaxOil = 0;
}
void clearODO() {
distkm = 0;
distenkm = 0;
disthundredkm = 0;
disthousandkm = 0;
disttenthousandkm = 0;
disthundredthousandkm = 0;
}
void clearservice() {
servicedisthundredm = 0;
servicedistkm = 0;
servicedisthundredkm = 0;
servicedistthousandkm = 0;
distance_since_service = 0;
}
//-----------------------DRAW LOGO--------------------------------------------------------
void drawTVR(void) {
display.clearDisplay();
display.drawBitmap(
(display.width() - LOGO_WIDTH ) / 2,
(display.height() - LOGO_HEIGHT) / 2,
logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
display.display();
}
//==========================================END MISC FUNTIONS=======================================================
//========================================START EEPROM FUNCTIONS====================================================
void updateeeprom() {
EEPROMWriteCount = EEPROMWriteCount + 1;
EEPROM.update(S2 + (EEPROM_OFFSET * EEPROMAddress), EEPROMWriteCount);
EEPROM.update(S3 + (EEPROM_OFFSET * EEPROMAddress), tripdisthundredm);
EEPROM.update(S4 + (EEPROM_OFFSET * EEPROMAddress), tripdistkm);
EEPROM.update(S5 + (EEPROM_OFFSET * EEPROMAddress), tripdisthundredkm);
EEPROM.update(S6 + (EEPROM_OFFSET * EEPROMAddress), tripdistthousandkm);
EEPROM.update(S7 + (EEPROM_OFFSET * EEPROMAddress), disthundredm);
EEPROM.update(S8 + (EEPROM_OFFSET * EEPROMAddress), distkm);
EEPROM.update(S9 + (EEPROM_OFFSET * EEPROMAddress), distenkm);
EEPROM.update(S10 + (EEPROM_OFFSET * EEPROMAddress), disthundredkm);
EEPROM.update(S11 + (EEPROM_OFFSET * EEPROMAddress), disthousandkm);
EEPROM.update(S12 + (EEPROM_OFFSET * EEPROMAddress), disttenthousandkm);
EEPROM.update(S13 + (EEPROM_OFFSET * EEPROMAddress), disthundredthousandkm);
EEPROM.update(S14 + (EEPROM_OFFSET * EEPROMAddress), Best060);
EEPROM.update(S15 + (EEPROM_OFFSET * EEPROMAddress), PrevMPG);
EEPROM.update(S16 + (EEPROM_OFFSET * EEPROMAddress), MaxRPM);
EEPROM.update(S17 + (EEPROM_OFFSET * EEPROMAddress), MaxSpeed);
EEPROM.update(S18 + (EEPROM_OFFSET * EEPROMAddress), MaxTemp);
EEPROM.update(S19 + (EEPROM_OFFSET * EEPROMAddress), MaxOil);
EEPROM.update(S20 + (EEPROM_OFFSET * EEPROMAddress), servicedisthundredm);
EEPROM.update(S21 + (EEPROM_OFFSET * EEPROMAddress), servicedistkm);
EEPROM.update(S22 + (EEPROM_OFFSET * EEPROMAddress), servicedisthundredkm);
EEPROM.update(S23 + (EEPROM_OFFSET * EEPROMAddress), servicedistthousandkm);
EEPROM.update(S24 + (EEPROM_OFFSET * EEPROMAddress), menu);
EEPROM.update(S25 + (EEPROM_OFFSET * EEPROMAddress), Neutralp);
EEPROM.update(S26 + (EEPROM_OFFSET * EEPROMAddress), Gear1p);
EEPROM.update(S27 + (EEPROM_OFFSET * EEPROMAddress), Gear2p);
EEPROM.update(S28 + (EEPROM_OFFSET * EEPROMAddress), Gear3p);
EEPROM.update(S29 + (EEPROM_OFFSET * EEPROMAddress), Gear4p);
EEPROM.update(S30 + (EEPROM_OFFSET * EEPROMAddress), Gear5p);
EEPROM.update(S31 + (EEPROM_OFFSET * EEPROMAddress), Gear6p);
EEPROM.update(S32 + (EEPROM_OFFSET * EEPROMAddress), Reversep);
EEPROM.update(S33 + (EEPROM_OFFSET * EEPROMAddress), MODE_SPEED);
EEPROM.update(S34 + (EEPROM_OFFSET * EEPROMAddress), MODE_RPM);
EEPROM.update(S35 + (EEPROM_OFFSET * EEPROMAddress), MODE_COOLANT_TEMP);
EEPROM.update(S36 + (EEPROM_OFFSET * EEPROMAddress), MODE_OIL_TEMP);
EEPROM.update(S37 + (EEPROM_OFFSET * EEPROMAddress), MODE_AMBIENT_TEMP);
EEPROM.update(S38 + (EEPROM_OFFSET * EEPROMAddress), SPEED_DISPLAY);
}
// EEPROM SETTING--------------------------------------------------------------------------
void loadEEPROMSettings() {
if (EEPROM.read(E_INIT) == 'T') {
//settings have been initialized, read them
if (EEPROMWriteCount > 100000) {
EEPROMWriteCount = 0;
EEPROMAddress = EEPROMAddress + 1;
}
EEPROMAddress = EEPROM.read(S1);
EEPROMWriteCount = EEPROM.read(S2 + (EEPROM_OFFSET * EEPROMAddress));
tripdisthundredm = EEPROM.read(S3 + (EEPROM_OFFSET * EEPROMAddress));
tripdistkm = EEPROM.read(S4 + (EEPROM_OFFSET * EEPROMAddress));
tripdisthundredkm = EEPROM.read(S5 + (EEPROM_OFFSET * EEPROMAddress));
tripdistthousandkm = EEPROM.read(S6 + (EEPROM_OFFSET * EEPROMAddress));
disthundredm = EEPROM.read(S7 + (EEPROM_OFFSET * EEPROMAddress));
distkm = EEPROM.read(S8 + (EEPROM_OFFSET * EEPROMAddress));
distenkm = EEPROM.read(S9 + (EEPROM_OFFSET * EEPROMAddress));
disthundredkm = EEPROM.read(S10 + (EEPROM_OFFSET * EEPROMAddress));
disthousandkm = EEPROM.read(S11 + (EEPROM_OFFSET * EEPROMAddress));
disttenthousandkm = EEPROM.read(S12 + (EEPROM_OFFSET * EEPROMAddress));
disthundredthousandkm = EEPROM.read(S13 + (EEPROM_OFFSET * EEPROMAddress));
Best060 = EEPROM.read(S14 + (EEPROM_OFFSET * EEPROMAddress));
PrevMPG = EEPROM.read(S15 + (EEPROM_OFFSET * EEPROMAddress));
MaxRPM = EEPROM.read(S16 + (EEPROM_OFFSET * EEPROMAddress));
MaxSpeed = EEPROM.read(S17 + (EEPROM_OFFSET * EEPROMAddress));
MaxTemp = EEPROM.read(S18 + (EEPROM_OFFSET * EEPROMAddress));
MaxOil = EEPROM.read(S19 + (EEPROM_OFFSET * EEPROMAddress));
servicedisthundredm = EEPROM.read(S20 + (EEPROM_OFFSET * EEPROMAddress));
servicedistkm = EEPROM.read(S21 + (EEPROM_OFFSET * EEPROMAddress));
servicedisthundredkm = EEPROM.read(S22 + (EEPROM_OFFSET * EEPROMAddress));
servicedistthousandkm = EEPROM.read(S23 + (EEPROM_OFFSET * EEPROMAddress));
MenuMem = EEPROM.read(S24 + (EEPROM_OFFSET * EEPROMAddress));
Neutralp = EEPROM.read(S25 + (EEPROM_OFFSET * EEPROMAddress));
Gear1p = EEPROM.read(S26 + (EEPROM_OFFSET * EEPROMAddress));
Gear2p = EEPROM.read(S27 + (EEPROM_OFFSET * EEPROMAddress));
Gear3p = EEPROM.read(S28 + (EEPROM_OFFSET * EEPROMAddress));
Gear4p = EEPROM.read(S29 + (EEPROM_OFFSET * EEPROMAddress));
Gear5p = EEPROM.read(S30 + (EEPROM_OFFSET * EEPROMAddress));
Gear6p = EEPROM.read(S31 + (EEPROM_OFFSET * EEPROMAddress));
Reversep = EEPROM.read(S32 + (EEPROM_OFFSET * EEPROMAddress));
MODE_SPEED = EEPROM.read(S33 + (EEPROM_OFFSET * EEPROMAddress));
MODE_RPM = EEPROM.read(S34 + (EEPROM_OFFSET * EEPROMAddress));
MODE_COOLANT_TEMP = EEPROM.read(S35 + (EEPROM_OFFSET * EEPROMAddress));
MODE_OIL_TEMP = EEPROM.read(S36 + (EEPROM_OFFSET * EEPROMAddress));
MODE_AMBIENT_TEMP = EEPROM.read(S37 + (EEPROM_OFFSET * EEPROMAddress));
SPEED_DISPLAY = EEPROM.read(S38 + (EEPROM_OFFSET * EEPROMAddress));
if (MODE_SPEED != 1 && MODE_SPEED != 2) MODE_SPEED = 2;
if (MODE_RPM != 1 && MODE_RPM != 2) MODE_RPM = 2;
if (MODE_COOLANT_TEMP != 1 && MODE_COOLANT_TEMP != 2) MODE_COOLANT_TEMP = 2;
if (MODE_OIL_TEMP != 1 && MODE_OIL_TEMP != 2) MODE_OIL_TEMP = 2;
if (MODE_AMBIENT_TEMP != 1 && MODE_AMBIENT_TEMP != 2) MODE_AMBIENT_TEMP = 2;
if (SPEED_DISPLAY != 1 && SPEED_DISPLAY != 2) SPEED_DISPLAY = 1;
} else {
//first time run, settings were never set
EEPROM.write(S1, 0);
EEPROM.write(S2, 0);
EEPROM.write(S3, 0);
EEPROM.write(S4, 0);
EEPROM.write(S4, 0);
EEPROM.write(S5, 0);
EEPROM.write(S6, 0);
EEPROM.write(S7, 0);
EEPROM.write(S8, 0);
EEPROM.write(S9, 0);
EEPROM.write(S10, 0);
EEPROM.write(S11, 0);
EEPROM.write(S12, 0);
EEPROM.write(S13, 0);
EEPROM.write(S14, 0);
EEPROM.write(S15, 0);
EEPROM.write(S16, 0);
EEPROM.write(S17, 0);
EEPROM.write(S18, 0);
EEPROM.write(S19, 0);
EEPROM.write(S20, 0);
EEPROM.write(S21, 0);
EEPROM.write(S22, 0);
EEPROM.write(S23, 0);
EEPROM.write(S24, 0);
EEPROM.write(S25, 0);
EEPROM.write(S26, 0);
EEPROM.write(S27, 0);
EEPROM.write(S28, 0);
EEPROM.write(S29, 0);
EEPROM.write(S30, 0);
EEPROM.write(S31, 0);
EEPROM.write(S32, 0);
EEPROM.write(S33, 2);
EEPROM.write(S34, 2);
EEPROM.write(S35, 2);
EEPROM.write(S36, 2);
EEPROM.write(S37, 2);
EEPROM.write(S38, 0);
EEPROMAddress = 0;
EEPROMWriteCount = 0;
tripdisthundredm = 0;
tripdistkm = 0;
tripdisthundredkm = 0;
tripdistthousandkm = 0;
disthundredm = 0;
distkm = 0;
distenkm = 0;
disthundredkm = 0;
disthousandkm = 0;
disttenthousandkm = 0;
disthundredthousandkm = 0;
Best060 = 0;
PrevMPG = 0;
MaxRPM = 0;
MaxSpeed = 0;
MaxTemp = 0;
MaxOil = 0;
servicedisthundredm = 0;
servicedistkm = 0;
servicedisthundredkm = 0;
servicedistthousandkm = 0;
MenuMem = 1;
Neutralp = 219;
Gear1p = 202;
Gear2p = 167;
Gear3p = 132;
Gear4p = 98;
Gear5p = 64;
Gear6p = 30;
Reversep = 0;
MODE_SPEED = 2;
MODE_RPM = 2;
MODE_COOLANT_TEMP = 2;
MODE_OIL_TEMP = 2;
MODE_AMBIENT_TEMP = 2;
SPEED_DISPLAY = 1;
EEPROM.write(E_INIT, 'T');
}
}
//=============================================================================================END EEPROM FUNCTIONS
//======================================================================================START OLED DISPLAY FUNCTIONS
void AlignmentBox() {
display.clearDisplay();
display.drawRect(0, 0, 128, 32, WHITE);
display.display();
}
//---------------------------------------------------------------------------------------START Display Modes
//---------------------------------------------------------------------DISPLAY ODOMETER
void display_Odometer() {
if (distkm != distkm_PREV || tripdisthundredm != tripdisthundredm_PREV || menu != menu_PREV) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.println("ODO");
//-----Display hundred thousand km units-----
display.setTextSize(2);
display.setCursor(30, 0);
display.println(disthundredthousandkm);
//-----Display ten thousand km units--------
display.setCursor(45, 0);
display.println(disttenthousandkm);
//----Display thousand km units------------
display.setCursor(60, 0);
display.println(disthousandkm);
//----Display hundreds km units-------------
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(75, 0);
display.println(disthundredkm);
//----Display tens km units-----------------
display.setCursor(90, 0);
display.println(distenkm);
//----Display km units----------------------
display.setCursor(105, 0);
display.println(distkm);
//----Display km units----------------------
display.setTextSize(1);
display.setCursor(125, 0);
//-------------------------------------------------------------------DISPLAY TRIP
display.setCursor(0, 20);
//display.println("TRIP");
// if (digitalRead(ShutDownPin) == LOW)display.println("TRIP SD");
// else {
// if (digitalRead(ShutDownPin) == HIGH) {
// display.println("TRIP");
// }
// }
if (numDTC > 0)display.println("TRIP DTC");
else display.println("TRIP");
//----Display Thousands---------------------
display.setTextSize(2);
display.setCursor(75, 17);
display.println(tripdistthousandkm);
//-----Display Hundreds----------------------
display.setCursor(90, 17);
display.println(tripdisthundredkm);
//-----Display KMs---------------------------
display.setCursor(105, 17);
display.println(tripdistkm);
//----------------Display Hundred M---------
display.setTextSize(1);
display.setCursor(120, 17);
display.println(tripdisthundredm);
display.display();
distkm_PREV = distkm;
tripdisthundredm_PREV = tripdisthundredm;
menu_PREV = menu;
}
}
//-------------------------------------------------------------------------------START MAIN DISPLAY
void display_Main() {
if (GEAR != GEAR_PREV || AMBIENT_TEMP != AMBIENT_TEMP_PREV || INTAKE_TEMP != INTAKE_TEMP_PREV || OIL_TEMP != OIL_TEMP_PREV || INTAKE_TEXT_PREV != INTAKE_TEXT || menu != menu_PREV) {
display.clearDisplay();
display.setCursor(89, 3);
display.setTextSize(4.9);
display.println(GEAR);
display.setCursor(55, 0);
display.setTextSize(1);
display.println("Gear");
if (numDTC > 0) {
display.setCursor(58, 25);
display.println("DTC");
}
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 5);
display.println("Air");
display.setCursor(25, 5);
display.println(AMBIENT_TEMP);
display.setCursor(0, 15);
display.println("Itk");
display.setCursor(25, 15);
display.setTextColor(INTAKE_TEXT);
display.println(INTAKE_TEMP);
display.setCursor(0, 25);
display.setTextColor(WHITE);
display.println("Oil");
display.setCursor(25, 25);
display.setTextColor(OIL_TEMP_TEXT);
display.println(OIL_TEMP);
display.display();
GEAR_PREV = GEAR;
AMBIENT_TEMP_PREV = AMBIENT_TEMP;
INTAKE_TEMP_PREV = INTAKE_TEMP;
OIL_TEMP_PREV = OIL_TEMP;
INTAKE_TEXT_PREV = INTAKE_TEXT;
menu_PREV = menu;
}
}
//-------------------------------------------------------------------------------GEAR ONLY
void display_GearOnly() {
if (GEAR != GEAR_PREV || menu != menu_PREV) {
display.clearDisplay();
display.setCursor(89, 3);
display.setTextSize(4.9);
display.println(GEAR);
display.setCursor(55, 0);
display.setTextSize(1);
display.println("Gear");
if (numDTC > 0) {
display.setCursor(58, 25);
display.println("DTC");
}
display.display();
GEAR_PREV = GEAR;
menu_PREV = menu;
}
}
//-------------------------------------------------------------------------------SPEED
void display_speedmph() {
if (SPEED_MPH_PREV != SPEED_MPH || menu != menu_PREV) {
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.clearDisplay();
if (SPEED_DISPLAY == 1) display.println("MPH");
else if (SPEED_DISPLAY == 2) display.println("KPH");
display.setTextSize(4);
display.setCursor(40, 0);
display.println(int(SPEED_MPH * SPEED_MULTIPLIER));
display.display();
SPEED_MPH_PREV = SPEED_MPH;
menu_PREV = menu;
}
}
//-------------------------------------------------------------------------------RPM
void display_RPM() {
if (RPM != RPM_PREV || BlinkState_PREV != BlinkState || menu != menu_PREV) {
display.clearDisplay();
display.drawRect(0, 18, 125, 14, WHITE);
int RPMbar = map (RPM, 0, 7000, 0, 122);
display.fillRect(3, 21, RPMbar, 8, RPM_TEXT);
display.setCursor(79, 0);
display.setTextSize(2);
display.println(RPM);
display.setTextSize(1);
display.setCursor(0, 0);
display.println("RPM");
display.display();
RPM_PREV = RPM;
BlinkState_PREV = BlinkState;
menu_PREV = menu;
}
}
//--------------------------------------------------------------------INTAKE TEMP & WATER TEMP
void display_oil_water() {
if (OIL_TEMP != OIL_TEMP_PREV || COOLANT_TEMP != COOLANT_TEMP_PREV || BlinkState_PREV != BlinkState || menu != menu_PREV) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(OIL_TEMP_TEXT);
display.setCursor(0, 0);
display.println("Oil T");
display.setCursor(0, 10);
display.setTextSize(3);
display.setTextColor(OIL_TEMP_TEXT);
display.setCursor(1, 10);
display.println(OIL_TEMP);
display.setTextSize(1);
display.setCursor(70, 0);
display.setTextColor(WATER_TEXT);
display.println("Water T");
display.setTextColor(WATER_TEXT);
display.setTextSize(3);
display.setCursor(70, 10);
display.println(COOLANT_TEMP);
display.display();
COOLANT_TEMP_PREV = COOLANT_TEMP;
OIL_TEMP_PREV = OIL_TEMP;
BlinkState_PREV = BlinkState;
menu_PREV = menu;
}
}
//------------------------------------------------------------------------OIL TEMP & OIL PRESSURE
void display_OilP_FuelP() {
if (OIL_PRESS != OIL_PRESS_PREV || FUEL_PRESSURE != FUEL_PRESSURE_PREV || BlinkState_PREV != BlinkState || menu != menu_PREV) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(textflashoilp);
display.setCursor(0, 0);
display.println("Oil P");
display.setCursor(0, 10);
display.setTextSize(3);
display.setTextColor(textflashoilp);
display.setCursor(1, 10);
display.println(OIL_PRESS);
display.setTextSize(1);
display.setCursor(70, 0);
display.setTextColor(WHITE);
display.println("Fuel P");
display.setTextColor(WHITE);
display.setTextSize(3);
display.setCursor(70, 10);
display.println(FUEL_PRESSURE);
display.display();
OIL_PRESS_PREV = OIL_PRESS;
FUEL_PRESSURE_PREV = FUEL_PRESSURE;
BlinkState_PREV = BlinkState;
menu_PREV = menu;
}
}
//-----------------------------------------------------------------------------MILES REMAINING & AIR TEMP
void display_FuelR() {
if (BlinkState_PREV != BlinkState || FUEL_LEVEL != FUEL_LEVEL_PREV || int(FUEL_RATE) != int(FUEL_RATE_PREV) || menu != menu_PREV) {
display.clearDisplay();
display.drawRect(0, 18, 125, 14, WHITE);
//FuelTime
int FuelRbar = map (int(FUEL_LEVEL), 0, 57, 0, 119);
display.fillRect(3, 21, FuelRbar, 8, textflashfuel);
display.setCursor(75, 0);
display.setTextSize(1);
display.setTextColor(WHITE);
display.print(FUEL_RATE, 1);
display.println(" l/h");
display.setCursor(103, 0);
display.setTextSize(1);
display.setCursor(0, 0);
display.setTextColor(textflashfuel);
display.println("Fuel");
display.display();
FUEL_LEVEL_PREV = FUEL_LEVEL;
FUEL_RATE_PREV = FUEL_RATE;
BlinkState_PREV = BlinkState;
menu_PREV = menu;
}
}
//--------------------------------------------------------------------------------BATT VOLTAGE DISPLAY
void display_BattV() {
if (BATT_VOLTAGE != BATT_VOLTAGE_PREV || menu != menu_PREV) {
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.setTextColor(WHITE);
display.println("Batt");
display.setTextColor(WHITE);
display.setTextSize(3);
display.setCursor(35, 10);
display.print(BATT_VOLTAGE, 1);
display.println("v");
display.display();
BATT_VOLTAGE_PREV = BATT_VOLTAGE;
menu_PREV = menu;
}
}
//---------------------------------------------------------------------------------DTC CODES
void display_troublecodes() {
if (numDTC != numDTC_PREV || DTC != DTC_PREV || menu != menu_PREV) {
display.clearDisplay();
display.setTextSize(1);
display.setCursor(20, 0);
display.setTextColor(WHITE);
display.print(numDTC);
display.println(" DTCs Detected");
display.setTextColor(WHITE);
display.setTextSize(2);
if (DTC != 4) {
display.setCursor(35, 15);
display.setTextSize(2);
}
else {
display.setCursor(30, 20);
display.setTextSize(1);
}
if (DTC == 4) display.println("DTCs Cleared");
if (DTC == 1) display.println(DTC1);
if (DTC == 2) display.println(DTC2);
//Serial.println(DTC);
display.display();
numDTC_PREV = numDTC;
DTC_PREV = DTC;
menu_PREV = menu;
}
}
//---------------------------------------------------------------------------------STATS DISPLAY
void display_Stats() {
if (MaxSpeed != MaxSpeed_PREV || MaxRPM != MaxRPM_PREV || MaxTemp != MaxTemp_PREV || MaxOil != MaxOil_PREV || menu != menu_PREV) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(38, 0);
display.println("Max Stats");
display.setCursor(5, 15);
display.println("MPH");
display.setCursor(30, 15);
display.println(MaxSpeed);
display.setCursor(5, 25);
display.println("RPM");
display.setCursor(30, 25);
display.println(MaxRPM);
display.setCursor(70, 15);
display.println("WatT");
display.setCursor(100, 15);
display.println(MaxTemp);
display.setCursor(70, 25);
display.println("OilT");
display.setCursor(100, 25);
display.println(MaxOil, 0);
display.display();
MaxSpeed_PREV = MaxSpeed;
MaxRPM_PREV = MaxRPM;
MaxTemp_PREV = MaxTemp;
MaxOil_PREV = MaxOil;
menu_PREV = menu;
}
}
//-------------------------------------------------------------------------------SERVICE INTERVAL
void display_servicedist() {
distance_since_service = (servicedistthousandkm * 1000) + (servicedisthundredkm * 100) + (servicedistkm * 10) + servicedisthundredm ;
distance_to_service = service_interval - distance_since_service;
if (distance_to_service != distance_to_service_PREV || menu != menu_PREV) {
if (distance_since_service <= service_interval) {
servicetext = ("NEXT SERVICE");
}
else {
servicetext = ("SERVICE OVERDUE");
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 3);
display.println(servicetext);
display.setCursor(80, 17);
display.setTextSize(2);
display.println(distance_to_service);
display.display();
distance_to_service_PREV = distance_to_service;
menu_PREV = menu;
}
}
//--------------------------------------------------------------------------------0-60 TIMER
void display_Acceltimer() {
//display.clearDisplay();
if (timerstart == 1 && timerstop == 0) {
mode060 = 1;
if (mode060 != mode060_PREV || menu != menu_PREV) {
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(15, 0);
display.println("READY..");
display.setTextSize(1);
display.setCursor(0, 23);
display.println("Prev: ");
display.setCursor(30, 23);
display.println(timeseconds);
display.setCursor(65, 23);
display.println("Best: ");
display.setCursor(95, 23);
display.println(Best060);
display.display();
mode060_PREV = mode060;
menu_PREV = menu;
}
}
if (SPEED_MPH >= 1 && timerstart == 1) {
mode060 = 2;
Startmillis = millis();
timerstart = 0;
timerstop = 1;
}
if (mode060 == 2 && SPEED_MPH < 60 && SPEED_MPH != SPEED_MPH_PREV) {
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(15, 0);
display.println("GO!");
display.setTextSize(4);
display.setCursor(70, 0);
display.println(SPEED_MPH);
display.display();
menu_PREV = menu;
SPEED_MPH_PREV = SPEED_MPH;
}
if (SPEED_MPH >= 60 && timerstop == 1) {
mode060 = 4;
Finishmillis = millis();
timerstop = 0;
timeto60 = Finishmillis - Startmillis;
timeseconds = timeto60 / 1000.0;
if ((timeseconds * 1000) < (Best060 * 1000)) {
Best060 = timeseconds;
}
if (Best060 == 0) {
Best060 = timeseconds;
}
}
if (timerstart == 0 && timerstop == 0) {
mode060 = 3;
if (mode060 != mode060_PREV || menu != menu_PREV) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.println("Time");
display.setTextSize(2);
display.setCursor(40, 0);
display.println(timeseconds);
display.setTextSize(1);
display.setCursor(5, 23);
display.println("Stop Car To Restart");
display.display();
mode060_PREV = mode060;
menu_PREV = menu;
}
if (SPEED_MPH == 0) {
timerstart = 1;
}
}
}
//--------------------------------------------------------------------------------SETUP
void display_Setup() {
if (menu != menu_PREV) {
display.setTextSize(2);
display.setTextColor(WHITE);
display.clearDisplay();
display.setCursor(35, 0);
display.print("Setup");
display.setTextSize(1);
display.setCursor(31, 24);
display.print("Short Press");
display.display();
menu_PREV = menu;
}
}
//===============================================================================================SETUP SUB-MENU
//--------------------------------------------------------------------------------GEARS
void Gear_Setup() {
if (SetGear != SetGear_PREV || menu != menu_PREV) {
}
display.setTextSize(1);
display.setTextColor(WHITE);
display.clearDisplay();
display.setCursor(5, 0);
if (SetGear == 1) display.println("Select Neutral");
if (SetGear == 2) display.println("Select 1st Gear");
if (SetGear == 3) display.println("Select 2nd Gear");
if (SetGear == 4) display.println("Select 3rd Gear");
if (SetGear == 5) display.println("Select 4th Gear");
if (SetGear == 6) display.println("Select 5th Gear");
if (SetGear == 7) display.println("Select 6th Gear");
if (SetGear == 8) display.println("Select Reverse");
if (SetGear == 9) display.println("Gear Positions Saved");
display.setCursor(15, 15);
display.println("Press Menu Button");
display.display();
SetGear_PREV = SetGear;
menu_PREV = menu;
}
//--------------------------------------------------------------------------------SPEED UNITS
void setup_SpeedUnits() {
if (ChangeSource == 1 || menu != menu_PREV) {
display.setTextSize(1);
display.setTextColor(WHITE);
display.clearDisplay();
display.setCursor(7, 0);
display.print("Speed Display Units");
display.setCursor(45, 16);
display.setTextSize(2);
if (SPEED_DISPLAY == 1) display.print("MPH");
else if (SPEED_DISPLAY == 2) display.print("KPH");
display.display();
ChangeSource = 0;
menu_PREV = menu;
}
}
//--------------------------------------------------------------------------------SPEED INPUT SOURCE
void setup_SpeedSource() {
if (ChangeSource == 1 || menu != menu_PREV) {
display.setTextSize(1);
display.setTextColor(WHITE);
display.clearDisplay();
display.setCursor(32, 0);
display.print("Speed Input");
display.setTextSize(2);
if (MODE_SPEED == 1) {
display.setCursor(30, 16);
display.print("Analog");
}
else if (MODE_SPEED == 2) {
display.setCursor(45, 17);
display.print("CAN");
}
display.display();
ChangeSource = 0;
menu_PREV = menu;
}
}
//--------------------------------------------------------------------------------RPM INPUT SOURCE
void setup_RPMSource() {
if (ChangeSource == 1 || menu != menu_PREV) {
display.setTextSize(1);
display.setTextColor(WHITE);
display.clearDisplay();
display.setCursor(38, 0);
display.print("RPM Input");
display.setTextSize(2);
if (MODE_RPM == 1) {
display.setCursor(30, 16);
display.print("Analog");
}
else if (MODE_RPM == 2) {
display.setCursor(45, 17);
display.print("CAN");
}
display.display();
ChangeSource = 0;
menu_PREV = menu;
}
}
//--------------------------------------------------------------------------------COOLANT TEMP INPUT SOURCE
void setup_CoolTSource() {
if (ChangeSource == 1 || menu != menu_PREV) {
display.setTextSize(1);
display.setTextColor(WHITE);
display.clearDisplay();
display.setCursor(11, 0);
display.print("Coolant Temp Input");
display.setTextSize(2);
if (MODE_COOLANT_TEMP == 1) {
display.setCursor(30, 16);
display.print("Analog");
}
else if (MODE_COOLANT_TEMP == 2) {
display.setCursor(45, 17);
display.print("CAN");
}
display.display();
ChangeSource = 0;
menu_PREV = menu;
}
}
//--------------------------------------------------------------------------------AIR TEMP INPUT SOURCE
void setup_AirTSource() {
if (ChangeSource == 1 || menu != menu_PREV) {
display.setTextSize(1);
display.setTextColor(WHITE);
display.clearDisplay();
display.setCursor(11, 0);
display.print("Ambient Temp Input");
display.setTextSize(2);
if (MODE_AMBIENT_TEMP == 1) {
display.setCursor(30, 16);
display.print("Analog");
}
else if (MODE_AMBIENT_TEMP == 2) {
display.setCursor(45, 17);
display.print("CAN");
}
display.display();
ChangeSource = 0;
menu_PREV = menu;
}
}
//--------------------------------------------------------------------------------OIL TEMP INPUT SOURCE
void setup_OilTSource() {
if (ChangeSource == 1 || menu != menu_PREV) {
display.setTextSize(1);
display.setTextColor(WHITE);
display.clearDisplay();
display.setCursor(23, 0);
display.print("Oil Temp Input");
display.setTextSize(2);
if (MODE_OIL_TEMP == 1) {
display.setCursor(30, 16);
display.print("Analog");
}
else if (MODE_OIL_TEMP == 2) {
display.setCursor(45, 17);
display.print("CAN");
}
display.display();
ChangeSource = 0;
menu_PREV = menu;
}
}
//--------------------------------------------------------------------------------ZERO STEPPERS
void setup_ZeroStep() {
if (Done != Done_PREV || menu != menu_PREV) {
display.setTextSize(1);
display.setTextColor(WHITE);
display.clearDisplay();
display.setCursor(16, 0);
display.print("Re-Zero Steppers");
display.setTextSize(1);
if (Done == 0) {
display.setCursor(33, 24);
display.print("Long Press");
}
else if (Done == 1) {
display.setTextSize(2);
display.setCursor(40, 17);
display.print("DONE");
}
display.display();
menu_PREV = menu;
Done_PREV = Done;
}
}
//--------------------------------------------------------------------------------SET UP GEARS
void setup_Gears() {
if (menu != menu_PREV) {
display.setTextSize(1);
display.setTextColor(WHITE);
display.clearDisplay();
display.setCursor(12, 0);
display.print("Recalibrate Gears");
display.setTextSize(1);
display.setCursor(33, 24);
display.print("Long Press");
display.display();
menu_PREV = menu;
}
}
//--------------------------------------------------------------------------------ZERO ODOMETER
void setup_ZeroODO() {
if (Done != Done_PREV || menu != menu_PREV) {
display.setTextSize(1);
display.setTextColor(WHITE);
display.clearDisplay();
display.setCursor(20, 0);
display.print("Reset Odometer");
display.setTextSize(1);
if (Done == 0) {
display.setCursor(33, 24);
display.print("Long Press");
}
else if (Done == 1) {
display.setTextSize(2);
display.setCursor(40, 17);
display.print("DONE");
}
display.display();
menu_PREV = menu;
Done_PREV = Done;
}
}
//--------------------------------------------------------------------------------SHOW ALIGNMENT BOX
void setup_ShowAlignBox() {
if (menu != menu_PREV) {
display.setTextSize(1);
display.setTextColor(WHITE);
display.clearDisplay();
display.setCursor(11, 0);
display.print("Show Alignment Box");
display.setTextSize(1);
display.setCursor(33, 24);
display.print("Long Press");
display.display();
menu_PREV = menu;
}
}
//--------------------------------------------------------------------------------EXIT SUB MENU
void setup_ExitSubmenu() {
if (menu != menu_PREV) {
display.setTextSize(2);
display.setTextColor(WHITE);
display.clearDisplay();
display.setCursor(6, 0);
display.print("Exit Setup");
display.setTextSize(1);
display.setCursor(31, 24);
display.print("Short Press");
display.display();
menu_PREV = menu;
}
}
//--------------------------------------------------------------------------------DARK MODE
void display_DarkMode() {
if (menu != menu_PREV || DarkMode != DarkMode_PREV) {
if (DarkMode == 0) {
display.setTextSize(2);
display.setTextColor(WHITE);
display.clearDisplay();
display.setCursor(12, 0);
display.print("Dark Mode");
display.setTextSize(1);
display.setCursor(31, 24);
display.print("Short Press");
display.display();
menu_PREV = menu;
}
else if (DarkMode == 1) {
display.clearDisplay();
display.display();
}
DarkMode_PREV = DarkMode;
}
}
//========================================================================================END OLED DISPLAY FUNCTIONS