/*
Aircraft Header Tank Advisory Indicator
Arduino Nano Every (ATmega4809)
Industrial / Aviation Version
*/
#include <avr/io.h>
#include <avr/wdt.h>
// ================= PIN DEFINITIONS =================
const uint8_t level1Pin = 2;
const uint8_t level2Pin = 3;
const uint8_t green1Pin = 5;
const uint8_t red1Pin = 6;
const uint8_t green2Pin = 9;
const uint8_t red2Pin = 10;
// ================= TIMING =================
const unsigned long debounceTime = 3000;
const unsigned long redFlashInterval = 250;
const unsigned long heartbeatInterval = 10000;
const unsigned long heartbeatPulse = 100;
const unsigned long startupDuration = 1000;
// ================= STATE =================
bool level1State = false;
bool level2State = false;
bool lastReading1 = false;
bool lastReading2 = false;
unsigned long lastDebounce1 = 0;
unsigned long lastDebounce2 = 0;
unsigned long lastRedFlash = 0;
bool redFlashState = false;
unsigned long lastHeartbeat = 0;
bool heartbeatActive = false;
unsigned long heartbeatStart = 0;
unsigned long startupStart;
bool startupActive = true;
// ===================================================
// WATCHDOG
// ===================================================
void enableWatchdog()
{
RSTCTRL.RSTFR = RSTCTRL_WDRF_bm;
CCP = CCP_IOREG_gc;
WDT.CTRLA = WDT_PERIOD_8KCLK_gc; // ~8 seconds
}
void resetWatchdog()
{
__asm__ __volatile__("wdr");
}
// ===================================================
void setup()
{
// Safe startup state
digitalWrite(green1Pin, LOW);
digitalWrite(red1Pin, LOW);
digitalWrite(green2Pin, LOW);
digitalWrite(red2Pin, LOW);
pinMode(green1Pin, OUTPUT);
pinMode(red1Pin, OUTPUT);
pinMode(green2Pin, OUTPUT);
pinMode(red2Pin, OUTPUT);
pinMode(level1Pin, INPUT_PULLUP);
pinMode(level2Pin, INPUT_PULLUP);
Serial.begin(115200);
delay(200);
logResetCause();
startupStart = millis();
enableWatchdog();
}
// ===================================================
void loop()
{
unsigned long now = millis();
if (startupActive)
{
handleStartup(now);
resetWatchdog();
return;
}
handleDebounce(level1Pin, level1State, lastReading1, lastDebounce1, 1);
handleDebounce(level2Pin, level2State, lastReading2, lastDebounce2, 2);
handleRedFlash(now);
handleHeartbeat(now);
updateOutputs();
resetWatchdog();
}
// ===================================================
void handleDebounce(uint8_t pin, bool &state,
bool &lastReading,
unsigned long &lastDebounce,
uint8_t channel)
{
bool reading = (digitalRead(pin) == LOW);
if (reading != lastReading)
lastDebounce = millis();
if ((millis() - lastDebounce) >= debounceTime)
{
if (state != reading)
{
state = reading;
Serial.print("Level ");
Serial.print(channel);
Serial.print(": ");
Serial.println(state ? "FLUID PRESENT" : "NO FLUID");
}
}
lastReading = reading;
}
// ===================================================
void handleRedFlash(unsigned long now)
{
if (now - lastRedFlash >= redFlashInterval)
{
lastRedFlash = now;
redFlashState = !redFlashState;
}
}
// ===================================================
void handleHeartbeat(unsigned long now)
{
if (now - lastHeartbeat >= heartbeatInterval)
{
heartbeatActive = true;
heartbeatStart = now;
lastHeartbeat = now;
Serial.println("Heartbeat OK");
}
if (heartbeatActive &&
(now - heartbeatStart > heartbeatPulse))
{
heartbeatActive = false;
}
}
// ===================================================
// *** FIXED OUTPUT LOGIC ***
void updateOutputs()
{
// LEVEL 1
bool green1 = level1State;
bool red1 = (!level1State) ? redFlashState : LOW;
// LEVEL 2
bool green2 = level2State;
bool red2 = (!level2State) ? redFlashState : LOW;
// Heartbeat overlays green LEDs
if (heartbeatActive)
{
green1 = !green1;
green2 = !green2;
}
digitalWrite(green1Pin, green1);
digitalWrite(red1Pin, red1);
digitalWrite(green2Pin, green2);
digitalWrite(red2Pin, red2);
}
// ===================================================
void handleStartup(unsigned long now)
{
if (now - startupStart >= startupDuration)
{
startupActive = false;
Serial.println("Startup Complete");
return;
}
if ((now / 250) % 2 == 0)
{
digitalWrite(green1Pin, HIGH);
digitalWrite(green2Pin, HIGH);
digitalWrite(red1Pin, LOW);
digitalWrite(red2Pin, LOW);
}
else
{
digitalWrite(green1Pin, LOW);
digitalWrite(green2Pin, LOW);
digitalWrite(red1Pin, HIGH);
digitalWrite(red2Pin, HIGH);
}
}
// ===================================================
void logResetCause()
{
uint8_t flags = RSTCTRL.RSTFR;
Serial.println("---- RESET DETECTED ----");
if (flags & RSTCTRL_PORF_bm) Serial.println("Power-On Reset");
if (flags & RSTCTRL_BORF_bm) Serial.println("Brown-Out Reset");
if (flags & RSTCTRL_EXTRF_bm) Serial.println("External Reset");
if (flags & RSTCTRL_WDRF_bm) Serial.println("Watchdog Reset");
if (flags & RSTCTRL_SWRF_bm) Serial.println("Software Reset");
Serial.println("------------------------");
RSTCTRL.RSTFR = flags;
}