The Sensing Principle: How Flex Resistors Work

The Adafruit flex sensor (manufactured by Spectra Symbol) relies on a carbon-polymer conductive ink printed onto a flexible polyimide substrate. When the substrate is bent, the conductive particles within the ink are physically pulled apart, lengthening the electron path and increasing electrical resistance. A standard 2.2-inch sensor rests at roughly 10,000 ohms (10kΩ) when perfectly flat and rises to 30kΩ–40kΩ when bent to a full 90-degree angle. The 4.3-inch variant operates on the exact same physics but offers a wider physical range of motion and a slightly higher baseline resistance.

Because it is a passive resistive element, the sensor does not natively output a voltage, current, or digital signal. It strictly outputs a variable resistance. To interface it with a microcontroller, you must construct a voltage divider circuit to convert this resistance change into a measurable analog voltage. The microcontroller's ADC (Analog-to-Digital Converter) then digitizes that voltage into a raw integer, which your code must mathematically scale back into a physical bend angle.

Wiring and Voltage Divider Design

You cannot wire a flex sensor directly to a digital GPIO pin or an analog pin without a pull-up/pull-down network. Doing so will result in floating pins and random noise. You must build a voltage divider using a fixed resistor. The optimal value for this fixed resistor ($R_{fixed}$) is roughly the average of the sensor's flat and bent resistances. For the 2.2-inch sensor, a 10kΩ or 22kΩ fixed resistor provides the best voltage swing across the ADC range.

Adafruit Flex Sensor Voltage Divider Wiring
Component / Pin Connection Notes
VCC (Supply) 3.3V or 5V Supply range: 3.3V to 5.0V. Match to your MCU logic level.
Fixed Resistor ($R_{fixed}$) Between VCC and ADC Pin Use 10kΩ or 22kΩ 1% tolerance metal film resistor.
ADC Pin (Analog Out) MCU Analog Input (e.g., A0, GPIO34) The junction between $R_{fixed}$ and the flex sensor.
Flex Sensor Pin 1 ADC Pin (Analog Out) Sensor polarity does not matter; it is a passive resistor.
Flex Sensor Pin 2 GND Common ground with the microcontroller.
Callout Tip: Wire Length and EMI
Analog signals are highly susceptible to electromagnetic interference (EMI). If your flex sensor is mounted on a glove or moving joint, keep the unshielded analog wire between the sensor and the microcontroller as short as possible. For runs longer than 6 inches, use shielded twisted-pair cable and tie the shield to GND at the microcontroller end only to prevent ground loops.

Output Signal Math: Raw ADC to Bend Angle

Translating the raw ADC reading into a usable physical unit (degrees) requires a three-step mathematical conversion. We will assume a 5V system with a 10-bit ADC (like the Arduino Uno) and a 10kΩ fixed resistor.

Step 1: Convert Raw ADC to Voltage ($V_{out}$)
The ADC returns an integer between 0 and 1023. V_out = ADC_raw * (V_ref / 1023.0)

Step 2: Convert Voltage to Sensor Resistance ($R_{flex}$)
Using the voltage divider formula rearranged to solve for the sensor resistance: R_flex = R_fixed * (V_out / (V_in - V_out))

Step 3: Map Resistance to Bend Angle
Assuming a linear response between 0° (flat, ~10kΩ) and 90° (bent, ~35kΩ), we use linear interpolation. Angle = (R_flex - R_flat) * (90.0 / (R_bent - R_flat))

Here is the complete, compilable C++ implementation for an Arduino or ESP32 environment:

// Pin Definitions
const int FLEX_PIN = A0; // Use GPIO34 for ESP32

// Circuit Constants
const float V_REF = 5.0;       // 5.0 for Arduino Uno, 3.3 for ESP32
const float R_FIXED = 10000.0; // 10k Ohm fixed resistor
const int ADC_MAX = 1023;      // 10-bit for Uno, 4095 for ESP32 (12-bit)

// Calibration Constants (Measure these with your multimeter!)
const float R_FLAT = 10500.0;  // Resistance at 0 degrees
const float R_BENT = 35000.0;  // Resistance at 90 degrees

void setup() {
  Serial.begin(115200);
  analogReadResolution(10); // Standardize to 10-bit if using ESP32
}

void loop() {
  int adc_raw = analogRead(FLEX_PIN);
  
  // Step 1: ADC to Voltage
  float v_out = adc_raw * (V_REF / ADC_MAX);
  
  // Prevent division by zero if sensor is disconnected
  if (v_out >= V_REF) v_out = V_REF - 0.01; 
  
  // Step 2: Voltage to Resistance
  float r_flex = R_FIXED * (v_out / (V_REF - v_out));
  
  // Step 3: Resistance to Angle
  float angle = (r_flex - R_FLAT) * (90.0 / (R_BENT - R_FLAT));
  
  // Constrain angle to physical limits
  angle = constrain(angle, 0.0, 90.0);
  
  Serial.print("Resistance: ");
  Serial.print(r_flex);
  Serial.print(" ohms | Angle: ");
  Serial.println(angle);
  
  delay(50);
}
ESP32 ADC Non-Linearity Warning
If you are using an ESP32, the native analogRead() function is notoriously non-linear near 0V and 3.3V, which will skew your angle calculations at the extremes of the bend. For production ESP32 code, bypass analogRead() and use analogReadMilliVolts() (available in ESP32 Arduino Core v2.0.0+) or the esp_adc_cal library to apply factory Vref eFuse calibration data. See the Espressif ADC Oneshot Documentation for implementation details.

Calibration, Creep, and Interference Sources

Flex sensors are not precision laboratory instruments; they are qualitative transducers. To get reliable data, you must account for three primary interference sources and physical limitations:

  1. Hysteresis and Creep: The polymer substrate exhibits "memory." If you bend the sensor to 90 degrees and hold it for 30 seconds, the resistance will slowly drift upward (creep). When you release it, it will not instantly return to exactly 10kΩ; it will take several seconds to relax back to baseline. Fix: Implement a software low-pass filter or require a "flat calibration" button press in your UI before taking critical measurements.
  2. Temperature Drift: The carbon ink has a negative temperature coefficient (NTC). As ambient temperature rises, the baseline flat resistance drops. If your sensor is worn close to the human body (like in a smart glove), body heat will shift your 0-degree baseline by 5% to 10%. Fix: Calibrate the sensor at operating temperature, not room temperature.
  3. Mechanical Fatigue: Bending the sensor past its rated radius (typically a 1-inch bend radius minimum) or creasing it near the termination pads will permanently fracture the carbon trace. Fix: Never solder directly to the flex sensor pads with a high-wattage iron. Use a low-temperature soldering iron (under 300°C), apply Kapton tape for strain relief, or use the Adafruit Flex Sensor Connector to avoid heat damage entirely.

Frequently Asked Questions

How do I calibrate the Adafruit flex sensor for exact degree readings?

Because every sensor has slight manufacturing variances, you cannot rely solely on the datasheet's typical 10kΩ-35kΩ range. To calibrate for exact degrees, wire the sensor to your microcontroller and open the serial monitor. Lay the sensor perfectly flat on a desk and record the average resistance value over 50 reads—this is your R_FLAT. Next, use a physical protractor or a 3D-printed 90-degree jig to bend the sensor exactly to 90 degrees, and record the average resistance—this is your R_BENT. Plug these two exact numbers into the code provided above. For multi-point accuracy, map a 5-point lookup table (0°, 22°, 45°, 67°, 90°) and use linear interpolation between the nodes.

Why is my Adafruit flex sensor reading drifting over time?

Drifting is almost always caused by polymer creep or temperature changes, not a faulty microcontroller. When the sensor is held in a bent position, the internal carbon matrix stretches and slowly relaxes, causing the resistance to climb even if the physical angle remains static. Additionally, if the sensor is enclosed in a tight housing or worn on the skin, localized heat will lower the baseline resistance. To mitigate drift in software, implement a moving average filter (e.g., averaging the last 20 reads) and avoid using the sensor for static, long-duration positional holding; they are much better suited for dynamic, repetitive motion tracking.

Can I wire the Adafruit flex sensor directly to an ESP32 GPIO pin?

No. The flex sensor is a passive variable resistor, not a digital switch or an active sensor module with an onboard microcontroller. If you wire it directly to a digital GPIO pin, the pin will float, reading random electromagnetic noise as HIGH/LOW toggles. You must use an analog-capable pin (like GPIO32, GPIO33, GPIO34, GPIO35, GPIO36, or GPIO39 on the original ESP32) and build the voltage divider circuit outlined in the wiring table. Note that pins like GPIO34-39 on the ESP32 are input-only and do not have internal pull-up resistors, making the external fixed resistor mandatory.

What is the difference between the 2.2-inch and 4.3-inch Adafruit flex sensors?

Both sensors use the same Spectra Symbol carbon-polymer technology and operate on the same voltage divider principles, but their physical geometry dictates their use case. The 2.2-inch sensor has a baseline resistance of ~10kΩ and a bent resistance of ~30kΩ-40kΩ, making it ideal for tracking individual finger knuckles in smart gloves. The 4.3-inch sensor has a slightly higher baseline (~15kΩ) and a much higher bent resistance (~45kΩ-60kΩ) because the conductive trace is longer. The 4.3-inch version is better suited for tracking larger joints like wrists, elbows, or knees, where the bend radius is wider and distributed over a longer physical distance.