# =============================================================================
# UNIVERSIDAD INTERNACIONAL DE LA RIOJA (UNIR) - MAESTRÍA INDUSTRIA 4.0
# Autor: [Tu Nombre] - Versión: 2.3 - Fecha: [28/04/2025]
# =============================================================================
# DESCRIPCIÓN: Control avanzado de servo motor con ESP32 mediante MicroPython.
# - Movimiento angular preciso (0° a 180°) con PWM de 16 bits
# - Configuración personalizable de velocidades de barrido
# - Protección integrada contra ángulos inválidos
# - Lógica térmica deshabilitada (sección comentada como referencia)
# - Operación en bucle continuo con modo bajo consumo
# =============================================================================
from machine import Pin, PWM # Módulos para control GPIO y PWM
import time # Funciones de tiempo y delays
SERVO_PIN = 15 # GPIO para conexión del servo (D15 en ESP32)
PWM_FREQ = 50 # Frecuencia PWM estándar (50Hz = periodo 20ms)
PWM_BITS = 16 # Resolución de 16 bits para precisión
MAX_DUTY = 65535 # Valor máximo duty cycle (2^16 - 1)
MIN_PULSE_US = 500 # Ancho mínimo de pulso para 0° (500μs)
MAX_PULSE_US = 2400 # Ancho máximo de pulso para 180° (2400μs)
PWM_PERIOD_US = 20000 # Periodo completo PWM (20ms)
SPEED_0_TO_180 = 20 # Tiempo entre pasos ascendentes (20ms/°)
SPEED_180_TO_0 = 1 # Tiempo entre pasos descendentes (1ms/°)
servo = PWM( # Configurar PWM para servo
Pin(SERVO_PIN), # Usar pin físico especificado
freq=PWM_FREQ, # Establecer frecuencia a 50Hz
duty_u16=0 # Iniciar en duty cycle 0 (0°)
)
def set_angle(angle):
"""Control preciso de posición angular con protección integrada"""
angle = max(0, min(180, angle)) # Limitar ángulo entre 0-180°
pulse_us = MIN_PULSE_US + (angle * (MAX_PULSE_US - MIN_PULSE_US) / 180) # Calcular μs
duty_value = int(pulse_us * MAX_DUTY / PWM_PERIOD_US) # Convertir a valor 16 bits
servo.duty_u16(duty_value) # Aplicar valor al registro PWM
def servo_0():
"""Bucle principal con lógica de movimiento continuo"""
motor_activo = True # Estado inicial de operación
while True: # Bucle infinito de control
# Lógica térmica deshabilitada (conservar como referencia):
# if temperatura_actual > (UMBRAL_TEMP + HISTERESIS): motor_activo = True
# elif temperatura_actual < (UMBRAL_TEMP - HISTERESIS): motor_activo = False
if motor_activo: # Modo de operación activo
for ang in range(0, 181, 1): # Barrido ascendente 0°→180°
set_angle(ang) # Actualizar posición
time.sleep_ms(SPEED_0_TO_180) # Mantener velocidad subida
if not motor_activo: break # Salida anticipada por cambio estado
for ang in range(180, -1, -1): # Barrido descendente 180°→0°
set_angle(ang) # Actualizar posición
time.sleep_ms(SPEED_180_TO_0) # Máxima velocidad bajada
if not motor_activo: break # Salida anticipada por cambio estado
else: # Modo de reposo/bajo consumo
set_angle(0) # Posición segura en 0°
time.sleep_ms(100) # Ciclo de espera eficiente
servo_0() # Iniciar bucle principal (NOTA: Operación bloqueante)