The Objective: To engineer a high-speed, autonomous differential-drive robot capable of navigating complex trajectories defined by high-contrast visual markers. The project focuses on implementing a real-time closed-loop control system that dynamically adjusts motor velocity based on continuous sensor feedback. This system serves as a foundational prototype for automated guided vehicles (AGVs) used in industrial logistics.
System Architecture: The robot is built upon the Arduino Nano (ATmega328P) architecture, chosen for its small form factor and efficient interrupt handling. It employs a sensor fusion strategy using dual Infrared (IR) Reflectance sensors to constantly poll the surface albedo. This data is processed by a custom control algorithm that drives a Dual H-Bridge (L293D), allowing for precise differential steering and rapid course correction.
Power Electronics Challenge: A critical engineering hurdle was power delivery. Standard 6V setups suffer from voltage sag under load, causing processor brownouts. I engineered a robust 12V DC Rail (8x AA Series Configuration). This high-voltage rail drives the DC motors directly to overcome static friction (stiction) during sharp turns, while the Arduino's onboard linear regulator steps it down to a stable 5V logic level, ensuring processor stability even during peak current draw.
System Validation: Dynamic Path Tracking & Motor Response
The hardware was selected to balance weight, torque, and computational efficiency.
To ensure reliability during autonomous operation, the power distribution network was split into two isolated domains.
TCCR0B register to increase PWM frequency, ensuring smoother motor response curves.The robot operates on a high-frequency polling loop that implements a Bang-Bang Control System. By treating the line position as a binary error state, the system applies immediate corrective torque to the opposing motor. This approach minimizes computation time, allowing for faster reaction speeds compared to float-heavy PID loops on 8-bit controllers.
| State Vector | Left Sensor (IR) | Right Sensor (IR) | Control Action (Differential Drive) | System Behavior |
|---|---|---|---|---|
| On Track | Low (0) | Low (0) | Left: FWD | Right: FWD | Maintains linear velocity (Error = 0). |
| Right Deviation | Low (0) | High (1) | Left: FWD | Right: REV | Rapid Pivot Right to correct heading. |
| Left Deviation | High (1) | Low (0) | Left: REV | Right: FWD | Rapid Pivot Left to correct heading. |
| Stop Condition | High (1) | High (1) | Left: STOP | Right: STOP | Destination Reached / Intersection Hold. |
The following C++ firmware demonstrates advanced embedded concepts, including direct register manipulation for PWM frequency optimization (`TCCR0B`), bitwise operations for sensor fusion, and modular driver design. The code is structured for modularity and scalability.
// Define pins for the IR sensors #define IR_SENSOR_RIGHT 11 // Right IR sensor connected to pin 11 #define IR_SENSOR_LEFT 12 // Left IR sensor connected to pin 12 // Define the motor speed #define MOTOR_SPEED 180 // Motor speed (PWM value between 0-255) // Define pins for the right motor const int enableRightMotor = 6; // PWM pin to control the speed of the right motor const int rightMotorPin1 = 7; // Pin to control the direction of the right motor (forward) const int rightMotorPin2 = 8; // Pin to control the direction of the right motor (backward) // Define pins for the left motor const int enableLeftMotor = 5; // PWM pin to control the speed of the left motor const int leftMotorPin1 = 9; // Pin to control the direction of the left motor (forward) const int leftMotorPin2 = 10; // Pin to control the direction of the left motor (backward) // Function prototypes for modular code void setupMotors(); // Sets up the motor control pins void setPWMFrequency(); // Adjusts the PWM frequency for smoother motor control void controlMotors(int leftSpeed, int rightSpeed); // Controls motor speed and direction int readLineSensors(); // Reads the IR sensors and returns a combined binary value void setup() { // Initialize motor pins setupMotors(); // Adjust the PWM frequency for smoother motor control setPWMFrequency(); // Initialize sensor pins as inputs pinMode(IR_SENSOR_RIGHT, INPUT); pinMode(IR_SENSOR_LEFT, INPUT); // Stop motors initially to ensure the robot does not move controlMotors(0, 0); } void loop() { // Read the sensor values and determine the state of the robot int sensorState = readLineSensors(); // Perform actions based on the sensor state using a switch-case statement switch (sensorState) { case 0b00: // No line detected by either sensor controlMotors(MOTOR_SPEED, MOTOR_SPEED); // Move straight break; case 0b01: // Line detected by the left sensor only controlMotors(MOTOR_SPEED, -MOTOR_SPEED); // Turn left break; case 0b10: // Line detected by the right sensor only controlMotors(-MOTOR_SPEED, MOTOR_SPEED); // Turn right break; case 0b11: // Line detected by both sensors controlMotors(0, 0); // Stop the robot break; default: // Fallback case to stop the robot for safety controlMotors(0, 0); } } // Function to initialize motor pins void setupMotors() { // Set motor control pins as outputs pinMode(enableRightMotor, OUTPUT); pinMode(rightMotorPin1, OUTPUT); pinMode(rightMotorPin2, OUTPUT); pinMode(enableLeftMotor, OUTPUT); pinMode(leftMotorPin1, OUTPUT); pinMode(leftMotorPin2, OUTPUT); } // Function to adjust PWM frequency for smoother motor control void setPWMFrequency() { // Set PWM frequency for pins 5 and 6 (Timer0) // Timer0 default frequency is ~490 Hz; this changes it to ~7812.5 Hz TCCR0B = TCCR0B & 0b11111000 | 0b00000010; } // Function to control motor speed and direction void controlMotors(int rightSpeed, int leftSpeed) { // Control the right motor direction digitalWrite(rightMotorPin1, rightSpeed > 0); // Forward if speed > 0 digitalWrite(rightMotorPin2, rightSpeed < 0); // Backward if speed < 0 // Control the left motor direction digitalWrite(leftMotorPin1, leftSpeed > 0); // Forward if speed > 0 digitalWrite(leftMotorPin2, leftSpeed < 0); // Backward if speed < 0 // Control the motor speeds using PWM analogWrite(enableRightMotor, abs(rightSpeed)); // Set speed for the right motor analogWrite(enableLeftMotor, abs(leftSpeed)); // Set speed for the left motor } // Function to read IR sensors and return a combined binary value int readLineSensors() { // Read the state of the right and left IR sensors int rightSensor = digitalRead(IR_SENSOR_RIGHT); // 0 = no line, 1 = line detected int leftSensor = digitalRead(IR_SENSOR_LEFT); // 0 = no line, 1 = line detected // Combine the two sensor readings into a single binary number // Example: if rightSensor = 1 and leftSensor = 0, the result will be 0b10 (decimal 2) return (rightSensor << 1) | leftSensor; }