Hardware components | ||||||
| × | 1 | ||||
| × | 1 | ||||
| × | 2 | ||||
| × | 3 | ||||
| × | 1 | ||||
| × | 4 | ||||
| × | 1 | ||||
| × | 2 | ||||
| × | 1 | ||||
Software apps and online services | ||||||
| ||||||
Hand tools and fabrication machines | ||||||
|
This is my fourth project with Arduino.
This device enables the photovoltaic cell to be aligned with the incoming rays of the sun. It uses 2 stepper motors and 3 "end position" switches (two for the horizontal, one for the vertical movement). The alignment of the photovoltaic cell is made possible by the simultaneous measurement of 4 ldr (Light Dependent Resistor). The number of volts generated and the actual temperature are displayed on two 7 segment displays.
The parts required were designed with a CAD program.
Then the parts were created by a laser cutter from 4mm poplar plywood. In the download area you will find the corresponding file for the laser cutter.
At the beginning the "end positions" are approached. Then the panel aligns itself with the sun's rays.
The current status of the system is always displayed on the serial monitor.
It should be mentioned, that...
.) before the start- and after the endtime the system is in deep sleep mode
.) the current analoge signal from the photovoltaic system varies considerably. An average value is calculated here.
.) the arithmetic mean between the left and right an the up and down side will be calculated. The movement is initialized based on this difference, but only if the difference is greater than a threshold value (in this example = 20).
.) a 9 volt power supply is recommended for operating the stepper motors.
In the next revision, the expansion with a lithium ion battery is planned to make the system self-sufficient.
/*
solar tracker
by smi1100 - 10/10/2022
based on the project by "az delivery" - https://www.az-delivery.de/blogs/azdelivery-blog-fur-arduino-und-raspberry-pi/solar-tracker-mit-schrittmotoren-und-oled-display
pins:
LDR: A0, A1, A2, A3
solar panel: A4
2 x 7 segment display: 23, 25, 27, 29
2 x motors: 4, 5, 6, 7, 8, 9, 10, 11
3 x limit switches: 49, 51, 53
clock: SDA 29, SCL 21
dht22: 12
libraries:
- Wire.h
- Arduino.h
- TM1637Display.h
- RTClib.h
- LowPower.h
- DHT.h
*/
// 7 Segment display
#include <Wire.h>
#include <Arduino.h>
#include <TM1637Display.h>
#define CLKTemp 29
#define DIOTemp 27
#define CLKVoltage 25
#define DIOVoltage 23
TM1637Display displayTemp(CLKTemp, DIOTemp);
TM1637Display displayVoltage(CLKVoltage, DIOVoltage);
const uint8_t SEG_OFF[] = // display "OFF" when system is in deep sleep (out of working time)
{
SEG_D,
SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F, // O
SEG_A | SEG_E | SEG_F | SEG_G, // F
SEG_A | SEG_E | SEG_F | SEG_G, // F
};
// LDR
int LDR_SD = A0; // Upper right LDR
int LDR_SI = A1; // Upper left LDR
int LDR_II = A2; // Down left LDR
int LDR_ID = A3; // Down right LDR
int SD, SI, II, ID; // LDR resistor voltage variables
int sup_aver, inf_aver, right_aver, left_aver; // Arithmetic mean of the sides
int tolerance = 20; // Above the tolerance a movement is initiated, below it not
// solar panel
int SPV = A4; // solar Panel connected to the analog pin 4
int solar_panel_read; // Variable value of the direct voltage of the solar panel (0 - 1024)
float solar_panel_voltage; // Analog-to-Digital converted voltage value variable (0 - 5 Volt)
int number_of_measurements = 0; // The analoge signal from the photovoltaic system varies considerably. An average value is calculated here.
float total_solar_panel_voltage = 0;
float average_solar_panel_voltage = 0;
// motors
int speed = 5; // Normal speed of motor movement.
int speed_initialization = 5; // Speed of movement of the initialization motors.
int horizontal_direction; // 1 - left, 2 - right, 0 - Stop
int vertical_direction; // 1 - up, 2 - down, 0 - Stop
String sign; // plus or minus
int pin_horizontal_in1 = 4;
int pin_horizontal_in2 = 5;
int pin_horizontal_in3 = 6;
int pin_horizontal_in4 = 7;
int pin_vertical_in1 = 8;
int pin_vertical_in2 = 9;
int pin_vertical_in3 = 10;
int pin_vertical_in4 = 11;
// limit switchs
int sunrise_pin = 53;
int switch_sunrise = HIGH; // Normal status of the sunrise limit switch.
int sunset_pin = 51;
int switch_sunset = HIGH;
int vertical_low_pin = 49;
int switch_vertical_low = HIGH;
// clock
#include "RTClib.h"
RTC_DS3231 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
int starttime = 8; // before the starttime and after the endtime the system is in deep sleep mode
int endtime = 21;
// low power
#include "LowPower.h"
const unsigned interval = 16; // standard is 8 seconds
// DHT22
#include "DHT.h"
#define DHT22PIN 12
#define DHT22TYPE DHT22
DHT dht22(DHT22PIN, DHT22TYPE);
void setup()
{
Serial.begin(9600);
delay (1000);
// 7 Segment display
displayTemp.setBrightness(7);
displayVoltage.setBrightness(7);
// LDR
pinMode (LDR_SD, INPUT);
pinMode (LDR_SI, INPUT);
pinMode (LDR_II, INPUT);
pinMode (LDR_ID, INPUT);
// solar panel
pinMode (SPV, INPUT);
/* motors ***************************************
* Horizontal motor step by step Vertical motor step by step *
* *
* Microcontroller Driver ULN2003 Microcontroller Driver ULN2003 *
* =============== ============== =============== ============== *
* 2 53 IN1 6 52 IN1 *
* 3 51 IN2 7 50 IN2 *
* 4 49 IN3 8 48 IN3 *
* 5 47 IN4 9 46 IN4 *
***********************************************************************************/
pinMode (pin_horizontal_in1, OUTPUT);
pinMode (pin_horizontal_in2, OUTPUT);
pinMode (pin_horizontal_in3, OUTPUT);
pinMode (pin_horizontal_in4, OUTPUT);
pinMode (pin_vertical_in1, OUTPUT);
pinMode (pin_vertical_in2, OUTPUT);
pinMode (pin_vertical_in3, OUTPUT);
pinMode (pin_vertical_in4, OUTPUT);
// test run
pinMode (sunset_pin, INPUT);
switch_sunset = digitalRead(sunset_pin);
Serial.println("");
delay (500);
while (switch_sunset == HIGH) // Check of the sunrise limit switch for initialization.
{
Serial.println("Approach the start position of the horizontal motor (west - sunset)");
initialize_motor_horizontal_left();
switch_sunset = digitalRead(sunset_pin); // Sunrise limit switch check, initial status must be LOW to exit the loop.
}
pinMode (sunrise_pin, INPUT);
switch_sunrise = digitalRead(sunrise_pin);
Serial.println("");
delay (500);
while (switch_sunrise == HIGH)
{
Serial.println("Approach the start position of the horizontal motor (east - sunrise)");
initialize_motor_horizontal_right();
switch_sunrise = digitalRead(sunrise_pin);
}
pinMode (vertical_low_pin, INPUT);
switch_vertical_low = digitalRead(vertical_low_pin);
Serial.println("");
delay (500);
while (switch_vertical_low == HIGH)
{
Serial.println("Approach the start position of the vertical motor (vertical)");
initialize_motor_vertical_down();
switch_vertical_low = digitalRead(vertical_low_pin);
}
// Clock
if (! rtc.begin())
{
Serial.println("Couldn't find RTC");
while (1);
}
if (rtc.lostPower())
{
Serial.println("RTC lost power, lets set the time!");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
// DHT22
dht22.begin();
}
void loop()
{
DateTime now = rtc.now();
if (now.hour()>=endtime || now.hour()<=starttime)
{
horizontal_motor_stop();
vertical_motor_stop();
Serial.print("---> actual time: ");Serial.print(now.hour());Serial.print(" : "); Serial.println(now.minute());
Serial.print("---> Unit outside the time window from ");Serial.print(starttime);Serial.print(" - "); Serial.println(endtime);
displayTemp.clear();
displayTemp.setSegments(SEG_OFF);
while(1);
delay(500);
int sleepcycles = interval / 8;
for (int i=0; i<sleepcycles; i++)
{
LowPower.idle(SLEEP_8S, ADC_OFF, TIMER5_OFF, TIMER4_OFF, TIMER3_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF, SPI_OFF, USART3_OFF, USART2_OFF, USART1_OFF, USART0_OFF, TWI_OFF);
}
}
else
{
switch_sunrise = digitalRead(sunrise_pin);
switch_sunset = digitalRead(sunset_pin);
switch_vertical_low = digitalRead(vertical_low_pin);
SD = analogRead(LDR_SD);
SI = analogRead(LDR_SI);
II = analogRead(LDR_II);
ID = analogRead(LDR_ID);
float t22 = dht22.readTemperature();
number_of_measurements++;
if (number_of_measurements == 1000) {number_of_measurements == 0;}
solar_panel_read = analogRead(SPV);
solar_panel_voltage = (solar_panel_read*5.0)/1023.0; // Analog-to-digital conversion of the voltage obtained by the solar panel.
total_solar_panel_voltage = total_solar_panel_voltage + solar_panel_voltage;
average_solar_panel_voltage = total_solar_panel_voltage / number_of_measurements;
sup_aver = (SD + SI)/2; // Calculation of the average voltage value of the LDRs on each side.
inf_aver = (ID + II)/2;
right_aver = (SD + ID)/2;
left_aver = (SI + II)/2;
Serial.println("");
Serial.println("-------------------------------------------");
Serial.println("");
Serial.print("time: ");
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.println(now.minute(), DEC);
Serial.print("operating time ");
Serial.print(starttime);
Serial.print(":00 - ");
Serial.print(endtime);
Serial.println(":00");
Serial.println("");
Serial.print("Current voltage of the solar module: ");
Serial.print(solar_panel_voltage, 2);
Serial.println(" volt");
Serial.print("average voltage of the solar module: ");
Serial.print(average_solar_panel_voltage, 2);
Serial.print(" volt");
Serial.print(" (");
Serial.print(number_of_measurements);
Serial.println(" runs)");
Serial.println("");
Serial.print("DHT22 Temp: ");
Serial.print(t22);
Serial.println(" C ");
Serial.println();
Serial.print("sunrise limit switch: ");
Serial.println(switch_sunrise);
Serial.print("sunset limt switch: ");
Serial.println(switch_sunset);
Serial.print("vertical position limit switch: ");
Serial.println(switch_vertical_low);
Serial.println("");
Serial.print(" Sup.av.: ");
Serial.println(sup_aver);
Serial.print(" SI: ");
Serial.print(SI);
Serial.print(" | SD: ");
Serial.println(SD);
Serial.print("Left.av : ");
Serial.print(left_aver);
Serial.print(" --------|--------- Right.av.: ");
Serial.println(right_aver);
Serial.print(" II: ");
Serial.print(II);
Serial.print(" | ID: ");
Serial.println(ID);
Serial.print(" Inf.av : ");
Serial.println(inf_aver);
Serial.println();
displayTemp.clear();
displayTemp.showNumberDecEx(t22*100, 0b11100000, false, 4, 0);
displayVoltage.clear();
displayVoltage.showNumberDecEx(average_solar_panel_voltage*100, 0b11100000, true, 4, 0);
// horizontal motor movements
while (switch_sunrise == LOW)
{
Serial.println("Horizontal engine -> easternmost state reached");
horizontal_move_left();
switch_sunrise = digitalRead(sunrise_pin);
}
while (switch_sunset == LOW)
{
Serial.println("Horizontal engine -> westernmost state achieved");
horizontal_move_right();
switch_sunset = digitalRead(sunset_pin);
}
if (right_aver == left_aver)
{
horizontal_motor_stop();
horizontal_direction = 0;
}
if (right_aver > left_aver && (right_aver-left_aver) > tolerance) // When a measurement is higher and the difference is greater than the tolerance,
{
horizontal_move_right();
horizontal_direction = 2;
}
if (left_aver > right_aver && (left_aver-right_aver) > tolerance)
{
horizontal_move_left();
horizontal_direction = 1;
}
if (right_aver > left_aver && (right_aver-left_aver) <= tolerance) // When a measurement is higher and the difference is less than the tolerance,
{
horizontal_motor_stop();
horizontal_direction = 0;
}
if (left_aver > right_aver && (left_aver-right_aver) <= tolerance)
{
horizontal_motor_stop();
horizontal_direction = 0;
}
horizontal_motor_stop();
delay(500);
Serial.println("");
Serial.print("Delta horizontal: ");
if (left_aver-right_aver>0) {sign = "+";}
if (left_aver-right_aver<0) {sign = "";}
Serial.print(sign); Serial.print(left_aver-right_aver);Serial.print(" (");Serial.print(tolerance);Serial.print(")");
Serial.print(" -- direction: ");
if (horizontal_direction == 0)
{
Serial.println("STOP");
}
if (horizontal_direction == 1)
{
Serial.println("<<<<");
}
if (horizontal_direction == 2)
{
Serial.println(">>>>");
}
// vertical motor movements
while (switch_vertical_low == LOW)
{
Serial.println("verticale motor -> lowest state reached");
vertical_motor_up();
switch_vertical_low = digitalRead(vertical_low_pin);
}
if (sup_aver == inf_aver)
{
vertical_motor_stop();
vertical_direction = 0;
}
if (sup_aver > inf_aver && (sup_aver-inf_aver) > tolerance)
{
vertical_motor_down();
vertical_direction = 2;
}
if (inf_aver > sup_aver && (inf_aver-sup_aver) > tolerance)
{
vertical_motor_up();
vertical_direction = 1;
}
if (sup_aver > inf_aver && (sup_aver-inf_aver) <= tolerance)
{
vertical_motor_stop();
vertical_direction = 0;
}
if (inf_aver > sup_aver && (inf_aver-sup_aver) <= tolerance)
{
vertical_motor_stop();
vertical_direction = 0;
}
vertical_motor_stop();
delay(500);
Serial.println("");
Serial.print("Delta vertical: "); // Messages on the serial monitor of the averages value.
if (sup_aver-inf_aver>0) {sign = "+";}
if (sup_aver-inf_aver<0) {sign = "";}
Serial.print(sign);Serial.print(sup_aver-inf_aver);Serial.print(" (");Serial.print(tolerance);Serial.print(")");
Serial.print(" -- direction: ");
if (vertical_direction == 0)
{
Serial.println("STOP");
}
if (vertical_direction == 1)
{
Serial.println("");
}
if (vertical_direction == 2)
{
Serial.println("");
}
}
}
void horizontal_move_right()
{
digitalWrite(pin_horizontal_in4, LOW);
digitalWrite(pin_horizontal_in3, LOW);
digitalWrite(pin_horizontal_in2, HIGH);
digitalWrite(pin_horizontal_in1, HIGH);
delay(speed);
digitalWrite(pin_horizontal_in4, LOW);
digitalWrite(pin_horizontal_in3, HIGH);
digitalWrite(pin_horizontal_in2, HIGH);
digitalWrite(pin_horizontal_in1, LOW);
delay(speed);
digitalWrite(pin_horizontal_in4, HIGH);
digitalWrite(pin_horizontal_in3, HIGH);
digitalWrite(pin_horizontal_in2, LOW);
digitalWrite(pin_horizontal_in1, LOW);
delay(speed);
digitalWrite(pin_horizontal_in4, HIGH);
digitalWrite(pin_horizontal_in3, LOW);
digitalWrite(pin_horizontal_in2, LOW);
digitalWrite(pin_horizontal_in1, HIGH);
delay(speed);
}
void horizontal_move_left()
{
digitalWrite(pin_horizontal_in4, HIGH);
digitalWrite(pin_horizontal_in3, HIGH);
digitalWrite(pin_horizontal_in2, LOW);
digitalWrite(pin_horizontal_in1, LOW);
delay(speed);
digitalWrite(pin_horizontal_in4, LOW);
digitalWrite(pin_horizontal_in3, HIGH);
digitalWrite(pin_horizontal_in2, HIGH);
digitalWrite(pin_horizontal_in1, LOW);
delay(speed);
digitalWrite(pin_horizontal_in4, LOW);
digitalWrite(pin_horizontal_in3, LOW);
digitalWrite(pin_horizontal_in2, HIGH);
digitalWrite(pin_horizontal_in1, HIGH);
delay(speed);
digitalWrite(pin_horizontal_in4, HIGH);
digitalWrite(pin_horizontal_in3, LOW);
digitalWrite(pin_horizontal_in2, LOW);
digitalWrite(pin_horizontal_in1, HIGH);
delay(speed);
}
void horizontal_motor_stop()
{
digitalWrite(pin_horizontal_in4, LOW);
digitalWrite(pin_horizontal_in3, LOW);
digitalWrite(pin_horizontal_in2, LOW);
digitalWrite(pin_horizontal_in1, LOW);
}
void vertical_motor_up()
{
digitalWrite(pin_vertical_in4, LOW);
digitalWrite(pin_vertical_in3, LOW);
digitalWrite(pin_vertical_in2, HIGH);
digitalWrite(pin_vertical_in1, HIGH);
delay(speed);
digitalWrite(pin_vertical_in4, LOW);
digitalWrite(pin_vertical_in3, HIGH);
digitalWrite(pin_vertical_in2, HIGH);
digitalWrite(pin_vertical_in1, LOW);
delay(speed);
digitalWrite(pin_vertical_in4, HIGH);
digitalWrite(pin_vertical_in3, HIGH);
digitalWrite(pin_vertical_in2, LOW);
digitalWrite(pin_vertical_in1, LOW);
delay(speed);
digitalWrite(pin_vertical_in4, HIGH);
digitalWrite(pin_vertical_in3, LOW);
digitalWrite(pin_vertical_in2, LOW);
digitalWrite(pin_vertical_in1, HIGH);
delay(speed);
}
void vertical_motor_down()
{
digitalWrite(pin_vertical_in4, HIGH);
digitalWrite(pin_vertical_in3, HIGH);
digitalWrite(pin_vertical_in2, LOW);
digitalWrite(pin_vertical_in1, LOW);
delay(speed);
digitalWrite(pin_vertical_in4, LOW);
digitalWrite(pin_vertical_in3, HIGH);
digitalWrite(pin_vertical_in2, HIGH);
digitalWrite(pin_vertical_in1, LOW);
delay(speed);
digitalWrite(pin_vertical_in4, LOW);
digitalWrite(pin_vertical_in3, LOW);
digitalWrite(pin_vertical_in2, HIGH);
digitalWrite(pin_vertical_in1, HIGH);
delay(speed);
digitalWrite(pin_vertical_in4, HIGH);
digitalWrite(pin_vertical_in3, LOW);
digitalWrite(pin_vertical_in2, LOW);
digitalWrite(pin_vertical_in1, HIGH);
delay(speed);
}
void vertical_motor_stop()
{
digitalWrite(pin_vertical_in4, LOW);
digitalWrite(pin_vertical_in3, LOW);
digitalWrite(pin_vertical_in2, LOW);
digitalWrite(pin_vertical_in1, LOW);
}
void initialize_motor_horizontal_left()
{
digitalWrite(pin_horizontal_in4, HIGH);
digitalWrite(pin_horizontal_in3, HIGH);
digitalWrite(pin_horizontal_in2, LOW);
digitalWrite(pin_horizontal_in1, LOW);
delay(speed_initialization);
digitalWrite(pin_horizontal_in4, LOW);
digitalWrite(pin_horizontal_in3, HIGH);
digitalWrite(pin_horizontal_in2, HIGH);
digitalWrite(pin_horizontal_in1, LOW);
delay(speed_initialization);
digitalWrite(pin_horizontal_in4, LOW);
digitalWrite(pin_horizontal_in3, LOW);
digitalWrite(pin_horizontal_in2, HIGH);
digitalWrite(pin_horizontal_in1, HIGH);
delay(speed_initialization);
digitalWrite(pin_horizontal_in4, HIGH);
digitalWrite(pin_horizontal_in3, LOW);
digitalWrite(pin_horizontal_in2, LOW);
digitalWrite(pin_horizontal_in1, HIGH);
delay(speed_initialization);
}
void initialize_motor_horizontal_right()
{
digitalWrite(pin_horizontal_in4, LOW);
digitalWrite(pin_horizontal_in3, LOW);
digitalWrite(pin_horizontal_in2, HIGH);
digitalWrite(pin_horizontal_in1, HIGH);
delay(speed_initialization);
digitalWrite(pin_horizontal_in4, LOW);
digitalWrite(pin_horizontal_in3, HIGH);
digitalWrite(pin_horizontal_in2, HIGH);
digitalWrite(pin_horizontal_in1, LOW);
delay(speed_initialization);
digitalWrite(pin_horizontal_in4, HIGH);
digitalWrite(pin_horizontal_in3, HIGH);
digitalWrite(pin_horizontal_in2, LOW);
digitalWrite(pin_horizontal_in1, LOW);
delay(speed_initialization);
digitalWrite(pin_horizontal_in4, HIGH);
digitalWrite(pin_horizontal_in3, LOW);
digitalWrite(pin_horizontal_in2, LOW);
digitalWrite(pin_horizontal_in1, HIGH);
delay(speed_initialization);
}
void initialize_motor_vertical_down()
{
digitalWrite(pin_vertical_in4, HIGH);
digitalWrite(pin_vertical_in3, HIGH);
digitalWrite(pin_vertical_in2, LOW);
digitalWrite(pin_vertical_in1, LOW);
delay(speed_initialization);
digitalWrite(pin_vertical_in4, LOW);
digitalWrite(pin_vertical_in3, HIGH);
digitalWrite(pin_vertical_in2, HIGH);
digitalWrite(pin_vertical_in1, LOW);
delay(speed_initialization);
digitalWrite(pin_vertical_in4, LOW);
digitalWrite(pin_vertical_in3, LOW);
digitalWrite(pin_vertical_in2, HIGH);
digitalWrite(pin_vertical_in1, HIGH);
delay(speed_initialization);
digitalWrite(pin_vertical_in4, HIGH);
digitalWrite(pin_vertical_in3, LOW);
digitalWrite(pin_vertical_in2, LOW);
digitalWrite(pin_vertical_in1, HIGH);
delay(speed_initialization);
}
void initialize_motor_vertical_up()
{
digitalWrite(pin_vertical_in4, LOW);
digitalWrite(pin_vertical_in3, LOW);
digitalWrite(pin_vertical_in2, HIGH);
digitalWrite(pin_vertical_in1, HIGH);
delay(speed_initialization);
digitalWrite(pin_vertical_in4, LOW);
digitalWrite(pin_vertical_in3, HIGH);
digitalWrite(pin_vertical_in2, HIGH);
digitalWrite(pin_vertical_in1, LOW);
delay(speed_initialization);
digitalWrite(pin_vertical_in4, HIGH);
digitalWrite(pin_vertical_in3, HIGH);
digitalWrite(pin_vertical_in2, LOW);
digitalWrite(pin_vertical_in1, LOW);
delay(speed_initialization);
digitalWrite(pin_vertical_in4, HIGH);
digitalWrite(pin_vertical_in3, LOW);
digitalWrite(pin_vertical_in2, LOW);
digitalWrite(pin_vertical_in1, HIGH);
delay(speed_initialization);
}
Comments