PC controlado por gestos con Arduino y Python: Operación manos libres
Componentes y suministros
| Arduino UNO | × | 1 |
| Sensor ultrasónico HC-SR04 (Genérico) | × | 2 |
| Cables jumper (genéricos) | × | 1 |
Aplicaciones y servicios en línea
- Arduino IDE
- Python IDLE
- Librería PySerial
- Librería PyAutoGUI
Sobre este proyecto
En este proyecto, aprenderemos a construir portátiles u ordenadores controlados por gestos. Se basa en la combinación de Arduino y Python.
En lugar de usar teclado, ratón o joystick, podemos usar gestos de la mano para controlar ciertas funciones del ordenador como reproducir/pausar un vídeo, mover izquierda/derecha en una presentación de fotos, desplazarse arriba/abajo en una página web y mucho más. Por eso decidí controlar VLC Media Player como proyecto de gestos manuales.
La idea es bastante fácil usando dos sensores ultrasónicos (HC-SR04) con Arduino. Colocaremos los dos sensores en la parte superior de la pantalla del portátil y calcularemos la distancia entre la mano y el sensor. Basándonos en la información de Arduino que se envía a Python a través del puerto serie, esta información será leída por Python que se ejecuta en el ordenador para realizar ciertas acciones.
Componentes hardware:
- Arduino
- Dos sensores ultrasónicos (HC-SR04)
- Algunos cables
Apps de software:
- Arduino IDE
- Python IDLE
- Librería PySerial (para comunicar con puertos serie).
- Librería PyAutoGUI (para realizar acciones).
Asumo que ya tienes Python y PySerial instalados y has hecho algunos proyectos básicos. Si no, no te preocupes; te aconsejo seguir mi tutorial anterior (Programar Arduino usando Python). También si quieres familiarizarte con el sensor ultrasónico, puedes echar un vistazo aquí.
Paso 1: Ver el vídeo para más detalles
Paso 2: Propósito de los gestos manuales
Los siguientes son los 5 comandos de gestos que he programado para demostración:
- Primer gesto: Permite 'Play/Pausa' en VLC colocando las dos manos frente al sensor ultrasónico derecho/izquierdo a una distancia lejana determinada.
- Segundo gesto: Permite 'Rebobinar' el vídeo colocando una mano frente al sensor izquierdo a una distancia lejana determinada.
- Tercer gesto: Permite 'Adelantar' el vídeo colocando una mano frente al sensor derecho a una distancia lejana determinada.
- Cuarto gesto: Permite 'Subir volumen' colocando una mano frente al sensor izquierdo a una distancia lejana y alejándose del sensor.
- Quinto gesto: Permite 'Bajar volumen' colocando una mano frente al sensor izquierdo a una distancia lejana y acercándose al sensor.
Paso 3: Esquemático
El esquemático es bastante simple, solo sigue las instrucciones. Cada sensor tiene 4 pines:
- Vcc - conectado a 5V+.
- Trig - definir este pin en tu programa.
- Echo - igual que Trig, definirlo también.
- GND - conectado a tierra.
Paso 4: Programar Python
1. Instalar Python IDLE
Puedes saltar este paso si ya tienes Python IDLE instalado. Si sí, ve al paso 2, sino sigue las instrucciones.
- Ve a la web de Python y descárgalo (aquí).
- Una vez descargado, instálalo manteniendo el directorio por defecto.
NOTA: Aunque tu ordenador sea de 64 bits, puedes usar Python de 32 bits debido a la falta de compatibilidad con librerías de Arduino.
2. Instalar librería PySerial
PySerial es un módulo API de Python para leer y escribir datos serie en Arduino u otro microcontrolador. Para instalar en Windows, visita la página de descarga de PySerial y sigue los pasos:
- Descarga PySerial desde el enlace.
- Instálalo manteniendo la configuración por defecto. Debes asegurar que PySerial funciona correctamente. Para ello, escribe:
import serial
Si no hay error, todo bien. Sino, revisa tu instalación y extensión de Python IDLE.
3. Instalar librería PyAutoGUI
El propósito de PyAutoGUI es proporcionar un módulo Python multiplataforma para automatización de GUI para humanos. La API está diseñada para ser lo más simple posible con valores por defecto sensatos. Sigue los pasos para instalar pyautogui en Windows. (Para seguir estos pasos ya debes tener Python IDLE instalado).
Si usas otras plataformas, te aconsejo ver aquí.
- Abre Símbolo del sistema de Windows
- Escribe el siguiente comando
cd C:\Python27
- Luego escribe:
python –m pip install –upgrade pip
- El último comando es:
python –m pip install pyautogui
NOTA: Para asegurar que pyautogui funciona, escribe:
import pyautogui
Si no hay error, todo bien.
Paso 5: Código Arduino
Para iniciar una conexión con Arduino desde Python, primero averiguamos en qué puerto COM está el Arduino. Esto se hace fácilmente con el entorno de programación de Arduino como se muestra en la imagen.
const int trigger1 = 2; //Pin Trigger del 1er Sensor
const int echo1 = 3; //Pin Echo del 1er Sensor
const int trigger2 = 4; //Pin Trigger del 2do Sensor
const int echo2 = 5; //Pin Echo del 2do Sensor
long time_taken;
int dist, distL, distR;
void setup() {
Serial.begin(9600);
pinMode(trigger1, OUTPUT);
pinMode(echo1, INPUT);
pinMode(trigger2, OUTPUT);
pinMode(echo2, INPUT);
}
/*### Función para calcular distancia ###*/
void calculate_distance(int trigger, int echo) {
digitalWrite(trigger, LOW);
delayMicroseconds(2);
digitalWrite(trigger, HIGH);
delayMicroseconds(10);
digitalWrite(trigger, LOW);
time_taken = pulseIn(echo, HIGH);
dist = time_taken * 0.034 / 2;
if (dist > 60) dist = 60;
}
void loop() {
// Bucle infinito
calculate_distance(trigger1, echo1);
distL = dist; // obtener distancia sensor izquierdo
calculate_distance(trigger2, echo2);
distR = dist; // obtener distancia sensor derecho
// Modo Pausa - Mantener
if ((distL > 40 && distR > 40) && (distL < 60 && distR < 60)) // Detectar ambas manos
{
Serial.println("Play/Pause");
delay(500);
}
calculate_distance(trigger1, echo1);
distL = dist;
calculate_distance(trigger2, echo2);
distR = dist;
// Modos de Control
// Bloqueo Izquierdo - Modo Control
if (distL >= 13 && distL <= 17) {
delay(100); // Tiempo de retención de mano
calculate_distance(trigger1, echo1);
distL = dist;
if (distL >= 13 && distL <= 17) {
Serial.println("Left Locked");
while (distL <= 40) {
calculate_distance(trigger1, echo1);
distL = dist;
if (distL < 10) // Mano empujada hacia adentro
{
Serial.println("Volume Increased");
delay(300);
}
if (distL > 20) // Mano retirada
{
Serial.println("Volume Decreased");
delay(300);
}
}
}
}
// Bloqueo Derecho - Modo Control
if (distR >= 13 && distR <= 17) {
delay(100); // Tiempo de retención de mano
calculate_distance(trigger2, echo2);
distR = dist;
if (distR >= 13 && distR <= 17) {
Serial.println("Right Locked");
while (distR <= 40) {
calculate_distance(trigger2, echo2);
distR = dist;
if (distR < 10) // Mano derecha empujada
{
Serial.println("Rewind");
delay(300);
}
if (distR > 20) // Mano derecha retirada
{
Serial.println("Forward");
delay(300);
}
}
}
}
delay(200);
}
Si lees el código de Arduino, observarás 5 comandos que controlan ciertas funciones de teclado para lograr la tarea requerida.
arduino_pythogui.ino (Descargar)
Paso 6: Código Python
Primero, necesitamos un programa simple para que Python envíe datos por el puerto serie.
import serial #Serial importado para comunicación serie
import time #Requerido para funciones de delay
import pyautogui #Requerido para realizar acciones
ArduinoSerial = serial.Serial('com15', 9600) #Crear objeto puerto serie llamado arduinoSerialData
time.sleep(2) #esperar 2 segundos para que la comunicación se establezca
while 1:
incoming = str(ArduinoSerial.readline()) #leer datos serie e imprimir como línea
print(incoming)
if 'Play/Pause' in incoming:
pyautogui.typewrite(['space'], 0.2)
if 'Rewind' in incoming:
pyautogui.hotkey('ctrl', 'left')
if 'Forward' in incoming:
pyautogui.hotkey('ctrl', 'right')
if 'Volume Increased' in incoming:
pyautogui.hotkey('ctrl', 'down')
if 'Volume Decreased' in incoming:
pyautogui.hotkey('ctrl', 'up')
incoming = "";
Código
- Fragmento de código #5 (Arduino)
- Fragmento de código #6 (Python)
Fragmento de código #5 Texto plano
const int trigger1 = 2; //Pin Trigger del 1er Sensor
const int echo1 = 3; //Pin Echo del 1er Sensor
const int trigger2 = 4; //Pin Trigger del 2do Sensor
const int echo2 = 5; //Pin Echo del 2do Sensor
long time_taken;
int dist, distL, distR;
void setup() {
Serial.begin(9600);
pinMode(trigger1, OUTPUT);
pinMode(echo1, INPUT);
pinMode(trigger2, OUTPUT);
pinMode(echo2, INPUT);
}
/*### Función para calcular distancia ###*/
void calculate_distance(int trigger, int echo) {
digitalWrite(trigger, LOW);
delayMicroseconds(2);
digitalWrite(trigger, HIGH);
delayMicroseconds(10);
digitalWrite(trigger, LOW);
time_taken = pulseIn(echo, HIGH);
dist = time_taken * 0.034 / 2;
if (dist > 60) dist = 60;
}
void loop() {
calculate_distance(trigger1, echo1);
distL = dist;
calculate_distance(trigger2, echo2);
distR = dist;
if ((distL > 40 && distR > 40) && (distL < 60 && distR < 60)) {
Serial.println("Play/Pause");
delay(500);
}
calculate_distance(trigger1, echo1);
distL = dist;
calculate_distance(trigger2, echo2);
distR = dist;
if (distL >= 13 && distL <= 17) {
delay(100);
calculate_distance(trigger1, echo1);
distL = dist;
if (distL >= 13 && distL <= 17) {
Serial.println("Left Locked");
while (distL <= 40) {
calculate_distance(trigger1, echo1);
distL = dist;
if (distL < 10) {
Serial.println("Volume Increased");
delay(300);
}
if (distL > 20) {
Serial.println("Volume Decreased");
delay(300);
}
}
}
}
if (distR >= 13 && distR <= 17) {
delay(100);
calculate_distance(trigger2, echo2);
distR = dist;
if (distR >= 13 && distR <= 17) {
Serial.println("Right Locked");
while (distR <= 40) {
calculate_distance(trigger2, echo2);
distR = dist;
if (distR < 10) {
Serial.println("Rewind");
delay(300);
}
if (distR > 20) {
Serial.println("Forward");
delay(300);
}
}
}
}
delay(200);
}
Fragmento de código #6 Texto plano
import serial
import time
import pyautogui
ArduinoSerial = serial.Serial('com15', 9600)
time.sleep(2)
while 1:
incoming = str(ArduinoSerial.readline())
print(incoming)
if 'Play/Pause' in incoming:
pyautogui.typewrite(['space'], 0.2)
if 'Rewind' in incoming:
pyautogui.hotkey('ctrl', 'left')
if 'Forward' in incoming:
pyautogui.hotkey('ctrl', 'right')
if 'Volume Increased' in incoming:
pyautogui.hotkey('ctrl', 'down')
if 'Volume Decreased' in incoming:
pyautogui.hotkey('ctrl', 'up')
incoming = "";
Proceso de manufactura
- Crea un Impresionante Sistema Ambilight para Monitor con Arduino
- Mando universal Android con Arduino, 1Sheeld y control IR
- Construye un Voltímetro Inteligente con Arduino y Smartphone – Proyecto DIY Fácil
- Control Remoto IoT de Brazo Robótico Personalizado con Arduino MKR1000 y ThingSpeak
- Medición precisa de frecuencia y ciclo de trabajo con Arduino UNO
- Controla un Rover Arduino con Firmata y Mando Xbox One - Guía Completa
- Pistola de Agua Inteligente Activada por Movimiento con Arduino Nano
- Control de brillo LED sin interrupciones con Bolt IoT y Arduino UNO
- Brazo Robótico Inteligente Controlado por Arduino: Tutorial DIY Fácil
- Controla tu TV con Alexa mediante Arduino IoT Cloud: Guía Paso a Paso
- Construye una Radio FM Compacta con Arduino Nano y RDA5807M