Autonomous Dynamic Sensor RC Automobile - an Arduino Project

by sabethonlouis5 in Circuits > Arduino

80 Views, 0 Favorites, 0 Comments

Autonomous Dynamic Sensor RC Automobile - an Arduino Project

IMG_2596.jpg
Copy of Swanky Blorr.png
Screenshot 2026-07-07 030952.png
Screenshot 2026-07-07 025457.png

This project is an Arduino-based object-detection RC car that can drive using four DC gearbox motors, avoid obstacles with ultrasonic sensors, and scan its surroundings using a servo-mounted distance sensor. I built it as a small robotics platform that combines CAD design, circuit simulation, soldering, and real-world testing into one project.

At first glance it may look like a basic Arduino car, but the goal was to make it more complete than just “connect motors and upload code.” I designed the layout, tested the wiring logic in Tinkercad, used a motor driver for proper motor control, added a fixed front safety sensor, added a second scanning ultrasonic sensor on a servo, and planned the wiring so the same control logic could transfer from simulation to the real DRV8833 driver.

The car uses skid steering, which means the two left motors always move together and the two right motors always move together. Driving both sides forward moves the car straight. Reversing one side while driving the other forward makes the car pivot.

This build is meant to show the full engineering process: planning, simulation, wiring, coding, troubleshooting, and final assembly.

Supplies

IMG_2597.jpg

Electronics

  1. Arduino Uno R3
  2. DRV8833 Dual Motor Driver Carrier
  3. 4x TT yellow DC gearbox motors
  4. 2x HC-SR04 ultrasonic distance sensors
  5. Micro servo, SG90/SG92R style
  6. IR receiver and IR remote
  7. Jumper wires
  8. Breadboard or solderable prototyping board
  9. Battery pack for motor power, preferably 4xAA or 6V range
  10. Battery pack or USB power for Arduino
  11. Capacitor for motor power smoothing, such as 100 µF to 470 µF
  12. Optional heat sinks for the motor driver

Chassis / Mechanical Parts

  1. 3D printed chassis or laser-cut/cardboard/acrylic chassis
  2. 4 wheels compatible with TT motors
  3. Screws, nuts, spacers, or hot glue
  4. Small platform/bracket for the servo-mounted ultrasonic sensor
  5. Zip ties or tape for wire management

Tools

  1. Computer with Arduino IDE
  2. Tinkercad Circuits
  3. Soldering iron
  4. Solder
  5. Wire cutters / wire strippers
  6. Screwdriver
  7. Multimeter, optional but very useful

Design the Car Before Wiring Anything

FL63KKGMR0YB3GE.png

Before wiring the circuit, I planned the basic layout of the car. I wanted the final robot to be compact, but still easy to troubleshoot. The important design choices were:

  1. Four powered wheels for better traction.
  2. Skid steering instead of a steering rack.
  3. A fixed front ultrasonic sensor for quick obstacle detection.
  4. A second ultrasonic sensor mounted on a servo so the car can scan left and right.
  5. A motor driver placed near the motors to keep motor wiring short.
  6. The Arduino placed where USB access would still be easy.

The main reason for using skid steering is simplicity. Instead of building a steering mechanism, the car turns by changing the direction of the left and right motor pairs. This is how many tank-style robots drive.

The left front and left rear motors are wired together as one side. The right front and right rear motors are wired together as the other side. That gives the robot four-wheel drive while only needing two motor channels.

Simulate the Circuit in Tinkercad

Screenshot 2026-07-07 030503.png
FFTZ1QKMR0YB3G7.png

Tinkercad does not include the DRV8833 motor driver, so I used the L293D motor driver as a simulation stand-in. The exact physical pinout is different, but the control idea is the same: each motor channel has two input pins, and the Arduino controls direction by setting one input HIGH and the other LOW.

The simulated pin map was:

FunctionArduino Pin

Front ultrasonic TRIG

D2

Front ultrasonic ECHO

D3

Sweep ultrasonic TRIG

D4

Left motor IN1

D5

Left motor IN2

D6

Right motor IN1

D7

Right motor IN2

D8

Servo signal

D9

IR receiver signal

D11

Sweep ultrasonic ECHO

D12

The fixed front sensor is the safety sensor. It checks directly in front of the car. The sweep sensor is used for navigation. It moves left and right on the servo and records which direction has the most open space.

One of the most important wiring rules is that all grounds must connect together. The Arduino, sensors, servo, motor driver, and motor battery all need a shared ground so the signals have the same reference point.

Power wiring:

FromTo

Arduino 5V

Sensor VCC, servo VCC, driver logic/enable

Motor battery +

Motor driver motor power input

Arduino GND

Shared ground

Motor battery –

Shared ground

Motor driver GND

Shared ground

For the real DRV8833, the motor battery connects to VM, not to the Arduino 5V pin. The Arduino 5V is only for logic-level parts like sensors and control signals.

Build the Chassis and Mount the Motors

Screenshot 2026-07-07 030913.png

I mounted the four TT gearbox motors so that each side of the car had two motors. Since this is a skid-steering robot, motor placement matters. Both motors on the left side should spin together, and both motors on the right side should spin together.

The left motors are wired in parallel to one motor-driver output pair. The right motors are wired in parallel to the other motor-driver output pair.

That means:

  1. Left front motor + and left rear motor + go to the same driver output.
  2. Left front motor – and left rear motor – go to the other output for that channel.
  3. Right front motor + and right rear motor + go to the same output on the second channel.
  4. Right front motor – and right rear motor – go to the other output for that channel.

If one motor spins backward compared to the other motor on the same side, flip that motor’s two wires. Both motors on the same side need to push the car in the same direction.

I also left enough room on top of the car for the Arduino, motor driver, batteries, and servo scanner.

Solder and Wire the DRV8833 Motor Driver

IMG_2598.jpg

The DRV8833 is the motor driver that controls the four motors. The Arduino pins cannot directly power four TT motors, so the motor driver acts like a switch that lets the Arduino control a separate motor power supply.

The DRV8833 has two motor channels. Since the car uses skid steering, one channel controls the left motor pair and one channel controls the right motor pair.

Basic DRV8833 wiring:

DRV8833 Pin Connects To

VM

Motor battery positive

GND

Shared ground

AIN1

Arduino D5

AIN2

Arduino D6

BIN1

Arduino D7

BIN2

Arduino D8

AOUT1 / AOUT2

Left motor pair

BOUT1 / BOUT2

Right motor pair

SLP / nSLEEP, if present

5V or pulled HIGH

I also added a capacitor across the motor power input. This helps reduce voltage dips when the motors start, stop, or suddenly reverse direction.

Important: the Arduino 5V pin should not be connected to the motor battery positive. The motor battery powers the motors through the driver. The Arduino 5V powers logic parts like sensors and servo signal logic. The shared connection between the two systems is ground.

Add the Sensors and Servo Scanner

F06MW4TMR0YB3HL.png

This car uses two ultrasonic sensors:

  1. A fixed front sensor.
  2. A servo-mounted sweep sensor.

The front sensor is like an emergency reflex. If the car gets too close to something, the code stops the motors, backs up, and turns.

The sweep sensor gives the robot more information. The servo moves the sensor from side to side, and the code keeps track of which angle has the most open space. When the car needs to turn, it uses that best open angle to decide whether to pivot left or right.

Sensor wiring:

PartSignal PinVCCGND

Front HC-SR04 TRIG

D2

5V

GND

Front HC-SR04 ECHO

D3

5V

GND

Sweep HC-SR04 TRIG

D4

5V

GND

Sweep HC-SR04 ECHO

D12

5V

GND

Servo signal

D9

5V

GND

IR receiver signal

D11

5V

GND

I tested the sensors separately before combining everything. This helped confirm that the servo and ultrasonic sensors were working before troubleshooting the motor system.

Upload the Code

Screenshot 2026-07-07 030811.png

Upload this code to the Arduino. It uses the fixed front sensor for obstacle detection, the sweep sensor for scanning, and the motor driver pins for skid steering.


#include <Servo.h>

#define FRONT_TRIG 2
#define FRONT_ECHO 3
#define SWEEP_TRIG 4
#define SWEEP_ECHO 12
#define LEFT_IN1 5
#define LEFT_IN2 6
#define RIGHT_IN1 7
#define RIGHT_IN2 8
#define SERVO_PIN 9

#define SAFE_DISTANCE_CM 15
#define SWEEP_MIN_ANGLE 30
#define SWEEP_MAX_ANGLE 150
#define SWEEP_STEP_DEGREES 15
#define SWEEP_STEP_INTERVAL_MS 60
#define SENSOR_TIMEOUT_US 20000
Before running the full code, I recommend testing one subsystem at a time:

Test the servo by sweeping from 30 to 150 degrees.
Test each ultrasonic sensor in the serial monitor.
Test the left motor pair alone.
Test the right motor pair alone.
Then test the full obstacle-avoidance code.

This makes troubleshooting much easier.
Servo sweepServo;

int sweepAngle = 90;
int sweepDirection = 1;
unsigned long lastSweepStepTime = 0;
long bestOpenDistance = 0;
int bestOpenAngle = 90;
unsigned long lastStatusPrintTime = 0;

long readDistanceCM(int trigPin, int echoPin) {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);

digitalWrite(trigPin, HIGH);
delayMicroseconds(10);

digitalWrite(trigPin, LOW);

unsigned long duration = pulseIn(echoPin, HIGH, SENSOR_TIMEOUT_US);

if (duration == 0) return -1;

return duration * 0.0343 / 2;
}

void setMotors(bool leftForward, bool leftActive, bool rightForward, bool rightActive) {
digitalWrite(LEFT_IN1, leftActive && leftForward);
digitalWrite(LEFT_IN2, leftActive && !leftForward);

digitalWrite(RIGHT_IN1, rightActive && rightForward);
digitalWrite(RIGHT_IN2, rightActive && !rightForward);
}

void driveForward() {
setMotors(true, true, true, true);
}

void driveBackward() {
setMotors(false, true, false, true);
}

void pivotLeft() {
setMotors(false, true, true, true);
}

void pivotRight() {
setMotors(true, true, false, true);
}

void stopMotors() {
setMotors(true, false, true, false);
}

void updateSweep() {
if (millis() - lastSweepStepTime < SWEEP_STEP_INTERVAL_MS) return;

lastSweepStepTime = millis();

sweepAngle += sweepDirection * SWEEP_STEP_DEGREES;

if (sweepAngle >= SWEEP_MAX_ANGLE) {
sweepAngle = SWEEP_MAX_ANGLE;
sweepDirection = -1;
bestOpenDistance = 0;
}

if (sweepAngle <= SWEEP_MIN_ANGLE) {
sweepAngle = SWEEP_MIN_ANGLE;
sweepDirection = 1;
bestOpenDistance = 0;
}

sweepServo.write(sweepAngle);
delay(50);

long distance = readDistanceCM(SWEEP_TRIG, SWEEP_ECHO);

if (distance < 0) {
Serial.println("SWEEP SENSOR: NO ECHO - CHECK TRIG/ECHO WIRING");
return;
}

if (distance > bestOpenDistance) {
bestOpenDistance = distance;
bestOpenAngle = sweepAngle;
}
}

void runObstacleAvoidance() {
long frontDistance = readDistanceCM(FRONT_TRIG, FRONT_ECHO);

if (frontDistance < 0) {
Serial.println("FRONT SENSOR: NO ECHO - CHECK TRIG/ECHO WIRING");
return;
}

if (frontDistance < SAFE_DISTANCE_CM) {
Serial.print("OBSTACLE DETECTED AT ");
Serial.print(frontDistance);
Serial.println(" CM - AVOIDING");

stopMotors();
delay(150);

driveBackward();
delay(300);

stopMotors();
delay(100);

if (bestOpenAngle < 90) {
Serial.println("TURNING LEFT TOWARD OPEN PATH");
pivotLeft();
} else {
Serial.println("TURNING RIGHT TOWARD OPEN PATH");
pivotRight();
}

delay(300);
stopMotors();
} else {
driveForward();
}
}

void printStatus() {
if (millis() - lastStatusPrintTime < 500) return;

lastStatusPrintTime = millis();

Serial.print("SWEEP ANGLE=");
Serial.print(sweepAngle);

Serial.print(" | BEST OPEN ANGLE=");
Serial.print(bestOpenAngle);

Serial.print(" | BEST OPEN DIST=");
Serial.print(bestOpenDistance);

Serial.println(" CM");
}

void setup() {
Serial.begin(9600);

pinMode(FRONT_TRIG, OUTPUT);
pinMode(FRONT_ECHO, INPUT);

pinMode(SWEEP_TRIG, OUTPUT);
pinMode(SWEEP_ECHO, INPUT);

pinMode(LEFT_IN1, OUTPUT);
pinMode(LEFT_IN2, OUTPUT);

pinMode(RIGHT_IN1, OUTPUT);
pinMode(RIGHT_IN2, OUTPUT);

stopMotors();

sweepServo.attach(SERVO_PIN);
sweepServo.write(sweepAngle);

Serial.println("SYSTEM READY");
}

void loop() {
updateSweep();
runObstacleAvoidance();
printStatus();
}

Before running the full code, I recommend testing one subsystem at a time:

  1. Test the servo by sweeping from 30 to 150 degrees.
  2. Test each ultrasonic sensor in the serial monitor.
  3. Test the left motor pair alone.
  4. Test the right motor pair alone.
  5. Then test the full obstacle-avoidance code.

This makes troubleshooting much easier.

Troubleshooting and Tuning

images.png

This project taught me that most robot problems are not caused by the code first. They are usually caused by wiring, power, or motor direction.

Here are the problems I checked during testing:

Motors do not spin

Check:

Motor battery positive goes to the motor driver motor power input.

Motor battery negative connects to shared ground.

Arduino ground connects to the same shared ground.

Motor driver sleep/enable pin is HIGH.

Motors are connected to driver outputs, not directly to Arduino pins.

The motor driver is not overheating.

The motor battery is not dead.

One side spins backward

Flip the two motor wires for that side, or reverse the HIGH/LOW logic in code.

Servo works but motors do not

That usually means the Arduino side is powered correctly, but the motor power side is not. Check VM, GND, and the motor driver output wiring.

Ultrasonic sensor says “NO ECHO”

Check the TRIG and ECHO pins. It is very easy to swap them. Also make sure the sensor has 5V and GND.

Car turns instead of going straight

One motor pair may be reversed, or one side may be weaker. First fix motor direction, then check battery power and friction.

Car resets when motors start

The motors are pulling too much current or causing voltage dips. Use a separate motor battery, add a capacitor across motor power, and make sure grounds are connected correctly.

Final Testing

images.jpg

For final testing, I placed the car on the floor with a few objects in front of it. I watched the serial monitor first to make sure the front sensor and sweep sensor were giving reasonable distances.

The final behavior I wanted was:

  1. Drive forward when the path is clear.
  2. Continuously scan left and right.
  3. Stop if the front sensor sees an obstacle too close.
  4. Reverse briefly.
  5. Turn toward the side with more open space.
  6. Continue driving.

This made the robot feel more intentional than a car that simply bumps into things or randomly turns. The sweep sensor gives it a basic way to “look around” before choosing a direction.

Conclusion

This project combines mechanical design, electronics, programming, and troubleshooting into one small robot. The most important part was not just making the car move, but building a system that could sense, decide, and react.

The final car uses four-wheel skid steering, a motor driver, two ultrasonic sensors, and a servo scanner. I also used Tinkercad to plan and test the wiring before moving to the real build. That saved time because I could confirm the logic before soldering and assembling everything.

If I built a second version, I would improve the chassis layout, add cleaner wire routing, and possibly add speed control using PWM. I would also add a more complete manual RC mode using the IR remote, so the car could switch between autonomous obstacle avoidance and manual driving.

Overall, this project is a strong beginner-to-intermediate robotics build because it goes beyond a basic Arduino car. It includes simulation, CAD planning, soldering, sensor scanning, motor-driver control, and real debugging. That full process is what makes the project interesting: it is not just a car that moves, but a small robot that senses its environment and makes driving decisions.