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.

Pages
Contributors: Toni_K
Favorited Favorite 2

Communicating with the Shield

Once you've got your shield assembled, it's time to start talking to it! You can download the example code here, or find the most up-to-date version in the GitHub repository.

Open up the Touch_Sensor_Shield_Example.ino file. The other files set the register definitions for the MPR121 chip, so you shouldn't need to mess with these at all.

language:c
    // Match key inputs with electrode numbers
    #define ONE 8
    #define TWO 5
    #define THREE 2
    #define FOUR 7
    #define FIVE 4
    #define SIX 1
    #define SEVEN 6
    #define EIGHT 3
    #define NINE 0

    //extras (not connected to button)
    #define ELE9 9
    #define ELE10 10
    #define ELE11 11

    //interupt pin
    int irqPin = 2;  // D2

First thing the code shows is the pin definitions. This is laying out the keypad functionality (ONE, TWO, etc.) and defining which electrode pin corresponds to each number. As the comment states, electrode pins 9, 10 and 11 are not currently connected to anything, but if you did solder on additional buttons to those pins on the shield, you can change this.

The interrupt pin is also defined as D2. This can't be modified without some hardware hacking on the shield, so keep that in mind if you are interfacing additional hardware into your set up.

language:c
    void setup()
    {
      //make sure the interrupt pin is an input and pulled high
      pinMode(irqPin, INPUT);
      digitalWrite(irqPin, HIGH);

      //configure serial out
      Serial.begin(9600);

      // initalize I2C bus. Wiring lib not used. 
      i2cInit();

      // initialize mpr121
      mpr121QuickConfig();

      // Create and interrupt to trigger when a button
      // is hit, the IRQ pin goes low, and the function getNumber is run. 
      attachInterrupt(0,getNumber,LOW);

      // prints 'Ready...' when you can start hitting numbers
      Serial.println("Ready...");
    }

The setup loop starts by setting the interrupt pin as an input and pulling it high. The serial bus is started at 9600 bps. Next, the code initializes the I2C communication lines without using the Wiring library.

The MPR121 chip is then configured with the proper sensitivity settings on the electrodes. The final step in the setup loop creates an interrupt in the code that will trigger when any of the buttons are hit.

language:c

    void loop()
{
  //You can put additional code here. The interrupt will run in the backgound. 
}

The loop function is actually empty currently, as the button presses use the interrupt we created in the setup loop. If you did have additional hardware you wanted to incorporate into your project, the code for it can live in this loop.

The last two functions in the example code tell the Arduino to check the electrode states for a button press and what to print out when a button press is detected.

language:c
void getNumber()
{
  int touchNumber = 0;
  uint16_t touchstatus;
  char digits;

  touchstatus = getTouchStatus();

  for (int j=0; j<12; j++)  // Check how many electrodes were pressed
  {
    if ((touchstatus & (1<<j)))
      touchNumber++;
  }

  if (touchNumber == 1)
  {
    if (touchstatus & (1<<SEVEN))
    {
      digits = '7';
    }
    else if (touchstatus & (1<<FOUR))
    {
      digits = '4';
    }
    else if (touchstatus & (1<<ONE))
    {
      digits = '1';
    }
    else if (touchstatus & (1<<EIGHT))
    {
      digits = '8';
    }
    else if (touchstatus & (1<<FIVE))
    {
      digits = '5';
    }
    else if (touchstatus & (1<<TWO))
    {
      digits = '2';
    }
    else if (touchstatus & (1<<NINE))
    {
      digits = '9';
    }
    else if (touchstatus & (1<<SIX))
    {
      digits = '6';
    }
    else if (touchstatus & (1<<THREE))
    {
      digits = '3';
    }
    Serial.println(digits);
  }
  //do nothing if more than one button is pressed, or if all are released
  else if (touchNumber == 0)
    ;
  else
    ;
}

The function getTouchStatus() actually returns at 16-bit value which gives the status of each button. The status of 1 indicates that an electrode is being activated.

language: c
    int getTouchStatus()
{
  int touch;

  touch = mpr121Read(0x01) << 8;
  touch |= mpr121Read(0x00);

  return touch;
}

Now that you have basic communication up and running with your shield, you can start integrating this into projects. If you haven't yet connected anything to electrodes 9, 10 and 11, consider adding in additional buttons here. You will also need to update the code. You'll want to add the following block of code into the example sketch right before Serial.println(digits);. You can change the digits values to have the buttons output different values instead of "A", "B", or "C".

language:c
    else if (touchstatus & (1 << ELE9))
{
  digits = 'A';
}
else if (touchstatus & (1 << ELE10))
{
  digits = 'B';
}
else if (touchstatus & (1 << ELE11))
{
  digits = 'C';
}