Introduction: Arduino-controlled Dual Axis Solar Tracker

About: I live in the desert country Namibia, in severe drought at the moment. There is not much to do other than drink beer :-P So we have to keep ourselves busy in the south.

I had to build and program a solar tracker for my BTech project.

I got most parts laser cut out of wood from a drawing I made in Solidworks.

Step 1: Parts

You need:

4 x LDRs

4 x 1kOhm resistors

female pin connectors

chipboard screws

M6 bolts & washers

M8 bolts&washers

Arduino Mega 2560

Motor Control shield (for 2 servos)

1x6V battery if you want to drive it without cables

1 x 180° Servo

1 x 360° continuous rotation servo

Step 2: Step 1: Shaft

I turned a stepped shaft on the lathe where the bearing fits onto. This bearing then fits snugly into the laser-cut base of the compartment. On top of the shaft is the connecting union for the motor. It is fixed through the shaft with a bolt.

The shaft is pressed into a stainless steel shaft, so it looks like the tracker is sitting on a post.

Only for aesthetics really.

Step 3: Step 2: Box Assembly

As you can see, the box fits together nicely, with holes at the exact right place for mounting purposes.

I made two small shafts out of brass round bar, and drilled and tapped them for the side shafts. They both run through a cylindrical bearing in the side of the box.

I had a 180° servo for the vertical, and a 360° continuous rotation servo for the horizontal. The 360° servo gave me some trouble, and I have not streamlined it 100% yet. But it works.

Only one side is driven, and the other follows as it is attached to the other arm.

Step 4:

I got a perspex lid, so one can look into the compartment and see what's going on.

Step 5:

Here is another image of the inside

Step 6: The Sensors

The sensors are mounted in 4 Quadrants as seen on a few other projects.

Step 7: Circuit

Here is the circuit setup. The motor shield is of course stacked on top of the Mega. I left it off just for demo.

Step 8: TEST

Here is the result :-)
The image is the readings that are displayed in the Serial monitor

Step 9: Code

I used parts of Geo Bruce's code, and added a bunch of stuff to it.

#include //Library for Servo

#include //Library for Motor Sheld

// 180 horizontal MAX Servo horizontal; // Horizontal/Azimuth servo

int servoh = 90; // Make servo stationary

int servohLimitHigh = 92; int servohLimitLow = 88;

Servo vertical; // Vertical/Zenith servo

int servov = 45; // Make servo horizontal

int servovLimitHigh = 110; int servovLimitLow = 20;

// LDR pin connections //position = Analog pin

int ldrbl = 11; //Bottom Left

int ldrbr = 10; //Bottom Right

int ldrtl = 9; //Top Left

int ldrtr = 8; //Top Right

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

// servo connections

// name.attacht(digital pin);





void loop() { int bl = analogRead(ldrbl); // Bottom left

int br = analogRead(ldrbr); // Bottom Right

int tl = analogRead(ldrtl); // Top Left

int tr = analogRead(ldrtr); // Top Right

int percentb, percentt, percentl, percentr;

// int dtime = analogRead(4)/20; // read potentiometers

// int tol = analogRead(5)/4;

int dtime = 500; int tol = 10;

int avb = (bl + br) / 2; // average value bottom

int avt = (tl + tr) / 2; // average value top

int avl = (bl + tl) / 2; // average value left

int avr = (br + tr) / 2; // average value right

percentb = map(avb,0,1023,0,100); percentt = map(avt,0,1023,0,100); percentl = map(avl,0,1023,0,100); percentr = map(avr,0,1023,0,100);

int dvert = avt - avb; // check the diffirence of top and bottom

int dhoriz = avl - avr;// check the diffirence of left and rigt


Serial.println(" percent t ");


Serial.println(" percent b ");


Serial.println(" percent l ");


Serial.println(" percent r ");


Serial.println(" delay time");


Serial.println(" tolerance ");


Serial.println(" Difference Horizontal ");


Serial.println(" Difference Vertical ");

if (-1*tol > dvert || dvert > tol) // check if there is a difference,within the tolerance, or else change vertical angle


if (avt > avb)


servov = ++servov;

if (servov > servovLimitHigh)


servov = servovLimitHigh;



else if (avt < avb)


servov= --servov;

if (servov < servovLimitLow)


servov = servovLimitLow;





if (-1*tol > dhoriz || dhoriz > tol) // check if there is a difference,within the tolerance, or else change horizontal angle


if (avl > avr)


servoh = (90-1);

if (servoh < servohLimitLow)


servoh = servohLimitLow;



else if (avl < avr)


servoh = (90+1);

if (servoh > servohLimitHigh)


servoh = servohLimitHigh;



else if (avl = avr)


// nothing