Smart Soccer Bot
Last updated: 28 October 2026 · r2
Build a small two-wheel robot using an Induino or Arduino Uno and an L298N dual H-bridge motor driver, then add an HC-SR04 ultrasonic sensor and a TCRT5000 IR line sensor module in stages. This guide covers the parts, wiring, firmware, and first checks.
Despite its name, this version is a starting point for a soccer-bot experiment: it drives forward, pivots right when something is close, and if the IR sensor is enabled, also backs away from a detected white boundary. It does not distinguish a ball from another obstacle or track a goal.
Before you start: safety for students
Build and test this robot with your teacher’s guidance. Ask your teacher to check every connection before switching on the power. If you are unsure, stop and ask.
- Use battery power only for running the robot. Ask your teacher to choose the motor battery pack and USB power bank. Never connect the robot, a battery, or a loose wire to a wall socket or any AC supply. Do not use wall adapters or open chargers for this project.
- Disconnect power before changing wires. Remove the motor battery connection and unplug the USB cable before adding, removing, or moving any wire. Switching off the motors in code is not the same as disconnecting power.
- Do not join battery + and − directly. A wire, coin, screwdriver, or other metal object touching both ends can cause a short circuit: a path that can make the battery and wires very hot. Keep spare batteries away from loose metal objects.
- Do not bridge pins on the board. Never connect 5V directly to GND. Keep loose wire ends, screws, and tools away from the board’s pins and metal contacts. Work on a dry wooden or plastic surface, and use spacers so the underside of each board cannot touch metal.
- Let your teacher handle the batteries. Use a proper battery holder or an enclosed pack selected by your teacher. Do not use loose 18650 lithium-ion cells, take apart a battery pack, or try to charge batteries yourself. Have your teacher check the + and − markings before connecting power.
- Stop if anything seems wrong. If you notice unusual heat, a burning smell, smoke, or a damaged battery, step back and tell your teacher immediately. Do not touch a hot battery or try to repair it. Keep fingers, hair, and loose clothing away from moving wheels.
Code: Smart Soccer Bot
Download Smart Soccer Bot — C++ Arduino sketch (.ino)
When you open the downloaded sketch file, the Arduino IDE may prompt you to create a folder and move the sketch into it. Accept the prompt. This is normal: smart-soccer-bot.ino needs to be inside a folder named smart-soccer-bot.
//
// Created by Rahul Ashokayan on 2026.10.22.
// Copyright © 2026 Riant Studio. All rights reserved.
//
// ==============================================================
// Smart Soccer Bot with Ultrasonic & IR Line Boundary Defense
// Platform: Induino / Arduino Uno
// ==============================================================
// --- Build stages: enable only the sensors you have connected ---
// Stage 1: both false for motor-only forward movement.
// Stage 2: ultrasonic true for ball / obstacle response.
// Stage 3: IR boundary true for white-line defense.
const bool ENABLE_ULTRASONIC = true;
const bool ENABLE_IR_BOUNDARY = false;
// CAUTION: Enable a sensor only after it is wired.
// With IR off, the robot has no edge protection, so test in a contained area,
// away from stairs or raised edges. Alternatively, test with the wheels raised.
// --- Stage 2: Ultrasonic Sensor (HC-SR04) ---
const int trigPin = A0;
const int echoPin = A1;
// --- Stage 3: IR Line Sensor (TCRT5000) ---
const int lineSensorPin = A2; // Digital reading on Analog pin A2
// --- Stage 1: L298N Motor Driver Pins ---
const int enLeft = 3; // PWM Left
const int motorL_Fwd = 4;
const int motorL_Rev = 5;
const int enRight = 9; // PWM Right
const int motorR_Fwd = 7;
const int motorR_Rev = 8;
const int statusLed = 13; // Induino onboard LED
// --- Speeds & Distance ---
const int DRIVE_SPEED = 175;
const int TURN_SPEED = 160;
const int BALL_ZONE_CM = 20;
// Set to LOW if your module outputs active LOW on white surface
const int WHITE_DETECTED = LOW;
// CAUTION: If you change this to HIGH, the IR module must be connected.
// With INPUT_PULLUP an unplugged sensor reads HIGH and looks like a
// constant white boundary.
void setup() {
if (ENABLE_ULTRASONIC) {
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
if (ENABLE_IR_BOUNDARY) {
// Pull-up keeps an unconnected pin HIGH (no white line detected).
pinMode(lineSensorPin, INPUT_PULLUP);
}
pinMode(enLeft, OUTPUT);
pinMode(motorL_Fwd, OUTPUT);
pinMode(motorL_Rev, OUTPUT);
pinMode(enRight, OUTPUT);
pinMode(motorR_Fwd, OUTPUT);
pinMode(motorR_Rev, OUTPUT);
pinMode(statusLed, OUTPUT);
delay(1500); // Power-on stabilizing delay
}
// --- Stage 1: Motor movement ---
void setMotors(int leftDir, int rightDir, int speedL, int speedR) {
digitalWrite(motorL_Fwd, leftDir == 1 ? HIGH : LOW);
digitalWrite(motorL_Rev, leftDir == -1 ? HIGH : LOW);
digitalWrite(motorR_Fwd, rightDir == 1 ? HIGH : LOW);
digitalWrite(motorR_Rev, rightDir == -1 ? HIGH : LOW);
analogWrite(enLeft, speedL);
analogWrite(enRight, speedR);
}
void forward() { setMotors(1, 1, DRIVE_SPEED, DRIVE_SPEED); }
void reverse() { setMotors(-1, -1, DRIVE_SPEED, DRIVE_SPEED); }
void spinTurn() { setMotors(1, -1, TURN_SPEED, TURN_SPEED); }
void stopBot() { setMotors(0, 0, 0, 0); }
// --- Stage 3: Return true after responding to a boundary ---
bool handleBoundary() {
int lineState = digitalRead(lineSensorPin);
if (lineState == WHITE_DETECTED) {
digitalWrite(statusLed, HIGH);
stopBot();
delay(100);
// Pull back into the pitch
reverse();
delay(350);
// Pivot right before checking the line again
spinTurn();
delay(400);
stopBot();
delay(100);
return true;
}
return false;
}
// --- Stage 2: Distance measurement and obstacle response ---
long readDistanceCM() {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
long duration = pulseIn(echoPin, HIGH, 25000);
if (duration == 0) return 999;
return (duration * 0.034) / 2;
}
bool handleObstacle() {
long distance = readDistanceCM();
if (distance > 0 && distance <= BALL_ZONE_CM) {
digitalWrite(statusLed, HIGH);
stopBot();
delay(100);
// Quick evasive turn
spinTurn();
delay(300);
return true;
}
return false;
}
void loop() {
// Boundary response takes priority when enabled.
if (ENABLE_IR_BOUNDARY && handleBoundary()) {
return;
}
// Disabled sensors are not read; otherwise advance when clear.
if (!ENABLE_ULTRASONIC || !handleObstacle()) {
digitalWrite(statusLed, LOW);
forward();
}
delay(30);
}
The code above is included directly from the downloadable sketch when the site is built.
First time uploading a program to Arduino? Follow Upload a sketch to your Arduino with your teacher.
Choose your build stage
Two settings near the top of the sketch control the optional sensors: ENABLE_ULTRASONIC and ENABLE_IR_BOUNDARY. Set each to true only when that sensor is connected and ready to use. The download ships at Stage 2 (ENABLE_ULTRASONIC = true, ENABLE_IR_BOUNDARY = false). Enable IR boundary defense once the IR module is wired.
| Build | ENABLE_ULTRASONIC | ENABLE_IR_BOUNDARY | Behaviour |
|---|---|---|---|
| Stage 1: motors only | false | false | Drive forward without sensing obstacles or boundaries |
| Stage 2: add ultrasonic | true | false | Drive forward and pivot right near an object |
| Stage 3: add IR boundary defense | true | true | Respond to objects and give white boundaries priority |
| Alternative: motors and IR only | false | true | Drive forward and back away from white boundaries, without distance sensing |
For example, to build with the ultrasonic sensor but no IR module, leave the download’s settings as they are: ENABLE_ULTRASONIC is true and ENABLE_IR_BOUNDARY is false. You can leave all the IR code in place and skip its wiring section. Disabled sensors are neither configured nor read, so an unconnected IR input cannot trigger a boundary response. Upload the sketch again after changing a setting.
The sketch groups motor movement, ultrasonic response, and IR boundary response into labelled sections. handleObstacle() and handleBoundary() each return true after performing their manoeuvre; loop() calls only enabled capabilities and drives forward when neither responds.
Begin stage 1 with the wheels raised: it drives forward continuously after startup. For later stages, follow only the checks for enabled sensors. With IR disabled there is no boundary defense; with ultrasonic disabled there is no obstacle response.
1. Gather the parts
- Controller: InduinoX or a standard Arduino Uno.
- Chassis: a two-wheel-drive robot kit with two DC gear motors, wheels, and a caster.
- Motor driver: an L298N dual H-bridge module.
- Distance sensor (stage 2): an HC-SR04 ultrasonic distance sensor.
- Boundary sensor (stage 3): a TCRT5000 IR line sensor module with a digital output, suitable for the board’s 5V logic.
- Practice pitch (stage 3): a darker surface with a white boundary that the IR sensor can distinguish from the playing area.
- Motor power: a teacher-selected battery pack in a proper holder or enclosure, matched to the motors and driver. Your teacher must check the voltage, current rating, and connections; do not assemble a pack from loose lithium-ion cells.
- Controller power: a teacher-approved USB power bank connected through the board’s USB connector.
- Connections: jumper wires, suitable motor/power leads, and an optional small breadboard for signal wiring.
2. Wire the motor driver
Disconnect all power while wiring. With your teacher, remove the ENA and ENB jumpers on the L298N module so that the Arduino can control motor speed through those inputs.
| L298N pin | Arduino pin | Purpose |
|---|---|---|
| ENA | D3 | Left motor PWM speed |
| IN1 | D4 | Left motor forward |
| IN2 | D5 | Left motor reverse |
| IN3 | D7 | Right motor forward |
| IN4 | D8 | Right motor reverse |
| ENB | D9 | Right motor PWM speed |
| GND | GND | Common ground |
Connect the left motor to OUT1/OUT2 and the right motor to OUT3/OUT4. Connect the motor battery positive to the driver’s motor-supply terminal, often labelled +12V, and its negative to GND. Join the driver and Arduino grounds.
Ask your teacher to check your specific module’s instructions for its logic supply and regulator jumper: the ENA/ENB jumpers are separate from the regulator jumper. Use the controller supply described above, and do not connect the module’s 5V terminal to it without your teacher confirming that terminal’s role for your board. Motors are powered through the driver, never from an Arduino GPIO or its 5V pin.
3. Connect the ultrasonic sensor
Skip this section if ENABLE_ULTRASONIC is false.
Set ENABLE_ULTRASONIC to true only once the HC-SR04 is wired. An unconnected echo pin can float and give false readings, causing unexpected turns. For a motor-only build, change it to false before uploading.
Mount the HC-SR04 at the front of the chassis, pointing forward.
| HC-SR04 pin | Arduino pin | Purpose |
|---|---|---|
| VCC | 5V | Sensor power |
| Trig | A0 | Trigger pulse |
| Echo | A1 | Echo input |
| GND | GND | Ground |
The sketch uses A0 and A1 as digital pins. Its motor connections leave D10–D12 free, and D13 is used as the status LED. This arrangement avoids using those pins for the motor driver or ultrasonic sensor.
4. Connect the IR line sensor
Skip this section if ENABLE_IR_BOUNDARY is false.
Mount the IR module near the front underside of the chassis, pointing down at the pitch. Position it so it can detect the boundary before the wheels reach it, with its sensing height set for your module and surface.
| IR module pin | Arduino pin | Purpose |
|---|---|---|
| VCC | 5V | Module power |
| DO / OUT (digital) | A2 | Boundary input |
| GND | GND | Common ground |
The sketch uses A2 as a digital input with digitalRead, so connect the module’s digital output, not its analog output (AO). Check the pin labels and power requirements on your particular module with your teacher.
When IR boundary defense is enabled, the sketch enables the Arduino’s internal pull-up on A2, so an unconnected input reads HIGH (no boundary with the default WHITE_DETECTED = LOW) rather than floating. The IR module’s digital output still drives the pin normally.
WHITE_DETECTED is initially LOW: the sketch treats a LOW input as a white boundary. Before running the motors, check the module’s digital output over the white line and darker playing area. Adjust the module’s threshold control, if fitted, until those surfaces give distinct readings. If your module outputs HIGH over white, change WHITE_DETECTED to HIGH before uploading. If you change it to HIGH, make sure the IR module is connected. With the pull-up, an unplugged input reads HIGH and would look like a constant boundary. Surface reflectivity, mounting height, and room lighting can affect detection; visible colour alone is not enough to confirm it works.
5. Assemble and upload
For help with opening the saved file, choosing the board and port, and using Verify and Upload, follow the step-by-step upload guide.
- Mount the motors, wheels, and caster on the chassis. Secure the controller and driver using spacers, keeping exposed contacts away from conductive surfaces.
- Leave the motor battery disconnected while uploading. Download the sketch above and open it in Arduino IDE. If prompted, allow the IDE to create a matching sketch folder. Set
ENABLE_ULTRASONICandENABLE_IR_BOUNDARYfor your build stage before uploading. - Select Arduino Uno under the board menu for an Uno-compatible board, then select the connected board’s port.
- Upload the sketch and confirm completion in the IDE. The sketch does not include an upload-confirmation blink.
- Secure the chassis with the wheels off the ground, reconnect motor power, and check direction. After the sketch’s 1.5-second startup delay, both wheels should turn forward. If IR is enabled, hold a sample of the darker playing surface beneath it at its intended sensing distance; if ultrasonic sensing is enabled, keep nearby objects out of its path.
- If one wheel turns backward, disconnect power and swap that motor’s two output wires. Repeat the check before putting the robot on the floor.
6. Understand the movement
First priority: IR line boundary defense
When ENABLE_IR_BOUNDARY is true, each loop checks the IR line sensor first. If its reading matches WHITE_DETECTED, the status LED lights and the robot performs this sequence:
- Stop for 100 milliseconds.
- Reverse for 350 milliseconds.
- Pivot right for 400 milliseconds.
- Stop for 100 milliseconds.
The loop then returns immediately, skipping the ultrasonic check and the normal end-of-loop delay. The next loop checks the line sensor again. If it still detects the boundary, the sequence repeats.
Second priority: ball or obstacle proximity
When no boundary response occurs and ENABLE_ULTRASONIC is true, the sketch measures distance and compares it with BALL_ZONE_CM, initially 20 cm. For a reading greater than zero and no more than that threshold, it lights the status LED, stops for 100 milliseconds, and pivots right for 300 milliseconds. This branch does not reverse or stop after the pivot; the next loop decides what to do next.
When neither enabled capability responds, the LED is off and the robot drives forward. Every loop without a boundary response has an additional 30-millisecond delay at the end, including motor-only operation.
The ultrasonic read has a 25-millisecond timeout. When no echo is received, the sketch returns 999 and takes the forward-driving branch. A timeout therefore does not stop the robot. Neither sensor is checked during the timed manoeuvres, and a boundary reached during a pivot will only be checked on the next loop. A single front sensor cannot monitor every edge of the robot or guarantee that it stays inside the pitch.
7. Test and tune
Start with the chassis secured and wheels raised, and check forward wheel direction for every build stage. If IR is enabled, move samples of the darker playing surface and white boundary beneath the IR sensor at its intended sensing distance. Check that only the white boundary triggers the stop–reverse–pivot–stop sequence. If both sensors are enabled, place an object in front of the ultrasonic sensor while a boundary is detected and confirm that the boundary sequence still takes priority.
For sensor-enabled builds, then use a clear, contained area at low speed, away from stairs or raised edges. If IR is enabled, approach the white boundary from several angles and check that the robot has enough room to back away. If ultrasonic sensing is enabled, place a ball or another object roughly 15–20 cm in front of it and check that the robot stops briefly and pivots right; keep the IR sensor over the darker playing area if fitted. Try different positions: a curved ball can give different readings from a flat obstacle.
- Drive speed:
DRIVE_SPEEDstarts at175on the PWM scale of 0–255 and controls both forward and reverse movement. Try150or140if the wheels skid. - Turning speed:
TURN_SPEEDstarts at160. Adjust it alongside the pivot duration to change the turn. - Detection distance: change
BALL_ZONE_CMto alter when the manoeuvre begins. - Boundary response: tune the 350-millisecond reverse and 400-millisecond pivot durations in the boundary branch for your chassis and pitch. A right pivot does not guarantee an inward heading from every approach angle.
- IR calibration: recheck the threshold,
WHITE_DETECTED, and mounting height on the actual pitch under the lighting you will use. - Ultrasonic position: aim it toward the ball while checking for unwanted floor reflections. Adjust height and angle using readings from your actual setup.
The supplied firmware is a simple baseline for experimenting with motion, distance sensing, and line boundary detection. Ball tracking and goal-directed play would require additional sensing and control logic.
Teacher references: Arduino power-supply guidance and the CPSC warning about loose 18650 lithium-ion cells.
Compiled and curated with AI-assisted drafting and firmware scaffolding.