project feasability using chip mpr121

Hello, I’m new to these forums so I hope I’m posting this question in the right place. I have a question about a project I’m doing that uses the chip mptr121. Basically the project is just a flat electrode that senses how hard a finger is pressed against it, and I would like to know if this project is possible. I have done a succesful test with the chip before, by wiring it to an arduino with the attached diagram 1. In this diagram, there is the i2c pins connected to the arduino, the interupt pin is 12, and There are power and ground pins connected too. Also, each output of the mpr121 is connected to a different electrode. Each time a electrode is touched or released, I can see a print on the serial monitor letting me know witch electrode was pushed or released. Here is the code I used:

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


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


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){
    Wire.beginTransmission(address);
    Wire.write(r);
    Wire.write(v);
    Wire.endTransmission();
}
void setup(){
  Serial.begin(9600);
  
  pinMode(irqpin, INPUT);
  digitalWrite(irqpin, HIGH); //enable pullup resistor
  
  Wire.begin();

  mpr121_setup();
}

void loop(){
  readTouchInputs();
  for(int i = 0; i < 12; i++){
    if(touchStates[i]){
      
    } else {
     
    }
  }
}


void readTouchInputs(){
  if(!checkInterrupt()){
    
    //read the touch state from the MPR121
    Wire.requestFrom(0x5A,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[i] == 0){
          //pin i was just touched
          Serial.print("pin ");
          Serial.print(i);
          Serial.println(" was just touched");
          touchStates[i] = 0;
        }
    
      }
    
    }
  }
}

mpr.h can be found here: MPR121_Capacitive_Touch_Breakout/mpr121.h at master · sparkfun/MPR121_Capacitive_Touch_Breakout · GitHub

So now I tried wiring the electrodes differently to try out my idea. I shorted all the inputs into one electrode, and uploaded the following code:

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


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


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

  for(int i = 0; i< 24; i++){
    set_register(0x5A, ELE0_T+i, TOU_THRESH+4*i);
    i++;
    set_register(0x5A, ELE0_T+i, REL_THRESH+4*i);
  }
  // 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){
    Wire.beginTransmission(address);
    Wire.write(r);
    Wire.write(v);
    Wire.endTransmission();
}
void setup(){
  Serial.begin(9600);
  
  pinMode(irqpin, INPUT);
  digitalWrite(irqpin, HIGH); //enable pullup resistor
  
  Wire.begin();

  mpr121_setup();
}

void loop(){
  readTouchInputs();
  for(int i = 0; i < 12; i++){
    if(touchStates[i]){
      
    } else {
     
    }
  }
}


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

    Serial.println(touched);
    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.print(i);
          Serial.println(" was just touched");
          touchStates[i] = 0;
        }
    
      }
    
    }
  }
}

And mpr.h unchanged. My goal with this sketch is to detect the intesity that someone is pushing against the electrode. There are 12 different levels of intensity that can be detected, but the code doesn’t work, and nothing is printed on the monitor. I would apreciate any guidance that you guys can offer me to acheive my objective, Thanks.

diagram2.jpg

Hello there!

This sounds like an interesting project. The electrode idea sounds like it can function for your project, but may take a lot of time to get set up right. May I suggest you look into a device called an FSR (Force-Sensing-Resistor) They are extremely straight-forward and can probably accomplish the same as your electrode theory.

Well I really want to make this project work the way I explained it, because it would be very usefull for an autoleveling feature in 3D printers.

Basically the project is just a flat electrode that senses how hard a finger is pressed against it, and I would like to know if this project is possible.

As you describe it, this is not possible. That chip is a capacitance sensor, it will sense a touch or close proximity but not pressure.

There might be a very small effect as the area of contact increases very slightly due to the finger spreading out and more contact area being made but is is not pressure as such, and will be not very repeatable from person to person, or day to day.

BohbotJames:
Well I really want to make this project work the way I explained it, because it would be very usefull for an autoleveling feature in 3D printers.

I see. As Grumpy_Mike pointed out, that method may not give results that you want. I know there are auto-leveling 3D printers that use lasers to determine distance. Can you hook up an IR sensor or maybe and ultrasonic sensor to use as a proximity sensor?