Capturar Teclas del Usuario Mediante Python y Arduino

En este Laboratorio vamos a realizar la captura de las teclas apretadas por el usuario mediante Python, la enviaremos hacia Arduino mediante comunicación serial y presentaremos los datos mediante un Display LCD 16×2.

AVISO IMPORTANTE:

Capturar las teclas del usuario sin su conocimiento puede ser considerado comportamiento malicioso (keylogger). Esta funcionalidad está permitida solo con fines educativos y en entornos controlados.

Paso 1

Ensamblar el circuito en el Protoboard de acuerdo al diseño presentado en clase. Tener mucho cuidado con la conexión de cables para evitar dañar el Display LCD 16×2. Las resistencias son de 220 Ohmios; sin embargo, en la implementación física puede ser necesario reemplazarlas por resistencias de 1000 ohmios.

Paso 2

Subir al Arduino el código que recibirá los datos desde Python mediante comunicación serial y mostrará la información en pantalla.

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

String linea1 = "";
String linea2 = "";
bool recibidoLinea1 = false;

void setup() {
  lcd.begin(16, 2);
  Serial.begin(9600);
  lcd.print("Iniciando...");
  delay(1000);
  lcd.clear();
}

void loop() {
  static String input = "";

  // Leer línea desde Serial
  while (Serial.available()) {
    char c = Serial.read();
    if (c == '\n') {
      if (!recibidoLinea1) {
        linea1 = input;
        recibidoLinea1 = true;
      } else {
        linea2 = input;
      }
      input = "";
    } else {
      input += c;
    }
  }

  // Scroll automático para ambas líneas
  scrollLCD(linea1, linea2);
}

void scrollLCD(String texto1, String texto2) {
  static unsigned long ultimaActualizacion = 0;
  static int offset1 = 0;
  static int offset2 = 0;

  if (millis() - ultimaActualizacion >= 500) {
    lcd.setCursor(0, 0);
    lcd.print(ajustarScroll(texto1, offset1));

    lcd.setCursor(0, 1);
    lcd.print(ajustarScroll(texto2, offset2));

    offset1 = (offset1 + 1) % (texto1.length() + 1);
    offset2 = (offset2 + 1) % (texto2.length() + 1);

    ultimaActualizacion = millis();
  }
}

String ajustarScroll(String texto, int offset) {
  texto += "                "; // relleno para evitar corte abrupto
  if (offset > texto.length() - 16) offset = 0;
  return texto.substring(offset, offset + 16);
}

Paso 3

Preparar el Script en Python, el cual capturará los datos del sistema: Hora, Usuario, Sistema Operativo y teclas oprimidas por el usuario para ser enviadas mediante la librería PySerial al Arduino.

Requisitos y Librerías:

  • Pyhton 3.12 (Recomendado)
  • pip install keyboard pyserial
  • pip install requests

Crear el Script en Python y no olvidar cambiar el puerto COM8 con el valor de tu computador.

import serial
import time
import os
import platform
import getpass
import keyboard
from datetime import datetime

puerto_serial = "COM8"  # Cambiar según corresponda
baudrate = 9600

def obtener_info_sistema():
    usuario = getpass.getuser()
    sistema = platform.system()
    hora = datetime.now().strftime("%H:%M")
    return f"{hora} {usuario} {sistema}"

def enviar_serial(ser, linea1, linea2):
    ser.write((linea1 + "\n").encode())
    time.sleep(0.2)
    ser.write((linea2 + "\n").encode())

def limpiar_y_reiniciar(ser):
    print("Reiniciando sistema...")
    ser.write(("LIMPIANDO...\n").encode())
    time.sleep(2)
    ser.reset_input_buffer()
    ser.reset_output_buffer()

if __name__ == "__main__":
    while True:
        try:
            with serial.Serial(puerto_serial, baudrate, timeout=1) as ser:
                time.sleep(2)

                # Enviar datos del sistema al iniciar
                info = obtener_info_sistema()
                ser.write((info + "\n").encode())
                print("Info enviada:", info)

                buffer = ""

                while True:
                    if keyboard.is_pressed('esc'):
                        print("Finalizando por ESC...")
                        break

                    event = keyboard.read_event()
                    if event.event_type == keyboard.KEY_DOWN:
                        tecla = event.name
                        if tecla == "space":
                            tecla = " "
                        elif len(tecla) > 1:
                            tecla = f"<{tecla}>"
                        buffer += tecla

                        # Limitar a últimos 32 caracteres para scroll
                        buffer_scroll = buffer[-32:]
                        ser.write((buffer_scroll + "\n").encode())
                        print("Enviado:", buffer_scroll)

                        # Si se alcanzan 100 caracteres: reiniciar
                        if len(buffer) >= 100:
                            limpiar_y_reiniciar(ser)
                            break  # sale del loop y reinicia desde cero

        except Exception as e:
            print("ERROR:", e)
            time.sleep(3)

Paso 4

Conectar el Arduino al PC

Ejecutar el Script en Python

Resultado Final

El Display LCD mostrará los datos capturados del teclado, la hora, el usuario y el sistema operativo. Asi mismo reiniciará su buffer por cada 100 caracteres enviados.

Entregable a presentar

Mejorar el proyecto para que el LCD muestre también la dirección IP del equipo y el Hostname en la primera línea sin perder la captura del teclado en la segunda línea.


Presentar su informe por correo al instructor detallando Integrantes, Materiales, Procedimiento y el código de Arduino y Pyhton explicado.