Analog Inputs
Wiring potentiometers, slide pots and hall-effect sensors to an ESP32 for throttles, trim wheels, and panel dimmers — and turning their jittery readings into a steady 0–1 value.
A button or switch is either on or off. An analog input reports a position anywhere along its travel: how far the throttle lever is pushed, where the trim wheel sits, how bright the panel lights should be. The sensor turns that position into a voltage between 0 V and 3.3 V, and the ESP32's analog-to-digital converter (ADC) reads it as a number from 0 to 4095. At its widest setting (11 dB attenuation) the ADC tops out at about 3.1 V, so the last few degrees of a pot's travel all read 4095. Calibration sets the real end points, so that doesn't matter.
| Sensor | Example | Cockpit use |
|---|---|---|
| Rotary potentiometer | 10 kΩ linear (B10K), 16 mm or 24 mm | Panel dimmers, rudder trim, cabin temperature |
| Slide potentiometer | 60–100 mm travel, 10 kΩ linear | Throttle, mixture and prop levers, flap lever |
| Hall-effect sensor | SS49E or DRV5055 (3.3 V version) with a magnet | Yokes, pedals and levers that must never wear out |
| Multi-turn potentiometer | 10-turn wirewound | Elevator trim wheel with many turns end to end |
A potentiometer is a voltage divider. Its two outer legs go to 3.3 V and GND, and the middle leg (the wiper) goes to the ESP32 pin. As the shaft turns, the wiper voltage moves between 0 V and 3.3 V. Swap the outer legs if the value runs the wrong way, or leave the wiring and swap the ends in calibration instead.
| Potentiometer leg | Connect to |
|---|---|
| Outer leg 1 | 3.3 V |
| Wiper (middle) | ADC1 pin, e.g. GPIO 34 — optional 100 nF capacitor to GND at the pin |
| Outer leg 2 | GND |
Hall-effect sensors
A linear hall sensor such as the SS49E or the 3.3 V DRV5055 (DRV5055A1–A4) has three legs: VCC, GND and OUT. Pick one rated for 3.3 V and power it from 3.3 V, so its output never exceeds what the ADC tolerates, then wire OUT to an ADC1 pin. Parts that need 5 V, such as the A1324, would need a voltage divider on OUT. Fix a small neodymium magnet to the moving part so it sweeps past the sensor face. The output sits near half the supply with no field and moves up or down with the magnet's pole, so expect a usable range well inside 0–4095 — calibration takes care of that.
More analog inputs than ADC1 pins
A CD4067 16-channel multiplexer puts sixteen potentiometers on one ADC pin plus four select lines. Wire each wiper to a mux channel and the mux signal pin to an ADC1 pin. See the I/O expanders page for the mux wiring.
analogRead() returns 0–4095 at 12-bit resolution. Dividing by 4095 gives a 0–1 value that does not depend on the ADC's resolution.
// Read a potentiometer on an ADC1 pin and print a 0–1 value
const int POT_PIN = 34; // ADC1 — keeps working while WiFi is on
void setup() {
Serial.begin(115200);
analogReadResolution(12); // 0–4095
analogSetPinAttenuation(POT_PIN, ADC_11db); // widest range, about 0–3.1 V
}
void loop() {
int raw = analogRead(POT_PIN);
float value = raw / 4095.0f;
Serial.println(value, 3);
delay(20);
}Raw readings are never as clean as the basic sketch suggests. Three things turn them into a value a simulator can use:
| Setting | What it fixes | Typical value |
|---|---|---|
| Calibration (min / max) | A lever whose linkage only turns the pot part of the way, e.g. from 180 to 3900. Those readings become 0 and 1. Set min above max to reverse the direction. | Measured per lever |
| Centre | A self-centring part such as a yoke or rudder pedals, whose rest point is not exactly at half travel | Reading at rest |
| Centre deadzone | Small wobble around the centre of a spring-centred axis | 0–0.2 of the travel |
| Deadband | An idle ADC pin jitters by a few counts all the time; changes smaller than the deadband are not reported | 0.005 (0.5 %), range 0.001–0.1 |
// Oversample, smooth, calibrate and only report real movement
const int POT_PIN = 34;
const int RAW_MIN = 180; // reading at one end of the travel
const int RAW_MAX = 3900; // reading at the other end
const float DEADBAND = 0.005f; // ignore changes smaller than 0.5 %
float smoothed = 0;
float lastSent = -1;
int oversample(int pin) {
long sum = 0;
for (int i = 0; i < 16; i++) {
sum += analogRead(pin);
}
return sum / 16;
}
void setup() {
Serial.begin(115200);
analogReadResolution(12);
smoothed = oversample(POT_PIN);
}
void loop() {
smoothed += (oversample(POT_PIN) - smoothed) * 0.2f; // simple low-pass
float value = (smoothed - RAW_MIN) / float(RAW_MAX - RAW_MIN);
value = constrain(value, 0.0f, 1.0f);
if (fabs(value - lastSent) >= DEADBAND) {
lastSent = value;
Serial.println(value, 3);
}
delay(20); // at most 50 reports a second
} On a CockpitConnect controller you don't write this: the board oversamples, smooths and calibrates every Analog Input itself, then reports a value from 0 to 1 — only when it moves by more than the deadband, and at most 50 times a second. You set the calibration, centre deadzone and deadband per pin in the Flow Builder, and a Mapping's map transform takes 0–1 to the dataref's range.
| Application | Sensor | Notes |
|---|---|---|
| Throttle quadrant | Slide pot or rotary pot on the lever pivot | Calibrate idle and full power; one ADC1 pin per lever |
| Panel & flood light dimmers | Rotary pot, linear | Map 0–1 straight to the brightness ratio dataref |
| Yoke and rudder pedals | Hall sensor and magnet | Calibrate the centre and add a small centre deadzone |
| Elevator trim wheel | Multi-turn pot | Or an encoder, if the wheel has no end stops |
| Flap lever with detents | Rotary pot | A range lookup turns the position into flap settings |