Young sunflowers turn to follow the sun during the day. Solar panels on tracking stands do the same, so they make more electricity. In this lesson you build a flower that looks for the light: a servo turns it slowly from one side to the other while a photoresistor measures how bright it is in each direction. Then it turns back to the brightest direction and waits. When the light changes, it looks around again.
What you'll learn
- How to scan with a servo and take a measurement at every step
- How to find the biggest value in a set of readings
- How to average several readings to get a steadier value
- How to react when a value changes by more than a set amount
What you need
- UNO R3 board and USB cable (UNO R3 Starter Kit)
- Servo motor (UNO R3 Starter Kit)
- Photoresistor module (45-in-1 Sensor Kit)
- 3 female-to-male jumper wires, or female-to-female and male-to-male wires plugged together
- A torch or a phone light to test with
- The printed parts from the 3D printing box below (servo stand, sunflower head and petals), or the cardboard version described there
- Breadboard and jumper wires (UNO R3 Starter Kit)
Wiring

| From | To |
|---|---|
| Photoresistor module S | UNO pin A0 |
| Photoresistor module + and − | 5V and GND |
| Servo orange / yellow wire | UNO pin 9 |
| Servo red wire | 5V |
| Servo brown / black wire | GND |
Sensor modules from different makers can label and order their pins differently. Always follow the labels printed on your module.
The sketch
#include <Servo.h>
const int LIGHT_PIN = A0;
const int SERVO_PIN = 9;
const int STEP = 5; // degrees between measurements
const unsigned long RESCAN_EVERY = 60000; // look around again every minute...
const int BIG_CHANGE = 60; // ...or sooner if the light changes this much
const bool BRIGHTER_IS_HIGHER = false; // see "Check your sensor"
Servo head;
int bestAngle = 90;
int bestLight = 0;
unsigned long lastScan = 0;
// Average of 8 readings, turned so that a bigger number always means more light
int readLight() {
long sum = 0;
for (int i = 0; i < 8; i++) {
sum += analogRead(LIGHT_PIN);
delay(2);
}
int value = sum / 8;
return BRIGHTER_IS_HIGHER ? value : 1023 - value;
}
void scan() {
Serial.println("Looking for the light...");
bestLight = -1;
for (int angle = 10; angle <= 170; angle += STEP) {
head.write(angle);
delay(angle == 10 ? 500 : 80); // wait for the servo to arrive
int light = readLight();
if (light > bestLight) {
bestLight = light;
bestAngle = angle;
}
}
head.write(bestAngle);
lastScan = millis();
Serial.print("Brightest at ");
Serial.print(bestAngle);
Serial.print(" degrees, light level ");
Serial.println(bestLight);
}
void setup() {
Serial.begin(9600);
head.attach(SERVO_PIN);
head.write(90);
delay(1000);
scan();
}
void loop() {
int light = readLight();
if (abs(light - bestLight) > BIG_CHANGE || millis() - lastScan > RESCAN_EVERY) {
scan();
}
delay(200);
}
Check your sensor
- Open the Serial Monitor at 9600 baud and wait for "Brightest at … degrees".
- Shine a torch at the flower from one side. Within a second it should look around and stop facing the torch.
- If it turns away from the torch instead, change
BRIGHTER_IS_HIGHERtotrueand upload again. Photoresistor modules are wired in two different ways, and this one setting covers both.
How it works
scan() is a classic "find the biggest" loop. It starts with bestLight = -1, so the first reading always wins, and then keeps a new reading only if it is brighter than the best one so far, together with the angle where it was measured.
In loop() the flower measures the light where it is pointing. If it is very different from the brightest value it found (because a cloud came or a lamp was switched on), or if a minute has passed, it scans again. Waiting between scans saves the servo from constant buzzing, just as a real solar tracker only moves every few minutes.
Try this next
- Make the scan faster or more precise by changing
STEP. What is the trade-off? - Put the flower on a windowsill for a day and log the best angle every 10 minutes. Can you see the sun moving?
- Add a second servo for up and down, like the radar stand, and track in two directions.
Troubleshooting
-
The flower turns away from the light: change
BRIGHTER_IS_HIGHER, see above. -
It scans again and again: the light is flickering (some LED lamps do) or
BIG_CHANGEis too small. Try 120. - The wires stop the head turning: route them behind the stand and leave a loose loop.
- The board restarts when the servo moves: servos draw bursts of current. Use a good USB port or a powered hub, and check that the servo's red wire is on 5V.
- A printed part is too tight or too loose: printers differ by a few tenths of a millimetre. Sand or file a tight hole, and fix a loose part with a drop of hot glue or a strip of tape.