Control Digital de Posición para Servomotor con NodeMCU (ESP8266) - Parte 2: Interacción Manual por Pulsadores y Filtrado Anti-rebote
Control Digital de Posición para Servomotor con NodeMCU (ESP8266) - Parte 2: Interacción Manual por Pulsadores y Filtrado Anti-rebote
En esta segunda entrega daremos vida a la interfaz de usuario, añadiendo control manual directo sobre la posición del servomotor mediante dos pulsadores físicos. Analizaremos cómo procesar las entradas digitales en el NodeMCU (ESP8266) y cómo se reflejan estos cambios en el ancho de pulso PWM mediante las capturas del osciloscopio en Proteus.
1. Configuración de Entradas Digitales y Filtro Anti-rebote (Debounce)
Para capturar la interacción del usuario se utilizan los pines D2 (para incrementar el ángulo) y D1 (para decrementar el ángulo).
Resistencias Pull-up Internas: Las entradas se configuran con
INPUT_PULLUP. Al estar en reposo, el pin detecta un valor ALTO (3.3V). Al presionar el pulsador, el pin se conecta a GND y la lectura conmuta a nivel BAJO (0V).Control Anti-rebote por Software: Todo pulsador mecánico presenta pequeñas vibraciones elásticas (chattering) al presionarse. Para evitar que una sola pulsación genere múltiples saltos de ángulo, implementamos un filtro temporal de 200 ms utilizando la función
millis(), descartando falsos disparos sin bloquear el ciclo de generación del PWM.Resolución del Paso: Se estableció un salto discreto de 15° por pulsación, lo que divide el rango dinámico de 0° a 180° en 12 posiciones claramente diferenciables.
2. Código Fuente Completo (Control Interactivo)
// --- PINES DE ENTRADA Y SALIDA ---
const int pinServo = 3; // Pin D3 -> Base del transistor 2N2222
const int pinBtnMas = 2; // Pin D2 -> Pulsador (+)
const int pinBtnMenos = 1; // Pin D1 -> Pulsador (-)
// --- CONFIGURACIÓN DE SEÑAL PWM ---
const unsigned long periodoTotalUs = 20000; // 50 Hz (20 ms)
const unsigned long pulsoMinUs = 1000; // 1 ms -> 0°
const unsigned long pulsoMaxUs = 2000; // 2 ms -> 180°
// --- PARÁMETROS DEL SERVOMOTOR ---
int anguloActual = 90; // Posición inicial centrada (90°)
const int pasoAngulo = 15; // Incremento/Decremento por pulsación (15°)
// --- VARIABLES DE TIEMPO Y CONTROL ---
unsigned long tiempoBajoUs = 0;
unsigned long ultimoTiempoMicros = 0;
// Anti-rebote (Debounce)
unsigned long ultimoTiempoBtn = 0;
const unsigned long tiempoDebounceMs = 200; // Intervalo mínimo entre lecturas (200 ms)
void actualizarAnchoPulso() {
// Mapear el ángulo actual (0 - 180°) a microsegundos (1000 - 2000 us)
unsigned long anchoPulsoServoUs = map(anguloActual, 0, 180, pulsoMinUs, pulsoMaxUs);
// Transistor NPN inversor:
// Para tener ALTO en el servo, la salida del pin DEBE estar en LOW
tiempoBajoUs = anchoPulsoServoUs;
}
void setup() {
pinMode(pinServo, OUTPUT);
digitalWrite(pinServo, HIGH); // Reposo inicial (Transistor saturado -> Servo en LOW)
// Configurar entradas con Pull-up interna (Pulsador presionado = LOW)
pinMode(pinBtnMas, INPUT_PULLUP);
pinMode(pinBtnMenos, INPUT_PULLUP);
actualizarAnchoPulso();
}
void loop() {
unsigned long tiempoActualUs = micros();
unsigned long tiempoActualMs = millis();
// --- 1. LECTURA DE PULSADORES (CON ANTI-REBOTE) ---
if (tiempoActualMs - ultimoTiempoBtn >= tiempoDebounceMs) {
// Incrementar ángulo (+)
if (digitalRead(pinBtnMas) == LOW) {
anguloActual += pasoAngulo;
if (anguloActual > 180) anguloActual = 180; // Límite superior
actualizarAnchoPulso();
ultimoTiempoBtn = tiempoActualMs;
}
// Decrementar ángulo (-)
else if (digitalRead(pinBtnMenos) == LOW) {
anguloActual -= pasoAngulo;
if (anguloActual < 0) anguloActual = 0; // Límite inferior
actualizarAnchoPulso();
ultimoTiempoBtn = tiempoActualMs;
}
}
// --- 2. GENERACIÓN DE SEÑAL PWM INVERTIDA PARA EL TRANSISTOR NPN ---
unsigned long tiempoTranscurrido = tiempoActualUs - ultimoTiempoMicros;
if (tiempoTranscurrido < tiempoBajoUs) {
digitalWrite(pinServo, LOW); // Transistor CORTADO -> Entrada Servo HIGH (+5V)
}
else if (tiempoTranscurrido < periodoTotalUs) {
digitalWrite(pinServo, HIGH); // Transistor SATURADO -> Entrada Servo LOW (0V)
}
else {
ultimoTiempoMicros = tiempoActualUs; // Reiniciar el ciclo de 20 ms
}
}
3. Análisis de Resultados en Simulación (Proteus)
Al ejecutar la simulación y observar el osciloscopio virtual en el punto de prueba CNTROL (entrada del servomotor), comprobamos el comportamiento dinámico según las tres imágenes adjuntas:
Posición Inicial (90° / Centrado): Como se observa en la primera imagen, al arrancar el programa en 90°, el pulso en ALTO mide exactamente 1.5 ms dentro del período total de 20 ms. La aguja del servo marca su punto medio (-2.57° según el sistema de coordenadas relativas del modelo en Proteus).
Avance en Sentido Antihorario (Pulsador
+): Al presionar de forma consecutiva el pulsador+, el ancho de pulso en ALTO se incrementa progresivamente hacia los 2.0 ms. En la segunda imagen vemos el reflejo inmediato en el osciloscopio con un pulso en ALTO más ancho y el servo rotando hacia valores positivos (+58.2°).
Avance en Sentido Horario (Pulsador
-): Al accionar el pulsador-, el tiempo de pulso en ALTO se reduce hacia 1.0 ms. En la tercera imagen el osciloscopio muestra un pulso angosto en ALTO y el servomotor gira en sentido opuesto hasta alcanzar el tope inferior (-59.7°).
Con este desarrollo se consolida la transición de un control puramente analógico a una plataforma digital versátil, lista para incorporar conectividad WiFi o integración Web en futuras fases del proyecto.
Comentarios
Publicar un comentario