Community project

Wagging Walking Robot Dog

Arduino
Photo of Wagging Walking Robot Dog
Generated with AI

Perla

Published October 15, 2026

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

Wiring diagram for Wagging Walking Robot Dog

Gather all the parts

QtyComponent
1

DFRobot MDV 2x2A DC Motor Controller (L298N)

L298N dual H-bridge motor driver carrier. 2A continuous per channel, 5-46V motor supply, ~1.8V dropout (BJT-based, hot at high currents). Drives 2 brushed DC motors or 1 bipolar stepper. Pair with PWM on EN pins for speed control.

1

4 x AA Battery Holder with On/Off Switch

Four-cell AA battery holder with snap-on cover and on/off switch. Provides approximately 6V with alkaline or rechargeable AA cells.

1

Motorreductor DC izquierdo delantero

Uno de los motores con rueda que hace avanzar el lado izquierdo del perro.

1

Motorreductor DC izquierdo trasero

Uno de los motores con rueda que hace avanzar el lado izquierdo del perro.

1

Motorreductor DC derecho delantero

Uno de los motores con rueda que hace avanzar el lado derecho del perro.

1

Motorreductor DC derecho trasero

Uno de los motores con rueda que hace avanzar el lado derecho del perro.

1

Servomotor de 5–6 V para la cola

El pequeño motor de tres cables que mueve la cola de lado a lado.

1

Regulador elevador-reductor Pololu S7V8F5 de 5 V

Un módulo que convierte el voltaje variable de las pilas en 5 V estables para el Arduino y la lógica del controlador.

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"

Functionbattery_packArduino
powerVOUT → DFRobot MDV 2x2A DC Motor Controller (L298N) VSEXT
powerVOUT → Servomotor de 5–6 V para la cola VCCEXT
powerVOUT → Regulador elevador-reductor Pololu S7V8F5 de 5 V VINEXT
groundGNDGND

2. Connections between "five_volt_regulator" and "Arduino"

Functionfive_volt_regulatorArduino
groundGNDGND
powerVOUT5V

3. Connections between "motor_driver" and "Arduino"

Functionmotor_driverArduino
groundGNDGND
power5V5V
digitalIN1GPIO 2
digitalIN2GPIO 4
pwmENAGPIO 5
pwmENBGPIO 6
digitalIN3GPIO 7
digitalIN4GPIO 8
outputOUT1 → Motorreductor DC izquierdo delantero M+EXT
outputOUT1 → Motorreductor DC izquierdo trasero M+EXT
outputOUT2 → Motorreductor DC izquierdo delantero M-EXT
outputOUT2 → Motorreductor DC izquierdo trasero M-EXT
outputOUT3 → Motorreductor DC derecho delantero M+EXT
outputOUT3 → Motorreductor DC derecho trasero M+EXT
outputOUT4 → Motorreductor DC derecho delantero M-EXT
outputOUT4 → Motorreductor DC derecho trasero M-EXT

4. Connections between "tail_servo" and "Arduino"

Functiontail_servoArduino
groundGNDGND
pwmSIGGPIO 9

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.

Open in Schematik