arduino-mpr121

Controla hasta 12 sensores táctiles capacitivos con Arduino y MPR121

¿Qué es un MPR121?

El MPR121 es un controlador de sensores capacitivos que puede ser empleado con un procesador como Arduino para controlar hasta 12 touch pads.

Usar este integrado hace mucho más fácil el empleo de sensores capacitivos ya que incluye filtrado, eliminación de rebotes, y el resto de lógica para leer sensores de forma correctal. También dispone de sensibilidad ajustable por software configurado para ajustar la sensibilidad.

Dispone de 12 entradas sensores capacitivos. Al tocar uno de los pad de entrada, variamos la capacitancia del sistema. EL MPR121 realiza la medición de la capacitancia, el filtrado, y determina el estado del pad, evitándonos tener que realizar estas operaciones.

Adicionalmente, 8 de los electrodos (pin 4 a 11) disponen de funcionalidad básica de GPIO. Por otro lado, dispone de un electrodo 13 “virtual”, que puede emplearse como sensor de proximidad.

La comunicación con el MPR121 se realiza a través de I2C, por lo que es muy sencillo conectarlo con un procesador como Arduino. La dirección se puede configurar con el pin Address entre 4 posibles opciones, para un total de 48 puntos táctiles en un único bus I2C.

La alimentación es de 3.3V, aunque algunos módulos añaden un regulador de voltaje y un adaptador de nivel lógico para poderlo emplear con un procesador de 5V. En caso contrario, deberemos añadir nosotros la adaptación de nivel.

Además de para la detección de sensores táctiles, el MPR121 puede ser empleado en aplicaciones de propósito general de detección de cambios en la capacitancia, como mediciones de nivel de líquido o sensor de detección de objetos.

Precio

Los MPR121 son dispositivos baratos. Podemos encontrar un módulo con MPR121 por 1.30€ en vendedores internacionales de Ebay y Aliexpress.

arduino-mpr121-componente

¿Cómo funciona un MPR121?

Para la medición de la capacitancia el MPR121 carga y descarga cada uno de los electrodos de forma secuencial, aplicando una pequeña corriente, y mide el decaimiento de la tensión. La tensión máxima aplicada se mide empleando un ADC interno de 10 bits.

arduino-mpr121-funcionamiento

La medición obtenida pasa por 3 filtros de distintas características. Los dos primeros filtros eliminan el ruido de la medición. El tercer filtro es un filtro de paso bajo, que proporciona una medición de referencia (baseline).

arduino-mpr121-filtrado

Comparando el valor tras el segundo filtro, con la referencia proporcionada por el tercer filtro, el MPR121 es capaz de detectar variaciones rápidas en la capacitancia en los electrodos. Esta forma de actuar permite que el MPR121 tenga una capacidad de auto calibración, ignorando los cambios de capacitancia del electrodo a lo largo del tiempo, y realizar la detección únicamente en los cambios bruscos de capacitancia.

arduino-mpr121-sensibilidad

Por su parte, la medición de la entrada 13 “virtual” se obtiene combinando la respuesta de los 12 electrodos físicos, obteniendo una especie de “sensor capacitivo de gran tamaño”, que puede emplearse para la detección de presencia.

El MPR121 está diseñado para tener un bajo consumo energético. La tensión de alimentación es de 1.71V a 3.6V, y el consumo es de 29uA (a periodo de muestreo de 16ms), y 3uA cuando no está midiendo.

La tensión de alimentación es de 3.3V, y la mayoría de módulos no disponen de regulador de voltaje para la alimentación, por lo que alimentar a 5V dañará el módulo. Sin embargo, muchos módulos sí incluyen un conversor de nivel en las líneas de comunicación I2C, por lo que es seguro realizar la comunicación desde un procesador de 5V.

Esquema de montaje

La conexión es sencilla, ya que la comunicación se realiza a través de I2C. Simplemente alimentamos el módulo desde Arduino a través del pin 3.3V y Gnd. Por otro lado, conectamos los pines SDA y SCL a los pines correspondientes de nuestro modelo de Arduino.

La dirección de I2C puede configurarse conectando el pin Address. Por defecto tiene una resistencia de pull down de 100K a Gnd, dando la dirección 0x5A. Puede conectarse a 3.3V, SDA, o SCL para cambiar la dirección, respectivamente, a 0x5B, 0x5C o 0x5D.

Opcionalmente, el pin de interrupción IRQ está conectado a 3.3V con una resistencia de pull up. Cuando el sensor detecta un cambio en alguno de los sensores el pin pasa a 0 hasta que el dato es leido a través de I2C. Podemos conectar este pin a una entrada con interrupción para realizar la lectura al detectar cambios.

arduino-mpr121-esquema

La conexión, vista desde Arduino, sería la siguiente.

arduino-mpr121-conexion

Si conectáis el MPR121 a 5V lo dañareis inmediata y permanentemente.

Comprobar que vuestro módulo tiene un conversor de nivel en las líneas de I2C antes de conectarlo directamente a 5V. Si no lo incluye, deberéis añadirlo externamente, o podéis dañar el módulo.

Ejemplos de código

Para realizar la lectura del MPR121 usaremos la librería desarrollada por Adafruit, disponible en este enlace.

La librería proporciona ejemplos de código, que resulta aconsejable revisar. El siguiente ejemplo es una modificación a partir de los disponibles en la librería, que realiza la lectura de los 12 sensores capacitivos y muestra por puerto serie un mensaje al tocar o soltar cualquiera de ellos.

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

Adafruit_MPR121 mpr121 = Adafruit_MPR121();
uint8_t mpr121Address = 0x5A;

uint16_t lasttouched = 0;
uint16_t currtouched = 0;

void setup() {
  Serial.begin(9600);

  // Iniciar el sensor
  if (!mpr121.begin(mpr121Address)) {
    Serial.println("MPR121 no encontrado");
    while (1);
  }
  Serial.println("MPR121 iniciado");
}

// Devuelve true si el pad se ha tocado
bool isPressed(uint8_t channel)
{
  return bitRead(currtouched, channel) && !bitRead(lasttouched, channel)
}

// Devuelve true si el pad se ha dejado de tocar
bool isReleased(uint8_t channel)
{
  return !bitRead(currtouched, channel) && bitRead(lasttouched, channel)
}

void loop()
{
  // Obtener los datos del sensor
  mpr121.updateTouchData();
  currtouched = mpr121.touched();

  // Comprobamos los cambios en todos los canales
  for (uint8_t sensorChannel  = 0; sensorChannel < 12; i++) 
  {
    if (isPressed(sensorChannel) ) 
    {
      Serial.print(sensorChannel ); 
      Serial.println(" tocado");
    }

    if (isReleased(sensorChannel))
    {
      Serial.print(sensorChannel); 
      Serial.println(" soltado");
    }
  }

  lasttouched = currtouched;
}

Descarga el código

Todo el código de esta entrada está disponible para su descarga en Github. github-full