
El robot Zumo 32U4, un modelo compacto, programable y listo para usar, basado en el microcontrolador ATmega32U4 y compatible con Arduino. Mide menos de 10×10 cm, pesa unos 160 g sin baterías y está especialmente diseñado para competiciones Mini-Sumo. Incorpora motores con reductora, encoders, pantalla OLED, sensores de línea y proximidad, una IMU (acelerómetro, giroscopio y magnetómetro), además de botones, LEDs y un buzzer para interacción.
El robot se programa directamente desde el entorno Arduino, sin necesidad de montaje previo, y se puede ampliar mediante sus líneas de E/S y alimentación, lo que lo hace ideal tanto para educación como para competición robótica.
En este blog nos hemos propuesto emular el Zumo 32U4 con hardware más sencillo y económico de un modo general https://soloelectronicos.com/2025/12/10/emulacion-de-zumo32u4-con-un-arduino/ (por ejemplo, con un Arduino Uno o Nano, controlador L298N, motores DC, pantalla LCD, LEDs y pulsadores).
También se ha tratado el sonido, un tema especialmente atractivo por su «sencillez» y resultados https://soloelectronicos.com/2025/12/11/emulacion-zumo-de-sonidos-con-atmega/
Esta emulación ofrece varias ventajas:
- Económica y accesible, permitiendo disponer de más unidades para enseñanza o experimentación.
- Formativa, ya que obliga a conectar y comprender cada componente (drivers, PWM, control de motor, entradas y salidas).
- Compatible y útil para desarrollo de código, permitiendo probar lógicas de control sin necesitar el robot original.
- Flexible y robusta, ideal para investigación o docencia, ya que se pueden introducir fallos o modificar el hardware sin riesgo.
Para emular el Zumo 32U4 con un ATmega328P y poder usar las clases de la librería Zumo32U4 (buttons, motors, buzzer, LEDs), como ya se ha hablado, necesitamos replicar su “interfaz lógica”: mismos pines Arduino que espera la librería, pero cableados a nuestro hardware equivalente. Hemos hablado de motores, pulsadores,leds y el sonido .
En este ultimo post vamos a resumir todos lo dispositivos fácilmente emulables ( leds, motores, pulsadores, buzzer ) a la vez que vamos a intentar sopesar el tema de la pantalla y su emulación con un Arduino Mega.
RESUMEN DE LA EMULACION DE ZUMO TRATADA EN POST ANTERIORES
1. Qué espera la librería Zumo32U4:La documentación indica, a nivel de pines Arduino:
- Botón A → pin digital 14 (A0)
- Botón B → pin digital 4
- Botón C → pin digital 17 (A3)
- LED amarillo usuario → pin 13
- LED rojo usuario → mismo pin que botón C (17/A3)
- Motores:
- Motor derecho velocidad (PWM) → pin 9
- Motor derecho dirección → pin 15 (A1)
- Motor izquierdo velocidad (PWM) → pin 10
- Motor izquierdo dirección → pin 16 (A2)
- Buzzer → pin 6
Las clases de la librería (Zumo32U4ButtonA/B/C, Zumo32U4Motors, Zumo32U4Buzzer, etc.) asumen estos números de pin.
2. Estrategia con ATmega328P (Uno “emulado”): como un ATmega328P no tiene el mismo mapeo interno, tenemos dos opciones:
- No tocar la librería y cablear tus periféricos a los mismos números de pin Arduino que usa el Zumo.
- Modificar la librería para cambiar números de pin a otros de nuestro gusto.
Lo más sencillo es la opción 1, es decir cablear de esta forma en una placa tipo Uno/Nano
La asignación recomendada (para no tocar la librería), suponiendo que compilamos como si fuera un Zumo32U4 (core 32U4) es complicado en un 328P, así que la forma práctica es reusar los números de pin lógicos y adaptar el hardware:
Botones (normalmente abiertos a GND, INPUT_PULLUP)
- Botón A:
- Zumo: pin 14 (A0) → en tu 328P: usa A0.
- Botón B:
- Zumo: pin 4 → en tu 328P: usa D4.
- Botón C:
- Zumo: pin 17 (A3) → en tu 328P: usa A3.
Cableado:
- Un terminal del pulsador → pin (A0, D4, A3).
- Otro terminal → GND.
- En código se usará
INPUT_PULLUP, lógica: LOW = pulsado.
Motores (con L298N)
- Motor derecho:
- Velocidad (PWM): Zumo pin 9 → usa D9.
- Dirección: Zumo pin 15 (A1) → usa A1 (o D3/D5 si prefieres digital puro).
- Motor izquierdo:
- Velocidad (PWM): Zumo pin 10 → usa D10.
- Dirección: Zumo pin 16 (A2) → usa A2.
Ejemplo lógico:
LEDs externos
- LED amarillo:
- Zumo: pin 13 → usa D13 (LED integrado + LED externo en serie o separado).
- LED rojo:
Buzzer
- Zumo: pin 6
- Para compatibilidad con la clase
Zumo32U4Buzzer, tendrías que:
3. Uso práctico con ATmega328P: la librería Zumo32U4 está pensada para un ATmega32U4 (Leonardo/Micro-like). Compilarla tal cual sobre un core Uno (328P) nos va a dar problemas porque internamente usa características específicas del 32U4 (USB, Timer4, etc.). Para nuestro objetivo (emulación docente):
- Más viable:
- Copiar solo las ideas/clases y escribir nuestras propias mini-clases equivalentes para 328P:
class ButtonA { pinMode(A0, INPUT_PULLUP); bool isPressed() { return !digitalRead(A0); } };class Motors { … }que use los pines de L298N.class Buzzer { tone(7, f); … }con el pin 7.
- Copiar solo las ideas/clases y escribir nuestras propias mini-clases equivalentes para 328P:
- Si insistes en usar exactamente
Zumo32U4.h:
4. Resumen de pines para una emulacion (versión directa 328P): para dejarlo claro, si ignoramos la librería y solo queremos el mismo comportamiento:
- Botón A: A0 (NO a GND,
INPUT_PULLUP). - Botón B: D4 (NO a GND).
- Botón C: A3 (NO a GND).
- Motor derecho: PWM D9, dirección A1.
- Motor izquierdo: PWM D10, dirección A2.
- LED amarillo: D13.
- LED rojo: D12 (o A3 si quieres imitar el multiplexado).
- Buzzer: D7 (y usas
tone(7, f)).
La librería Zumo32U4 solo funciona con microcontroladores ATmega32U4 y no con ATmega328P (Arduino Uno u otros). Es recomendable por tanto seleccionar una placa basada en 32U4 (como A-Star 32U4) en el menú Boards para usar esa librería.
Opciones para seguir con un ATmega328P (Arduino Uno):
- No usar la librería Zumo32U4 directamente, porque está diseñada específicamente para 32U4 y usa características hardware exclusivas ( ES JUSTAMENTE LO QUE SE HA TRATADO EN ESTE POST Y POST ANTERIOES).
- Crear tu propia implementación “simulada” de las clases Button, Motor, Led y Buzzer usando pines ATmega328P (tal como definimos los mapeos) para emular la funcionalidad básica.
- Cambiar a usar una placa basada en ATmega32U4 (como Arduino Leonardo, Micro o la A-Star 32U4) si quieres usar la librería oficial.
DISPLAY EMULADO
Centrémonos a ahora en la emulación de un Display OLED Zumo32U4 con LCD I2C ATmega328P
El Zumo32U4 tiene un display OLED 1.3″ monocromo (128×64 píxeles) conectado por I2C. EL Típico u LCD I2C es perfecto para emularlo. Es cierto que en versiones posteriores se ha sustituido por una pantalla OLED, pero por simplificar nos centraremos en el LCD dado que requiere menos lineas GPIO.

Debemos en el entorno Arduino importar la librería correspondiente:
Librería Display Zumo32U4 → LiquidCrystal_I2C
| Zumo32U4 | Tu LCD I2C |
|---|---|
Zumo32U4OLED | LiquidCrystal_I2C |
| I2C: SDA A4, SCL A5 | Igual: A4, A5 |
| Texto 21×4 caracteres | Tu LCD 16×2/20×4 |
Y respecto a los pines I2C (Fijos – No cambies)
Display I2C LCD:
SDA → A4 (todos Arduino)
SCL → A5 (todos Arduino)
VCC → 5V
GND → GND
No debemos ante de nada olvidar la instalación de la Librería LCD I2C
Arduino IDE → Tools → Manage Libraries
Buscar: **"LiquidCrystal I2C"** → Frank de Brabander
Instalar → Reiniciar IDE
Asimismo, es crucial encontrar Dirección I2C de tu Display, para lo cual una vez todo conectado podemos usar el siguiente código en nuestro entorno Arduino:
// Scanner I2C - Ejecuta UNA vez
#include <Wire.h>
void setup() {
Wire.begin();
Serial.begin(9600);
Serial.println("I2C Scanner");
}
void loop() {
for(byte i=8; i<120; i++) {
Wire.beginTransmission(i);
if (Wire.endTransmission() == 0) {
Serial.print("I2C: 0x"); Serial.println(i, HEX);
}
}
delay(5000);
}
Las direcciones típicas son 0x27 o 0x3F. Cambia en LiquidCrystal_I2C lcd(0x27, 16, 2);
Veamos ahora finalmente ver un ejemplo de código que usa un display con tres leds y dos pulsadores descritos estos últimos en post anteriores.
Código Completo: Emulación Display + LEDs + Botones
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Emulación Zumo32U4 display (16x2 típico)
LiquidCrystal_I2C lcd(0x27, 16, 2); // Cambia 0x27 por tu dirección I2C
#define BUTTON_A_PIN A0
#define BUTTON_B_PIN 4
#define LED_YELLOW_PIN 13
#define LED_RED_PIN 12
void setup() {
// Inicializar LCD I2C (emula Zumo OLED)
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Zumo32U4 EMU");
lcd.setCursor(0, 1);
lcd.print("Display OK!");
delay(2000);
// Botones y LEDs
pinMode(BUTTON_A_PIN, INPUT_PULLUP);
pinMode(BUTTON_B_PIN, INPUT_PULLUP);
pinMode(LED_YELLOW_PIN, OUTPUT);
pinMode(LED_RED_PIN, OUTPUT);
}
void loop() {
bool btnA = digitalRead(BUTTON_A_PIN) == LOW;
bool btnB = digitalRead(BUTTON_B_PIN) == LOW;
// LED ROJO: ON cuando botón A NO pulsado
digitalWrite(LED_RED_PIN, !btnA);
// LED AMARILLO: ON cuando botón B pulsado
digitalWrite(LED_YELLOW_PIN, btnB);
// EMULAR DISPLAY ZUMO32U4
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("BtnA:"); lcd.print(btnA ? "ON " : "OFF");
lcd.print(" BtnB:"); lcd.print(btnB ? "ON " : "OFF");
lcd.setCursor(0, 1);
lcd.print("Red:"); lcd.print(digitalRead(LED_RED_PIN) ? "ON " : "OFF");
lcd.print("Yel:"); lcd.print(digitalRead(LED_YELLOW_PIN) ? "ON" : "OFF");
delay(200); // Refresh 5Hz
}
Este código simula parte de la interfaz del robot Zumo 32U4 usando un Arduino con una pantalla LCD I2C y algunos elementos básicos como LEDs y botones. En la función setup(), se inicializa la pantalla LCD para mostrar un mensaje de bienvenida (“Zumo32U4 EMU – Display OK!”) y se configuran los pines: dos entradas con resistencia pull-up para los botones (A y B) y dos salidas para los LEDs rojo y amarillo. De este modo, se prepara el entorno para imitar la interacción que tendría un Zumo real con su pantalla y entradas físicas.
En el bucle principal loop(), el programa lee el estado de los botones y ajusta los LEDs de forma inversa o directa según el botón pulsado. Luego actualiza continuamente el LCD para mostrar en tiempo real el estado de los botones y de los LEDs, lo que permite verificar visualmente la interacción. Con un retardo de 200 ms (frecuencia de unas 5 actualizaciones por segundo), esta implementación emula de manera sencilla cómo el Zumo muestra información y responde a los mandos del usuario, sirviendo como práctica educativa de entrada/salida digital y manejo de pantallas I2C.
PROYECTO FINAL
Y ahora ya finalmente al proyecto anterior le añadimos la gestión de los motores junto a todo lo demás:
BOTONES:
A0 ← Btn A → GND
D4 ← Btn B → GND
A3 ← Btn C → GND
LEDS:
D13 ← LED Amarillo → 220Ω → GND
D12 ← LED Rojo → 220Ω → GND
BUZZER:
D6 ← Buzzer → GND
L298N:
D3 ← ENA (Izq)
A2 ← IN1 (Izq Dir)
D11 ← ENB (Der)
A1 ← IN3 (Der Dir)
OUT1,2 → Motor Izq
OUT3,4 → Motor Der
A continuación mostramos un código funcional que ejemplariza le emulación de la gestión del display LCD, pulsadores, leds y botones:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F, 16, 2);
#define BUTTON_A_PIN A0 // AVANZAR
#define BUTTON_B_PIN 4 // RETROCEDER
#define BUTTON_C_PIN A3 // PARAR
#define LED_YELLOW_PIN 13
#define LED_RED_PIN 12
#define BUZZER_PIN 6
// ✅ PINS L298N COMPLETOS
#define M1_ENA_PIN 3 // Enable Motor Izq (PWM)
#define M1_DIR_PIN A2 // Dirección Motor Izq
#define M2_ENB_PIN 11 // Enable Motor Der (PWM)
#define M2_DIR_PIN A1 // Dirección Motor Der
bool lastBtnA = false, lastBtnB = false, lastBtnC = false;
String estado = «PARADO»;
void setup() {
Wire.begin();
lcd.init(); lcd.backlight(); lcd.clear();
lcd.setCursor(0,0); lcd.print(«Zumo32U4 v3.0»);
lcd.setCursor(0,1); lcd.print(«Motores OK»);
delay(2000);
// Botones con pull-up
pinMode(BUTTON_A_PIN, INPUT_PULLUP);
pinMode(BUTTON_B_PIN, INPUT_PULLUP);
pinMode(BUTTON_C_PIN, INPUT_PULLUP);
// LEDs
pinMode(LED_YELLOW_PIN, OUTPUT);
pinMode(LED_RED_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
// ✅ MOTORES – TODOS LOS PINES
pinMode(M1_ENA_PIN, OUTPUT);
pinMode(M1_DIR_PIN, OUTPUT);
pinMode(M2_ENB_PIN, OUTPUT);
pinMode(M2_DIR_PIN, OUTPUT);
// INICIALIZAR PINES EN LOW
digitalWrite(M1_ENA_PIN, LOW);
digitalWrite(M1_DIR_PIN, LOW);
digitalWrite(M2_ENB_PIN, LOW);
digitalWrite(M2_DIR_PIN, LOW);
parar(); // Estado inicial
}
void loop() {
bool btnA = digitalRead(BUTTON_A_PIN) == LOW;
bool btnB = digitalRead(BUTTON_B_PIN) == LOW;
bool btnC = digitalRead(BUTTON_C_PIN) == LOW;
// Detectar pulsación única (flanco ↓)
bool btnA_pressed = btnA && !lastBtnA;
bool btnB_pressed = btnB && !lastBtnB;
bool btnC_pressed = btnC && !lastBtnC;
// CONTROL MOTORES
if (btnA_pressed) {
avanzar();
tone(BUZZER_PIN, 1000, 200);
}
if (btnB_pressed) {
retroceder();
tone(BUZZER_PIN, 800, 200);
}
if (btnC_pressed) {
parar();
tone(BUZZER_PIN, 500, 300);
}
// LEDs indicadores
digitalWrite(LED_YELLOW_PIN, (estado == «AVANZAR»));
digitalWrite(LED_RED_PIN, (estado == «RETROCEDER»));
// DISPLAY
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(«Estado: «); lcd.print(estado);
lcd.setCursor(0, 1);
lcd.print(«A:»); lcd.print(btnA ? «ON » : «OFF»);
lcd.print(«B:»); lcd.print(btnB ? «ON » : «OFF»);
lcd.print(«C:»); lcd.print(btnC ? «ON» : «OFF»);
// Actualizar estados
lastBtnA = btnA;
lastBtnB = btnB;
lastBtnC = btnC;
delay(50);
}
// ✅ FUNCIONES MOTORES CORREGIDAS
void avanzar() {
digitalWrite(M1_DIR_PIN, HIGH); // Izq adelante
digitalWrite(M2_DIR_PIN, LOW); // Der adelante
analogWrite(M1_ENA_PIN, 180); // Velocidad suave
analogWrite(M2_ENB_PIN, 180);
estado = «AVANZAR»;
}
void retroceder() {
digitalWrite(M1_DIR_PIN, LOW); // Izq atrás
digitalWrite(M2_DIR_PIN, HIGH); // Der atrás
analogWrite(M1_ENA_PIN, 180); // Velocidad suave
analogWrite(M2_ENB_PIN, 180);
estado = «RETROCEDER»;
}
void parar() {
// ✅ APAGAR COMPLETAMENTE AMBOS MOTORES
analogWrite(M1_ENA_PIN, 0); // Motor 1 OFF
analogWrite(M2_ENB_PIN, 0); // Motor 2 OFF
digitalWrite(M1_DIR_PIN, LOW); // Direcciones LOW
digitalWrite(M2_DIR_PIN, LOW);
estado = «PARADO»;
}
Este código implementa una emulación de control de robot tipo Zumo usando un Arduino, una pantalla LCD I2C, tres botones, dos LEDs, un buzzer y un módulo de potencia L298N para dos motores DC. En setup() se inicializa la LCD en la dirección I2C 0x3F, se muestra un mensaje de arranque, se configuran los botones con INPUT_PULLUP, los LEDs, el buzzer y todos los pines del L298N como salidas, dejando los motores apagados inicialmente mediante parar(). Además, se usa una variable de estado (estado) que mantiene si el “robot” está AVANZAR, RETROCEDER o PARADO y que luego se mostrará en pantalla.
| Botón | Acción | LED | Display | Sonido |
|---|---|---|---|---|
| A | Avanzar | Amarillo ON | «AVANZAR» | 1000Hz |
| B | Retroceder | Rojo ON | «RETROCEDER» | 800Hz |
| C | PARAR | OFF | «PARADO» | 500Hz |
En loop() se leen los tres botones (A=avanzar, B=retroceder, C=parar) con lógica de flanco descendente para que cada pulsación cuente solo una vez, y según el botón se llama a avanzar(), retroceder() o parar(), disparando también un tono distinto en el buzzer con tone() como feedback sonoro. Las funciones de motor fijan la dirección con los pines M1_DIR_PIN y M2_DIR_PIN y la velocidad mediante PWM en M1_ENA_PIN y M2_ENB_PIN, tal y como se hace habitualmente al controlar el L298N con Arduino. Los LEDs indican el modo (amarillo al avanzar, rojo al retroceder) y la LCD se refresca continuamente para mostrar el estado actual y si cada botón está ON/OFF, creando una interfaz sencilla pero completa de prueba y depuración del “robot” emulado.
