Control Interactivo de Motor Paso a Paso con NodeMCU/Arduino - Programación No Bloqueante, Inversión de Giro y Control de Velocidad

Control Interactivo de Motor Paso a Paso con NodeMCU/Arduino - Programación No Bloqueante, Inversión de Giro y Control de Velocidad

En esta entrega evolucionaremos nuestro sistema de control para motores paso a paso unipolares. Migraremos de una secuencia rígida hacia una interfaz interactiva y multitarea, utilizando la función millis() para evitar el uso de funciones bloqueantes como delay(). Esto permitirá al microcontrolador atender en tiempo real las peticiones de 4 pulsadores físicos mientras mantiene el motor en movimiento continuo.

1. Interfaz de Usuario e Integración en Protoboard

Para esta práctica se incorporan 4 pulsadores táctiles conectados a las entradas D0, D1, D2 y D3 del NodeMCU (o pines digitales 0, 1, 2 y 3 en entornos genéricos). Cada entrada se configura mediante la resistencia interna de pull-up (INPUT_PULLUP), requiriendo únicamente conectar el otro extremo del pulsador a masa (GND):



  • D0 (S-GIRO): Invierte el sentido de giro del motor (Horario / Antihorario). Para evitar daños mecánicos o brincos bruscos de corriente en el driver, el programa realiza una pausa de seguridad de 300 ms antes de conmutar la secuencia.

  • D1 (+VEL): Incrementa la velocidad de rotación reduciendo el intervalo de tiempo entre pasos (pasoDelay).

  • D2 (-VEL): Disminuye la velocidad de rotación aumentando el intervalo entre pasos.

  • D3 (ON-OFF): Activa o pausa la marcha del motor de forma inmediata, apagando todas las fases para evitar consumo innecesario en reposo.

  • Filtro Anti-rebote (Debounce): Implementado por software con un temporizador de 200 ms, garantizando que cada pulsación sea leída una sola vez sin falsos disparos provocados por el rebote mecánico.

2. Mapeo de Conexiones y Display de Estados

  1. Entradas de Control: Conectar los 4 pulsadores entre los pines D0, D1, D2, D3 y la línea común de GND.

  2. Display de LEDs: Mantener la etapa de visualización con 4 LEDs (D5, D6, D7, D8) y sus resistencias limitadoras de 330 ohms conectados en paralelo a las salidas de fase A, B, C y D.

  3. Driver de Potencia: Conectar las líneas de control A, B, C y D hacia la tira de pines del driver discreto (transistores NPN 2N2222 y diodos 1N4007).

  4. Alimentación y Masa Común: Alimentar el driver a través de la bornera azul e interconectar obligatoriamente la masa (GND) de la fuente de alimentación, del microcontrolador y del protoboard.



3. Código Fuente Completo (Multitarea No Bloqueante)

C++
// --- PINES DE SALIDA PARA FASES DEL MOTOR (D5, D6, D7, D8) ---
const int motorPins[4] = {5, 6, 7, 8};

// --- PINES DE ENTRADA PARA PULSADORES (D0, D1, D2, D3) ---
const int pinInvertir  = 0; // D0: Invertir sentido de giro
const int pinVelMas    = 1; // D1: Incrementar velocidad
const int pinVelMenos  = 2; // D2: Decrementar velocidad
const int pinStartStop = 3; // D3: Marcha / Parada

// --- MATRIZ DE SECUENCIA WAVE DRIVE ---
const int waveDrive[4][4] = {
  {HIGH, LOW,  LOW,  LOW},  // Paso 0
  {LOW,  HIGH, LOW,  LOW},  // Paso 1
  {LOW,  LOW,  HIGH, LOW},  // Paso 2
  {LOW,  LOW,  LOW,  HIGH}   // Paso 3
};

// --- CONTROL DE VELOCIDAD Y ESTADO ---
int pasoDelay = 100;          // Tiempo inicial por paso (100 ms)
const int pasoDelayMin = 10;  // Velocidad máxima (10 ms entre pasos)
const int pasoDelayMax = 500; // Velocidad mínima (500 ms entre pasos)
const int pasoDelta = 15;     // Factor de cambio de velocidad (15 ms)

int pasoActual = 0;
bool sentidoHorario = true;
bool motorActivo = true;

// --- VARIABLES DE TIEMPO (MILLIS) ---
unsigned long ultimoTiempoPaso = 0;
unsigned long ultimoTiempoBtn  = 0;
const unsigned long tiempoDebounceMs = 200; // Anti-rebote por software

void apagarMotor() {
  for (int i = 0; i < 4; i++) {
    digitalWrite(motorPins[i], LOW);
  }
}

void aplicarPaso(int paso) {
  for (int i = 0; i < 4; i++) {
    digitalWrite(motorPins[i], waveDrive[paso][i]);
  }
}

void setup() {
  // Configurar las 4 salidas del motor
  for (int i = 0; i < 4; i++) {
    pinMode(motorPins[i], OUTPUT);
  }
  apagarMotor();

  // Configurar las 4 entradas con Pull-up interna
  pinMode(pinInvertir, INPUT_PULLUP);
  pinMode(pinVelMas, INPUT_PULLUP);
  pinMode(pinVelMenos, INPUT_PULLUP);
  pinMode(pinStartStop, INPUT_PULLUP);
}

void loop() {
  unsigned long tiempoActual = millis();

  // =========================================================
  // 1. LECTURA Y PROCESAMIENTO DE PULSADORES (ANTI-REBOTE)
  // =========================================================
  if (tiempoActual - ultimoTiempoBtn >= tiempoDebounceMs) {

    // --- PULSADOR D0: INVERTIR SENTIDO DE GIRO ---
    if (digitalRead(pinInvertir) == LOW) {
      motorActivo = false; // Pausa temporal
      apagarMotor();
      delay(300);          // Pausa de seguridad (300 ms)
      
      sentidoHorario = !sentidoHorario; // Cambiar sentido
      motorActivo = true;
      ultimoTiempoBtn = tiempoActual;
    }

    // --- PULSADOR D1: INCREMENTAR VELOCIDAD ---
    else if (digitalRead(pinVelMas) == LOW) {
      pasoDelay -= pasoDelta;
      if (pasoDelay < pasoDelayMin) pasoDelay = pasoDelayMin;
      ultimoTiempoBtn = tiempoActual;
    }

    // --- PULSADOR D2: DECREMENTAR VELOCIDAD ---
    else if (digitalRead(pinVelMenos) == LOW) {
      pasoDelay += pasoDelta;
      if (pasoDelay > pasoDelayMax) pasoDelay = pasoDelayMax;
      ultimoTiempoBtn = tiempoActual;
    }

    // --- PULSADOR D3: MARCHA / PARADA ---
    else if (digitalRead(pinStartStop) == LOW) {
      motorActivo = !motorActivo;
      if (!motorActivo) apagarMotor();
      ultimoTiempoBtn = tiempoActual;
    }
  }

  // =========================================================
  // 2. GENERACIÓN DE SECUENCIA NO BLOQUEANTE PARA EL MOTOR
  // =========================================================
  if (motorActivo && (tiempoActual - ultimoTiempoPaso >= (unsigned long)pasoDelay)) {
    ultimoTiempoPaso = tiempoActual;

    // Incrementar o decrementar el paso según el sentido de giro
    if (sentidoHorario) {
      pasoActual = (pasoActual + 1) % 4;
    } else {
      pasoActual = (pasoActual - 1 + 4) % 4;
    }

    aplicarPaso(pasoActual);
  }
}

4. Análisis de Funcionamiento

Al ejecutar la simulación en Proteus o en el circuito físico:

  • El temporizador basado en millis() compara continuamente el tiempo transcurrido, permitiendo que la lectura de las entradas sea instantánea sin interrumpir la secuencia de conmutación.

  • Pulsar S-GIRO conmuta la dirección de barrido de la matriz (Paso 0->1->2->3 o Paso 3->2->1->0), invirtiendo el giro físico del motor.

  • Los pulsadores +VEL y -VEL ajustan dinámicamente la variable pasoDelay entre sus límites configurados (10 ms a 500 ms), acelerando o ralentizando la secuencia visualizada en el banco de LEDs.

  • El pulsador ON-OFF ofrece control de parada inmediata desenergizando todas las bobinas para proteger los transistores en periodos de inactividad.

Comentarios

Entradas populares de este blog

FUENTE DC CON PROTECCIÓN ELECTRÓNICA E INDICADORES LED

Control de velocidad y sentido de giro de un motor de corriente continua

Controlador de giro para motor paso a paso unipolar mediante 555, contador y lógica combinacional