1. The MPR121 is the second-generation capacitive touch sensor controller.
  2. MPR121 Proximity Capacitive Touch Sensor Controller features 12 electrodes with an independent calibration feature.
  3. The independent calibration simplifies designing touch applications for portable low-power electronic products
  1. Low power operation.
  2. 71 V to 3.6 V supply operation.
  3. 12 capacitance sensing inputs.
  4. 8 inputs are multifunctional for LED driver and GPIO.
  5. Complete touch detection.
  6. Auto-configuration for each sensing input.
  7. Auto-calibration for each sensing input.
  8. Touch/release threshold and debounce for touch detection.
  9. Touch Panel
  10. Near Proximity Detection.
  1. PC Peripherals
  2. MP3 Players
  3. Remote Controls
  4. Mobile Phones
  5. Lighting Controls.


#include "mpr121.h"
#include <Wire.h>

int irqpin = 2; // Digital 2
boolean touchStates[12]; //to keep track of the previous touch states

void setup(){
pinMode(irqpin, INPUT);
digitalWrite(irqpin, HIGH); //enable pullup resistor



void loop(){

void readTouchInputs(){

//read the touch state from the MPR121

byte LSB =;
byte MSB =;

uint16_t touched = ((MSB << 8) | LSB); //16bits that make up the touch states

for (int i=0; i < 12; i++){ // Check what electrodes were pressed
if(touched & (1<<i)){

if(touchStates[i] == 0){
//pin i was just touched
Serial.print("pin ");
Serial.println(" was just touched");

}else if(touchStates[i] == 1){
//pin i is still being touched

touchStates[i] = 1;
if(touchStates[i] == 1){
Serial.print("pin ");
Serial.println(" is no longer being touched");

//pin i is no longer being touched

touchStates[i] = 0;



void mpr121_setup(void){

set_register(0x5A, ELE_CFG, 0x00);

// Section A - Controls filtering when data is > baseline.
set_register(0x5A, MHD_R, 0x01);
set_register(0x5A, NHD_R, 0x01);
set_register(0x5A, NCL_R, 0x00);
set_register(0x5A, FDL_R, 0x00);

// Section B - Controls filtering when data is < baseline.
set_register(0x5A, MHD_F, 0x01);
set_register(0x5A, NHD_F, 0x01);
set_register(0x5A, NCL_F, 0xFF);
set_register(0x5A, FDL_F, 0x02);

// Section C - Sets touch and release thresholds for each electrode
set_register(0x5A, ELE0_T, TOU_THRESH);
set_register(0x5A, ELE0_R, REL_THRESH);

set_register(0x5A, ELE1_T, TOU_THRESH);
set_register(0x5A, ELE1_R, REL_THRESH);

set_register(0x5A, ELE2_T, TOU_THRESH);
set_register(0x5A, ELE2_R, REL_THRESH);

set_register(0x5A, ELE3_T, TOU_THRESH);
set_register(0x5A, ELE3_R, REL_THRESH);

set_register(0x5A, ELE4_T, TOU_THRESH);
set_register(0x5A, ELE4_R, REL_THRESH);

set_register(0x5A, ELE5_T, TOU_THRESH);
set_register(0x5A, ELE5_R, REL_THRESH);

set_register(0x5A, ELE6_T, TOU_THRESH);
set_register(0x5A, ELE6_R, REL_THRESH);

set_register(0x5A, ELE7_T, TOU_THRESH);
set_register(0x5A, ELE7_R, REL_THRESH);

set_register(0x5A, ELE8_T, TOU_THRESH);
set_register(0x5A, ELE8_R, REL_THRESH);

set_register(0x5A, ELE9_T, TOU_THRESH);
set_register(0x5A, ELE9_R, REL_THRESH);

set_register(0x5A, ELE10_T, TOU_THRESH);
set_register(0x5A, ELE10_R, REL_THRESH);

set_register(0x5A, ELE11_T, TOU_THRESH);
set_register(0x5A, ELE11_R, REL_THRESH);

// Section D
// Set the Filter Configuration
// Set ESI2
set_register(0x5A, FIL_CFG, 0x04);

// Section E
// Electrode Configuration
// Set ELE_CFG to 0x00 to return to standby mode
set_register(0x5A, ELE_CFG, 0x0C); // Enables all 12 Electrodes

// Section F
// Enable Auto Config and auto Reconfig
/*set_register(0x5A, ATO_CFG0, 0x0B);
set_register(0x5A, ATO_CFGU, 0xC9); // USL = (Vdd-0.7)/vdd*256 = 0xC9 @3.3V set_register(0x5A, ATO_CFGL, 0x82); // LSL = 0.65*USL = 0x82 @3.3V
set_register(0x5A, ATO_CFGT, 0xB5);*/ // Target = 0.9*USL = 0xB5 @3.3V

set_register(0x5A, ELE_CFG, 0x0C);


boolean checkInterrupt(void){
return digitalRead(irqpin);

void set_register(int address, unsigned char r, unsigned char v){