#include <U8glib.h>
#define logo_width 128
#define logo_height 64
// 'RevTech Arduino LOGO', 128x64px
static const unsigned char RevTech_Garage_Ardu_LOGO [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3f, 0xff, 0xf3, 0xff, 0xff, 0xbf, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3f, 0xff, 0xf3, 0xff, 0xff, 0x3f, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7f, 0xff, 0xf7, 0xff, 0xff, 0x3f, 0x80, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x3f, 0x80, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x1f, 0x81, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0f, 0xe3, 0xff, 0xfe, 0x1f, 0x83, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0f, 0xc7, 0xff, 0xfc, 0x1f, 0xc7, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7f, 0xff, 0xc7, 0xf0, 0x00, 0x0f, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0x87, 0xe0, 0x00, 0x0f, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xfe, 0x3f, 0x0f, 0xe0, 0x00, 0x0f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xfc, 0x3f, 0x0f, 0xc0, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0xfc, 0x1f, 0x9f, 0xff, 0xfc, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0xf8, 0x1f, 0x9f, 0xff, 0xfc, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0xf8, 0x0f, 0xdf, 0xff, 0xf8, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xfe, 0x7e, 0x1f, 0xc0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xfe, 0xfc, 0x1f, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xfe, 0xfc, 0x1f, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x03, 0xf0, 0x01, 0xfc, 0x3f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x01, 0xf8, 0x3f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x3f, 0xff, 0xe7, 0xe0, 0x01, 0xf8, 0x7e, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x3f, 0xff, 0xef, 0xe0, 0x03, 0xff, 0xfe, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x7f, 0x00, 0x0f, 0xc0, 0x03, 0xff, 0xfe, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x7e, 0x00, 0x0f, 0xc0, 0x03, 0xf0, 0xfc, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x7e, 0x00, 0x0f, 0xc0, 0x07, 0xe0, 0xfc, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0xfe, 0x00, 0x0f, 0x80, 0x07, 0xe0, 0xfc, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0xff, 0xff, 0xcf, 0xff, 0xef, 0xe1, 0xf8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0xff, 0xff, 0xcf, 0xff, 0xef, 0xc1, 0xf8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x01, 0xff, 0xff, 0xc3, 0xff, 0xef, 0xc3, 0xf0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0xfe, 0x03, 0xfc, 0x03, 0xfc, 0x3f, 0xc0, 0x3f, 0xe0, 0x7f, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x07, 0xff, 0x07, 0xfe, 0x07, 0xfe, 0x7f, 0xe0, 0x7f, 0xf0, 0xff, 0xe0, 0x00, 0x00,
0x00, 0x00, 0x0c, 0x00, 0x00, 0x03, 0x0c, 0x00, 0x00, 0x30, 0xc0, 0x01, 0x80, 0x30, 0x00, 0x00,
0x00, 0x00, 0x08, 0x00, 0x00, 0x01, 0x88, 0x00, 0x00, 0x18, 0x80, 0x01, 0x00, 0x18, 0x00, 0x00,
0x00, 0x00, 0x18, 0x00, 0x00, 0x01, 0x98, 0x00, 0x00, 0x19, 0x80, 0x03, 0x00, 0x18, 0x00, 0x00,
0x00, 0x00, 0x18, 0x7f, 0x0f, 0xff, 0x98, 0x00, 0xff, 0xf9, 0x87, 0xf3, 0x00, 0x30, 0x00, 0x00,
0x00, 0x00, 0x18, 0x01, 0x98, 0x01, 0x98, 0x01, 0x80, 0x19, 0x80, 0x1b, 0xff, 0xe0, 0x00, 0x00,
0x00, 0x00, 0x18, 0x01, 0x98, 0x01, 0x98, 0x01, 0x80, 0x19, 0x80, 0x1b, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x08, 0x01, 0x98, 0x01, 0x98, 0x01, 0x80, 0x18, 0x80, 0x19, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0c, 0x01, 0x8c, 0x01, 0x98, 0x00, 0xc0, 0x18, 0xc0, 0x19, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x08, 0x00, 0x7f, 0xf0, 0x7f, 0xf0, 0xff, 0xf0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);
const int encoderPinA = 2;
const int encoderPinB = 3;
const int encoderButtonPin = 4;
const int ledBarRelayPin = 6;
const int fanRelayPin = 7;
const int pumpRelayPin = 8;
volatile int encoderPosition = 0;
volatile bool encoderChanged = false; // Declare 'encoderChanged' as a global variable
int selectedRelayIndex = 0;
const int numOfRelays = 3; // Ensure 'numOfRelays' is declared globally
bool fanState = false;
bool ledBarState = false;
bool pumpState = true;
bool isManualControlEnabled = false; // Tracks if manual control is enabled
const float BETA = 3950;
int coolantThreshold = 79;
int intakeThreshold = 40;
void displayLogo() {
u8g.firstPage();
do {
u8g.drawBitmapP( 0, 0, 128/ 8, 64, RevTech_Garage_Ardu_LOGO);
} while (u8g.nextPage());
delay(2000);
}
void setup() {
Serial.begin(9600);
pinMode(encoderPinA, INPUT_PULLUP);
pinMode(encoderPinB, INPUT_PULLUP);
pinMode(encoderButtonPin, INPUT_PULLUP);
pinMode(fanRelayPin, OUTPUT);
pinMode(ledBarRelayPin, OUTPUT);
pinMode(pumpRelayPin, OUTPUT);
digitalWrite(fanRelayPin, fanState ? HIGH : LOW);
digitalWrite(ledBarRelayPin, ledBarState ? HIGH : LOW);
digitalWrite(pumpRelayPin, pumpState ? HIGH : LOW);
attachInterrupt(digitalPinToInterrupt(encoderPinA), onEncoderChange, CHANGE);
attachInterrupt(digitalPinToInterrupt(encoderPinB), onEncoderChange, CHANGE);
displayLogo(); // Ensure this is in setup to show the logo at startup
}
void loop() {
static unsigned long lastRefreshTime = 0;
const long refreshInterval = 200; // Set display refresh interval to 1000 milliseconds (1 second)
// Check and update fan state based on temperature readings
updateFanState();
// Continuously refresh the display every second, regardless of encoder movement
unsigned long currentTime = millis();
if (currentTime - lastRefreshTime > refreshInterval) {
displayMenu();
lastRefreshTime = currentTime;
}
if (encoderChanged) {
selectedRelayIndex = abs(encoderPosition % numOfRelays);
displayMenu();
encoderChanged = false;
}
checkButtonPress();
}
void updateFanState() {
// This function is called from the main loop to update the fan state based on temperature
if (!isManualControlEnabled) { // Only automatically control the fan if not in manual mode
float coolantTemp = readTemperature(analogRead(A3));
float intakeTemp = readTemperature(analogRead(A2));
bool shouldFanBeOn = (coolantTemp > coolantThreshold || intakeTemp > intakeThreshold);
if (fanState != shouldFanBeOn) {
fanState = shouldFanBeOn;
digitalWrite(fanRelayPin, fanState ? HIGH : LOW);
}
}
// If manual control is active, do nothing here, leaving the fan in its manually set state
}
// Make sure your toggleRelay function handles toggling the state of non-fan relays appropriately
void onEncoderChange() {
static bool lastA = LOW;
bool currentA = digitalRead(encoderPinA);
if (lastA == LOW && currentA == HIGH) {
if (digitalRead(encoderPinB) == LOW) {
encoderPosition++;
} else {
encoderPosition--;
}
encoderChanged = true; // Ensure this is set to true here
}
lastA = currentA;
}
void displayMenu() {
// Read the sensor values
float coolantTemp = readTemperature(analogRead(A3));
float intakeTemp = readTemperature(analogRead(A2));
float exhaustTemp = readTemperature(analogRead(A1));
float boost = analogRead(A0);
u8g.firstPage();
do {
u8g.setFont(u8g_font_helvR08); // Use a smaller font
// Display sensor readings
u8g.setPrintPos(0, 8); u8g.print("Coolant Temp: "); u8g.setPrintPos(94, 8); u8g.print(coolantTemp, 1); u8g.print(" C");
u8g.setPrintPos(0, 17); u8g.print("Intake Temp: "); u8g.setPrintPos(94, 17); u8g.print(intakeTemp, 1); u8g.print(" C");
u8g.setPrintPos(0, 26); u8g.print("Exhaust Temp: "); u8g.setPrintPos(94, 26); u8g.print(exhaustTemp, 1); u8g.print(" C");
u8g.setPrintPos(0, 35); u8g.print("Boost: "); u8g.setPrintPos(94, 35); u8g.print(boost / 100, 1); u8g.print(" Bar");
// Display relay controls with scrolling
displayRelayControl("LED Bar", ledBarState, 44, selectedRelayIndex == 0);
displayRelayControl("Fan's", fanState, 53, selectedRelayIndex == 1);
displayRelayControl("Pump", pumpState, 62, selectedRelayIndex == 2);
} while ( u8g.nextPage() );
}
void checkButtonPress() {
static unsigned long lastButtonPressTime = 0;
const unsigned long debounceTime = 50; // Debounce time in milliseconds
static bool lastButtonState = HIGH;
bool currentButtonState = digitalRead(encoderButtonPin);
unsigned long currentTime = millis();
// Debounce the button
if (currentButtonState != lastButtonState && (currentTime - lastButtonPressTime > debounceTime)) {
if (currentButtonState == LOW) { // Button pressed
lastButtonPressTime = currentTime; // Update the last button press time
// Toggle manual control only for the fan
if (selectedRelayIndex == 1) { // Assuming "1" is the index for the fan in your menu
isManualControlEnabled = !isManualControlEnabled; // Toggle manual control state
if (isManualControlEnabled) {
// If entering manual mode, toggle fan state
fanState = !fanState;
digitalWrite(fanRelayPin, fanState ? HIGH : LOW);
} // No else; leaving manual mode is handled by sensor logic in updateFanState
} else {
// For other relays, just toggle without entering manual mode
toggleRelay(selectedRelayIndex);
}
}
}
lastButtonState = currentButtonState;
}
void toggleRelay(int relayIndex) {
switch (relayIndex) {
case 0: ledBarState = !ledBarState; digitalWrite(ledBarRelayPin, ledBarState ? HIGH : LOW); break;
case 1: fanState = !fanState; digitalWrite(fanRelayPin, fanState ? HIGH : LOW); break;
case 2: pumpState = !pumpState; digitalWrite(pumpRelayPin, pumpState ? HIGH : LOW); break;
}
}
float readTemperature(int sensorValue) {
// Convert sensor reading to temperature using the Beta parameter equation
// Assuming a 10k thermistor. Change these values according to your specific sensor.
float R = 1023.0 / ((float)sensorValue) - 1.0;
R = 10000.0 / R;
float temperature = 1.0 / (log(R / 10000.0) / BETA + 1.0 / 298.15) - 273.15;
return temperature;
}
void displayRelayControl(String name, bool state, int y, bool isSelected) {
u8g.setPrintPos(0, y);
if (isSelected) u8g.print("> ");
else u8g.print(" ");
u8g.print(name);
u8g.print(": ");
u8g.setPrintPos(110, y);
u8g.print(state ? "On" : "Off");
}