MPR121 code

I want to connect four MPR121 boards (https://www.sparkfun.com/products/9695) to an arduino uno. I changed the jumpers and have tested the address of each individual board and these work. (Test code: http://code.bildr.org/download/1010.zip)

However, when I try to use the code below to address and read all of the four sensors, it doesn’t work. Even if I only attach one sensor using this code, it will not work. Any suggestions what can be wrong?

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

int irqpin1 = 2;  // Digital 2
int irqpin2 = 3;  // Digital 3
int irqpin3 = 4;  // Digital 4
int irqpin4 = 5;  // Digital 5
boolean touchStates[12]; //to keep track of the previous touch states

void setup(){
  pinMode(irqpin1, INPUT);
  digitalWrite(irqpin1, HIGH); //enable pullup resistor
  pinMode(irqpin2, INPUT);
  digitalWrite(irqpin2, HIGH); //enable pullup resistor
  pinMode(irqpin3, INPUT);
  digitalWrite(irqpin3, HIGH); //enable pullup resistor
  pinMode(irqpin4, INPUT);
  digitalWrite(irqpin4, HIGH); //enable pullup resistor
  
  Serial.begin(9600);
  Wire.begin();

  mpr121_setup();
}

void loop(){
  readTouchInputs1();
  readTouchInputs2();
  readTouchInputs3();
  readTouchInputs4();
}


void readTouchInputs1(){
  if(!checkInterrupt()){
    
    //read the touch state from the MPR121
    Wire.requestFrom(0x5A,2); //A heeft IRQ aan port 2
    
    byte LSB = Wire.read();
    byte MSB = Wire.read();
    
    uint16_t touched = ((MSB << 8) | LSB); //16bits that make up the touch states

    
    for (int i=00; 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.print(i+10);
          Serial.println("1");
        
        }else if(touchStates[i] == 1){
          //pin i is still being touched
        }  
      
        touchStates[i] = 1;      
      }else{
        if(touchStates[i] == 1){
         Serial.print("pin");
          Serial.print(i+10);
          Serial.println("0");
          
          //pin i is no longer being touched
       }
        
        touchStates[i] = 0;
      }
    
    }
    
  }
}

void readTouchInputs2(){
  if(!checkInterrupt()){
    
    //read the touch state from the MPR121
    Wire.requestFrom(0x5B,3); //B heeft IRQ aan port 3
    
    byte LSB = Wire.read();
    byte MSB = Wire.read();
    
    uint16_t touched = ((MSB << 8) | LSB); //16bits that make up the touch states

    
    for (int i=00; 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.print(i+20);
          Serial.println("1");
        
        }else if(touchStates[i] == 1){
          //pin i is still being touched
        }  
      
        touchStates[i] = 1;      
      }else{
        if(touchStates[i] == 1){
         Serial.print("pin");
          Serial.print(i+20);
          Serial.println("0");
          
          //pin i is no longer being touched
       }
        
        touchStates[i] = 0;
      }
    
    }
    
  }
}

void readTouchInputs3(){
  if(!checkInterrupt()){
    
    //read the touch state from the MPR121
    Wire.requestFrom(0x5C,4); //C heeft IRQ aan port 4
    
    byte LSB = Wire.read();
    byte MSB = Wire.read();
    
    uint16_t touched = ((MSB << 8) | LSB); //16bits that make up the touch states

    
    for (int i=00; 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.print(i+30);
          Serial.println("1");
        
        }else if(touchStates[i] == 1){
          //pin i is still being touched
        }  
      
        touchStates[i] = 1;      
      }else{
        if(touchStates[i] == 1){
         Serial.print("pin");
          Serial.print(i+30);
          Serial.println("0");
          
          //pin i is no longer being touched
       }
        
        touchStates[i] = 0;
      }
    
    }
    
  }
}

void readTouchInputs4(){
  if(!checkInterrupt()){
    
    //read the touch state from the MPR121
    Wire.requestFrom(0x5D,5); //D heeft IRQ aan port 5
    
    byte LSB = Wire.read();
    byte MSB = Wire.read();
    
    uint16_t touched = ((MSB << 8) | LSB); //16bits that make up the touch states

    
    for (int i=00; 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.print(i+40);
          Serial.println("1");
        
        }else if(touchStates[i] == 1){
          //pin i is still being touched
        }  
      
        touchStates[i] = 1;      
      }else{
        if(touchStates[i] == 1){
         Serial.print("pin");
          Serial.print(i+40);
          Serial.println("0");
          
          //pin i is no longer being touched
       }
        
        touchStates[i] = 0;
      }
    
    }
    
  }
}




void mpr121_setup(void){

//  set_register(0x5A, ELE_CFG, 0x00); 
  //Alle sections beide units bijzetten
  
  // 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);

  set_register(0x5B, MHD_R, 0x01);
  set_register(0x5B, NHD_R, 0x01);
  set_register(0x5B, NCL_R, 0x00);
  set_register(0x5B, FDL_R, 0x00);
  
  set_register(0x5C, MHD_R, 0x01);
  set_register(0x5C, NHD_R, 0x01);
  set_register(0x5C, NCL_R, 0x00);
  set_register(0x5C, FDL_R, 0x00);
  
  set_register(0x5D, MHD_R, 0x01);
  set_register(0x5D, NHD_R, 0x01);
  set_register(0x5D, NCL_R, 0x00);
  set_register(0x5D, 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);
  
  set_register(0x5B, MHD_F, 0x01);
  set_register(0x5B, NHD_F, 0x01);
  set_register(0x5B, NCL_F, 0xFF);
  set_register(0x5B, FDL_F, 0x02);
  
  set_register(0x5C, MHD_F, 0x01);
  set_register(0x5C, NHD_F, 0x01);
  set_register(0x5C, NCL_F, 0xFF);
  set_register(0x5C, FDL_F, 0x02);
  
  set_register(0x5D, MHD_F, 0x01);
  set_register(0x5D, NHD_F, 0x01);
  set_register(0x5D, NCL_F, 0xFF);
  set_register(0x5D, 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);
  
  set_register(0x5B, ELE0_T, TOU_THRESH);
  set_register(0x5B, ELE0_R, REL_THRESH);
  set_register(0x5B, ELE1_T, TOU_THRESH);
  set_register(0x5B, ELE1_R, REL_THRESH);
  set_register(0x5B, ELE2_T, TOU_THRESH);
  set_register(0x5B, ELE2_R, REL_THRESH);
  set_register(0x5B, ELE3_T, TOU_THRESH);
  set_register(0x5B, ELE3_R, REL_THRESH);
  set_register(0x5B, ELE4_T, TOU_THRESH);
  set_register(0x5B, ELE4_R, REL_THRESH);
  set_register(0x5B, ELE5_T, TOU_THRESH);
  set_register(0x5B, ELE5_R, REL_THRESH);
  set_register(0x5B, ELE6_T, TOU_THRESH);
  set_register(0x5B, ELE6_R, REL_THRESH);
  set_register(0x5B, ELE7_T, TOU_THRESH);
  set_register(0x5B, ELE7_R, REL_THRESH);
  set_register(0x5B, ELE8_T, TOU_THRESH);
  set_register(0x5B, ELE8_R, REL_THRESH);
  set_register(0x5B, ELE9_T, TOU_THRESH);
  set_register(0x5B, ELE9_R, REL_THRESH);
  set_register(0x5B, ELE10_T, TOU_THRESH);
  set_register(0x5B, ELE10_R, REL_THRESH);
  set_register(0x5B, ELE11_T, TOU_THRESH);
  set_register(0x5B, ELE11_R, REL_THRESH);
  
  set_register(0x5C, ELE0_T, TOU_THRESH);
  set_register(0x5C, ELE0_R, REL_THRESH);
  set_register(0x5C, ELE1_T, TOU_THRESH);
  set_register(0x5C, ELE1_R, REL_THRESH);
  set_register(0x5C, ELE2_T, TOU_THRESH);
  set_register(0x5C, ELE2_R, REL_THRESH);
  set_register(0x5C, ELE3_T, TOU_THRESH);
  set_register(0x5C, ELE3_R, REL_THRESH);
  set_register(0x5C, ELE4_T, TOU_THRESH);
  set_register(0x5C, ELE4_R, REL_THRESH);
  set_register(0x5C, ELE5_T, TOU_THRESH);
  set_register(0x5C, ELE5_R, REL_THRESH);
  set_register(0x5C, ELE6_T, TOU_THRESH);
  set_register(0x5C, ELE6_R, REL_THRESH);
  set_register(0x5C, ELE7_T, TOU_THRESH);
  set_register(0x5C, ELE7_R, REL_THRESH);
  set_register(0x5C, ELE8_T, TOU_THRESH);
  set_register(0x5C, ELE8_R, REL_THRESH);
  set_register(0x5C, ELE9_T, TOU_THRESH);
  set_register(0x5C, ELE9_R, REL_THRESH);
  set_register(0x5C, ELE10_T, TOU_THRESH);
  set_register(0x5C, ELE10_R, REL_THRESH);
  set_register(0x5C, ELE11_T, TOU_THRESH);
  set_register(0x5C, ELE11_R, REL_THRESH);
  
  set_register(0x5D, ELE0_T, TOU_THRESH);
  set_register(0x5D, ELE0_R, REL_THRESH);
  set_register(0x5D, ELE1_T, TOU_THRESH);
  set_register(0x5D, ELE1_R, REL_THRESH);
  set_register(0x5D, ELE2_T, TOU_THRESH);
  set_register(0x5D, ELE2_R, REL_THRESH);
  set_register(0x5D, ELE3_T, TOU_THRESH);
  set_register(0x5D, ELE3_R, REL_THRESH);
  set_register(0x5D, ELE4_T, TOU_THRESH);
  set_register(0x5D, ELE4_R, REL_THRESH);
  set_register(0x5D, ELE5_T, TOU_THRESH);
  set_register(0x5D, ELE5_R, REL_THRESH);
  set_register(0x5D, ELE6_T, TOU_THRESH);
  set_register(0x5D, ELE6_R, REL_THRESH);
  set_register(0x5D, ELE7_T, TOU_THRESH);
  set_register(0x5D, ELE7_R, REL_THRESH);
  set_register(0x5D, ELE8_T, TOU_THRESH);
  set_register(0x5D, ELE8_R, REL_THRESH);
  set_register(0x5D, ELE9_T, TOU_THRESH);
  set_register(0x5D, ELE9_R, REL_THRESH);
  set_register(0x5D, ELE10_T, TOU_THRESH);
  set_register(0x5D, ELE10_R, REL_THRESH);
  set_register(0x5D, ELE11_T, TOU_THRESH);
  set_register(0x5D, ELE11_R, REL_THRESH);
  
  // Section D
  // Set the Filter Configuration
  // Set ESI2
  set_register(0x5A, FIL_CFG, 0x04);
  set_register(0x5B, FIL_CFG, 0x04);
  set_register(0x5C, FIL_CFG, 0x04);
  set_register(0x5D, 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
  set_register(0x5B, ELE_CFG, 0x0C);  // Enables all 12 Electrodes  
  set_register(0x5C, ELE_CFG, 0x0C);  // Enables all 12 Electrodes
  set_register(0x5D, 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(irqpin1);
  return digitalRead(irqpin2);
  return digitalRead(irqpin2);
  return digitalRead(irqpin4);
}


void set_register(int address, unsigned char r, unsigned char v){
    Wire.beginTransmission(address);
    Wire.write(r);
    Wire.write(v);
    Wire.endTransmission();
}

Fixed it…

For those interested, here’s the code:

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

int irqpin[] = {2,3,4,5};  // Digital 2,3,4,5 used for the 4 sensors

int touchStates[4][12]; //to keep track of the previous touch states

void setup(){
  pinMode(irqpin[0], INPUT);
  pinMode(irqpin[1], INPUT);
  pinMode(irqpin[2], INPUT);
  pinMode(irqpin[3], INPUT);
  
  digitalWrite(irqpin[0], HIGH); //enable pullup resistor
  digitalWrite(irqpin[1], HIGH); //enable pullup resistor
  digitalWrite(irqpin[2], HIGH); //enable pullup resistor
  digitalWrite(irqpin[3], HIGH); //enable pullup resistor
  
  Serial.begin(9600);
  Wire.begin();

   mpr121_setup(0x5A);
   mpr121_setup(0x5B);
   mpr121_setup(0x5C);
   mpr121_setup(0x5D);
}

void loop(){
  readTouchInputs(0x5A, 1);
  readTouchInputs(0x5B, 2);
  readTouchInputs(0x5C, 3);
  readTouchInputs(0x5D, 4);
}


void readTouchInputs(int sensorAddress, int sensor){
  if(!checkInterrupt(sensor - 1)){
    
    //read the touch state from the MPR121
    Wire.requestFrom(sensorAddress,2); 
    
    byte LSB = Wire.read();
    byte MSB = Wire.read();
    
    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[sensor-1][i] == 0){
          //pin i was just touched
          Serial.print("sensor ");
          Serial.print(sensor);
          Serial.print(" pin ");
          Serial.print(i);
          Serial.println(" was just touched");
        
        }else if(touchStates[sensor-1][i] == 1){
          //pin i is still being touched
        }  
      
        touchStates[sensor-1][i] = 1;      
      }else{
        if(touchStates[sensor-1][i] == 1){
          Serial.print("sensor ");
          Serial.print(sensor);
          Serial.print("pin ");
          Serial.print(i);
          Serial.println(" is no longer being touched");
          
          //pin i is no longer being touched
       }
        
        touchStates[sensor-1][i] = 0;
      }
    
    }
    
  }
}




void mpr121_setup(byte address){

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

  // Section B - Controls filtering when data is < baseline.
  set_register(address, MHD_F, 0x01);
  set_register(address, NHD_F, 0x01);
  set_register(address, NCL_F, 0xFF);
  set_register(address, FDL_F, 0x02);
  
  // Section C - Sets touch and release thresholds for each electrode
  set_register(address, ELE0_T, TOU_THRESH);
  set_register(address, ELE0_R, REL_THRESH);

  set_register(address, ELE1_T, TOU_THRESH);
  set_register(address, ELE1_R, REL_THRESH);
  
  set_register(address, ELE2_T, TOU_THRESH);
  set_register(address, ELE2_R, REL_THRESH);
  
  set_register(address, ELE3_T, TOU_THRESH);
  set_register(address, ELE3_R, REL_THRESH);
  
  set_register(address, ELE4_T, TOU_THRESH);
  set_register(address, ELE4_R, REL_THRESH);
  
  set_register(address, ELE5_T, TOU_THRESH);
  set_register(address, ELE5_R, REL_THRESH);
  
  set_register(address, ELE6_T, TOU_THRESH);
  set_register(address, ELE6_R, REL_THRESH);
  
  set_register(address, ELE7_T, TOU_THRESH);
  set_register(address, ELE7_R, REL_THRESH);
  
  set_register(address, ELE8_T, TOU_THRESH);
  set_register(address, ELE8_R, REL_THRESH);
  
  set_register(address, ELE9_T, TOU_THRESH);
  set_register(address, ELE9_R, REL_THRESH);
  
  set_register(address, ELE10_T, TOU_THRESH);
  set_register(address, ELE10_R, REL_THRESH);
  
  set_register(address, ELE11_T, TOU_THRESH);
  set_register(address, ELE11_R, REL_THRESH);
  
  // Section D
  // Set the Filter Configuration
  // Set ESI2
  set_register(address, FIL_CFG, 0x04);
  
  // Section E
  // Electrode Configuration
  // Set ELE_CFG to 0x00 to return to standby mode
  set_register(address, ELE_CFG, 0x0C);  // Enables all 12 Electrodes
  
  
  // Section F
  // Enable Auto Config and auto Reconfig
  /*set_register(address, ATO_CFG0, 0x0B);
  set_register(address, ATO_CFGU, 0xC9);  // USL = (Vdd-0.7)/vdd*256 = 0xC9 @3.3V   set_register(address, ATO_CFGL, 0x82);  // LSL = 0.65*USL = 0x82 @3.3V
  set_register(address, ATO_CFGT, 0xB5);*/  // Target = 0.9*USL = 0xB5 @3.3V
  
  set_register(address, ELE_CFG, 0x0C);
  
}


boolean checkInterrupt(int sensor){
  return digitalRead(irqpin[sensor]);
}


void set_register(int address, unsigned char r, unsigned char v){
    Wire.beginTransmission(address);
    Wire.write(r);
    Wire.write(v);
    Wire.endTransmission();
}

hi lekirst! thank you for posting the code! I am currently working on something quite the same, and are connecting 3 MPR121 boards together to an Arduino Duemilanove, now I am wondering how you have connected the ADDR pins on MPR121 board 2 and 3, since I can’t get it to work… thank you already!

I am using a arduino uno, here’s how I connected it. It is fairly simple.

Connect all 3.3V pins from the MPR boards to the 3.3V arduino pin

Connect all GRND pins from the MPR boards to the GRND arduino pin

Connect all SDA pins from the MPR boards to the SDA arduino pin (analog in a4)

Connect all SDL pins from the MPR boards to the SDL arduino pin (analog in a5)

Connect IRQ pin from the first MPR board to arduino digital pin 2

Connect IRQ pin from the second MPR board to arduino digital pin 3

Connect IRQ pin from the third MPR board to arduino digital pin 4

Connect IRQ pin from the fourth MPR board to arduino digital pin 5

Good luck!

To adress all the boards individually, you also need to change the addresses of the boards by shorting the ADD to a different pin.

On the bottom of the breakout you have two solder pads with a thin connection between them. Cut that through (it connects ADD to GND) for the three modules you want to change the address for. Then connect the pin with Vcc, SCL or SDA (for the three versions).

Also the modules have pull-ups for the I2C installed. Cut these:

On the bottom of the module you have four pairs of solder pads, each connected with a thin line of copper. One is the connection of the ADD to GND, the others are the pull-ups of SCL, SDA and INT. Cut the copper line for SDA and SCL.

@lekirst Any idea how the code would be needed to be changed if i want to write all the informations from mpr121 sensors directly on the sd card of an openlog over the arduino?

@jumbo9001: sorry, no experience with that…