MPR121 Hookup Guide

This Tutorial is Retired!

This tutorial covers concepts or technologies that are no longer current. It's still here for you to read and enjoy, but may not be as useful as our newest tutorials.

Contributors: Toni_K
Favorited Favorite 2

Communicating with the Breakout Board

To communicate with your breakout board, you will need the Arduino sketch available as a zip file here. Alternatively, you can also find the most up-to-date firmware for working with the breakout board available on GitHub. Let's take a look and see exactly what the code is doing.

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

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

In this first section of the code, the MPR121 library and the Wire library are initialized. The Wire library makes I2C communication easy to use on the Arduino. The sketch also defines digital pin 2 as the IRQ pin connection, and creates 12 instances of the boolean variable touchStates.

For the second section of the code, we define the irqpin as an INPUT, telling the Arduino to monitor the digital signal coming in over that pin. Serial communication is also started at 9600 bps, s well as the Wire and mpr121 libraries.

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



The main loop of the code is incredibly simple, as it only calls a single function.

    void loop(){

The function is actually described in the next section of the code. The Arduino requests the electrode states from the sensor in the first section, and the least significant bits and most significant bits are defined for the sensor.

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;



The Arduino scans each electrode and prints out a message over serial if an electrode is triggered as being touched. The Arduino will then print out a message as soon as the electrode is no longer being touched.

The last major section of the code defines the threshold values for each electrode. Each electrode must have a touch threshold and a release threshold for the Arduino to compare the current state of the electrode.

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);


It looks like a lot of code, but it simply repeating the procedure of setting the threshold values for each electrode pin.

The last two functions in the example sketch simply check the status of the irqpin to determine if the IC is signaling that an electrode has been touched. The very last function set_register simply runs the Arduino through the standard steps in the Wire library to write the registers to the IC.

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

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

Now that you have a basic understanding of the code, let's start reading the data. Open up the sketch from the file you downloaded earlier, and upload it to your Arduino. Once it is uploaded, open the Serial monitor in the Arduino IDE. You should start seeing the Arduino print out sentences if you press any electrodes or release any electrodes.