¡Crea tu Base Giratoria! con UNIT Pulsar ESP32-C6 y Motor a pasos 28BYJ-48

¡Crea tu Base Giratoria! con UNIT Pulsar ESP32-C6 y Motor a pasos 28BYJ-48

En este tutorial aprenderás a construir una base giratoria con un diámetro de 16 cm controlada con la UNIT Pulsar ESP32-C6, utilizando un motor a pasos 28BYJ-48, su controlador ULN2003, un potenciómetro para regular la velocidad y un botón para cambiar el sentido de giro.

El proyecto combina diseño e impresión 3D, electrónica y programación, dando como resultado una plataforma giratoria compacta y portátil que puedes utilizar para exhibir productos, grabar videos de objetos en 360°, realizar fotografía, crear pequeños proyectos de automatización o experimentar con motores a pasos.

La base incorpora una batería Li-Ion 18650 de 3.7 V, un módulo de carga y elevación de voltaje, puerto USB Tipo C e interruptor general, permitiendo utilizarla sin necesidad de mantenerla conectada a una computadora o fuente externa.

MATERIALES

Manos a la obra! Para construir la base giratoria necesitaremos los siguientes materiales:

Para facilitar el armado del proyecto, puedes consultar y adquirir lista materiales en el siguiente link:

Las piezas que forman la estructura de la base están diseñadas para impresión 3D. Puedes descargar los archivos e imprimirlos directamente:

¿No cuentas con una impresora 3D? Puedes utilizar nuestro servicio de impresión 3D para fabricar las piezas necesarias para este proyecto:


DIAGRAMA DE CONEXIÓN

A continuación se muestra el diagrama de conexión para la base giratoria. Se divide en 3 faces:

  1. Alimentación de energia
  2. Control de giro y velocidad
  3. Tarjeta de control

Utiliza el diagrama de conexión como referencia para realizar el cableado del proyecto, o sigue los siguientes recomendaciones de conexión para cada elemento que integra la base giratoria.

Alimentación

Para que la base sea portátil utilizamos una batería recargable Li-Ion 18650 de 3.7 V.

La batería se conecta al módulo de carga TP4056 con Boost Step Up:

Batería 18650Módulo TP4056 con Boost Step Up
PositivoBAT+
NegativoBAT−

Carga de batería

Para la carga de la base se utiliza un Conector USB Tipo C de chasis el cual se conecta:

USB-CMódulo TP4056 con Boost Step Up
PositivoIN+
NegativoIN−

El Módulo TP4056 con Boost Step Up debe ajustarse a 5V DC de salida con la ayuda del potenciómetro que integra y un multímetro, ya que esta salida se VOUT+ de 5V será la encargada de alimentar:

  • UNIT Pulsar ESP32-C6
  • Controlador ULN2003

Es importante que ajustes el Módulo TP4056 con Boost Step Up a 5V de salida de lo contrario dañaras la tarjeta UNIT Pulsar.

Encendido y Apagado

El interruptor ON/OFF se coloca en serie con la alimentación general para desconectar el sistema cuando no esté en uso.

Conexión del motor 28BYJ-48 y ULN2003

El motor 28BYJ-48 se conecta directamente al conector de cinco terminales del controlador ULN2003. Posteriormente, las cuatro entradas del ULN2003 se conectan a la UNIT Pulsar de la siguiente manera:

ULN2003Pulsar ESP32-C6GPIO
IN1D5GPIO19
IN2D6GPIO20
IN3D7GPIO21
IN4D10GPIO18
VCC / +5 V
GNDGND

Botón para control de giro

El botón cambia el sentido de giro de la plataforma. Conéctalo de la siguiente manera:

BotónPulsar ESP32-C6
Terminal 1D4 / GPIO15
Terminal 2GND

No es necesario colocar una resistencia pull-up externa porque utilizaremos:

pinMode(buttonPin, INPUT_PULLUP);

Cuando el botón está libre tendremos un estado HIGH. Cuando presionamos el botón, D4 se conecta a GND y obtenemos un estado LOW.

Control de velocidad

El potenciómetro será el encargado de establecer la velocidad de giro. Realiza las conexiones de la siguiente manera:

PotenciómetroPulsar ESP32-C6
Terminal lateral3.3 V
Terminal centralA1 / D15 / GPIO1
Terminal lateralGND

La entrada A1 corresponde a GPIO1 y ADC1_CH1 en la Pulsar ESP32-C6.

Importante: Aunque el motor y el ULN2003 trabajan con una alimentación de 5 V, no debemos aplicar esos 5 V directamente a A1.


ENSAMBLE DE LA BASE GIRATORIA

Una vez realizadas las conexiones podemos comenzar con el montaje mecánico.

El diseño está formado principalmente por una base inferior, donde se colocan todos los componentes electrónicos, y una plataforma superior giratoria.

1. Ensamble de rodamientos

Antes de ensamblar la electrónica primero debemos ensamblar los rodamiento608ZZ-7 internos en la base inferior con los poste de impresión 3D como se muestra en el siguiente video de referencia:

2. Ensamble de la electrónica

Ya que ensamblaste los rodamientos 608ZZ-7 podrás ensamblar la electrónica, en el siguiente video tendrás la referencio de como ubicar la electrónica:

Nota: El video es una referencia pero te recomendamos conectar el motor a pasos y ULN2003 en sus barrenos correspondientes, puedes utilizar tornillos M3 para sujetarlos a los barrenos. De igual forma puedes utilizar una PCB perforada de 6x4cm la cual te recomendamos para montar la pulsar con hearder hembra, utilizar borneras o conectores JTS en la PCB para facilitar la conexión del potenciómetro, botón, interruptor lo demás lo puedes conectar soldando alambre de protoboard o cables dupont.

3. Ensamble de tapa superior

Finalmente instala el rodamiento 608ZZ-7 en tapa superior y después ensámblala en la base inferior, como se muestra en el siguiente video:


CÓDIGO

Una vez ensamblada la base giratoria y realizadas todas las conexiones, es momento de programarla. Antes de cargar el código en la UNIT Pulsar ESP32-C6, realiza las siguientes configuraciones:

1. Configuración de entorno de programación

Usaremos Arduino IDE como entorno de desarrollo. Sigue estos pasos:

  • Agrega la placas de desarrollo UNIT Electronics ESP32 a Arduino IDE
    Abre el IDE y ve a Archivo > Preferencias
    En el campo “Gestor de URLs adicionales de tarjetas”, agrega la siguiente dirección:
    👉 https://raw.githubusercontent.com/UNIT-Electronics/Uelectronics-ESP32-Arduino-Package/main/package_Uelectronics_esp32_index.json
  • Instala las placas UNIT Electronics ESP32 desde el Gestor de placas de Arduino IDE.
    Después la URL al preferencias dirígete a la pestaña Herramientas > Placa > Gestor de placas, busca “UNIT Electronics ESP32” e instala las placas. En la siguiente imagen tienes la referencia

Una ventaja de este proyecto es que no necesitamos instalar ninguna librería adicional para controlar el motor. La secuencia del 28BYJ-48 se genera directamente desde código.

Es importante que cuando programes la base giratoria la tarjeta UNT Pulsar ESP32 C6 debe estar desconectada de la base, solo debe de estar conectada al puerto USB de tu computadora y laptop después sigue estos pasos:

  • Selecciona la placa UNIT Pulsar ESP32 C6 en Arduino IDE
  • Antes de compilar y cargar el código, verifica que tengas seleccionada la siguiente tarjeta:
  • Herramientas > Placa > UNIT Electronics ESP32-C6 > Pulsar ESP32 C6
  • Selecciona el puerto COM que te asigno la computadora.
Crea un Carrito WiFi con WebSockets usando la placa UNIT Pulsar ESP32-C6 (2)

Con estas configuraciones completadas, tu entorno estará listo para compilar y cargar el siguiente código en la Pulsar.

// --------------------------------------------------
// Pines de la UNIT Pulsar ESP32-C6
// --------------------------------------------------

// Potenciómetro conectado a A1 / D15 / GPIO1
const uint8_t potPin = 1;

// Botón conectado a D4 / GPIO15
const uint8_t buttonPin = 15;

// ULN2003
const uint8_t motorPins[4] = {
  19,  // D5  -> IN1
  20,  // D6  -> IN2
  21,  // D7  -> IN3
  18   // D10 -> IN4
};

// --------------------------------------------------
// Configuración del motor 28BYJ-48
// --------------------------------------------------

// Número aproximado de medios pasos por vuelta
const uint16_t pasosPorVuelta = 4096;

// Secuencia de medio paso para el ULN2003
const uint8_t secuencia[8][4] = {
  {1, 0, 0, 0},
  {1, 1, 0, 0},
  {0, 1, 0, 0},
  {0, 1, 1, 0},
  {0, 0, 1, 0},
  {0, 0, 1, 1},
  {0, 0, 0, 1},
  {1, 0, 0, 1}
};

int indicePaso = 0;
bool sentidoHorario = true;

unsigned long tiempoUltimoPaso = 0;
unsigned long intervaloPaso = 1000;

// --------------------------------------------------
// Variables del botón
// --------------------------------------------------

int lecturaAnteriorBoton = HIGH;
int estadoEstableBoton = HIGH;

unsigned long tiempoAntirrebote = 0;
const unsigned long retardoAntirrebote = 50;

// --------------------------------------------------
// Variables de control
// --------------------------------------------------

int velocidadRPM = 1;

unsigned long tiempoMonitorSerial = 0;
const unsigned long intervaloMonitorSerial = 300;

void setup() {
  Serial.begin(115200);

  // Botón con resistencia pull-up interna
  pinMode(buttonPin, INPUT_PULLUP);

  // Configura los cuatro pines del ULN2003 como salidas
  for (uint8_t i = 0; i < 4; i++) {
    pinMode(motorPins[i], OUTPUT);
    digitalWrite(motorPins[i], LOW);
  }

  // ADC de 12 bits: valores de 0 a 4095
  analogReadResolution(12);

  Serial.println("Control de motor 28BYJ-48");
  Serial.println("UNIT Pulsar ESP32-C6");
}

void loop() {
  leerBoton();

  // Promedio de varias lecturas para reducir variaciones
  uint16_t valorPotenciometro = leerPotenciometro();

  // Convierte la lectura analógica a una velocidad de 1 a 15 RPM
  velocidadRPM = map(
    valorPotenciometro,
    0,
    4095,
    1,
    15
  );

  velocidadRPM = constrain(velocidadRPM, 1, 15);

  // Calcula el tiempo entre cada medio paso
  intervaloPaso =
    60000000UL /
    ((unsigned long)pasosPorVuelta * velocidadRPM);

  moverMotor();

  // Muestra los datos sin saturar el monitor serial
  if (millis() - tiempoMonitorSerial >= intervaloMonitorSerial) {
    tiempoMonitorSerial = millis();

    Serial.print("ADC: ");
    Serial.print(valorPotenciometro);

    Serial.print(" | Velocidad: ");
    Serial.print(velocidadRPM);
    Serial.print(" RPM");

    Serial.print(" | Sentido: ");
    Serial.println(
      sentidoHorario ? "Horario" : "Antihorario"
    );
  }
}

// --------------------------------------------------
// Movimiento no bloqueante
// --------------------------------------------------

void moverMotor() {
  unsigned long tiempoActual = micros();

  if (tiempoActual - tiempoUltimoPaso >= intervaloPaso) {
    tiempoUltimoPaso = tiempoActual;

    if (sentidoHorario) {
      indicePaso++;

      if (indicePaso > 7) {
        indicePaso = 0;
      }
    } else {
      indicePaso--;

      if (indicePaso < 0) {
        indicePaso = 7;
      }
    }

    aplicarPaso(indicePaso);
  }
}

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

// --------------------------------------------------
// Lectura del botón con antirrebote
// --------------------------------------------------

void leerBoton() {
  int lecturaActual = digitalRead(buttonPin);

  if (lecturaActual != lecturaAnteriorBoton) {
    tiempoAntirrebote = millis();
    lecturaAnteriorBoton = lecturaActual;
  }

  if (millis() - tiempoAntirrebote >= retardoAntirrebote) {
    if (lecturaActual != estadoEstableBoton) {
      estadoEstableBoton = lecturaActual;

      // El botón está presionado cuando su estado es LOW
      if (estadoEstableBoton == LOW) {
        sentidoHorario = !sentidoHorario;
      }
    }
  }
}

// --------------------------------------------------
// Promedio de lectura analógica
// --------------------------------------------------

uint16_t leerPotenciometro() {
  uint32_t suma = 0;
  const uint8_t muestras = 8;

  for (uint8_t i = 0; i < muestras; i++) {
    suma += analogRead(potPin);
  }

  return suma / muestras;
}

¿CÓMO FUNCIONA EL CÓDIGO?

Configuración de los pines

Primero definimos los pines que utilizaremos:

const uint8_t potPin = 1;
const uint8_t buttonPin = 15;

GPIO1 corresponde a A1 y recibe la señal analógica del potenciómetro.

GPIO15 corresponde a D4 y recibe el estado del botón.

Posteriormente declaramos las cuatro señales que controlan el ULN2003:

const uint8_t motorPins[4] = {
  19,
  20,
  21,
  18
};

Estas corresponden a:

D5 → IN1
D6 → IN2
D7 → IN3
D10 → IN4

CONTROL DEL 28BYJ-48

El motor 28BYJ-48 contiene cuatro fases que deben energizarse siguiendo una determinada secuencia.

En este proyecto utilizamos una secuencia de medio paso de ocho estados:

const uint8_t secuencia[8][4] = {
  {1, 0, 0, 0},
  {1, 1, 0, 0},
  {0, 1, 0, 0},
  {0, 1, 1, 0},
  {0, 0, 1, 0},
  {0, 0, 1, 1},
  {0, 0, 0, 1},
  {1, 0, 0, 1}
};

Cada fila representa las bobinas que deben permanecer activadas durante un medio paso.

Este método nos permite obtener un movimiento más suave y una mayor resolución que utilizando únicamente pasos completos.

Para simplificar el control consideramos aproximadamente:

const uint16_t pasosPorVuelta = 4096;

Es decir, aproximadamente 4096 medios pasos para completar una vuelta del eje de salida del 28BYJ-48.

CONTROL DE VELOCIDAD CON EL POTENCIÓMETRO

La Pulsar utiliza su ADC de 12 bits para leer el potenciómetro.

analogReadResolution(12);

Por lo tanto obtenemos valores comprendidos entre:

0 → Potenciómetro al mínimo
4095 → Potenciómetro al máximo

Posteriormente utilizamos:

velocidadRPM = map(
  valorPotenciometro,
  0,
  4095,
  1,
  15
);

De esta manera convertimos la lectura del potenciómetro en una velocidad aproximada entre:

1 RPM y 15 RPM.

Si necesitas una base todavía más lenta puedes modificar fácilmente estos valores. Por ejemplo:

1,
8

para trabajar entre 1 y 8 RPM.

Esto puede ser útil cuando se colocan objetos más pesados o se busca un movimiento especialmente suave para fotografía.

¿CÓMO SE CALCULA LA VELOCIDAD DEL MOTOR?

Para controlar la velocidad calculamos cuánto tiempo debe transcurrir entre cada medio paso:

intervaloPaso =
  60000000UL /
  ((unsigned long)pasosPorVuelta * velocidadRPM);

60,000,000 representa la cantidad de microsegundos que existen en un minuto.

Por ejemplo, si seleccionamos:

1 RPM

el programa distribuye aproximadamente 4096 pasos durante un minuto.

Si aumentamos a:

10 RPM

el intervalo entre pasos disminuye y el motor gira más rápidamente.

MOVIMIENTO SIN BLOQUEAR EL PROGRAMA

Una característica importante de este código es que no utiliza delay() para generar el movimiento.

En su lugar se utiliza:

micros();

para saber cuándo corresponde realizar el siguiente paso.

Esto permite que, mientras el motor está girando, la Pulsar pueda seguir:

  • Leyendo el potenciómetro.
  • Detectando el botón.
  • Actualizando el Monitor Serial.
  • Ejecutando futuras funciones.

Este método también facilita ampliar posteriormente el proyecto con Wi-Fi, Bluetooth BLE, sensores o una interfaz web sin detener el movimiento del motor.

CAMBIO DEL SENTIDO DE GIRO

Cada vez que presionamos el botón ejecutamos:

sentidoHorario = !sentidoHorario;

Si el motor estaba girando en sentido horario pasará a antihorario y viceversa.

La dirección se determina incrementando o disminuyendo la posición dentro de la secuencia:

if (sentidoHorario) {
  indicePaso++;
} else {
  indicePaso--;
}

Por ello no necesitamos realizar ninguna modificación física en el cableado para invertir el movimiento.

ANTIRREBOTE DEL BOTÓN

Los botones mecánicos no producen una transición eléctrica perfecta cuando se presionan. Durante algunos milisegundos pueden cambiar varias veces entre HIGH y LOW.

Para evitar que una sola pulsación cambie varias veces el sentido del motor utilizamos un tiempo de antirrebote de:

const unsigned long retardoAntirrebote = 50;

De esta forma solo se acepta el cambio cuando la señal se mantiene estable.

FILTRADO DEL POTENCIÓMETRO

Las entradas analógicas pueden tener pequeñas variaciones eléctricas.

Para conseguir un movimiento más estable realizamos ocho lecturas:

const uint8_t muestras = 8;

Posteriormente obtenemos su promedio:

return suma / muestras;

Esto reduce pequeñas fluctuaciones que podrían provocar cambios constantes en la velocidad del motor aunque no estemos moviendo el potenciómetro.


CONCLUSIÓN

Con este proyecto aprendimos a construir una base giratoria utilizando la UNIT Pulsar ESP32-C6 y un motor a pasos 28BYJ-48. Gracias al potenciómetro podemos ajustar fácilmente la velocidad de giro y, mediante el botón, cambiar la dirección de movimiento.

Además de ser un proyecto práctico para fotografía, exhibición de productos o proyectos DIY, también es una excelente forma de aprender sobre motores a pasos, control de velocidad, electrónica y programación con ESP32-C6. A partir de este diseño puedes seguir experimentando y agregar nuevas funciones como control mediante Bluetooth o Wi-Fi.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *