Toggle Switches
Wiring and reading SPST and SPDT toggle switches on an ESP32 for cockpit overhead panels and control inputs.
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:
| Type | Poles / Throws | Positions | Cockpit use |
|---|---|---|---|
| SPST | Single Pole Single Throw | ON / OFF | Master battery, avionics master, fuel pump |
| SPDT ON-ON | Single Pole Double Throw | UP / DOWN | Fuel selector (L / R tank), carb heat |
| SPDT ON-OFF-ON | Single Pole Double Throw | UP / OFF / DOWN | Magneto (L / BOTH / R), trim |
| DPDT | Double Pole Double Throw | Two independent SPDT | Rarely needed; useful for isolated circuits |
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 terminal | Connect to |
|---|---|
| Terminal 1 | GPIO pin |
| Terminal 2 | GND |
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 position | GPIO 23 (A) | GPIO 22 (B) |
|---|---|---|
| UP (A) | LOW | HIGH |
| Centre (OFF) | HIGH | HIGH |
| DOWN (B) | HIGH | LOW |
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);
}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
}// 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.
| Application | Switch type | Notes |
|---|---|---|
| Master battery / alternator | SPST (red guard cover) | Map to sim electrical system datarefs |
| Avionics master | SPST | Can simulate boot-up delay in firmware before enabling avionics datarefs |
| Fuel selector (L / R) | SPDT ON-ON | Two throws map to two tank datarefs |
| Magneto (L / BOTH / R) | SPDT ON-OFF-ON | Three states encoded with two GPIO pins |
| Pitot heat / de-ice | SPST | Direct ON/OFF toggle to anti-ice dataref |
| Gear override guard | SPST (guard cover) | Guard physically prevents accidental actuation |