Programming your assembled miniAuto for basic movements and behaviors
🤖 From assembly to programming - bringing your robot to life
The miniAuto uses Mecanum wheels that allow omnidirectional movement. Each wheel has rollers at 45° angles that enable the robot to move forward, backward, sideways, and rotate without changing orientation.
This complete program includes all movement functions and demonstrates the full capabilities of your miniAuto robot:
// Complete miniAuto Movement Control Program
// Lesson 12: Basic miniAuto Programming
// Motor pin definitions (using official Hiwonder pinout)
const static uint8_t motorpwmPin[4] = {10, 9, 6, 11}; // Motor PWM pins
const static uint8_t motordirectionPin[4] = {12, 8, 7, 13}; // Motor direction pins
const static uint8_t pwm_min = 50; // Minimum PWM for motor movement
// LED pin for status indication
const int statusLED = 2;
void setup() {
Serial.begin(9600);
Serial.setTimeout(500);
// Initialize motor pins
Motor_Init();
// Initialize status LED
pinMode(statusLED, OUTPUT);
digitalWrite(statusLED, HIGH); // Turn on LED to show ready
Serial.println("=== miniAuto Movement Control System ===");
Serial.println("Robot initialized and ready for movement!");
Serial.println("Starting comprehensive movement demonstration...");
// Flash LED to indicate start
for(int i = 0; i < 3; i++) {
digitalWrite(statusLED, LOW);
delay(200);
digitalWrite(statusLED, HIGH);
delay(200);
}
delay(2000); // Wait 2 seconds before starting
}
void loop() {
// Comprehensive movement demonstration sequence
demonstrateAllMovements();
// Wait 5 seconds before repeating
Serial.println("\nWaiting 5 seconds before next demonstration...");
delay(5000);
}
void demonstrateAllMovements() {
Serial.println("\n--- Starting Movement Demonstration ---");
// 1. Forward Movement
Serial.println("1. Moving Forward");
digitalWrite(statusLED, HIGH);
Velocity_Controller(0, 80, 0, false); // Forward at 80% speed
delay(2000);
stopRobot();
delay(1000);
// 2. Backward Movement
Serial.println("2. Moving Backward");
Velocity_Controller(180, 80, 0, false); // Backward at 80% speed
delay(2000);
stopRobot();
delay(1000);
// 3. Left Strafe
Serial.println("3. Strafing Left");
Velocity_Controller(270, 80, 0, false); // Left strafe
delay(2000);
stopRobot();
delay(1000);
// 4. Right Strafe
Serial.println("4. Strafing Right");
Velocity_Controller(90, 80, 0, false); // Right strafe
delay(2000);
stopRobot();
delay(1000);
// 5. Clockwise Rotation
Serial.println("5. Rotating Clockwise");
digitalWrite(statusLED, LOW); // Different LED state for rotation
Velocity_Controller(0, 0, -60, false); // Clockwise rotation
delay(2000);
stopRobot();
delay(1000);
// 6. Counter-Clockwise Rotation
Serial.println("6. Rotating Counter-Clockwise");
Velocity_Controller(0, 0, 60, false); // Counter-clockwise rotation
delay(2000);
stopRobot();
delay(1000);
// 7. Diagonal Movements
Serial.println("7. Diagonal Forward-Right");
digitalWrite(statusLED, HIGH);
Velocity_Controller(45, 70, 0, false); // 45-degree angle
delay(1500);
stopRobot();
delay(1000);
Serial.println("8. Diagonal Backward-Left");
Velocity_Controller(225, 70, 0, false); // 225-degree angle
delay(1500);
stopRobot();
delay(1000);
// 8. Advanced: Drift Movement
Serial.println("9. Drift Movement (Right + Rotation)");
flashLED(3); // Special indication for advanced move
Velocity_Controller(90, 60, 40, true); // Right movement with rotation and drift
delay(2500);
stopRobot();
delay(1000);
// 9. Figure-8 Pattern (Advanced)
Serial.println("10. Figure-8 Pattern");
performFigure8();
Serial.println("--- Movement Demonstration Complete ---");
digitalWrite(statusLED, HIGH);
}
void performFigure8() {
// Create a figure-8 pattern using curved movements
Serial.println(" Starting Figure-8 pattern...");
// First loop of the 8
for(int i = 0; i < 8; i++) {
Velocity_Controller(0, 50, 30, false); // Forward with left turn
delay(300);
}
// Transition
Velocity_Controller(0, 40, 0, false);
delay(200);
// Second loop of the 8 (opposite direction)
for(int i = 0; i < 8; i++) {
Velocity_Controller(0, 50, -30, false); // Forward with right turn
delay(300);
}
stopRobot();
Serial.println(" Figure-8 pattern complete!");
delay(1000);
}
void Motor_Init(void) {
// Initialize all motor direction pins as outputs
for(uint8_t i = 0; i < 4; i++) {
pinMode(motordirectionPin[i], OUTPUT);
}
// Stop all motors initially
Velocity_Controller(0, 0, 0, false);
}
void Velocity_Controller(uint16_t angle, uint8_t velocity, int8_t rot, bool drift) {
// Advanced velocity controller using Hiwonder's algorithm
int8_t velocity_0, velocity_1, velocity_2, velocity_3;
float speed = 1;
angle += 90; // Adjust for coordinate system
float rad = angle * PI / 180;
// Adjust speed based on rotation
if (rot == 0) speed = 1;
else speed = 0.5;
velocity /= sqrt(2);
// Calculate individual motor velocities
if (drift) {
// Drift mode - special algorithm for drifting movements
velocity_0 = (velocity * sin(rad) - velocity * cos(rad)) * speed;
velocity_1 = (velocity * sin(rad) + velocity * cos(rad)) * speed;
velocity_2 = (velocity * sin(rad) - velocity * cos(rad)) * speed - rot * speed * 2;
velocity_3 = (velocity * sin(rad) + velocity * cos(rad)) * speed + rot * speed * 2;
} else {
// Normal mode
velocity_0 = (velocity * sin(rad) - velocity * cos(rad)) * speed + rot * speed;
velocity_1 = (velocity * sin(rad) + velocity * cos(rad)) * speed - rot * speed;
velocity_2 = (velocity * sin(rad) - velocity * cos(rad)) * speed - rot * speed;
velocity_3 = (velocity * sin(rad) + velocity * cos(rad)) * speed + rot * speed;
}
// Apply velocities to motors
Motors_Set(velocity_0, velocity_1, velocity_2, velocity_3);
}
void Motors_Set(int8_t Motor_0, int8_t Motor_1, int8_t Motor_2, int8_t Motor_3) {
// Set individual motor speeds and directions
int8_t pwm_set[4];
int8_t motors[4] = {Motor_0, Motor_1, Motor_2, Motor_3};
bool direction[4] = {1, 0, 0, 1}; // Default forward directions
for(uint8_t i = 0; i < 4; ++i) {
// Handle direction based on motor value sign
if(motors[i] < 0) direction[i] = !direction[i];
// Set PWM value
if(motors[i] == 0) pwm_set[i] = 0;
else pwm_set[i] = map(abs(motors[i]), 0, 100, pwm_min, 255);
// Apply to hardware
digitalWrite(motordirectionPin[i], direction[i]);
analogWrite(motorpwmPin[i], pwm_set[i]);
}
}
void stopRobot() {
// Stop all motors immediately
Velocity_Controller(0, 0, 0, false);
Serial.println(" Robot stopped.");
}
void flashLED(int times) {
// Flash status LED specified number of times
for(int i = 0; i < times; i++) {
digitalWrite(statusLED, LOW);
delay(150);
digitalWrite(statusLED, HIGH);
delay(150);
}
} The following programs are based on the official Hiwonder miniAuto documentation and provide comprehensive motor testing capabilities using the manufacturer's advanced control functions.
Tests basic forward movement and in-place rotation using the Hiwonder velocity controller system. The robot moves forward for 1 second, turns left for 1 second, then turns right for 1 second.
// 5.2 Forward Movement & Turning Test
#include <Arduino.h>
const static uint8_t pwm_min = 50;
const static uint8_t motorpwmPin[4] = {10, 9, 6, 11}; // Motor PWM pins
const static uint8_t motordirectionPin[4] = {12, 8, 7, 13}; // Motor direction pins
void Motor_Init(void);
void Velocity_Controller(uint16_t angle, uint8_t velocity, int8_t rot, bool drift);
void Motors_Set(int8_t Motor_0, int8_t Motor_1, int8_t Motor_2, int8_t Motor_3);
void setup() {
Serial.begin(9600);
Serial.setTimeout(500);
Motor_Init();
Velocity_Controller(0, 100, 0, 0); // Move forward
delay(1000);
Velocity_Controller(0, 0, 100, 0); // Turn left in place
delay(1000);
Velocity_Controller(0, 0, -100, 0); // Turn right in place
delay(1000);
Velocity_Controller(0, 0, 0, 0); // Stop
}
void loop() {
// Empty - single test sequence
}
void Motor_Init(void) {
for(uint8_t i = 0; i < 4; i++) {
pinMode(motordirectionPin[i], OUTPUT);
}
Velocity_Controller(0, 0, 0, 0);
}
void Velocity_Controller(uint16_t angle, uint8_t velocity, int8_t rot, bool drift) {
int8_t velocity_0, velocity_1, velocity_2, velocity_3;
float speed = 1;
angle += 90;
float rad = angle * PI / 180;
if (rot == 0) speed = 1;
else speed = 0.5;
velocity /= sqrt(2);
if (drift) {
velocity_0 = (velocity * sin(rad) - velocity * cos(rad)) * speed;
velocity_1 = (velocity * sin(rad) + velocity * cos(rad)) * speed;
velocity_2 = (velocity * sin(rad) - velocity * cos(rad)) * speed - rot * speed * 2;
velocity_3 = (velocity * sin(rad) + velocity * cos(rad)) * speed + rot * speed * 2;
} else {
velocity_0 = (velocity * sin(rad) - velocity * cos(rad)) * speed + rot * speed;
velocity_1 = (velocity * sin(rad) + velocity * cos(rad)) * speed - rot * speed;
velocity_2 = (velocity * sin(rad) - velocity * cos(rad)) * speed - rot * speed;
velocity_3 = (velocity * sin(rad) + velocity * cos(rad)) * speed + rot * speed;
}
Motors_Set(velocity_0, velocity_1, velocity_2, velocity_3);
}
void Motors_Set(int8_t Motor_0, int8_t Motor_1, int8_t Motor_2, int8_t Motor_3) {
int8_t pwm_set[4];
int8_t motors[4] = {Motor_0, Motor_1, Motor_2, Motor_3};
bool direction[4] = {1, 0, 0, 1}; // Forward direction defaults
for(uint8_t i = 0; i < 4; ++i) {
if(motors[i] < 0) direction[i] = !direction[i];
if(motors[i] == 0) pwm_set[i] = 0;
else pwm_set[i] = map(abs(motors[i]), 0, 100, pwm_min, 255);
digitalWrite(motordirectionPin[i], direction[i]);
analogWrite(motorpwmPin[i], pwm_set[i]);
}
} When you upload and run this code, your miniAuto should perform the following sequence:
💡 Troubleshooting: If the robot moves in unexpected directions, check your wiring connections and ensure the Bluetooth module is removed during upload.
🎬 Watch Official Demo: View Hiwonder GIF demonstration of this movement sequence.
Tests all four basic movement directions: forward, backward, left strafe, and right strafe. Each movement lasts 1 second, demonstrating the full omnidirectional capabilities of mecanum wheels.
// 5.3 Four-Direction Movement Test
#include <Arduino.h>
const static uint8_t pwm_min = 50;
const static uint8_t motorpwmPin[4] = {10, 9, 6, 11}; // Motor PWM pins
const static uint8_t motordirectionPin[4] = {12, 8, 7, 13}; // Motor direction pins
void Motor_Init(void);
void Velocity_Controller(uint16_t angle, uint8_t velocity, int8_t rot, bool drift);
void Motors_Set(int8_t Motor_0, int8_t Motor_1, int8_t Motor_2, int8_t Motor_3);
void setup() {
Serial.begin(9600);
Serial.setTimeout(500);
Motor_Init();
Serial.println("Starting 4-direction movement test...");
// Forward movement
Serial.println("Moving Forward");
Velocity_Controller(0, 100, 0, 0);
delay(1000);
Velocity_Controller(0, 0, 0, 0); // Stop
delay(500);
// Backward movement
Serial.println("Moving Backward");
Velocity_Controller(180, 100, 0, 0);
delay(1000);
Velocity_Controller(0, 0, 0, 0); // Stop
delay(500);
// Left strafe
Serial.println("Moving Left");
Velocity_Controller(270, 100, 0, 0);
delay(1000);
Velocity_Controller(0, 0, 0, 0); // Stop
delay(500);
// Right strafe
Serial.println("Moving Right");
Velocity_Controller(90, 100, 0, 0);
delay(1000);
Velocity_Controller(0, 0, 0, 0); // Stop
Serial.println("4-direction test complete!");
}
void loop() {
// Empty - single test sequence
}
void Motor_Init(void) {
for(uint8_t i = 0; i < 4; i++) {
pinMode(motordirectionPin[i], OUTPUT);
}
Velocity_Controller(0, 0, 0, 0);
}
void Velocity_Controller(uint16_t angle, uint8_t velocity, int8_t rot, bool drift) {
int8_t velocity_0, velocity_1, velocity_2, velocity_3;
float speed = 1;
angle += 90;
float rad = angle * PI / 180;
if (rot == 0) speed = 1;
else speed = 0.5;
velocity /= sqrt(2);
if (drift) {
velocity_0 = (velocity * sin(rad) - velocity * cos(rad)) * speed;
velocity_1 = (velocity * sin(rad) + velocity * cos(rad)) * speed;
velocity_2 = (velocity * sin(rad) - velocity * cos(rad)) * speed - rot * speed * 2;
velocity_3 = (velocity * sin(rad) + velocity * cos(rad)) * speed + rot * speed * 2;
} else {
velocity_0 = (velocity * sin(rad) - velocity * cos(rad)) * speed + rot * speed;
velocity_1 = (velocity * sin(rad) + velocity * cos(rad)) * speed - rot * speed;
velocity_2 = (velocity * sin(rad) - velocity * cos(rad)) * speed - rot * speed;
velocity_3 = (velocity * sin(rad) + velocity * cos(rad)) * speed + rot * speed;
}
Motors_Set(velocity_0, velocity_1, velocity_2, velocity_3);
}
void Motors_Set(int8_t Motor_0, int8_t Motor_1, int8_t Motor_2, int8_t Motor_3) {
int8_t pwm_set[4];
int8_t motors[4] = {Motor_0, Motor_1, Motor_2, Motor_3};
bool direction[4] = {1, 0, 0, 1}; // Forward direction defaults
for(uint8_t i = 0; i < 4; ++i) {
if(motors[i] < 0) direction[i] = !direction[i];
if(motors[i] == 0) pwm_set[i] = 0;
else pwm_set[i] = map(abs(motors[i]), 0, 100, pwm_min, 255);
digitalWrite(motordirectionPin[i], direction[i]);
analogWrite(motorpwmPin[i], pwm_set[i]);
}
} When you upload and run this code, your miniAuto should demonstrate omnidirectional movement:
🔍 Key Observation: Notice how the robot maintains its orientation while moving in all four directions - this is the power of mecanum wheels!
🎬 Watch Official Demo: View Hiwonder GIF demonstration of four-direction movement.
Tests diagonal movements by controlling specific wheel combinations. Demonstrates advanced mecanum wheel kinematics: forward-left, backward-right, forward-right, and backward-left movements.
// 5.4 Diagonal Movement Test
#include <Arduino.h>
const static uint8_t pwm_min = 50;
const static uint8_t motorpwmPin[4] = {10, 9, 6, 11}; // Motor PWM pins
const static uint8_t motordirectionPin[4] = {12, 8, 7, 13}; // Motor direction pins
void Motor_Init(void);
void Velocity_Controller(uint16_t angle, uint8_t velocity, int8_t rot, bool drift);
void Motors_Set(int8_t Motor_0, int8_t Motor_1, int8_t Motor_2, int8_t Motor_3);
void setup() {
Serial.begin(9600);
Serial.setTimeout(500);
Motor_Init();
Serial.println("Starting diagonal movement test...");
// Forward-Left diagonal
Serial.println("Moving Forward-Left");
Velocity_Controller(315, 100, 0, 0); // 45° angle for diagonal
delay(1000);
Velocity_Controller(0, 0, 0, 0); // Stop
delay(500);
// Backward-Right diagonal
Serial.println("Moving Backward-Right");
Velocity_Controller(135, 100, 0, 0); // 135° angle
delay(1000);
Velocity_Controller(0, 0, 0, 0); // Stop
delay(500);
// Forward-Right diagonal
Serial.println("Moving Forward-Right");
Velocity_Controller(45, 100, 0, 0); // 45° angle
delay(1000);
Velocity_Controller(0, 0, 0, 0); // Stop
delay(500);
// Backward-Left diagonal
Serial.println("Moving Backward-Left");
Velocity_Controller(225, 100, 0, 0); // 225° angle
delay(1000);
Velocity_Controller(0, 0, 0, 0); // Stop
Serial.println("Diagonal movement test complete!");
}
void loop() {
// Empty - single test sequence
}
void Motor_Init(void) {
for(uint8_t i = 0; i < 4; i++) {
pinMode(motordirectionPin[i], OUTPUT);
}
Velocity_Controller(0, 0, 0, 0);
}
void Velocity_Controller(uint16_t angle, uint8_t velocity, int8_t rot, bool drift) {
int8_t velocity_0, velocity_1, velocity_2, velocity_3;
float speed = 1;
angle += 90;
float rad = angle * PI / 180;
if (rot == 0) speed = 1;
else speed = 0.5;
velocity /= sqrt(2);
if (drift) {
velocity_0 = (velocity * sin(rad) - velocity * cos(rad)) * speed;
velocity_1 = (velocity * sin(rad) + velocity * cos(rad)) * speed;
velocity_2 = (velocity * sin(rad) - velocity * cos(rad)) * speed - rot * speed * 2;
velocity_3 = (velocity * sin(rad) + velocity * cos(rad)) * speed + rot * speed * 2;
} else {
velocity_0 = (velocity * sin(rad) - velocity * cos(rad)) * speed + rot * speed;
velocity_1 = (velocity * sin(rad) + velocity * cos(rad)) * speed - rot * speed;
velocity_2 = (velocity * sin(rad) - velocity * cos(rad)) * speed - rot * speed;
velocity_3 = (velocity * sin(rad) + velocity * cos(rad)) * speed + rot * speed;
}
Motors_Set(velocity_0, velocity_1, velocity_2, velocity_3);
}
void Motors_Set(int8_t Motor_0, int8_t Motor_1, int8_t Motor_2, int8_t Motor_3) {
int8_t pwm_set[4];
int8_t motors[4] = {Motor_0, Motor_1, Motor_2, Motor_3};
bool direction[4] = {1, 0, 0, 1}; // Forward direction defaults
for(uint8_t i = 0; i < 4; ++i) {
if(motors[i] < 0) direction[i] = !direction[i];
if(motors[i] == 0) pwm_set[i] = 0;
else pwm_set[i] = map(abs(motors[i]), 0, 100, pwm_min, 255);
digitalWrite(motordirectionPin[i], direction[i]);
analogWrite(motorpwmPin[i], pwm_set[i]);
}
} When you upload and run this code, your miniAuto should demonstrate advanced diagonal movements:
⚡ Advanced Feature: These diagonal movements showcase the sophisticated kinematics possible with mecanum wheels - impossible with regular wheels!
🎬 Watch Official Demo: View Hiwonder GIF demonstration of diagonal movements.
Tests advanced drifting capabilities where the robot moves sideways while rotating. This demonstrates the drift parameter in the velocity controller, creating car-like drifting motion.
// 5.5 Drifting Movement Test
#include <Arduino.h>
const static uint8_t pwm_min = 50;
const static uint8_t motorpwmPin[4] = {10, 9, 6, 11}; // Motor PWM pins
const static uint8_t motordirectionPin[4] = {12, 8, 7, 13}; // Motor direction pins
void Motor_Init(void);
void Velocity_Controller(uint16_t angle, uint8_t velocity, int8_t rot, bool drift);
void Motors_Set(int8_t Motor_0, int8_t Motor_1, int8_t Motor_2, int8_t Motor_3);
void setup() {
Serial.begin(9600);
Serial.setTimeout(500);
Motor_Init();
Serial.println("Starting drift movement test...");
// Clockwise drift
Serial.println("Drifting Clockwise");
Velocity_Controller(90, 80, 50, true); // Right movement with rotation and drift enabled
delay(2000);
Velocity_Controller(0, 0, 0, 0); // Stop
delay(1000);
// Counter-clockwise drift
Serial.println("Drifting Counter-Clockwise");
Velocity_Controller(270, 80, -50, true); // Left movement with opposite rotation and drift
delay(2000);
Velocity_Controller(0, 0, 0, 0); // Stop
delay(1000);
// Forward drift with rotation
Serial.println("Forward Drift with Rotation");
Velocity_Controller(0, 60, 40, true); // Forward with rotation and drift
delay(2000);
Velocity_Controller(0, 0, 0, 0); // Stop
Serial.println("Drift test complete!");
}
void loop() {
// Empty - single test sequence
}
void Motor_Init(void) {
for(uint8_t i = 0; i < 4; i++) {
pinMode(motordirectionPin[i], OUTPUT);
}
Velocity_Controller(0, 0, 0, 0);
}
void Velocity_Controller(uint16_t angle, uint8_t velocity, int8_t rot, bool drift) {
int8_t velocity_0, velocity_1, velocity_2, velocity_3;
float speed = 1;
angle += 90;
float rad = angle * PI / 180;
if (rot == 0) speed = 1;
else speed = 0.5;
velocity /= sqrt(2);
if (drift) {
velocity_0 = (velocity * sin(rad) - velocity * cos(rad)) * speed;
velocity_1 = (velocity * sin(rad) + velocity * cos(rad)) * speed;
velocity_2 = (velocity * sin(rad) - velocity * cos(rad)) * speed - rot * speed * 2;
velocity_3 = (velocity * sin(rad) + velocity * cos(rad)) * speed + rot * speed * 2;
} else {
velocity_0 = (velocity * sin(rad) - velocity * cos(rad)) * speed + rot * speed;
velocity_1 = (velocity * sin(rad) + velocity * cos(rad)) * speed - rot * speed;
velocity_2 = (velocity * sin(rad) - velocity * cos(rad)) * speed - rot * speed;
velocity_3 = (velocity * sin(rad) + velocity * cos(rad)) * speed + rot * speed;
}
Motors_Set(velocity_0, velocity_1, velocity_2, velocity_3);
}
void Motors_Set(int8_t Motor_0, int8_t Motor_1, int8_t Motor_2, int8_t Motor_3) {
int8_t pwm_set[4];
int8_t motors[4] = {Motor_0, Motor_1, Motor_2, Motor_3};
bool direction[4] = {1, 0, 0, 1}; // Forward direction defaults
for(uint8_t i = 0; i < 4; ++i) {
if(motors[i] < 0) direction[i] = !direction[i];
if(motors[i] == 0) pwm_set[i] = 0;
else pwm_set[i] = map(abs(motors[i]), 0, 100, pwm_min, 255);
digitalWrite(motordirectionPin[i], direction[i]);
analogWrite(motorpwmPin[i], pwm_set[i]);
}
} When you upload and run this code, your miniAuto should demonstrate spectacular drifting movements:
🏎️ Cool Factor: This is the most impressive test - your robot will look like it's performing automotive-style drifts! Perfect for demonstrations.
🎬 Watch Official Demo: View Hiwonder GIF demonstration of drifting movements.
Each demo is a separate program you can upload and run independently. Upload the code, disconnect the USB cable, and watch your robot perform the movement pattern without being tethered to your computer!
Tests all basic movements: forward, backward, left, right, and rotations. Perfect for verifying your robot works correctly.
// Demo 1: Basic Movement Test
// Upload this code, disconnect USB, and watch your robot move!
const static uint8_t motorpwmPin[4] = {10, 9, 6, 11};
const static uint8_t motordirectionPin[4] = {12, 8, 7, 13};
const static uint8_t pwm_min = 50;
void setup() {
Motor_Init();
delay(3000); // Wait 3 seconds after power on
}
void loop() {
// Forward movement
Velocity_Controller(0, 80, 0, false);
delay(2000);
stopRobot();
delay(1000);
// Backward movement
Velocity_Controller(180, 80, 0, false);
delay(2000);
stopRobot();
delay(1000);
// Left strafe
Velocity_Controller(270, 80, 0, false);
delay(2000);
stopRobot();
delay(1000);
// Right strafe
Velocity_Controller(90, 80, 0, false);
delay(2000);
stopRobot();
delay(1000);
// Clockwise rotation
Velocity_Controller(0, 0, -60, false);
delay(2000);
stopRobot();
delay(1000);
// Counter-clockwise rotation
Velocity_Controller(0, 0, 60, false);
delay(2000);
stopRobot();
delay(5000); // Wait 5 seconds before repeating
}
// Motor control functions (include in all demos)
void Motor_Init(void) {
for(uint8_t i = 0; i < 4; i++) {
pinMode(motordirectionPin[i], OUTPUT);
}
Velocity_Controller(0, 0, 0, false);
}
void Velocity_Controller(uint16_t angle, uint8_t velocity, int8_t rot, bool drift) {
int8_t velocity_0, velocity_1, velocity_2, velocity_3;
float speed = 1;
angle += 90;
float rad = angle * PI / 180;
if (rot == 0) speed = 1;
else speed = 0.5;
velocity /= sqrt(2);
if (drift) {
velocity_0 = (velocity * sin(rad) - velocity * cos(rad)) * speed;
velocity_1 = (velocity * sin(rad) + velocity * cos(rad)) * speed;
velocity_2 = (velocity * sin(rad) - velocity * cos(rad)) * speed - rot * speed * 2;
velocity_3 = (velocity * sin(rad) + velocity * cos(rad)) * speed + rot * speed * 2;
} else {
velocity_0 = (velocity * sin(rad) - velocity * cos(rad)) * speed + rot * speed;
velocity_1 = (velocity * sin(rad) + velocity * cos(rad)) * speed - rot * speed;
velocity_2 = (velocity * sin(rad) - velocity * cos(rad)) * speed - rot * speed;
velocity_3 = (velocity * sin(rad) + velocity * cos(rad)) * speed + rot * speed;
}
Motors_Set(velocity_0, velocity_1, velocity_2, velocity_3);
}
void Motors_Set(int8_t Motor_0, int8_t Motor_1, int8_t Motor_2, int8_t Motor_3) {
int8_t pwm_set[4];
int8_t motors[4] = {Motor_0, Motor_1, Motor_2, Motor_3};
bool direction[4] = {1, 0, 0, 1};
for(uint8_t i = 0; i < 4; ++i) {
if(motors[i] < 0) direction[i] = !direction[i];
if(motors[i] == 0) pwm_set[i] = 0;
else pwm_set[i] = map(abs(motors[i]), 0, 100, pwm_min, 255);
digitalWrite(motordirectionPin[i], direction[i]);
analogWrite(motorpwmPin[i], pwm_set[i]);
}
}
void stopRobot() {
Velocity_Controller(0, 0, 0, false);
} Makes your robot draw a perfect square using forward movement and 90-degree turns. Note: Turn timing has been calibrated for accurate 90° rotations.
// Demo 2: Square Pattern
// Upload, disconnect, and watch your robot draw a square!
const static uint8_t motorpwmPin[4] = {10, 9, 6, 11};
const static uint8_t motordirectionPin[4] = {12, 8, 7, 13};
const static uint8_t pwm_min = 50;
void setup() {
Motor_Init();
delay(3000); // Wait 3 seconds after power on
}
void loop() {
// Draw a square (4 sides with 4 turns)
for(int i = 0; i < 4; i++) {
// Move forward for one side
Velocity_Controller(0, 70, 0, false);
delay(2500);
// Stop briefly
stopRobot();
delay(500);
// Turn right 90 degrees
Velocity_Controller(0, 0, -50, false);
delay(1100);
// Stop briefly
stopRobot();
delay(500);
}
// Wait 10 seconds before drawing another square
delay(10000);
}
// Include motor control functions here (same as Demo 1)
// [Motor_Init, Velocity_Controller, Motors_Set, stopRobot functions]
The delay(1100) value has been tested on ceramic tile floors for accurate 90° turns:
• Smooth surfaces (tile, hardwood): Use delay(1100)
• Carpet or rough surfaces: May need delay(1200-1300)
• Turns too much? Reduce to delay(1000)
• Turns too little? Increase to delay(1200)
• Battery level affects rotation speed - fresh batteries may need less time
For more accurate navigation, robots can use sensors instead of timing:
• IMU/Gyroscope: Measures actual rotation angles (±1° accuracy)
• Magnetometer/Compass: Provides absolute directional heading
• Encoders: Count wheel rotations for precise distance measurement
• Future lesson: We'll explore adding these sensors to miniAuto!
Creates smooth circular motion by combining forward movement with continuous rotation.
// Demo 3: Circle Pattern
// Upload, disconnect, and watch your robot draw circles!
const static uint8_t motorpwmPin[4] = {10, 9, 6, 11};
const static uint8_t motordirectionPin[4] = {12, 8, 7, 13};
const static uint8_t pwm_min = 50;
void setup() {
Motor_Init();
delay(3000); // Wait 3 seconds after power on
}
void loop() {
// Draw a circle using forward movement + rotation
for(int i = 0; i < 25; i++) {
Velocity_Controller(0, 60, 30, false); // Forward with left turn
delay(400);
}
// Stop and wait
stopRobot();
delay(3000);
// Draw circle in opposite direction
for(int i = 0; i < 25; i++) {
Velocity_Controller(0, 60, -30, false); // Forward with right turn
delay(400);
}
// Stop and wait before repeating
stopRobot();
delay(5000);
}
// Include motor control functions here (same as Demo 1)
// [Motor_Init, Velocity_Controller, Motors_Set, stopRobot functions] Shows off the advanced drift capabilities - the most impressive demo for audiences!
// Demo 4: Drift Showcase
// Upload, disconnect, and watch impressive drift movements!
const static uint8_t motorpwmPin[4] = {10, 9, 6, 11};
const static uint8_t motordirectionPin[4] = {12, 8, 7, 13};
const static uint8_t pwm_min = 50;
void setup() {
Motor_Init();
delay(3000); // Wait 3 seconds after power on
}
void loop() {
// Right drift
Velocity_Controller(90, 70, 50, true);
delay(2500);
stopRobot();
delay(1000);
// Left drift
Velocity_Controller(270, 70, -50, true);
delay(2500);
stopRobot();
delay(1000);
// Forward spiral drift
Velocity_Controller(0, 60, 60, true);
delay(3000);
stopRobot();
delay(1000);
// Backward spiral drift
Velocity_Controller(180, 60, -60, true);
delay(3000);
stopRobot();
delay(5000); // Wait before repeating
}
// Include motor control functions here (same as Demo 1)
// [Motor_Init, Velocity_Controller, Motors_Set, stopRobot functions]