Solar Tracker mit Schrittmotoren und OLED-Display

Every day it is more and more proven that we are in a climate change that is due to environmental pollution. There is no doubt about it, the extreme weather phenomena in Europe are becoming increasingly common. That was the question I asked myself. There is a clean and cheap energy source in the world, namely the sun. Here in Spain we have many hours of light that we can use with the help of solar modules. In order to achieve the best performance, ideally you must always be aligned vertically to the sun's rays. One way to achieve this is to build a solar light tracker.

The project developed here is two axes of movement, both horizontally and vertically. In this way, the solar modules are always aligned vertically to the sun's rays and their efficiency is maximized. 4 LDR resistors are used as a reference for the amount of light that reaches the solar panel (Light Dependent REsistor; Light -dependent resistance). We use two final switches to recognize when the sunset and sunrise position is reached. Since it is a "green" project to say, I reused some of the chassis, the engine holder, the LDR resistors and the solar panel, some of the plywood fruit boxes and a few final switches from an old mouse.

Required hardware and materials

1

Mega 2560 board with Atmega2560 with USB cable

1

0.96 inch OLED SSD1306 Display I2C 128 x 64 pixels

4

Photo resistance Photo Resistor Diode Set 150V 5mm LDR5528 GL5528

4

Resistance 10 kohm

1

Resistance 220 Ohm

2

Uln2003 Step motor with drive module board

1

Solar panel 5V 1.5W waterproof polysilicon mini solar module

2

Microphone with a scooter

1

PCB Board Set Lochrasterboard

 

Cable

 

wood

 

Required software

  • Arduino die
  • solar_light_tracker sketch
  • Wire Library (integrated)
  • Adafruit_gfx library (about library administrator)
  • Adafruit_SSD1306 Library (via library manager)

circuit diagram

Download of the circuit diagram

Description of the functionality and the source code

As can be seen in the following photo, both the solar panel and the LDR resistors are located in the same level. This is necessary because the amount of light that the solar panel receives must be the same that also meets the four LDRs. These are arranged in a 2 x 2 matrix.

The following drawing shows the arrangement of the LDR resistors from the front. These references are taken into account in the calculations in order to obtain the best light measurement.

The heart of the structure is the Mega 2560 R3, which receives the measured values ​​of the 4 LDR resistors, carries out the necessary calculations, moves the two stepper motors and sends the voltage data to the OLED display.

First of all, the necessary libraries for I2C communication and the OLED display must be integrated into the sketch.

#include <Wire.H>
#include <Adafruit_gfx.H>
#include <Adafruit_ssd1306.H>

Then we have to define the number of pixels for the width and height of the OLED screen and implement a screen object. As a constructor parameter, we hand over the variables of the number of pixels for the width and height of the screen, the reference to the Wire object. In addition, here -1 for connecting the reset pin when it is available.

#define Screen_Width 128
#define Screen_height 64
Adafruit_ssd1306 display(Screen_Width, Screen_height, &Wire, -1);

We declare four variables to indicate which LDR resistance is connected to which port of the microcontroller. We also declare four other variables for the value of the resistance when the light occurs.

intimately LDR_SD = A0;
intimately LDR_SI = A1;
intimately LDR_II = A2;
intimately LDR_ID = A3;

intimately SD, Si, II, ID; 

In order to calculate average values ​​in the same columns and lines of the measured four values ​​of the LDR resistors, we declare another four variables. This gives us a reference to change the orientation of the solar panel. In the drawing above you can see which resistance are involved on each side. We also declare a tolerance variable to avoid constant movements.

intimately Sup_aver, inf_aver, right_aver, left_aver;     
intimately tolerance = 10;

For the voltage measurement on the solar panel, we declare the variable SPV. It contains the PIN to which we connect the panel (in our project it is pin 4). The variable solar_panel_read For the input value of the measurement of the voltage (it is analogous values) and the variable solar_panel_voltage, to carry out the analog digital conversion. We can work with the value and display it on the OLED screen.

intimately SPV = A4;
intimately solar_panel_read;
float solar_panel_voltaje;

We will declare two variables for the speed of the stepper motors. The variable retardo (Sp. Delay) is intended for the movement of the engines in normal operation. The variable retardo_inicializacion (Sp. Delay_initalization) we use for the movement of the horizontal engine when it moves into the starting position.

intimately retardo = 5;
intimately retardo_inicializacion = 15;

Two final switches for sunrise and demolition were installed in the system. When the sunrise takes place, the system is in the sunrise position. The sunrise switch (Switch_sunise) is normal closed (NC) and connected with pull-up resistance. It is always closed, which means that 5V is permanently on the pin and its condition is therefore high. It is pressed and opened when the panel is in an almost vertical position. It shows in an eastern direction because the sun rises there. If the panel follows the sun in the sky during the day of movement, it will be almost vertical when the sunset position is reached and will be aligned with the west.

Then the normal open (NO) sunset end switch (Switch_sunset) activated. It is connected to mass and the reset pin of the microcontroller. So it is reset when the PIN is placed on mass. As a result, the solar panel returns to the sunrise position. This code is in set up()-Part of the sketch. In the next two lines we configure the connection of the final switch to port 10 of the microcontroller and define it with high.

intimately Sunrise_pin = 10;
intimately Switch_sunise = HIGH;

After we have integrated the libraries, declared variables and instantiated the component objects, we have to use them in the method set up() initialize. First we initiate the serial monitor and the OLED screen to address 0x3c, We delete the screen and set the text color white.

Serial.Begin(9600);

IF(!display.Begin(Ssd1306_switchcapvcc, 0x3c)) {
  Serial.print(F("SSD1306 Allocation Failed"));
  for(;;);
}

display.Clear display();
display.SetteextColor(White);

Next we configure the microcontroller pins used by the LDR resistors, the solar panel, the engines and the final switch for sunrise as an input or output.

pin mode (LDR_SD, Input);      // LDR resistors
pin mode (LDR_SI, Input);
pin mode (LDR_II, Input);
pin mode (LDR_ID, Input); 

pin mode (SPV, Input);         // solar panel

pin mode (5, OUTPUT);          // horizontal engine
pin mode (4, OUTPUT);
pin mode (3, OUTPUT);
pin mode (2, OUTPUT);

pin mode (9, OUTPUT);          // vertical engine
pin mode (8, OUTPUT);
pin mode (7, OUTPUT);
pin mode (6, OUTPUT);

pin mode (Sunrise_pin, Input); // Sunrise Limit Switch

The last points we will configure are the conditions of the LDR resistance and the solar panel when the microcontroller is initialized. First of all, we have to have the condition of the final switch Switch_sunise know. If it is in the high state, i.e. is not pressed, we show a message about the serial monitor and lead the method inicializacion_motor_horizontal () (initialization_horizontal_motor). As long as it is not pressed, the engine of the horizontal axis moves until this final switch is pressed and the initialization is completed.

Switch_sunise = digital read(Sunrise_pin);
        
while (Switch_sunise == HIGH) { 
  Serial.print("Inicializando motor horizontal, eSper ......");
  inicializacion_motor_horizontal();
  Switch_sunise = digital read(Sunrise_pin);
}

We are with the set up()-Method finished, now we'll be the Loop ()-Analyze the method that is continuously carried out. In this method, the received light is measured and the engines moved.

An LDR (Light branch resistor - light -dependent resistance) changes its resistance with the amount of light that falls on it. The best performance is achieved when the light falls vertically. As you can see in the circuit diagram, a voltage division circuit was produced with each LDR and a 10K resistor. If we connect it to a voltage of 5V and each LDR is connected to an analog port of the microcontroller, we can measure the varied voltage. We will save the voltage values ​​of each LDR in the variables that we have declared for this purpose.

SD = analogead(LDR_SD);
Si = analogead(LDR_SI);
II = analogead(LDR_II);
ID = analogead(LDR_ID);

The calculations that the microcontroller must carry out for the movement of the engines are as follows:

The values ​​of the horizontally located LDRs are added and then halved. Then the vertical LDRs are also added and halved. So we get the mean values. We save the results in the previously declared variables. You can see the arrangement of the LDRs in the figure.

Sup_aver = (SD + Si)/2;
inf_aver = (ID + II)/2;
right_aver = (SD + ID)/2;
left_aver = (Si + II)/2;

Now that we have the average values, we have to set the two engines in motion. To do this, we compare the values ​​of the opposite pages with the tolerance. Whenever the calculated difference of the values ​​of the compared sides is larger than the tolerance (int tolerance = 10;), we have to use the methods paso_izq (), paso_der (), paso_up () y paso_down () (Step Left, Right, Up and Down) give the order to the corresponding engine. It changes the direction of the page, the value of which is higher until the value of the difference is smaller than the tolerance.

/*************** horizontal motor **********************
IF (right_aver == left_aver) {
   apagado_hor();
}
  
IF (right_aver > left_aver && (right_aver-left_aver) > tolerance) {
  Paso_izq();
}
 
IF (left_aver > right_aver && (left_aver-right_aver) > tolerance) {
  Paso_der();
}
apagado_hor();
delay(500);

/************* vertical motor ************************/

IF (Sup_aver == inf_aver) {
   apagado_ver();
}
  
IF (Sup_aver > inf_aver && (Sup_aver-inf_aver) > tolerance) {
    Paso_up();
}
 
IF (inf_aver > Sup_aver && (inf_aver-Sup_aver) > tolerance) {
    paso_down();
}
apagado_ver();
delay(500);

Two 28byJ engines and the associated Uln2003 controller modules were selected for the movement of the solar panel and the LDR resistors. One engine on the movement of the x-axis and the other motor on the Y axis acts.

Note: An external voltage source for the supply of the engines should be connected.

In the following lines of the sketch you can see that two coils, i.e. two pins, are always activated for a step of the motor. We regulate the speed of the engine rotation Delay (retardo).

void paso_xxx() {
  digital(5, Low); 
  digital(4, Low);  
  digital(3, HIGH);  
  digital(2, HIGH);  
     delay(retardo); 
  digital(5, Low); 
  digital(4, HIGH);  
  digital(3, HIGH);  
  digital(2, Low);  
     delay(retardo); 
  digital(5, HIGH); 
  digital(4, HIGH);  
  digital(3, Low);  
  digital(2, Low);  
     delay(retardo); 
  digital(5, HIGH); 
  digital(4, Low);  
  digital(3, Low);  
  digital(2, HIGH);  
     delay(retardo);  
}

In order to visualize the voltage values ​​that the solar module receives at a certain point in time, we have installed a 0.96-inch OLED screen. We determine the voltage of the solar panel on PIN 4. Before the output on the display, we have to convert the analog to a digital value.

The solar panel provides a maximum voltage of 5V, which corresponds to the value 1023 read at the analog input. With a simple operation we can convert this value and output it on the screen.

solar_panel_read = analogead(SPV);
solar_panel_voltaje = (solar_panel_read*5.0) / 1023.0;
oled_message();

The method for displaying data on the OLED screen (OLED_MESSAGE ()) is very simple. It performs the following steps:

Deleting the screen, adjusting the text size to 2, placing the cursor on the X and Y coordinates in pixels and preparation of the text to write it in the first line of the text. Set text size to 3, bring cursor to the new X and Y coordinates again, prepare the new text to be displayed (voltage value with 2 decimal places of the solar panel) and the last line is the output of the entire text previously set.

void oled_message() {
  display.Clear display();
  display.Settextsize(2);
  display.setcursor(7,0);
  display.print("Solar Vols");
  display.Settextsize(3);
  display.setcursor(20, 30);
  display.print(solar_panel_voltaje, 2);
  display.display();
}

Now that it is summer and the sun is shining, you could build a mobile phone charger, for example. A suitable project will follow soon.

DisplaysFür arduinoProjekte für anfänger

16 comments

Andreas Wolter

Andreas Wolter

@Eddy: ja es sollte direkt funktionieren. Ich vermute, dass die verwendeten Bibliotheken fehlen. Es kann noch andere Ursachen haben. Dort würde ich aber zuerst anfangen zu suchen. Sie können auch die Fehlermeldung posten. Die geben meistens schon die nötigen Informationen aus.

Grüße,
Andreas Wolter
AZ-Delivery Blog

Eddy Lösel

Eddy Lösel

hallo
ich hab versucht das teil zu bauen
Scheitere aber schon am kompilieren lauter Fehlermeldungen und google liefert leider auch keine lösung.
Sollet nach dem Software download nicht mit arduino ide ein einfaches kompilieren und anschliesender upload in den arduino möglich sein

?!?

Gruß Eddy

Hat das jemand vertig am laufen und kamm mir die Arduino datei senden

Thx

Andreas Wolter

Andreas Wolter

@Eddy: ich vermute, dass die fehlenden Bibliotheken (siehe Übersicht im Beitrag) nicht vollständig installiert wurden. Den Quelltext aus der Webseite zu kopieren, ist nicht notwendig, da einfach nur einzelne Teile daraus beschrieben werden. Den Sketch downloaden und per Arduino IDE auf den MC laden sollte direkt funktionieren. Ansonsten bitte auch gern die Fehlermeldung posten.

Grüße,
Andreas Wolter
AZ-Delivery Blog

Eddy

Eddy

Hallo
Also ich hab versucht das Ding nach zu bauen und scheitere aber schon am Upload zum Arduino (mega2560)
Arduino ide gestartet das file aus dem Zip geladen Board, Port usw. eingestellt aber schon beim Kompilieren ellen lange fehler meldungen

Wenn ich die weiter oben genannten code zeilen auch noch einfüge wir die Fehler meldungs seite nur um so länger

Kann da jemand helfen ?

big thx

Thorsten Hartwig

Thorsten Hartwig

Da überraschend viele Downloads auf Thingiverse zu verzeichnen sind, habe ich das Teil nun auch mal fertig gebaut.
Einige 3D-Teile wurden noch etwas verbessert, habe es auf Thingiverse aktualisiert.

Ich habe ein “Wemos D1 R32” Board verwendet. Das hat einen ESP32 anstatt des antiken 328P Prozessors. Einfach endgenial, dieses Board. Das gibts hier:
https://www.az-delivery.de/products/esp32-d1-r32-board

Da ich Lochraster hasse und für diese Kleinigkeit ein eigens konstruiertes PCB wohl übers Ziel hinausgeschossen wäre habe ich ein Breadboard genommen, das werde ich zur Stabilisierung einfach in Heisskleber ersäufen.
Gibts hier:
https://www.az-delivery.de/products/mini-breadboard

Wer sich das im Detail mit Bildern und Video ansehen möchte, es liegt alles auf GitHub nachbaufertig parat. (Auf Thingiverse sind halt nur STL und Fotos). Statt Fritzing-Bildchen ist da ein KiCad-Schematic, aber die PIN-Liste in PinConfig.h sollte auch reichen zum Nachbauen. Die Blaue Onboard-LED und der zugehörige 1k-Widerstand müssen vom Wemos Board entfernt werden, sonst geht der GPIO2 nicht wie gewünscht. GPIO33 ist zum Anlöten auf dem Board zu finden.

https://github.com/Pontifex42/SolarTracker
Hier das Video:
https://github.com/Pontifex42/SolarTracker/blob/master/Media/ProveSmall.mp4

Have fun!

Andreas Wolter

Andreas Wolter

@Thorsten Hartwig: Ich habe mir die Bilder kurz angesehen. Sieht sehr gut aus. Ich verlinke das im Projekt. Vielen Dank!

Grüße,
Andreas Wolter
AZ-Delivery Blog

Thorsten Hartwig

Thorsten Hartwig

Wie versprochen, hier die STL Dateien. Es ist so wesentlich einfacher als mit Holz. Habe natürlich einiges geändert, 3D-Druck ist halt ein völlig anderes Konstruieren. Eine finale Version des Solarpanel-Rahmens wird gelegentlich upgedated. Aber ohne die Skizzen wäre ich völlig hilflos gewesen, nochmals vielen Dank an den Autor.

https://www.thingiverse.com/thing:5437654

Freue mich über jeden Make. Haut rein.

Pontifex42

Pontifex42

Vielen vielen Dank für die Zeichnungen. Ich habe das soweit in Fusion360 abgezeichnet. Das ist aber alles für Holzschnitt gedacht. Für 3D Druck muss ich noch einiges ändern. Z.B. kann man alle Löcher gleichmit drucken anstatt später zu bohren. Ausserdem kann man einige Sachen gleich am Stück machen anstatt aus flachen Einzelteilen zusammenzustecken. Zudem sind einige Stellen auf “Maß” gemacht, d.h. man steckt ein 30mm Stück in einen 30mm Slot. Bei Druckteilen sollte man da ein oder zwei Zehntel mm Spiel vorsehen, spart das Feilen. Die Materialstärke von 3mm ist eh nicht so optimal für 3D-Druck, da werden es eher 1,5-2mm.
Ich schicke die Dateien zum Veröffentlichen, wenn ich das erfolgreich zusammengebaut habe. Vermutlich in den nächsten 5 Tagen.

Andreas Wolter

Andreas Wolter

Wir haben am Ende des Beitrags einen Link zu einer PDF-Datei ergänzt. Sie enhält Skizzen mit Maßangaben der einzelnen Bauteile.

Wenn Sie Parts für den 3D-Drucker erstellen und diese bei uns veröffentlichen möchten, dann geben Sie Bescheid. Wir können Sie dann hier ebenfalls veröffentlichen.

Grüße,
Andreas Wolter
AZ-Delivery Blog

Andreas Wolter

Andreas Wolter

Was die Maße angeht, ist der Autor des Beitrags dabei, eine Übersicht anzufertigen. Die werden wir nachreichen.

Grüße,
Andreas Wolter
AZ-Delivery Blog

Jack

Jack

Gibt es abmessungen von die drehscheibe und so weiter?
Danke.
Jack.

Peter

Peter

@Pontifex42
Bitte ich hätte Interesse an den..STL files
Danke!

Andreas Wolter

Andreas Wolter

@Alex: das ist korrekt. Nach Aussage des Autors hatte er zur Zeit der Erstellung des Projektes nur dieses andere Display zur Hand. Es hat jedoch den gleichen Chip und wird genauso verwendet, wie das verlinkte Display.

@Marco: theoretisch wäre es möglich. Es müssen jedoch Anpassunge an den Verbindungen und im Code vorgenommen werden. Der analoge Pin zum Auslesen der Spannung des Solarpanels muss dort für die Verbindung des OLEDs verwendet werden.
(Info des Autors)

Grüße,
Andreas Wolter
AZ-Delivery Blog

Pontifex42

Pontifex42

@Marco: Ja, Nano geht auch. Hab jetzt die Pins nicht durchgezählt, aber sollte reichen. Und wenn es knapp mit den Pins wird: einfach die Endschalter parallel zu zwei der LDRs schalten, das lässt sich dann per Software erkennen.
@Alex: Es gibt diese Displays tatsächlich in einer Variante, die oben fix einen gelben Bereich haben und darunter blau oder weiss sind. Findet man bei Suche nach “OLED Display blue yellow”, dauert halt einen Augenblick.
@AZDelivery: Wollte das schon lange mal nachbauen, aber da ist keine Skizze für die Holzteile. Gibt es da was? Bin etwas unbegabt beim mechanischen konstruieren. Würde ich sowieso nicht aus Holz machen sondern 3D-Drucken. Falls jemand dann interesse an den STL-Dateien hat, kann ich die gern publishen.

Marco

Marco

Hallo,
Ein interessantes Projekt. Ich habe noch einen Nano V3.0 mit Atmega328 CH340 herumliegen. Funktioniert das auch mit dem Arduino?
Danke Maro

Alex

Alex

Hallo,

das angegebene Display ist doch eigentlich weiss bzw. monochrom, wie ist es möglich, dass der angezeigte Text gelb und blau ist ?

Grüße

Leave a comment

All comments are moderated before being published