Desde hace algunos meses las flechas de dirección de mi teclado empezaron a fallar. Concretamente, mientras escribo este post, no sirve la tecla Flecha izquierda y Flecha arriba

Puedo vivir sin la de la izquierda, pero como bien saben, la de arriba sirve para el historial de comandos de la terminal.

ESP32-S3 con cables largos para medir touch y enviar tecla física

Así que, como no quería comprar un nuevo teclado y tenía mi ESP32-S3-WROOM me dispuse a emular las 4 flechas de dirección aprovechando que esta placa tiene soporte USB HID para actuar como teclado.

Eligiendo botones

Se puede conectar cualquier sensor compatible con la ESP y Arduino, pero yo no quería usar botones (push buttons) porque quería algo que pudiera colocar en mi escritorio sin tener que soldar.

Quería algo simple, algo improvisado, así que recordé que existe touchRead en mi ESP, que en pocas palabras permite la Detección táctil capacitiva.

Lo único que iba a necesitar era tocar los pines con mi dedo, y opcionalmente conectar 4 cables.

Simular teclado con la ESP32 S3 WROOM

Con la ESP32 S3 WROOM podemos simular un teclado completo nativamente gracias a:


#include "USB.h"
#include "USBHIDKeyboard.h"

Luego en el setup:

  Keyboard.begin();
  USB.begin();

Y en cualquier momento podemos enviar una tecla:

      Keyboard.press(KEY_UP_ARROW);
      delay(50);
      Keyboard.releaseAll();

Podemos enviar prácticamente todas las teclas de un teclado normal, y puede ser en respuesta a cualquier sensor o acción.

Nota: no olvides que para que esto funcione, el cable USB tipo C debe estar conectado en el conector izquierdo de la placa.

Detección táctil capacitiva

Esta ESP y muchas otras tienen un sensor touch incorporado en varios pines. Podemos leer de cualquier pin soportado usando touchRead y nos devolverá un touch_value_t que al momento de escribir esto es un uint32_t.

En mi caso específico el pin me arrojaba valores menores a 40000 cuando no lo tocaba, y valores mayores a 100000 cuando lo hacía, así que establecí mi umbral en 50000.

Puede que esto cambie en tu caso, así que es importante que calibres usando algo como Serial.println(touchRead(pin))

Otra cosa importante es que no todos los GPIO de la ESP sirven para leer toques, por ello es que he usado el 1,2,4 y 5. El 3 también sirve.

Reemplazar flechas de dirección

Yo solo quería enviar 4 teclas: las flechas de dirección, y quería hacer eso al tocar un simple cable.

Además de esto quería cambiar el color del LED RGB incorporado en cada pulsación.

Veamos el platformio.ini que tiene la dependencia del control del LED (Adafruit NeoPixel).


; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:freenove_esp32_s3_wroom]
platform = espressif32
board = freenove_esp32_s3_wroom
framework = arduino
lib_deps =
  adafruit/Adafruit NeoPixel

monitor_speed = 115200

Luego el código C++:


#include <Arduino.h>
#include <Adafruit_NeoPixel.h>
#include "USB.h"
#include "USBHIDKeyboard.h"

#define PIN_RGB 48
#define NUM_RGB 1

const int PIN_ABAJO = 1;
const int PIN_ARRIBA = 2;
const int PIN_DERECHA = 4;
const int PIN_IZQUIERDA = 5;
const int umbralDetectarCableTocado = 50000;
USBHIDKeyboard Keyboard;
Adafruit_NeoPixel ledRgb(NUM_RGB, PIN_RGB, NEO_GRB + NEO_KHZ800);

void setup()
{
  Serial.begin(115200);
  Serial.println("Hola mundo");
  Keyboard.begin();
  USB.begin();
  ledRgb.begin();
  ledRgb.setBrightness(255);
}

/*
Estas banderas evitan que se mantenga
presionada una tecla. Puedes modificarlo según te convenga, yo
he deshabilitado esa parte porque se detecta muy rápido
*/
bool tocandoArriba = false;
bool tocandoAbajo = false;
bool tocandoIzquierda = false;
bool tocandoDerecha = false;

void loop()
{
  bool mover = false;

  if (touchRead(PIN_ARRIBA) > umbralDetectarCableTocado)
  {
    if (!tocandoArriba)
    {
      Keyboard.press(KEY_UP_ARROW);
      delay(50);
      Keyboard.releaseAll();
      tocandoArriba = true;
      mover = true;
    }
  }
  else
  {
    tocandoArriba = false;
  }

  if (touchRead(PIN_ABAJO) > umbralDetectarCableTocado)
  {
    if (!tocandoAbajo)
    {
      Keyboard.press(KEY_DOWN_ARROW);
      delay(50);
      Keyboard.releaseAll();
      tocandoAbajo = true;
      mover = true;
    }
  }
  else
  {
    tocandoAbajo = false;
  }

  if (touchRead(PIN_IZQUIERDA) > umbralDetectarCableTocado)
  {
    if (!tocandoIzquierda)
    {
      Keyboard.press(KEY_LEFT_ARROW);
      delay(50);
      Keyboard.releaseAll();
      tocandoIzquierda = true;
      mover = true;
    }
  }
  else
  {
    tocandoIzquierda = false;
  }

  if (touchRead(PIN_DERECHA) > umbralDetectarCableTocado)
  {
    if (!tocandoDerecha)
    {
      Keyboard.press(KEY_RIGHT_ARROW);
      delay(50);
      Keyboard.releaseAll();
      tocandoDerecha = true;
      mover = true;
    }
  }
  else
  {
    tocandoDerecha = false;
  }

  if (mover)
  {
    static uint16_t hue = 0;
    ledRgb.setPixelColor(0, ledRgb.gamma32(ledRgb.ColorHSV(hue * 256)));
    ledRgb.show();
    hue = (hue + 1) % 360;
  }

  delay(10);
}

Básicamente es un:

if(touchRead(pin) > umbral){
    enviarTecla();
}

Combinado con unas banderas para que no se mantenga presionado como lo explico en los comentarios:

Estas banderas evitan que se mantenga presionada una tecla. Puedes modificarlo según te convenga, yo he deshabilitado esa parte porque se detecta muy rápido y envía varias pulsaciones en un toque muy pequeño

Y después de cargar el código simplemente cambié el tipo C al conector de la izquierda y todo funciona perfectamente.

Circuito

No hay circuito pues es muy simple. Basta con, literalmente, tocar los pines de la ESP32 S3 con tu dedo, ya sea directamente o a través de un cable (o cualquier material conductor) como yo lo he hecho.

Conclusión

Finalmente acomodé mi teclado como se ve en la siguiente imagen:

ESP32-S3 junto a teclado trabajando en conjunto para simular teclas que ya no funcionan en este último

Como ya había anunciado previamente, estoy haciendo un teclado TCP con WebSockets pero todavía no lo he publicado. Yo creo que será este mismo código + WS, pues físicamente tendremos las 4 flechas de dirección (para acceso instantáneo) e inalámbricamente tendremos todas las teclas.

Si el post ha sido de tu agrado te invito a que me sigas para saber cuando haya escrito un nuevo post, haya actualizado algún sistema o publicado un nuevo software. Facebook | X | Instagram | Telegram | También estoy a tus órdenes para cualquier contratación en mi página de contacto