A custom PCB light-following robot. Dual LDR differential sensing, ATmega328P brain, H-bridge motor control. Designed, built, and coded from scratch.
The photovore is a biologically inspired robot that chases light the way a moth chases a flame. Two light-dependent resistors mounted at the front act as "eyes," forming voltage dividers with 10k pulldown resistors. The ATmega328P reads both analog values, computes the brightness differential, and steers by adjusting individual motor speeds through an L298N dual H-bridge.
When more light falls on the left eye, the left motor slows down and the right motor speeds up, causing the robot to arc toward the light source. A configurable dead zone prevents jittery oscillation when both sensors read nearly equal values. Below a darkness threshold, the robot stops and waits.
The entire circuit runs on a custom-designed PCB powered by a 7.4V 2S LiPo, regulated down to 5V for the microcontroller while the motors run on the raw pack voltage for maximum torque.
Two LDRs in voltage divider configuration feed analog pins A0 and A1. Brightness difference drives proportional steering.
L298N H-bridge with PWM-capable enable pins allows smooth, variable-speed control for each wheel independently.
AMS1117-5.0 regulator with dual decoupling caps. Separate motor and logic power rails prevent noise coupling.
Configurable turn gain, dead zone, speed limits, and dark threshold. Serial debug output for real-time tuning.
| MCU Pin | Net | Connection | Function |
|---|---|---|---|
| A0 | SENSE_L | LDR-L / R1 divider | Left light sensor input |
| A1 | SENSE_R | LDR-R / R2 divider | Right light sensor input |
| D5 (PWM) | ENA | L298N Enable A | Left motor speed |
| D6 | IN1 | L298N Input 1 | Left motor direction A |
| D9 | IN2 | L298N Input 2 | Left motor direction B |
| D10 (PWM) | ENB | L298N Enable B | Right motor speed |
| D7 | IN3 | L298N Input 3 | Right motor direction A |
| D8 | IN4 | L298N Input 4 | Right motor direction B |
| D13 | STATUS | LED + R3 220R | Status indicator |
// Photovore Robot Firmware // ATmega328P / Arduino Nano / Pro Mini // Pin definitions const int LDR_LEFT_PIN = A0; const int LDR_RIGHT_PIN = A1; const int ENA_PIN = 5; // Left motor speed (PWM) const int IN1_PIN = 6; // Left motor dir A const int IN2_PIN = 9; // Left motor dir B const int ENB_PIN = 10; // Right motor speed (PWM) const int IN3_PIN = 7; // Right motor dir A const int IN4_PIN = 8; // Right motor dir B const int LED_PIN = 13; // Tuning parameters const int BASE_SPEED = 150; const int MAX_SPEED = 255; const int MIN_SPEED = 60; const int DEAD_ZONE = 30; const int DARK_THRESHOLD = 100; const float TURN_GAIN = 0.8; void setLeftMotor(int speed) { if (speed >= 0) { digitalWrite(IN1_PIN, HIGH); digitalWrite(IN2_PIN, LOW); analogWrite(ENA_PIN, constrain(speed, 0, MAX_SPEED)); } else { digitalWrite(IN1_PIN, LOW); digitalWrite(IN2_PIN, HIGH); analogWrite(ENA_PIN, constrain(-speed, 0, MAX_SPEED)); } } void setRightMotor(int speed) { if (speed >= 0) { digitalWrite(IN3_PIN, HIGH); digitalWrite(IN4_PIN, LOW); analogWrite(ENB_PIN, constrain(speed, 0, MAX_SPEED)); } else { digitalWrite(IN3_PIN, LOW); digitalWrite(IN4_PIN, HIGH); analogWrite(ENB_PIN, constrain(-speed, 0, MAX_SPEED)); } } void loop() { int leftVal = analogRead(LDR_LEFT_PIN); int rightVal = analogRead(LDR_RIGHT_PIN); int diff = leftVal - rightVal; int avg = (leftVal + rightVal) / 2; if (avg < DARK_THRESHOLD) { stopMotors(); // Too dark, stop } else if (abs(diff) < DEAD_ZONE) { setLeftMotor(BASE_SPEED); // Go straight setRightMotor(BASE_SPEED); } else { int turn = (int)(abs(diff) * TURN_GAIN); int lSpd, rSpd; if (diff > 0) { lSpd = BASE_SPEED - turn; // Turn left rSpd = BASE_SPEED + turn; } else { lSpd = BASE_SPEED + turn; // Turn right rSpd = BASE_SPEED - turn; } setLeftMotor(constrain(lSpd, MIN_SPEED, MAX_SPEED)); setRightMotor(constrain(rSpd, MIN_SPEED, MAX_SPEED)); } delay(20); }
Arduino Nano or Pro Mini module
5V LDO voltage regulator, SOT-223
Dual H-bridge motor driver
Light dependent resistors, CdS type
Voltage divider pulldowns, 1/4W
LED current limiter
Decoupling, electrolytic + ceramic
3-12V with wheels attached
Battery pack with JST connector
SPST power switch
Red, status indicator
Motor connections, programming pins