Sensitivity Calibration
Tune touch and release thresholds per-electrode, understand hysteresis, and use filtered data to set optimal values.
Why calibration matters
The default MPR121 thresholds work for fingers on bare metal pads. They may not work well for:
- Long painted traces (higher resting capacitance)
- Through-material sensing (needs higher sensitivity)
- Wet or humid environments (noise floor is higher)
- Large electrodes (naturally higher capacitance)
- Proximity sensing (needs much higher sensitivity)
Calibration means finding the threshold values that give reliable detection without false triggers.
The two thresholds
MPR121.setTouchThreshold(40); // electrode is "touched" when change exceeds this
MPR121.setReleaseThreshold(20); // electrode is "released" when change drops below this
Both values are in arbitrary units representing the capacitance change above the baseline. Higher value = less sensitive.
Hysteresis: the release threshold must always be lower than the touch threshold. This gap prevents rapid flickering when the value hovers near the boundary — a feature called hysteresis. A good ratio is 2:1 (touch = 40, release = 20).
Reading filtered data to find good thresholds
Upload this diagnostic sketch to see the raw sensor values:
#include <MPR121.h>
#include <Wire.h>
void setup() {
Serial.begin(57600);
if (!MPR121.begin(0x5C)) {
Serial.println("MPR121 error");
while (1);
}
MPR121.setInterruptPin(4);
}
void loop() {
MPR121.updateAll();
for (int i = 0; i < 12; i++) {
int filtered = MPR121.getFilteredData(i);
int baseline = MPR121.getBaselineData(i);
int delta = baseline - filtered; // positive = capacitance increased (touch)
Serial.print(delta);
Serial.print("\t");
}
Serial.println();
delay(50);
}
Open the Serial Monitor at 57600 baud. You’ll see 12 numbers — the delta (change from baseline) for each electrode.
Reading the data:
- With nothing touching: all values should be near 0 (±5)
- Touch an electrode firmly: that column’s value jumps up — note the peak value
- Hover your hand 1cm above: note the value at that distance
- The touch threshold should be between “hover” and “firm touch” values
Typical values:
- Resting: 0–5
- Hand 5cm away: 5–10
- Hand hovering 1cm: 15–25
- Firm direct touch: 60–150+
So a touch threshold of 40 and release of 20 works for direct touch. For proximity detection, drop to 15/8.
Per-electrode calibration
Each electrode can have its own thresholds:
// electrode 0 — small pad, direct touch needed
MPR121.setTouchThreshold(40, 0);
MPR121.setReleaseThreshold(20, 0);
// electrode 1 — through 3mm card, needs more sensitivity
MPR121.setTouchThreshold(15, 1);
MPR121.setReleaseThreshold(8, 1);
// electrode 2 — proximity mode, very sensitive
MPR121.setTouchThreshold(8, 2);
MPR121.setReleaseThreshold(4, 2);
// Set the rest to a sensible default
for (int i = 3; i < 12; i++) {
MPR121.setTouchThreshold(40, i);
MPR121.setReleaseThreshold(20, i);
}
Baseline reset and recalibration
The MPR121 auto-calibrates over time. But if you change your electrode setup significantly (add a long wire, cover with material), the baseline needs to reset:
MPR121.reset(); // full chip reset — takes ~100ms
MPR121.updateAll(); // re-read everything after reset
Or force baseline re-calibration without a full reset:
// In newer library versions:
MPR121.setBaselineTracking(BASELINE_TRACKING_ON);
Dealing with false triggers
If electrodes trigger randomly without touch:
Check 1 — environmental noise:
// Check if all 12 electrodes trigger simultaneously — if so, it's electrical noise not touch
MPR121.updateAll();
int touchCount = 0;
for (int i = 0; i < 12; i++) {
if (MPR121.isNewTouch(i)) touchCount++;
}
if (touchCount > 3) {
// Likely noise event — ignore
return;
}
Check 2 — adjacent trace cross-coupling: Separate electrode cables physically. If two cables run parallel for more than 10cm, they can cross-couple.
Check 3 — baseline drift: A slow baseline drift shouldn’t cause triggers. But if an electrode is very long, the slow drift can push the reading close to the touch threshold. Increase the threshold for that electrode.
Saving calibration to EEPROM
For projects where you want calibration to persist between power cycles:
#include <EEPROM.h>
void saveThresholds(int touch[], int release[]) {
for (int i = 0; i < 12; i++) {
EEPROM.write(i * 2, touch[i]);
EEPROM.write(i * 2 + 1, release[i]);
}
}
void loadThresholds() {
for (int i = 0; i < 12; i++) {
int t = EEPROM.read(i * 2);
int r = EEPROM.read(i * 2 + 1);
if (t > 0 && r > 0) {
MPR121.setTouchThreshold(t, i);
MPR121.setReleaseThreshold(r, i);
}
}
}
Key takeaways
- Touch threshold: how much capacitance change triggers a touch. Higher = less sensitive
- Release threshold: must be lower than touch threshold (hysteresis prevents flickering)
- Use the filtered-data diagnostic sketch to read actual sensor values and set thresholds empirically
- Per-electrode calibration with
setTouchThreshold(value, electrode)handles mixed setups - After changing electrodes significantly, call
MPR121.reset()to re-establish baseline - Multiple simultaneous triggers often indicate electrical noise rather than genuine touches