Control Digital de Velocidad y Sentido de Giro con Pulsadores para Motor DC

 Control Digital de Velocidad y Sentido de Giro con Pulsadores para Motor DC

En esta publicación llevaremos nuestro controlador de motor DC a su versión más completa y versátil. Añadiremos un sistema de control de velocidad por pasos mediante dos pulsadores adicionales (incrementar y decrementar velocidad), manteniendo el cambio de sentido de giro con transición segura mediante un tercer pulsador.

1. Arquitectura del Esquema Electrónico



Como se aprecia en la imagen de la simulación en Proteus, el circuito integra la interfaz de entrada y la etapa de potencia conectadas al NodeMCU (ESP8266):

  • Pulsadores de Entrada (Lógica Pull-Up):

    • Cambio de Sentido (Pin D2 / GPIO4): Conectado al primer pulsador de la izquierda.

    • Incrementar Velocidad (Pin D4 / GPIO2): Conectado al pulsador central.

    • Decrementar Velocidad (Pin D6 / GPIO12): Conectado al pulsador de la derecha.

  • Etapa Adaptadora de Nivel (Transistores NPN):

    • Salida PWM1 (Pin D3 / GPIO0): Excita la base de Q5 (2N2222) mediante R9 (1 kΩ) con resistencia de pull-up R8 (1 kΩ a +VCC) para conmutar la primera rama del puente H.

    • Salida R10(1) (Pin D5 / GPIO14): Excita la base de Q6 (2N2222) mediante R11 (1 kΩ) con resistencia de pull-up R10 (1 kΩ a +VCC) para conmutar la rama opuesta del puente H.

  • Etapa de Potencia: Transistores TIP32 (PNP) y TIP41 (NPN) configurados en puente H con diodos de protección en antiparalelo (1N4007) para absorber la fuerza electromotriz del motor DC.

2. Código Fuente en Arduino IDE

C++
// Pines de salida PWM conectados al Puente H
const int pinGiroA = 3; // Salida PWM Sentido A (D3 / GPIO0)
const int pinGiroB = 5; // Salida PWM Sentido B (D5 / GPIO14)

// Pines de entrada para los pulsadores
const int pinPulsadorGiro = 2; // Pulsador Cambio de Sentido (D2 / GPIO4)
const int pinSubirVel      = 4; // Pulsador + Velocidad (D4 / GPIO2)
const int pinBajarVel      = 6; // Pulsador - Velocidad (D6 / GPIO12)

// Configuración de la señal PWM (500 Hz -> Período = 2000 microsegundos)
const unsigned long periodoTotalUs = 2000; 

// Tabla de 8 pasos de velocidad (valores de 0 a 255)
// Paso 0 = Motor detenido, Paso 7 = Velocidad máxima (~100% PWM)
const int pasosVelocidad[8] = {0, 35, 70, 105, 140, 175, 210, 255};
int nivelVelocidadActual = 2; // Inicia en el Paso 2 (PWM = 70)

// Variables de tiempo para PWM
unsigned long tiempoON = 0;
unsigned long ultimoTiempoMicros = 0;

// Estado del sistema y antirrebotes de los pulsadores
bool sentidoActual = true; // true = Giro A, false = Giro B

bool antGiro  = HIGH;
bool antSubir = HIGH;
bool antBajar = HIGH;

void setup() {
  pinMode(pinGiroA, OUTPUT);
  pinMode(pinGiroB, OUTPUT);
  
  // Configuración de las entradas con resistencia interna Pull-Up
  pinMode(pinPulsadorGiro, INPUT_PULLUP);
  pinMode(pinSubirVel, INPUT_PULLUP);
  pinMode(pinBajarVel, INPUT_PULLUP);

  // Calcular el tiempo activo inicial
  tiempoON = (periodoTotalUs * pasosVelocidad[nivelVelocidadActual]) / 255;
}

void loop() {
  // --- LECTURA DE ESTADO DE LOS PULSADORES ---
  bool lectGiro  = digitalRead(pinPulsadorGiro);
  bool lectSubir = digitalRead(pinSubirVel);
  bool lectBajar = digitalRead(pinBajarVel);

  // 1. CAMBIO DE SENTIDO DE GIRO (Flanco de bajada)
  if (antGiro == HIGH && lectGiro == LOW) {
    digitalWrite(pinGiroA, LOW);
    digitalWrite(pinGiroB, LOW);
    delay(500); // Pausa de seguridad para disipar inercia
    sentidoActual = !sentidoActual;
    ultimoTiempoMicros = micros();
  }
  antGiro = lectGiro;

  // 2. INCREMENTAR VELOCIDAD CON TOPE SUPERIOR
  if (antSubir == HIGH && lectSubir == LOW) {
    if (nivelVelocidadActual < 7) { // Tope máximo: Paso 7
      nivelVelocidadActual++;
      tiempoON = (periodoTotalUs * pasosVelocidad[nivelVelocidadActual]) / 255;
    }
  }
  antSubir = lectSubir;

  // 3. DECREMENTAR VELOCIDAD CON TOPE INFERIOR
  if (antBajar == HIGH && lectBajar == LOW) {
    if (nivelVelocidadActual > 0) { // Tope mínimo: Paso 0
      nivelVelocidadActual--;
      tiempoON = (periodoTotalUs * pasosVelocidad[nivelVelocidadActual]) / 255;
    }
  }
  antBajar = lectBajar;

  // --- GENERACIÓN DE PWM NO BLOQUEANTE SEGÚN EL SENTIDO ---
  unsigned long tiempoActual = micros();
  unsigned long tiempoTranscurrido = tiempoActual - ultimoTiempoMicros;

  if (sentidoActual) {
    digitalWrite(pinGiroB, LOW);

    if (tiempoTranscurrido < tiempoON) {
      digitalWrite(pinGiroA, HIGH);
    } else if (tiempoTranscurrido < periodoTotalUs) {
      digitalWrite(pinGiroA, LOW);
    } else {
      ultimoTiempoMicros = tiempoActual;
    }
  } else {
    digitalWrite(pinGiroA, LOW);

    if (tiempoTranscurrido < tiempoON) {
      digitalWrite(pinGiroB, HIGH);
    } else if (tiempoTranscurrido < periodoTotalUs) {
      digitalWrite(pinGiroB, LOW);
    } else {
      ultimoTiempoMicros = tiempoActual;
    }
  }
}

3. Explicación Detallada del Código

  • Matriz de Velocidades (pasosVelocidad[8]): Arreglo con 8 niveles discretos de ancho de pulso (0, 35, 70, 105, 140, 175, 210, 255). Permite ajustar el ciclo de trabajo desde motor totalmente detenido (0%) hasta marcha completa (100%).

  • Validación de Límites (Topes de Velocidad): Las condiciones if (nivelVelocidadActual < 7) e if (nivelVelocidadActual > 0) actúan como barreras lógicas. Evitan desbordamientos del índice del arreglo al pulsar repetidamente los botones de incremento o decremento.

  • Detección por Flanco de Bajada: Comparar el estado anterior (antSubir) con el actual (lectSubir) detecta el instante preciso en que la señal pasa de HIGH a LOW. Esto asegura que se procese únicamente un paso por cada pulsación física.

  • Transición Segura en Inversión de Giro: Al detectar la orden en D2, el programa fija inmediatamente ambas salidas a LOW y aplica una pausa de 500 ms (delay(500)). Esto detiene la conducción en los transistores TIP32 y TIP41, permitiendo que la inercia del motor y la fuerza electromotriz se reduzcan antes de energizar la rama opuesta.

  • PWM No Bloqueante mediante micros(): Al controlar la duración del pulso activo (tiempoON) de forma matemática en el loop(), se obtiene un tren de pulsos cuadrado perfecto en el osciloscopio virtual (a 500 Hz), manteniendo el procesador receptivo a cualquier entrada de pulsador sin retardos.

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