Una de las formas de evitar el uso de botones aparatosos en tus proyectos Arduino es utilizar placas o módulos con pines táctiles, como algunos módulos de ESP32.

Eso sí, la mayoría de placas no cuentan con esta característica, pero leyendo esta entrada en el foro de esp32.com di con algo interesante:

https://www.esp32.com/viewtopic.php?t=23066

Con una rápida calibración, se puede usar cualquier pin analógico como sensor táctil. Aunque hay varias librerías al respecto, realmente solo necesitas un par de funciones, así que vamos al grano!

Componentes

Para este proyecto voy a usar los siguientes compontentes:

Cableado

Si usamos la Pro Micro, esta es la asignación de pines:

Pro MicroComponente
Puerto Micro USBCable USB
Pin 21 (A3)Cable puente desconectado
Pin 20LED+
GNDResistencia

Solo debemos tener en cuenta que el cable puente que usaremos como sensor táctil deberá ir conectado a un pin analógico.

(la placa mostrada no corresponde exactamente con la Pro Micro)

Sketch de Arduino

En mi github puedes encontrar un sketch de Arduino listo para usar:

https://github.com/TheRoam/TRW_AnalogTouch/blob/main/ProMicro_Blink_AnalogTouch.ino

Verás que indica "ProMicro", pero realmente es compatible con cualquier microcontrolador. Solo tienes que elegir tu placa en el menú de Herramientas.

La Pro Micro lleva un controlador ATMega32u4, que es compatible con la placa Arduino Leonardo.

Con esta configuración, compilamos el script y lo subimos a la placa.

Resultado

Abrimos el Monitor Serie, que debería aparecer en blanco ya que el texto de depuración está configurado al mínimo por defecto.

Ahora tocamos el extremo libre del cable puente y veremos cómo se ilumina el led, y cómo se detecta el "toque" en el Monitor Serie.

También verás que el script acumula los "toques" para poder utilizarlos en otros programas.

Al código

Brevemente explico lo que hace el programa:

  1. Durante el setup(), iniciamos la comunicación por serie, activamos el pin para el led, y rellenamos la matriz de lecturas analógicas con unas lecturas iniciales con setTouch (Por defecto se leen 20 valores).
void setup() {
  // initialize serial communication at 115200 bits per second:
  Serial.begin(115200);
  //enable LED pin
  pinMode(LP,OUTPUT);
  setTouch(TP);
}
  1. A continuación, pasamos a la función de ejecución continua loop() donde refrescaremos las lecturas al inicio de cada bucle.
setTouch(TP);
//------loop continues------//
void setTouch(int tp){
  //fill up the array
  for(int a=0;a<VALUES;a++){
    mean[a]=analogRead(tp);
    delay(10);
  }
}
  1. Comprobamos si la depuración es mínima o extendida y ejecutamos el programa principal correspondiente (es el mismo, pero con mayor salida al Monitor Serie).
//run check
  if(out==1){
    extended(TP);
  }else if(out==0){
    minimal(TP);
  }
  1. El programa principal:
    1. Recorre la matriz de lecturas,
    2. Obtiene la media de los valores,
    3. Obtiene una nueva lectura,
    4. Calcula la diferencia de tensión entre la última lectura y la media,
    5. Si el valor es mayor que la caida de tensión de referencia, se identifica "toque", se imprime por Monitor Serie, se suma al contador y se ilumina el led.
    6. Se restaura la media a 0, se apaga el led y se devuelve la variable de "toques".
int minimal(int tp){
  //start reading values
  for(int i=0;i<VALUES;i++){
    //get average of array
    for(int j=0;j<VALUES;j++){
      avg+=mean[j];
    }
    
    avg=avg/VALUES;

    //read current value
    fin=analogRead(tp);
    
    //compare average with current value
    if((avg-fin)>REFV){
      Serial.println("----------  T   O    U    C    H  ----------");
      //increase counter
      touch++;
      //print touch count
      Serial.print("T: ");
      Serial.println(touch);
      //light led
      ledON(LP);
      //wait 1 second after touch detected
      delay(1000);
    }
    //restart counter
    avg=0;
    //restart led
    ledOFF(LP);
    delay(VALINTERVAL);
  }
  return touch;
}
  1. Con esto se reinicia el bucle, volviendo al punto 2.

Otras configuraciones

El script cuenta con diversas variables de configuración que encontraremos en los '#define's

  • OUT: define la cantidad de texto de depuración. Valor 0: mínimo; Valor 1: extendido.
  • VALUES: tamaño de la matriz de valores analógicos.
  • TOUCHPIN: definir el número del pin analógico a usar.
  • LEDPIN: definir el número de pin usado por el led.
  • VALINTERVAL: intervalo de evaluación en milisegundos.
  • REFV: valor de caida de voltaje (en milivoltios) que identifica un "toque".
// OUTPUT verbosity
// 1: extended --> Prints ADC array, mean value, touch count and touch message with touch count
// 0: minimal  --> Prints touch message with touch count

#define OUT 0

// comparison variables
#define VALUES 20       //values for mean array
#define TOUCHPIN 3      //touch pin
#define LEDPIN 20       //led pin
#define VALINTERVAL 100 //evaluation interval
#define REFV 80         //reference voltage drop in mV

Calibración

Cambiando la configuración se puede calibrar el script para distintas placas. Con lo que he probado, esta es una buena secuencia:

  1. Define una REFV alta, por ejemplo 1000
  2. Carga el script con depuración extendida (OUT 1)
  3. Abre el Monitor Serie y observa los valores medios (Average: 230)
  4. Ahora, toca el cable puente y observa de nuevo los valores medios (Average: 170)
  5. Haz la resta entre las medias en 3. y en 4. (230-170=60).
  6. Define el REFV con este valor y calibra a partir de aquí.
    • Para más sensibilidad, defínelo más bajo (50).
    • Si es excesivo puede detectarse sin contacto. Auméntalo (80).
    • Debido a la carga del CPU, REFV puede variar si hay depuración OUT 1 respecto a OUT 0. Busca un valor que funcione para OUT 0.

¿Te ha sido útil o tienes dudas? Deja tu comentario en 🐦 Twitter!

🐦 @RoamingWorkshop