/* ARDUINO NANO
* ------|USB|------
* NOT USED <|D13 |___| D12|> NOT USED
* BAD 3.3VOLT OUTPUT, NEVER USE <|3V3 D11|> NOT USED
* NOT USED <|AREF D10|> NOT USED
* ANALOG INPUT FOR ECT <|A0 D9|> NOT USED
* ANALOG INPUT FOR EOT <|A1 D8|> NOT USED
* ANALOG INPUT FOR TOT <|A2 D7|> NOT USED
* ANALOG INPUT FOR EOP <|A3 D6|> NOT USED
* IIC SDA <|A4 D5|> NOT USED
* IIC SCL <|A5 D4|> DIGITAL OUTPUT FOR COLD TIMING ADVANCE SOLENOID
* NOT USED <|A6 D3|> DIGITAL OUTPUT FOR HIGH IDLE SOLENOID
* NOT USED <|A7 D2|> DIGITAL INPUT FOR MANUAL HIGH IDLE SWITCH
* 5V OUT <|5V GND|> GROUND
* NOT USED <|RESET RESET|> NOT USED
* GROUND <|GND RX |> NOT USED
* POWER IN <|VIN TX |> NOT USED
* -----------------
*/
//Libraries
#include <LiquidCrystal_I2C.h>
// Set the LCD I2C address and pinout
// address,EN,RW,RS,D4,D5,D6,D6,BL,Polarity
LiquidCrystal_I2C lcd(0x20, 4, 5, 6, 0, 1, 2, 3, 7, NEGATIVE);
// ADC
// NOTE: This section is to calibrate the Analog to Digital Converter
// NOTE2: The ADC is only capable of reading VREF - 1 count. EXP. if VREF = 5V, ADC will return 4.995V (See datasheet for reason why)
#define VREF 5.003 // Measued the value of 5 volt pin and enter it here
#define ADC_V VREF/1024.0 // Take the reference voltage and divide by the amount of steps the ADC has
// Input Declarations
// Analog
#define ECT A0 // Engine Coolant Temperatur Sensor connected to Analog pin 0
#define EOT A1 // Enigne Oil Temperature Sensor connected to Analog pin 1
#define TOT A2 // Transmission Oil Temperature Sensor connected to Analog pin 2
#define EOP A3 // Engine Oil Pressure Sensor connected to Analog pin 3
// Digital
#define MHI 2 // Manual High Idle Switch connected to Digital pin 2
// Output Declarations
// Digital
#define High_Idle 3 // High Idle Solenoid connected to Digital Outpput pin 3
#define Cold_Adv 4 // Cold timing Advance Solenoid connected to Digital Output pin 4
// Variables
signed int ect_t = 0; // Engine Coolant Temperature
signed int eot_t = 0; // Engine Oil Temperature
signed int tot_t = 0; // Transmission Oil Temperature
int eop_p = 0; // Engine Oil Pressure
int eop_v = 0; // Engine Oil Pressure Voltage
byte MHI_Switch = 0; // Manual High Idle Switch
unsigned long last_time = millis(); // Used to hold the previous time the LCD was updated
//Custom °F symbol for character display
byte degtempF[8] = {
B11000, // HH...
B11000, // HH...
B00111, // ..HHH
B00100, // ..H..
B00110, // ..HH.
B00100, // ..H..
B00100, // ..H..
B00000, // .....
};
// Ford Temperature sensor lookup table in °F
// NOTE: "PROGMEM const" is required so the lookup table doesn't get loaded into ram
// as that would use up all the ram, instead acess the lookup table from flash memory
PROGMEM const signed int Temp_ConvF[] = {
302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302,
302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 300,
298, 295, 293, 291, 289, 288, 286, 282, 280, 279, 277, 275, 273, 270, 268,
266, 264, 263, 262, 261, 260, 259, 257, 255, 254, 253, 252, 251, 250, 248,
247, 246, 245, 244, 243, 241, 240, 239, 237, 236, 235, 234, 233, 232, 231,
230, 229, 228, 227, 226, 226, 225, 224, 223, 222, 221, 221, 220, 219, 218,
217, 217, 216, 216, 215, 214, 213, 212, 212, 211, 210, 209, 208, 208, 208,
207, 206, 205, 204, 203, 203, 202, 201, 201, 200, 200, 199, 199, 199, 198,
198, 197, 197, 196, 196, 195, 194, 194, 193, 193, 192, 192, 191, 191, 190,
190, 190, 189, 189, 188, 188, 187, 187, 186, 185, 185, 184, 184, 183, 183,
182, 182, 181, 181, 181, 180, 180, 179, 178, 178, 177, 177, 176, 176, 175,
175, 174, 174, 174, 173, 173, 172, 172, 172, 172, 172, 171, 171, 171, 170,
170, 169, 169, 169, 168, 168, 167, 167, 167, 166, 166, 165, 165, 165, 164,
164, 163, 163, 163, 163, 163, 162, 162, 162, 161, 161, 160, 160, 160, 159,
159, 158, 158, 158, 157, 157, 157, 156, 156, 156, 156, 155, 155, 155, 155,
154, 154, 154, 154, 154, 154, 154, 154, 154, 153, 153, 153, 153, 152, 152,
152, 151, 151, 151, 151, 150, 150, 150, 150, 149, 149, 149, 149, 148, 148,
148, 147, 147, 147, 147, 146, 146, 146, 146, 145, 145, 145, 145, 145, 145,
145, 144, 144, 144, 144, 143, 143, 143, 143, 142, 142, 142, 142, 141, 141,
141, 141, 140, 140, 140, 140, 139, 139, 139, 138, 138, 138, 138, 137, 137,
137, 137, 136, 136, 136, 136, 136, 136, 136, 136, 135, 135, 135, 135, 134,
134, 134, 134, 133, 133, 133, 133, 132, 132, 132, 132, 131, 131, 131, 131,
130, 130, 130, 129, 129, 129, 129, 128, 128, 128, 128, 127, 127, 127, 127,
127, 127, 127, 127, 126, 126, 126, 126, 125, 125, 125, 125, 124, 124, 124,
124, 123, 123, 123, 123, 122, 122, 122, 122, 121, 121, 121, 120, 120, 120,
120, 119, 119, 119, 119, 118, 118, 118, 118, 118, 118, 118, 118, 117, 117,
117, 117, 116, 116, 116, 116, 115, 115, 115, 115, 114, 114, 114, 114, 113,
113, 113, 113, 112, 112, 112, 111, 111, 111, 111, 110, 110, 110, 110, 109,
109, 109, 109, 109, 109, 109, 109, 108, 108, 108, 108, 107, 107, 107, 107,
106, 106, 106, 106, 105, 105, 105, 105, 104, 104, 104, 104, 103, 103, 103,
103, 102, 102, 102, 102, 102, 101, 101, 101, 101, 101, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 99, 99, 99, 99, 99, 98, 98, 98, 98,
98, 97, 97, 97, 97, 97, 96, 96, 96, 96, 96, 95, 95, 95, 95,
95, 94, 94, 94, 94, 94, 93, 93, 93, 93, 93, 92, 92, 92, 92,
92, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 90, 90, 90, 90,
90, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 87, 87, 87, 87,
87, 86, 86, 86, 86, 86, 85, 85, 85, 85, 85, 84, 84, 84, 84,
84, 83, 83, 83, 83, 83, 82, 82, 82, 82, 82, 82, 82, 82, 82,
82, 81, 81, 81, 81, 81, 80, 80, 80, 80, 80, 79, 79, 79, 79,
79, 78, 78, 78, 78, 78, 77, 77, 77, 77, 77, 76, 76, 76, 76,
76, 75, 75, 75, 75, 75, 74, 74, 74, 74, 74, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 72, 72, 72, 72, 72, 71, 71, 71, 71,
71, 70, 70, 70, 70, 70, 69, 69, 69, 69, 69, 68, 68, 68, 68,
68, 67, 67, 67, 67, 66, 66, 66, 66, 66, 65, 65, 65, 65, 64,
64, 64, 64, 64, 64, 64, 64, 64, 63, 63, 63, 63, 63, 62, 62,
62, 62, 61, 61, 61, 61, 61, 60, 60, 60, 60, 59, 59, 59, 59,
59, 58, 58, 58, 58, 58, 57, 57, 57, 57, 57, 56, 56, 56, 56,
55, 55, 55, 55, 55, 55, 55, 55, 55, 54, 54, 54, 54, 54, 53,
53, 53, 53, 52, 52, 52, 52, 52, 51, 51, 51, 51, 50, 50, 50,
50, 50, 49, 49, 49, 49, 48, 48, 48, 48, 47, 47, 47, 47, 46,
46, 46, 46, 46, 46, 46, 46, 45, 45, 45, 45, 44, 44, 44, 44,
43, 43, 43, 43, 42, 42, 42, 42, 41, 41, 41, 41, 40, 40, 40,
40, 39, 39, 39, 39, 38, 38, 38, 37, 37, 37, 37, 37, 37, 37,
36, 36, 36, 36, 35, 35, 35, 35, 34, 34, 34, 34, 33, 33, 33,
32, 32, 32, 32, 31, 31, 31, 30, 30, 30, 29, 29, 29, 28, 28,
28, 28, 28, 28, 27, 27, 27, 26, 26, 26, 25, 25, 25, 24, 24,
24, 23, 23, 23, 22, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19,
19, 19, 18, 18, 18, 17, 17, 17, 16, 16, 16, 15, 15, 15, 14,
14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 10, 10, 9, 9, 9,
8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1,
1, 0, 0, -1, -1, -1, -1, -2, -2, -3, -3, -4, -4, -5, -6,
-7, -8, -9, -10, -10, -11, -12, -13, -14, -15, -16, -17, -17, -18, -19,
-19, -20, -21, -22, -23, -24, -25, -26, -27, -27, -28, -28, -29, -30, -31,
-32, -33, -34, -35, -36, -37, -37, -38, -39, -40, -40, -40, -40, -40, -40,
-40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40,
-40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40,
-40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40,
-40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, -40,
-40, -40, -40, -40,
};
// Note: "pgm_read_word" is needed so we can access the lookup table from flash memory
void Get_Sensors() {
ect_t = analogRead(ECT); // Get Engine Coolant Temperature ADC value
ect_t = pgm_read_word(&Temp_ConvF [ect_t]); // Lookup ADC value to temperature
eot_t = analogRead(EOT); // Get Engine Oil Temperature ADC value
eot_t = pgm_read_word(&Temp_ConvF [eot_t]); // Lookup ADC value to temperature
tot_t = analogRead(TOT); // Get Transmission Oil Temperature ADC value
tot_t = pgm_read_word(&Temp_ConvF [tot_t]); // Lookup ADC value to temperature
eop_p = analogRead(EOP); // Get Engine Oil Pressure ADC value
eop_v = eop_p * ADC_V; // Calculate to voltage
eop_p *= 0.030887; // Calculate to pressure
eop_p -= 20.826; // Subtract offset
} // End of Get_Sensors Function
// LCD layout for referance
/*********************
Postion
12345678901234567890
L 1*ECT:###F
I 2*EOT:###F
N 3*TOT:###F
E 4*EOP:###Psi
*********************/
void LCD_Update() {
lcd.setCursor(0, 0); // First line, postion 1
lcd.print("ECT:"); // Write ECT: to Lcd
lcd.print(ect_t); // Write Engine Coolant Temperature to Lcd
lcd.write(byte(0)); // Write °F
lcd.print(" "); // Clear extra charaters when going from 3 to 2 digit
lcd.setCursor(0, 1); // Second line, postion 1
lcd.print("EOT:"); // Write EOT: to Lcd
lcd.print(eot_t); // Write Engine Oil Temperature to Lcd
lcd.write(byte(0)); // Write °F
lcd.print(" "); // Clear extra charaters when going from 3 to 2 digit
lcd.setCursor(0, 2); // Third line, postion 1
lcd.print("TOT:"); // Write TOT: to Lcd
lcd.print(tot_t); // Write Transmission Oil Temperature to Lcd
lcd.write(byte(0)); // Write °F
lcd.print(" "); // Clear extra charaters when going from 3 to 2 digit
lcd.setCursor(0, 4); // Fourth line, postion 1
lcd.print("EOP:"); // Write EOP: to Lcd
lcd.print(eop_p); // Write Engine Oil Pressure to Lcd
lcd.print("Psi"); // Write Psi to Lcd
lcd.print(" "); // Clear extra charaters when going from 3 to 2 digit
} // End of LCD_Update Function
// This only runs once on intial power on
void setup() {
pinMode(High_Idle, OUTPUT); // Set High Idle as Output
pinMode(Cold_Adv, OUTPUT); // Set Cold Timing Advance as Output
pinMode(MHI_Switch, INPUT); // Set Manual High Idle Switch as Input
digitalWrite(High_Idle, HIGH); // Set the inital High Idle Solenoid state to on
digitalWrite(Cold_Adv, HIGH); // Set the intial Cold Timing Advance Solenoid to on
//Serial.begin(9600); // Serial Monitor
// Setup the LCD
lcd.begin(20, 4); // Init the LCD for 20 chars and 4 lines
lcd.setBacklight (HIGH); // Turn LCD backlight on
lcd.createChar(0, degtempF); // Load custom °F character into LCD
lcd.home(); // Go to line 1, postion 1
} // End of setup function
void loop() {
Get_Sensors(); // This updates the sensors valves in ram, this runs very fast!
if(millis() - last_time >= 100){ // If 100mS has elapsed update the LCD (10 updates per second)
LCD_Update(); // Update LCD
last_time = millis(); // Set to current time so it can be rechecked above
}
// High Idle and Cold Timing Advance on below 120°F Engine Coolant Temperature
MHI_Switch = digitalRead(MHI); // Read the state of the Manual High Idle Switch
if (MHI_Switch == HIGH) digitalWrite(High_Idle, HIGH); // If Manual High Idle switch is on, turn on High Idle solenoid
else if (ect_t > 120) digitalWrite(High_Idle, LOW); // High Idle Solenoid is off if Engine Coolant Temperature is higher than 120°F
if (ect_t > 120) digitalWrite(Cold_Adv, LOW); // Cold Timing Advance Solenoid is off if Engine Coolant Temperature is higher than 120°F
} // End of loop Function