Community project
Wagging Walking Robot Dog
This project builds a four-wheeled robot dog that walks forward, pauses, turns, and wags its tail in a continuous loop. The robot is powered by four geared DC motors for independent wheel control, a servo motor for tail movement, and an Arduino Uno that orchestrates the motion sequence through an L298N motor driver.
The guide provides a complete parts list, wiring diagram showing all motor and servo connections to the Arduino and motor controller, step-by-step assembly instructions for mounting the motors and servo, and ready-to-upload firmware that makes the robot walk with synchronized tail wagging. Builders will have a functional autonomous robot dog that demonstrates motor control, timing logic, and servo animation.
Wiring diagram

Gather all the parts
Assemble it in 5 steps
1. Preparen el cuerpo y los motores
Dejen las cuatro ruedas sujetas al chasis de chapas. Miren el perro desde arriba: llamen izquierdo a los dos motores de su izquierda y derecho a los otros dos. Cada grupo de dos motores se conectará junto para que las dos ruedas de ese lado avancen a la vez.
- Usen bridas, tornillos o cinta fuerte para que los cables no toquen las ruedas.
- Dejen libre una parte trasera del chasis para fijar el servomotor y una cola liviana de cartón, goma eva o plástico.
- No prueben los motores tocando los cables directamente con la pila durante mucho tiempo: pueden calentarse o hacer girar las ruedas de golpe.
2. Conecten las cuatro ruedas al controlador
Conecten los dos cables de ambos motores izquierdos en paralelo: un cable de cada motor al borne OUT1 del L298N y el otro cable de cada motor al borne OUT2. Conecten los dos motores derechos igual: un cable de cada motor a OUT3 y el otro a OUT4. Estos cables son los que llevan la energía a las ruedas.
- Si un motor gira al sentido contrario de su compañero, apaguen las pilas e inviertan solamente sus dos cables.
- No importa cuál cable del motor va primero; el programa puede invertir el sentido completo de un lado.
- Desconecten las pilas antes de cambiar cualquier cable: un cable suelto puede hacer un cortocircuito y calentar la pila o el controlador.
3. Lleven energía a cada parte
Con el interruptor del portapilas apagado, conecten el cable rojo VOUT del portapilas a VS del L298N, a VIN del regulador de 5 V y al cable rojo VCC del servo. Conecten el cable negro GND del portapilas a una fila de tierra común; desde esa fila lleven cables a GND del L298N, GND del regulador, GND del servo y GND del Arduino. Conecten VOUT del regulador al pin 5V del Arduino y al pin 5V del L298N. La tierra común permite que todos entiendan las mismas órdenes.
- El cable negro o marrón del servo va a tierra; el rojo va al positivo de las pilas.
- En muchos L298N hay un puente marcado 5V-EN: quítenlo cuando alimenten el pin 5V desde el regulador, para no unir dos fuentes de energía.
- Nunca conecten la salida de 6 V de las pilas directamente al pin 5V del Arduino: puede dañarlo.
- Antes de encender, revisen que el regulador entregue 5 V; conectar al revés VIN y GND puede estropearlo.
- Usen el servo solo si su etiqueta indica que acepta entre 4,8 y 6 V; un servo de menor voltaje puede dañarse con cuatro AA alcalinas nuevas.
4. Conecten las órdenes del Arduino
Conecten IN1 del L298N a D2 del Arduino (orden de giro izquierdo), IN2 a D4 (orden de giro izquierdo), ENA a D5 (velocidad izquierda), ENB a D6 (velocidad derecha), IN3 a D7 (orden de giro derecho) e IN4 a D8 (orden de giro derecho). Conecten el cable naranja, amarillo o blanco SIG del servo a D9 del Arduino (orden para la cola).
- Usen cables de colores y anoten los números en una etiqueta de papel.
- Los pines ENA y ENB suelen tener pequeños puentes: quítenlos para que D5 y D6 puedan regular la velocidad.
- No conecten el cable de señal del servo al positivo o a tierra: podría dejar de funcionar.
5. Fijen la cola y hagan la primera prueba
Atornillen o peguen el servo al chasis y sujeten una cola liviana a la pieza redonda del eje del servo. Coloquen cuatro pilas AA del mismo tipo y en el mismo sentido, enciendan el interruptor y mantengan el perro levantado para que las ruedas no salgan disparadas. Después de cargar el programa con Deploy, apoyen el perro en el piso: avanza unos segundos, se frena, gira y repite mientras mueve la cola.
- Antes de pegar la cola definitivamente, enciendan el sistema para comprobar que el servo puede moverse sin golpear el chasis.
- Si el perro retrocede en vez de avanzar, apaguen las pilas e inviertan los dos cables de ambos pares de motores, o de un solo lado si gira hacia el lado equivocado.
- Mantengan dedos, pelo y ropa lejos de las ruedas cuando esté encendido.
- Si el L298N se pone muy caliente o el perro se detiene, apaguen de inmediato: esos motores pueden pedir más corriente de la que el controlador soporta.
Review all connections
1. Connections between "battery_pack" and "Arduino"
2. Connections between "five_volt_regulator" and "Arduino"
3. Connections between "motor_driver" and "Arduino"
4. Connections between "tail_servo" and "Arduino"
Deploy the firmware
#include <Arduino.h>
#include <Servo.h>
const uint8_t LEFT_IN1 = 2;
const uint8_t LEFT_IN2 = 4;
const uint8_t LEFT_ENABLE = 5;
const uint8_t RIGHT_ENABLE = 6;
const uint8_t RIGHT_IN1 = 7;
const uint8_t RIGHT_IN2 = 8;
const uint8_t TAIL_PIN = 9;
const uint8_t DRIVE_SPEED = 180;
const unsigned long FORWARD_TIME_MS = 3000;
const unsigned long STOP_TIME_MS = 500;
const unsigned long TURN_TIME_MS = 700;
const unsigned long TAIL_STEP_MS = 120;
Servo tail;
unsigned long phaseStartedAt = 0;
unsigned long lastTailStepAt = 0;
uint8_t phase = 0;
int tailAngle = 65;
int tailStep = 8;
void setLeftMotor(bool forward, uint8_t speed) {
digitalWrite(LEFT_IN1, forward ? HIGH : LOW);
digitalWrite(LEFT_IN2, forward ? LOW : HIGH);
analogWrite(LEFT_ENABLE, speed);
}
void setRightMotor(bool forward, uint8_t speed) {
digitalWrite(RIGHT_IN1, forward ? HIGH : LOW);
digitalWrite(RIGHT_IN2, forward ? LOW : HIGH);
analogWrite(RIGHT_ENABLE, speed);
}
void stopMotors() {
analogWrite(LEFT_ENABLE, 0);
analogWrite(RIGHT_ENABLE, 0);
digitalWrite(LEFT_IN1, LOW);
digitalWrite(LEFT_IN2, LOW);
digitalWrite(RIGHT_IN1, LOW);
digitalWrite(RIGHT_IN2, LOW);
}
void startPhase(uint8_t newPhase) {
phase = newPhase;
phaseStartedAt = millis();
if (phase == 0) {
setLeftMotor(true, DRIVE_SPEED);
setRightMotor(true, DRIVE_SPEED);
} else if (phase == 1) {
stopMotors();
} else {
setLeftMotor(true, DRIVE_SPEED);
setRightMotor(false, DRIVE_SPEED);
}
}
void updateTail() {
unsigned long now = millis();
if (now - lastTailStepAt < TAIL_STEP_MS) return;
lastTailStepAt = now;
tailAngle += tailStep;
if (tailAngle >= 115) {
tailAngle = 115;
tailStep = -8;
} else if (tailAngle <= 65) {
tailAngle = 65;
tailStep = 8;
}
tail.write(tailAngle);
}
void setup() {
pinMode(LEFT_IN1, OUTPUT);
pinMode(LEFT_IN2, OUTPUT);
pinMode(LEFT_ENABLE, OUTPUT);
pinMode(RIGHT_IN1, OUTPUT);
pinMode(RIGHT_IN2, OUTPUT);
pinMode(RIGHT_ENABLE, OUTPUT);
tail.attach(TAIL_PIN);
tail.write(90);
delay(400);
startPhase(0);
}
void loop() {
updateTail();
unsigned long elapsed = millis() - phaseStartedAt;
if (phase == 0 && elapsed >= FORWARD_TIME_MS) {
startPhase(1);
} else if (phase == 1 && elapsed >= STOP_TIME_MS) {
startPhase(2);
} else if (phase == 2 && elapsed >= TURN_TIME_MS) {
startPhase(0);
}
}Remix this project
Make it yours in one click
Open a full copy of this project in your own Schematik workspace — diagram, code, parts, and assembly steps included. Swap the sensor, add features, or redesign the whole thing with AI. The author's original stays untouched.




