Haga clic para más productos.
No se encontraron productos.

Tutorial sensor táctil capacitivo MPR121

32284

En este tutorial se mostrara el código necesario para poder utilizar el módulo MPR121, se explicara sus características, funcionamiento  y un ejemplo básico para empezar a utilizarlo.

El módulo MPR121 puede controlar 12 electrodos, cada electrodo se comporta como un sensor táctil capacitivo, la comunicación es con interfaz I2C, por lo que solo utiliza dos pines y es fácil de implementar con cualquier microcontrolador.

Modulo MPR121

En el reverso del módulo MPR121 tiene 4 puentes, los cuales hay que romper si no se necesita usar las resistencias pullup que tiene el modulo. También se puede romper el puente de ADD para cambiar la dirección en caso se necesite conectar otro MPR121 al bus I2C

Modulo MPR121 reverso

El electrodo puede ser cualquier superficie conductora, como metal, papel metálico, cobre; para activar el electrodo no necesariamente tiene que haber contacto, la sensibilidad depende de cómo se calibre, esto se lo hace con umbrales el cual el módulo utiliza como referencia para que considere Touch o no. Para cada electrodo se le asigna un umbral de activación. En caso no se utilicen todos los electrodos, también se los puede configurar como salidas para activar LEDs

  

Conexiones entre el módulo MPR121 y Arduino

La alimentación es de 3.3V, la comunicación es a través del I2C del Arduino cuyos pines varía según la placa que se utilice, el pin IRQ generalmente va un pin de interrupción externa que trae el Arduino, a continuación se muestra la conexión del MPR121

   

MPR121

Arduino  Uno, Nano, Mini Pro

Arduino  Mega 2560

Arduino  Due

3.3V

Pin 3.3V (*)

Pin 3.3V (*)

Pin 3.3V (*)

IRQ

Pin 2  (**)

Pin 2(**)

Pin 2(**)

SCL

Pin A5

Pin 21

Pin 21

SDA

Pin A4

Pin 20

Pin 20

GND

Pin GND

Pin GND

Pin GND

 

*EL módulo PMR121 no tiene regulador de voltaje interno, por esto se utiliza la salida de voltaje 3.3V de Arduino, pero se puede usar una fuente externa siempre y cuando no exceda el voltaje de 3.3V.

**Para el pin IRQ se puede usar cualquier pin digital, en este caso no se usa interrupción, pero de ser el caso conectar al pin de interrupción externa correspondiente.

 Conexion MPR121

   

Programación del MPR121

Trabajaremos la programación sin usar librerías, de esta forma podrás migrar el código a cualquier otra plataforma o micro controlador, como los PICs de microchip

Empezamos declarando la librería para la comunicación I2C y el pin IRQ.

#include <Wire.h>
int  Pin_IRQ = 2;  // Pin IRQ en el pin digital 2
boolean EstadoAnterior[12]; //Para Alamacenar el ultimo estado del valor del touch
int address_mpr=0x5A; //dirección de nuestro MPR121

Notar que también creamos una variable para guardar los estados anteriores de los electrodos, para más adelante ver si han cambiado de estado. Además se declara una variable para especificar la dirección i2C de nuestro modulo PMR121

El siguiente paso es en configurar todos nuestros periféricos: los pines, la comunicación serial, el bus i2c y configurar el módulo MPR121.}

void setup(){
  pinMode(Pin_IRQ, INPUT);
  digitalWrite(Pin_IRQ, HIGH); //Habilitamos la resistencia pullup 
  Serial.begin(9600);
  Wire.begin();
  mpr121_Config(address_mpr);
}

Como se observa para configurar el modulo usamos la funcion mpr121_Config(address_mpr), dicha función se muestra a continuación:

void mpr121_Config(int address){

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

  // Section B - Controls filtering when data is < baseline.
  set_register(address, 0x2F, 0x01); //MHD_F
  set_register(address, 0x30, 0x01); //NHD_F
  set_register(address, 0x31, 0xFF); //NCL_F
  set_register(address, 0x32, 0x02); //FDL_F
  
  // Section C - Sets touch and release thresholds for each electrode
  int umbral_Touch=0x44;
  int umbral_Release=0x40;
  set_register(address, 0x41, umbral_Touch); //Umbral Touch 0
  set_register(address, 0x42, umbral_Release); //Umbral Release 0
 
  set_register(address, 0x43, umbral_Touch); //Umbral Touch 1
  set_register(address, 0x44, umbral_Release); //Umbral Release 1
  
  set_register(0x5A, 0x45, umbral_Touch); //Umbral Touch 2
  set_register(0x5A, 0x46, umbral_Release); //Umbral Release 2

  set_register(address, 0x47, umbral_Touch); //Umbral Touch 3
  set_register(address, 0x48, umbral_Release); //Umbral Release 3
  
  set_register(address, 0x49, umbral_Touch); //Umbral Touch 4
  set_register(address, 0x4A, umbral_Release); //Umbral Release 4
  
  set_register(address, 0x4B, umbral_Touch); //Umbral Touch 5
  set_register(address, 0x4C, umbral_Release); //Umbral Release 5
  
  set_register(address, 0x4D, umbral_Touch); //Umbral Touch 6
  set_register(address, 0x4E, umbral_Release); //Umbral Release 6
  
  set_register(address, 0x4F, umbral_Touch); //Umbral Touch 7
  set_register(address, 0x50, umbral_Release); //Umbral Release 7
  
  set_register(address, 0x51, umbral_Touch); //Umbral Touch 8
  set_register(address, 0x52, umbral_Release); //Umbral Release 8
  
  set_register(address, 0x53, umbral_Touch); //Umbral Touch 9
  set_register(address, 0x54, umbral_Release); //Umbral Release 9
  
  set_register(address, 0x55, umbral_Touch); //Umbral Touch 10
  set_register(address, 0x56, umbral_Release); //Umbral Release 10
  
  set_register(address, 0x57, umbral_Touch); //Umbral Touch 11
  set_register(address, 0x58, umbral_Release); //Umbral Release 11
  
  // Section D
  // Set the Filter Configuration
  // Set ESI2
  set_register(address, 0x5D, 0x04); //FIL_CFG
  
  // Section E
  // Electrode Configuration
  // Set ELE_CFG to 0x00 to return to standby mode
  set_register(address, 0x5E, 0x0C);  // ELE_CFG  Enables all 12 Electrodes
  
}

Básicamente en la función anterior se configura los registros necesarios para su funcionamiento, doce de los registros se utilizan para establecer los umbrales de “tocar” y otros doce para  los umbrales de “soltar”, estos valores de registros hay q aumentar o disminuir de acuerdo al tipo de electrodo que usemos, nosotros hemos creado dos variables para establecer los umbrales de Touch y reléase (presionar y soltar) de los 12 electrodos por igual, pero puedes calibrarlo de forma independiente si usas electrodos diferentes

  // Section C - Sets touch and release thresholds for each electrode
  int umbral_Touch=0x44;
  int umbral_Release=0x40;
  
  set_register(address, 0x41, umbral_Touch); //Umbral Touch 0
  set_register(address, 0x42, umbral_Release); //Umbral Release 0
 
  set_register(address, 0x43, umbral_Touch); //Umbral Touch 1
  set_register(address, 0x44, umbral_Release); //Umbral Release 1

Ambos umbrales generalmente son valores cercanos, pero se puede trabajar con un ciclo de histéresis si se pone el umbral de Release por debajo del de Touch.

Una vez configurado el módulo MPR121, el siguiente paso es leer si se ha presionado o tocado algún electrodo, para esto hacemos uso del pin IRQ, que se pone a 0 cada vez que hay una cambio en alguno de los electrodos.

Después de detectar el cambio a través del pin IRQ, leemos el estado de los electrodos, de la siguiente forma:

    if(!digitalRead(Pin_IRQ)){
      
      // Leemos los estados de los electrodos del MPR121
      Wire.requestFrom(address_mpr,2); 
      
      byte LSB = Wire.read();
      byte MSB = Wire.read();
      
      uint16_t touched = ((MSB << 8) | LSB); // 12 de los 16 bits corresponden a los estados táctiles

Como se observa el valor de los electrodos se almacena en una variable de 16bits, de los cuales los 12 menos significativos almacenan los valores del estado de los electrodos.

El siguiente paso es analizar el estado de cada uno de ellos de forma individual, el estado actual se compara con el estado anterior y si existe alguna cambio se realiza la acción correspondiente, que en nuestro caso simplemente es notificar por el puerto serie.

      for (int i=0; i < 12; i++)
      {  
        boolean EstadoActual=bitRead(touched, i);
        if(!(EstadoAnterior[i])&&EstadoActual)
        {
              Serial.print("Electrodo ");
              Serial.print(i);
              Serial.println(" se acaba de tocar");
        }
        
        if(EstadoAnterior[i]&&(!EstadoActual))
        {
              Serial.print("Electrodo ");
              Serial.print(i);
              Serial.println(" ya no está siendo tocado");
        }
        EstadoAnterior[i]=EstadoActual;  
      }     

A continuación se muestra el código completo para leer los 12 electrodos.

#include <Wire.h>
int  Pin_IRQ = 2;  // Pin IRQ en el pin digital 2
boolean EstadoAnterior[12]; //Para Alamacenar el ultimo estado del valor del touch
int address_mpr=0x5A; //dirección de nuestro MPR121

void setup(){
  pinMode(Pin_IRQ, INPUT);
  digitalWrite(Pin_IRQ, HIGH); //Habilitamos la resistencia pullup 
  Serial.begin(9600);
  Wire.begin();
  mpr121_Config(address_mpr);
}

void loop(){

  
    if(!digitalRead(Pin_IRQ)){
      
      // Leemos los estados de los electrodos del MPR121
      Wire.requestFrom(address_mpr,2); 
      
      byte LSB = Wire.read();
      byte MSB = Wire.read();
      
      uint16_t touched = ((MSB << 8) | LSB); // 12 de los 16 bits corresponden a los estados táctiles
  
      //Comprobamos si los electrodos se han presionado
      for (int i=0; i < 12; i++)
      {  
        boolean EstadoActual=bitRead(touched, i);
        if(!(EstadoAnterior[i])&&EstadoActual)
        {
              Serial.print("Electrodo ");
              Serial.print(i);
              Serial.println(" se acaba de tocar");
        }
        
        if(EstadoAnterior[i]&&(!EstadoActual))
        {
              Serial.print("Electrodo ");
              Serial.print(i);
              Serial.println(" ya no está siendo tocado");
        }
        EstadoAnterior[i]=EstadoActual;  
      }     
    }
}


void mpr121_Config(int address){

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

  // Section B - Controls filtering when data is < baseline.
  set_register(address, 0x2F, 0x01); //MHD_F
  set_register(address, 0x30, 0x01); //NHD_F
  set_register(address, 0x31, 0xFF); //NCL_F
  set_register(address, 0x32, 0x02); //FDL_F
  
  // Section C - Sets touch and release thresholds for each electrode
  int umbral_Touch=0x44;
  int umbral_Release=0x40;
  
  set_register(address, 0x41, umbral_Touch); //Umbral Touch 0
  set_register(address, 0x42, umbral_Release); //Umbral Release 0
 
  set_register(address, 0x43, umbral_Touch); //Umbral Touch 1
  set_register(address, 0x44, umbral_Release); //Umbral Release 1
  
  set_register(0x5A, 0x45, umbral_Touch); //Umbral Touch 2
  set_register(0x5A, 0x46, umbral_Release); //Umbral Release 2

  set_register(address, 0x47, umbral_Touch); //Umbral Touch 3
  set_register(address, 0x48, umbral_Release); //Umbral Release 3
  
  set_register(address, 0x49, umbral_Touch); //Umbral Touch 4
  set_register(address, 0x4A, umbral_Release); //Umbral Release 4
  
  set_register(address, 0x4B, umbral_Touch); //Umbral Touch 5
  set_register(address, 0x4C, umbral_Release); //Umbral Release 5
  
  set_register(address, 0x4D, umbral_Touch); //Umbral Touch 6
  set_register(address, 0x4E, umbral_Release); //Umbral Release 6
  
  set_register(address, 0x4F, umbral_Touch); //Umbral Touch 7
  set_register(address, 0x50, umbral_Release); //Umbral Release 7
  
  set_register(address, 0x51, umbral_Touch); //Umbral Touch 8
  set_register(address, 0x52, umbral_Release); //Umbral Release 8
  
  set_register(address, 0x53, umbral_Touch); //Umbral Touch 9
  set_register(address, 0x54, umbral_Release); //Umbral Release 9
  
  set_register(address, 0x55, umbral_Touch); //Umbral Touch 10
  set_register(address, 0x56, umbral_Release); //Umbral Release 10
  
  set_register(address, 0x57, umbral_Touch); //Umbral Touch 11
  set_register(address, 0x58, umbral_Release); //Umbral Release 11
  
  // Section D
  // Set the Filter Configuration
  // Set ESI2
  set_register(address, 0x5D, 0x04); //FIL_CFG
  
  // Section E
  // Electrode Configuration
  // Set ELE_CFG to 0x00 to return to standby mode
  set_register(address, 0x5E, 0x0C);  // ELE_CFG  Enables all 12 Electrodes
  
}

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

A continuación se muestra la salida del monitor serial cuando se está interactuando con los electrodos

  

Monitor serial MPR121

    

Como se observa en nuestro ejemplo estamos detectando cuando se toca un electrodo y cuando se suelta pero dependerá de su aplicación para ver cuál acción les es más útil.

 

Productos relacionados
Artículos relacionados
6 Comentarios
  • Da***

    Da*** 03/10/2022 Responder

    Cuales son los valores mínimos y máximos aceptados por umbral_touch y umbral_release?
  • Lu***

    Lu*** 09/04/2021 Responder

    estoy queriendo usarlo con un ESP32 pero no puedo conectar o nose conectar el IRQ
  • Ma**** ***** ****et

    Ma**** ***** ****et 15/06/2020 Responder

    Our the purpose is to share the related Movies, Gaming, Casual,Faux Leather Jackets, Coats And Vests available.
  • Bl*** ***** ******* ********nt

    Bl*** ***** ******* ********nt 03/02/2020 Responder

    Today students need to juggle up assignments, tests, social life and family time altogether. It has turned out extremely tough to get so much handled with perfection. Since college professors tend to establish high demands for their classes, with a belief that students can easily cope with all those requirements. However, students for coming up with the entire home assignment, need to either sacrifice their leisure time for studying harder or finish the work recklessly.
  • Ma****

    Ma**** 27/01/2020 Responder

    Tu código no funciona
    • Go***

      Go*** 12/05/2020 Responder

      Sí funciona! Yo tuve que modificar los umbrales para que detecte cuando toco directamente los cables (o los pines). Habría que ajustarlos según cada caso.
      En mi caso modifiqué estas dos líneas:

      // Section C - Sets touch and release thresholds for each electrode
      int umbral_Touch=0x44;
      int umbral_Release=0x40;

      //umbral_Touch: lo bajé a 0x10;
      //umbral_Release: lo bajé a 0x06;

      De esa forma me anduvo de perfectamente =)
Dejar un comentario
Deja su comentario

Menú

Ajustes

Crear una cuenta gratuita para usar listas de deseos.

Registrarse