A small robot finds a black tape path and changes its wheel speeds to stay over it. The fun is watching it turn; the useful skill is knowing exactly which sensor reading made it turn.
This is a two-sensor, rule-based beginner build, not a PID racer. Allow two to three hours. We deliberately start with the wheels off the ground and the motors disabled in software. Get one subsystem working at a time.
Mounting illustration: the cover is a side elevation, so the second sensor is hidden behind the first. The drawn air gap is enlarged for visibility, not to scale; measure about 2.5 mm from the real optical face to your track before calibrating.
Steer the robot before building it
Try it yourself
Picture a shopping trolley with one powered wheel on each side. To turn left, the left wheel travels more slowly than the right. The sensors tell the robot which side still sees the tape.
The tape is 30 mm wide and sensor centres are 20 mm apart. Both see black when centred; both seeing white stops the motors. This discrete model explains the decision table, not real tyre slip or motor dynamics. Two sensors cannot distinguish a wide junction from the centre of a line.
Slide the tape left and right under the two sensors. Watch the digital readings and motor commands. Change the sensor-polarity checkbox to see why calibration matters.
The shopping-trolley analogy is about relative speed. If both wheels turn forward equally, the chassis moves forward. Slow the left side and the right side travels farther, bending the path to the left. The real robot will also be affected by tyre grip, battery voltage, weight and motor mismatch.
Our geometry is deliberate: black tape is 30 mm wide and the sensor centres are 20 mm apart. Both sensors see black when centred. With a narrower tape or wider spacing, the truth table changes; do not copy this control rule onto a different geometry without checking it.
Build kit and power plan
🧰 Build kit
- 1×Arduino Uno R3ATmega328P board; this is the compiled targetGet it →
- 1×TB6612FNG motor driverBreakout with logic and motor supplies labelledGet it →
- 2×TCRT5000 digital sensor moduleUse DO outputs; verify each module pin orderGet it →
- 2×Geared DC motor and wheelChoose motors whose stall current suits your driverGet it →
- 1 set×2WD robot chassis and casterRigid sensor mounting is essentialGet it →
- 1×AA NiMH battery holderFour cells for the motors, with a switchGet it →
- 1×USB power bank and cablePowers Uno logic during untethered runsGet it →
- 1 set×Jumper wires30 mm black track and matte white baseGet it →
Wire the controller and driver
The robot sensors look at the floor
Mount down: Side view of one reflectance module: its emitter and detector face down, ahead of the wheel axle. The robot uses two modules side by side.
Side view of one of the two reflectance modules. Both optical packages must face the floor, ahead of the drive axle.
Use D2 for the left sensor DO and D3 for the right. PWMA/D5, AIN1/D7 and AIN2/D8 control the left motor. PWMB/D6, BIN1/D9 and BIN2/D10 control the right. STBY connects to D4. Driver A01/A02 go to the left motor; B01/B02 go to the right.
Mount both reflectance sensors facing the floor, side by side with centres 20 mm apart and about 2.5 mm from the optical faces to the surface as a starting point. Follow the module’s actual operating distance and adjust experimentally. Keep both at the same height and ahead of the wheel axle.
Calibrate the eyes, with motors disabled
Upload the sketch with CALIBRATION_ONLY = true. Open Serial Monitor at 115200. Hold both sensors over white, then over black tape. Record raw L and R. Turn each module’s comparator adjustment slowly until it switches consistently between your actual track colours.
The default is BLACK = LOW. Some sensor boards or comparator settings behave the other way; set BLACK to HIGH if that matches your observations. Test under the lighting you will use. A shiny base, bright sunlight or a high sensor mount can overwhelm the difference between tape and background.
| Left sees | Right sees | Logical action | Left / right PWM |
|---|---|---|---|
| Black | Black | Forward | 120 / 120 |
| Black | White | Steer left | 70 / 150 |
| White | Black | Steer right | 150 / 70 |
| White | White | Stop: no line detected | 0 / 0 |
Upload the complete control sketch
Select Arduino Uno in Arduino IDE. The sketch was compile-checked with Arduino AVR Boards 1.8.8. No third-party library is required. The PWM values are starting points on a 0–255 scale, not measured wheel speeds. A heavily loaded motor may not turn at a low command.
The two sensor booleans describe what the modules see after applying BLACK. That keeps the decision table independent of whether a module outputs HIGH or LOW on tape.
/* Kadosh Build: two-sensor line follower, Arduino Uno R3 + TB6612FNG.
30 mm black tape; 20 mm sensor-centre spacing. Start with wheels raised.
Original example code, MIT license. */
#include <Arduino.h>
constexpr uint8_t LEFT_SENSOR = 2, RIGHT_SENSOR = 3;
constexpr uint8_t PWMA = 5, AIN1 = 7, AIN2 = 8;
constexpr uint8_t PWMB = 6, BIN1 = 9, BIN2 = 10, STBY = 4;
constexpr uint8_t BLACK = LOW; // Check your own modules in calibration mode.
constexpr bool CALIBRATION_ONLY = true; // Change to false only after the sensor test.
constexpr uint8_t FORWARD = 120, INNER = 70, OUTER = 150;
uint32_t lastLog = 0;
void drive(uint8_t left, uint8_t right) {
digitalWrite(STBY, left || right ? HIGH : LOW);
digitalWrite(AIN1, HIGH); digitalWrite(AIN2, LOW);
digitalWrite(BIN1, HIGH); digitalWrite(BIN2, LOW);
analogWrite(PWMA, left); analogWrite(PWMB, right);
}
void setup() {
Serial.begin(115200);
pinMode(LEFT_SENSOR, INPUT); pinMode(RIGHT_SENSOR, INPUT);
const uint8_t outputs[] = {PWMA, AIN1, AIN2, PWMB, BIN1, BIN2, STBY};
for (uint8_t pin : outputs) pinMode(pin, OUTPUT);
drive(0, 0);
Serial.println(CALIBRATION_ONLY ? "CALIBRATION: motors disabled" : "RUN: stop by switching motor power off");
}
void loop() {
const int rawL = digitalRead(LEFT_SENSOR), rawR = digitalRead(RIGHT_SENSOR);
const bool left = rawL == BLACK, right = rawR == BLACK;
uint8_t speedL = 0, speedR = 0;
if (left && right) { speedL = FORWARD; speedR = FORWARD; }
else if (left) { speedL = INNER; speedR = OUTER; }
else if (right) { speedL = OUTER; speedR = INNER; }
// Neither sees the tape: stop; no blind searching.
drive(CALIBRATION_ONLY ? 0 : speedL, CALIBRATION_ONLY ? 0 : speedR);
if (millis() - lastLog > 100) {
lastLog = millis();
Serial.print("raw L="); Serial.print(rawL); Serial.print(" R="); Serial.print(rawR);
Serial.print(" | PWM L="); Serial.print(CALIBRATION_ONLY ? 0 : speedL);
Serial.print(" R="); Serial.println(CALIBRATION_ONLY ? 0 : speedR);
}
delay(20);
}Check motor direction before a floor run
Turn by changing the two wheel commands
Forward: Both sensors see black: both motor channels receive PWM 120 / 255.
Watch both wheel commands and duty-cycle bars. Verify real motor polarity with the chassis raised before the first floor run.
Raise the chassis securely so both wheels are free. Turn motor power off, set CALIBRATION_ONLY to false, upload and disconnect the laptop cable before moving to the floor. Use a USB power bank for logic. Have the motor power switch within reach.
With both sensors over black, the wheels should both drive the chassis forward. If one turns backwards, power everything off and swap that motor’s two output leads at the driver. Do not swap logic supply wires. With only the left sensor over black, the left wheel should run more slowly than the right.
Lay a track it can actually follow
Make a 30 mm wide track from matte black tape on a matte white base. Two overlapping strips can make the required width. Start with a straight section and broad curves, not sharp right-angle turns. The sensor geometry must match the interactive model.
Start centred, both sensors over black. Increase only one setting at a time: forward PWM, turning PWM or sensor height. If the robot oscillates from side to side, lower the speed and confirm the sensor readings before making the turning correction more aggressive.
| Test | Pass condition |
|---|---|
| Straight section | Both sensors report black and the robot moves forward |
| Gentle left/right curve | Correct inside wheel slows; robot stays near the tape |
| Lift off the line | Both sensors white; motors stop |
| Wide black patch | Robot continues forward: both sensors see black, just like the centred case |
| Five repeat runs | Record finishes, departures and battery condition instead of keeping only the best run |
Diagnose the movement
| Symptom | Likely explanation | Try this |
|---|---|---|
| Spins on the spot | One motor’s forward direction is reversed | Wheel-up direction test; swap that motor’s leads with power off |
| Stops immediately | Wrong BLACK polarity or tape too narrow | Re-run raw sensor calibration and check geometry |
| Moves but cannot turn | Driver channel/pin mix-up or wrong motor side | Cover one sensor at a time with wheels raised |
| Keeps wobbling | Too much speed, inconsistent sensor height or threshold | Reduce forward PWM; fix the mechanical mounting |
| Arduino resets when motors start | Supply sag, motor noise or poor grounding | Check separate supplies, wiring and the driver breakout’s decoupling guidance |
What this beginner robot cannot know
Two sensors cannot distinguish a broad black junction from a centred black line. This program stops when both see white; it does not search for a lost path. Those are explicit limits, not bugs to hide. Next, try a multi-sensor array and a proportional controller only after collecting a reliable baseline.
For a research exercise, compare five runs at each of three forward PWM settings, keeping the track and sensor height unchanged. Discuss completion rate and time together. The code compiles for the stated target; validate mounting, current and motion on your actual chassis.
References and further reading: Toshiba TB6612FNG datasheet · SparkFun driver hookup guide · Vishay TCRT5000 mounting distance · Arduino digital input examples · Arduino analogWrite reference
Did you build it? 🎉
Tell us if this tutorial helped and share it with your classmates.
Need parts or a hand with your project?
Get the components from our store, or talk to a Kadosh engineer about your build or research.
Questions & comments
Stuck on a step? Ask here — our engineers and other builders reply.
Sign in to ask a question or leave a comment.
Sign inCreate a free account