Arduino Large and Productive Solar Tracker - Do It Yourself

by Maurizio Miscio in Circuits > Arduino

1628 Views, 13 Favorites, 0 Comments

Arduino Large and Productive Solar Tracker - Do It Yourself

Storia Solar tracker (2)_Moment.jpg
Solar traker v24.png
Storia Solar tracker (2)

Hi everyone! In this article we are going to see how to build a solar tracker that knows how to do the job and that is not just for illustrative purposes!


If you don't know what I'm talking about, I'll explain it to you right away: when you search in the internet for a solar tracker, the first thing that comes out is childish designs of stupid and small solar trackers with panels so small that they would struggle to power some LEDs. in series.


Then you think: "what the hell am I looking at, I want to see an example of a real solar tracker, one that has a solar panel mounted on it that can power (and charge the batteries of) at least a small garage!"


And since I totally agree with you, I built it and now I'll show you how!


This article is also available at this link

Supplies

Quantity-1.jpg

All the components you will need are in the photo, but in summary they are:

  • 1x Aluminum square tube to make the frame of the structure
  • 1x Solar panel (of course)
  • 4x Photoresistors to measure the intensity of light
  • 2x Powerful enough servo motors (the MG996Rs did their job) to move the panel
  • 1x Arduino board of any type (it really doesn't matter; the program is very simple) to manage the electronics
  • 4x 1000-ohm photoresistors
  • Some x 3D printed components (if you don't have a 3d printer ... you'll make something up!)
  • Some x Various components, usually consumables such as screws, bolts and so on

How It Works

dualaxissolarpanel.jpg
Finale di How it works.mp4

When you move on to the next step you will understand what I am saying but for the moment you just need to know that there are 4 cross light sensors and there is a pillar that divides them.


That way, when one sensor is more exposed to sunlight, the other three likely experience the shadow of the pillar.


In the program that runs on the Arduino, I compare four directions of light: Above (averaging between the sensor at the top right and the sensor at the top left), Below (averaging between the sensor at the bottom right and the sensor in bottom left), left (averaging between the upper left sensor and the lower left sensor) and finally right (averaging between the upper right sensor and the lower right sensor)


By doing so, if, for example, I detect that there is lighter on the right (averaging between the sensor at the top right and the sensor at the bottom right), I make the servomotor move to the right.


With the same logic if, for example, I detect that there is lighter at the top, (taking the average between the sensor at the top right and the sensor at the top left), I move the servomotor of the vertical axis accordingly. that the panel faces the light.


By doing all the operations together, the way it works is very efficient.

Build the Structure

Finale di How me made it
C0024_Moment.jpg
Solar traker WB.png
schema_WCT3RidUoN.png

For the construction of the structure there is not much to say, let's face it clearly ... do as you like.


But if you really want to replicate the project, I leave you a fusion 360 file (and also the link) to see the CAD structure that I designed (even if it actually turned out slightly different).


You only need a couple of 3D printed parts for the base frame and to mount the profiles at 90 degrees

Program Arduino and Test the Code

Arduino_IDE_-_Blink.png

What's better than uploading the code to the Arduino, plug everything in and see it works? Nothing!


Then connect to your computer, copy this code, upload it to Arduino and that's it!


/* 
  Inseguitore Solare a due assi


  Fa seguire ad un pannello solare ancorato a due motori la direzione del sole


  by Maurizio Miscio - 12/05/2022*/

#include <Servo.h>


//inizializzo i servo nel programma
Servo ServoVeticale;
Servo ServoBase;


//inizializzo le variabili delle posizioni del servo 
int PosServoVeticale = 90;
int PosServoBase = 90;


//inizializzo le variabili dei valori della fotoresistenze
int BassoSinistra;
int AltoDestra;
int BassoDestra;
int AltoSinistra;


//inizializzo le variabile che contengono la media dei valori delle fotoresistenze in alto e basso
int MediaAlto;
int MediaBasso;


//inizializzo le variabile che contengono la media dei valori delle fotoresistenze a destra e sinistra
int MediaSinistra;
int MediaDestra;


//inizializzo le variabili che contengono la differenza tra le due coppie di resistenze Alto e Basso
int Differenza1Veticale;
int Differenza2Veticale;


//inizializzo le variabili che contengono la differenza tra le due coppie di resistenze Destra e Sinistra
int Differenza1Base;
int Differenza2Base;


//inizializzo la variabile che contiene il valore di errore delle due coppie di fotoresistenze (valore trascurabile)
int errore = 40;


//comandi che si ripetono una sola volta in tutto lo sketch
void setup() {
  Serial.begin(9600);


  ServoVeticale.attach(9);
  ServoBase.attach(10);


}


//comandi che si ripetono in loop
void loop() {


  //leggo i valori analogici delle fotoresistenze e li assegno alle variabili corrispondenti
  BassoSinistra = analogRead(A0);
  AltoDestra = analogRead(A1);
  BassoDestra = analogRead(A2);
  AltoSinistra = analogRead(A3);


  //imposto i limiti del servo verticale (e evito che il valore superi i MAX 180 gradi)
  if (PosServoVeticale >= 160) {
    PosServoVeticale = 160;
  }


  if (PosServoVeticale <= 0) {
    PosServoVeticale = 0;
  }


  //imposto i limiti del servo alla base ( e evito che il valore superi i MAX 180 gradi)
  if (PosServoBase >= 180) {
    PosServoBase = 180;
  }


  if (PosServoBase <= 0) {
    PosServoBase = 0;
  }


  //calcolo la media dei sensori a coppie per avere un solo valore medio
  MediaAlto = (AltoDestra + AltoSinistra) / 2;
  MediaBasso = (BassoSinistra + BassoDestra) / 2;


  MediaSinistra = (AltoSinistra + BassoSinistra) / 2;
  MediaDestra = (AltoDestra + BassoDestra) / 2;


  //calcolo la differenza in valore assoluto tra le due coppie di sensori alto-basso e sinistra-destra
  Differenza1Veticale = abs(MediaAlto - MediaBasso);
  Differenza2Veticale = abs(MediaBasso - MediaAlto);


  Differenza1Base = abs(MediaSinistra - MediaDestra);
  Differenza2Base = abs(MediaDestra - MediaSinistra);


  //pongo la condizione che solo se la differenza tra le due coppie di sensori è maggiore del valore di errore prestabilito...
  if ((Differenza1Veticale <= errore) || (Differenza2Veticale <= errore)) {


  } else {


    //cambio (sommo o sotraggo "1") posizione del servo finchè i due sensori non hanno lo stesso valore
    if (MediaBasso > MediaAlto) {
      PosServoVeticale = PosServoVeticale + 1;
    }
    if (MediaAlto > MediaBasso) {
      PosServoVeticale = PosServoVeticale - 1;
    }
  }


  //pongo la condizione che solo se la differenza tra le due coppie di sensori è maggiore del valore di errore prestabilito...
  if ((Differenza1Base <= errore) || (Differenza2Base <= errore)) {


  } else {
    //cambio (sommo o sotraggo "1") posizione del servo finchè i due sensori non hanno lo stesso valore
    if (MediaSinistra > MediaDestra) {
      PosServoBase = PosServoBase + 1;
    }
    if (MediaDestra > MediaSinistra) {
      PosServoBase = PosServoBase - 1;
    }
  }
  //stampo su una riga tutti i valori utili che mi serve leggere in tempo reale
  Serial.print("SS: ");
  Serial.print(BassoSinistra);
  Serial.print(",          ");


  Serial.print("SD: ");
  Serial.print(BassoDestra);
  Serial.print(",          ");


  Serial.print("AS: ");
  Serial.print(AltoSinistra);
  Serial.print(",          ");


  Serial.print("AD: ");
  Serial.print(AltoDestra);
  Serial.print(",          ");


  Serial.print("MA: ");
  Serial.print(MediaAlto);
  Serial.print(",          ");


  Serial.print("MB: ");
  Serial.print(MediaBasso);
  Serial.print(",          ");


  Serial.print("MD: ");
  Serial.print(MediaDestra);
  Serial.print(",          ");


  Serial.print("MS: ");
  Serial.print(MediaSinistra);
  Serial.print(",          ");


  Serial.print("Servo: ");
  Serial.println(PosServoVeticale);


  //faccio muovere finalmente i servo alla loro posizione 
  ServoVeticale.write(PosServoVeticale);
  ServoVeticale.write(PosServoBase);
}


Done!

Ok, now you can capture all the sun you want with your new solar tracker and don't worry, there is enough sun for everyone!


Have you ever noticed that sun rhymes with fun, in this case capturing the sun will have been fun.