Introduction: Arduino & Lego Solar Tracker (Dual Axis)

This is a solar tracker (tracks the sun by pointing to it) made with lego and an arduino. (No soldering required)

It's only for fun because the motors are not strong enough to support the weight of solar panels.

(Forgive the poor quality photos and vertical video)

Step 1: Parts

  • Arduino Duemilanove 2009 AVR ATmega328 (~12€)
  • 2x SG90 Mini Servo 9g (~4€)
  • 2-Axis FPV Nylon PTZ for SG90 (~2€)
  • Breadboard
  • Cables
  • 4x resistors 10k Ohms (all 3 in a kit ~10€)
  • 4x photo-resistors (i.e. light-dependent resistors) (~6€)
  • Lego's
  • 1 rubber band
  • Hot glue

I found everything except the lego's on eBay. Total price ~34€

Step 2: Principle

Every iteration step goes like this:

  1. The sun hits the head of the robot (wich is a cross with a photoresistor in each corner).
  2. Because of the cross, some photoresistors are more exposed to the the sun. wich reduces their resistance.
  3. We measure the resistance of each photoresistor.
  4. We compute if the right is more illuminated than the left (or the opposite).
  5. We action the horizontal motor to move towards the most illuminated side.
  6. We compute if the top is more illuminated than the bottom (or the opposite).
  7. We action the vertical motor to move towards the most illuminated side.

All the parameters you need here are:

  • How much difference of light (resistance) is enough to decide to move?
  • How far are you going to move your motors after each decision?
  • How fast are you going to move the motor at each step?
  • How long are you going to wait between steps?
  • What is the farthest you'll allow your motors to move.

Step 3: Circuit

The circuit is devided in two parts.

1. The sensors (4x)

  • Connect 1 resitor and 1 photoresitor in serie.
  • Connect the node in between the 2 to an analog input pin (in my case 0 to 4). This will measure the voltage.
  • Connect the other end of the resistor to the ground
  • Connect the other end of the photoresistor to 5V
  • (The last 2 steps can be inverted, but keep the same rule for all 4 sensors)

2. The motors (2x)

  • Connect + to 5V
  • Connect - to ground
  • Connect cotrol to PWM pins (in my case 9 & 10)

Step 4: Program

cf. attached .ino file

* by Mathias Leroy * Novembre 2014 * */

// INITIALISATION //------------------------------------------------ #include // sprintf #include // Servo library Servo servoH; // pin09 horizontal servo Servo servoV; // pin10 vertical servo

// analog read pin connections int analogPinTopLeft = 0; // yellow green int analogPinTopRight = 1; // gray blue int analogPinBottomRight = 2; // white black int analogPinBottomLeft = 3; // red brown

// PARAMETERS //------------------------------------------------ int initAngleH =80; int minAngleH =0; int maxAngleH =170; int initAngleV =90; int minAngleV =50; int maxAngleV =150;

int slowingDelay=50;

int sesitivityH=30; int sesitivityV=30; int stepH=10; int stepV=10;

// VARIABLES //------------------------------------------------ int angleH =initAngleH; int angleV =initAngleV;

char printLine [50];

int valueTopLeft = 0; int valueTopRight = 0; int valueBottomRight = 0; int valueBottomLeft = 0;

// SETUP //------------------------------------------------ void setup() { servoH.attach(9); // servoH.write(initAngleH);

servoV.attach(10); // servoV.write(initAngleV); Serial.begin(9600); Serial.println("Ready! :-)"); }

// LOOP //------------------------------------------------ void loop() { Serial.println("<<< Start Loop ---"); // read values valueTopLeft = analogRead(analogPinTopLeft); valueTopRight = analogRead(analogPinTopRight); valueBottomRight = analogRead(analogPinBottomRight); valueBottomLeft = analogRead(analogPinBottomLeft); // print values // sprintf (printLine, "%d | %d \n", valueTopLeft, valueTopRight);Serial.print(printLine); // sprintf (printLine, "%d | %d \n", valueBottomRight, valueBottomLeft);Serial.print(printLine); // delay(3000); // compute averages int averageTop = ( valueTopLeft + valueTopRight ) / 2; int averageRight = ( valueTopRight + valueBottomRight ) / 2; int averageBottom = ( valueBottomRight + valueBottomLeft ) / 2; int averageLeft = ( valueBottomLeft + valueTopLeft ) / 2; // print averages sprintf (printLine, "- %d - \n", averageTop);Serial.print(printLine); sprintf (printLine, "%d - %d \n", averageLeft,averageRight);Serial.print(printLine); sprintf (printLine, "- %d - \n", averageBottom);Serial.print(printLine); delay(slowingDelay);

// Horizontal decision & action Serial.print(angleH); Serial.print("\n"); if ( (averageLeft-averageRight)>sesitivityH && (angleH-stepH)>minAngleH ) { // going left Serial.print("going left"); Serial.print("\n"); delay(slowingDelay); for (int i=0; i < stepH; i++){ servoH.write(angleH--); delay(50); } } else if ( (averageRight-averageLeft)>sesitivityH && (angleH+stepH)

// vertical decision & action Serial.print(angleV); Serial.print("\n"); if ( (averageTop-averageBottom)>sesitivityV && (angleV-stepV)>minAngleV ) { // going up Serial.print("going up"); Serial.print("\n"); delay(slowingDelay); for (int i=0; i < stepV; i++){ servoV.write(angleV--); delay(50); } } else if ( (averageBottom-averageTop)>sesitivityV && (angleV+stepV)

Serial.println("--- End Loop >>>"); }

Step 5: Head

I tried a lot of different heads and I finally found that this classic cross shaped one performed the best.

The photo-resistors come quite easily in the holes of lego plates. I fixed the wires with an elastic band and lego's to hold them in place.

I don't have a specific plan on how to create this particular head. Lego's are meant to be creative. Here is what's important:

  • A cross;
  • Place the photoresistors as close as possible in the corners of the cross;
  • I found that a plate of lego of 4 wide just pinches perfectly in the 2-Axis FPV used here;
  • An andjstable angle between the cross and this 4-wide plate is nice to calibrate manually (not programatically).

Step 6: Base

For the base I glued a lego plate on the bottom of the 2-axis FPV and then attached it to other lego pieces in the form of a square. The form isn't really importe here.

What is important is to ensure the base is heavy enough to stay in place and to create a place to fix your breadboard and one to fix your arduino. The cables should stay free to move with the movement of the head.

Step 7: Discussion for Improvements

  • To improve sensitivity, the photo-resistors should fit more close in the corners of the cross.
  • Find better servo's. These are weak and sometimes unpredictable at various speeds.
  • Maybe a sensor shield could make the circuit easier and use less wires.
  • This robot isn't really fast compared to some others you can find on instructables. This can be changed in the program. I should make it even slower for real sun tracking.

Please let me know your ideas in the comments :) !

Explore Science Contest

Participated in the
Explore Science Contest