Skip to main content

Toggle Switches

Wiring and reading SPST and SPDT toggle switches on an ESP32 for cockpit overhead panels and control inputs.

Toggle Switch Types

Toggle switches maintain their position — ON stays ON until flipped OFF. Unlike push-buttons there is no need to track state in software; you can always read the physical position directly. Aviation panels use two main configurations:

TypePoles / ThrowsPositionsCockpit use
SPSTSingle Pole Single ThrowON / OFFMaster battery, avionics master, fuel pump
SPDT ON-ONSingle Pole Double ThrowUP / DOWNFuel selector (L / R tank), carb heat
SPDT ON-OFF-ONSingle Pole Double ThrowUP / OFF / DOWNMagneto (L / BOTH / R), trim
DPDTDouble Pole Double ThrowTwo independent SPDTRarely needed; useful for isolated circuits
Wiring — SPST Toggle
GPIO 23 GND SPST Toggle INPUT_PULLUP LOW = ON HIGH = OFF

Connect one terminal to the GPIO pin and the other terminal to GND. Enable the internal pull-up in firmware. When the switch is closed (ON) the pin is pulled to GND and reads LOW . When open (OFF) the internal pull-up holds the pin HIGH .

Switch terminalConnect to
Terminal 1GPIO pin
Terminal 2GND
Wiring — SPDT Toggle (3-Position)
GPIO 23 (A) Common → GND GPIO 22 (B) GND SPDT Toggle (arm shown at A)

An SPDT switch has three terminals: Common, A (e.g. UP), and B (e.g. DOWN). Connect Common to GND and each throw to a separate GPIO configured as INPUT_PULLUP . Only the active throw is pulled LOW; both HIGH indicates the centre-off position (ON-OFF-ON type only).

Switch positionGPIO 23 (A)GPIO 22 (B)
UP (A)LOWHIGH
Centre (OFF)HIGHHIGH
DOWN (B)HIGHLOW
Arduino Code — Single SPST

Toggle switches do not bounce significantly, so debouncing is usually not required. The switch state can simply be polled each loop iteration.

// SPST toggle — INPUT_PULLUP, LOW = switch ON
const int SW_PIN = 23;

void setup() {
    Serial.begin(115200);
    pinMode(SW_PIN, INPUT_PULLUP);
}

void loop() {
    bool isOn = (digitalRead(SW_PIN) == LOW);
    Serial.println(isOn ? "Switch: ON" : "Switch: OFF");
    delay(200);
}
Arduino Code — Overhead Panel (8 Switches)

Only report state changes rather than printing every poll tick. This produces clean serial output that maps directly to simulator dataref writes.

// Overhead panel — 8 toggle switches, only report on state change
const int SW_PINS[]    = { 23, 22, 21, 19, 18, 5, 4, 2 };
const char* SW_NAMES[] = {
    "MASTER BAT", "MASTER ALT", "AVIONICS",
    "FUEL PUMP",  "BEACON",     "LAND LIGHT",
    "TAXI LIGHT", "STROBE"
};
const int SW_COUNT = 8;

bool swStates[SW_COUNT];

void setup() {
    Serial.begin(115200);
    for (int i = 0; i < SW_COUNT; i++) {
        pinMode(SW_PINS[i], INPUT_PULLUP);
        swStates[i] = digitalRead(SW_PINS[i]);
    }
}

void loop() {
    for (int i = 0; i < SW_COUNT; i++) {
        bool state = digitalRead(SW_PINS[i]);
        if (state != swStates[i]) {
            swStates[i] = state;
            Serial.print(SW_NAMES[i]);
            Serial.println(state == LOW ? " -> ON" : " -> OFF");
        }
    }
    delay(20);   // 50 Hz poll — fast enough for human input
}
Arduino Code — SPDT (3-Position)
// SPDT toggle — two GPIOs, exactly one LOW when switch is thrown
// Common → GND;  Terminal A → GPIO 23;  Terminal B → GPIO 22
const int PIN_A = 23;
const int PIN_B = 22;

void setup() {
    Serial.begin(115200);
    pinMode(PIN_A, INPUT_PULLUP);
    pinMode(PIN_B, INPUT_PULLUP);
}

void loop() {
    bool a = (digitalRead(PIN_A) == LOW);
    bool b = (digitalRead(PIN_B) == LOW);

    if      (a) { Serial.println("Position: UP (A)");   }
    else if (b) { Serial.println("Position: DOWN (B)"); }
    else        { Serial.println("Position: CENTRE (OFF)"); }
    // ON-OFF-ON type: both HIGH = centre off position

    delay(200);
}

For a magneto switch (L / BOTH / R) the BOTH position is inferred when both A and B are HIGH on an ON-OFF-ON type, or use a 3-position rotary switch with three separate GPIOs instead.

Cockpit Applications
ApplicationSwitch typeNotes
Master battery / alternatorSPST (red guard cover)Map to sim electrical system datarefs
Avionics masterSPSTCan simulate boot-up delay in firmware before enabling avionics datarefs
Fuel selector (L / R)SPDT ON-ONTwo throws map to two tank datarefs
Magneto (L / BOTH / R)SPDT ON-OFF-ONThree states encoded with two GPIO pins
Pitot heat / de-iceSPSTDirect ON/OFF toggle to anti-ice dataref
Gear override guardSPST (guard cover)Guard physically prevents accidental actuation