/*************************************************************************** * Solar light tracker project with Mega 2560 R3 Board microcontroller, * * Solar panel, LDR resistors, 0.96 inch OLED 128X64 pixels display, * * ULN2003 modules and 28BYJ-48 step by step motors. * * * * Miguel Torres Gordo * * Getafe (Madrid) - ESPAÑA Last revisión 22-06-2022 * ***************************************************************************/ /************** OLED display library and configuration *************/ #include // I2C communication library. #include // Core graphics library for screen. #include // SSD1306 oled driver library for monochrome 128x64 display. #define SCREEN_WIDTH 128 // 128 pixels width screen. #define SCREEN_HEIGHT 64 // 64 pixels height screen. Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); // Screen object declaration. /******************* LDR config *********************/ int LDR_SD = A0; // Upper right LDR connected to the analog pin 0 of the microcontroller. int LDR_SI = A1; // Upper left LDR connected to the analog pin 1 of the microcontroller. int LDR_II = A2; // Down left LDR connected to the analog pin 2 of the microcontroller. int LDR_ID = A3; // Down right LDR connected to the analog pin 3 of the microcontroller. 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 = 10; /******************* Solar panel ********************/ int SPV = A4; // Solar Panel connected to the analog pin 4 of the microcontroller. int solar_panel_read; // Variable value of the direct voltage of the solar panel. float solar_panel_voltaje; // Analog-to-Digital converted voltage value variable. /****************** Motors speed ******************/ int retardo = 5; // Normal speed of motor movement. int retardo_inicializacion = 15; // Speed of movement of the initialization motors. /****************** limit switchs ********************************* * Normaly closed Sunrise limit switch * * Normaly opened Sunsent limit switch * ***********************************************************************/ int sunrise_pin = 10; // Sunrise limit switch connected to the digital pin 10 of the microcontroller. int switch_sunrise = HIGH; // Normal status of the sunrise limit switch. void setup() { Serial.begin(9600); // Serial monitor initialitation. if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // OLED screen initialitation. Serial.println(F("SSD1306 allocation failed")); // Message if display initialization fails. for(;;); } display.clearDisplay(); // Clear display. display.setTextColor(WHITE); // Set text to white color. pinMode (LDR_SD, INPUT); // Config the mocrocontroller pins as an input pins. pinMode (LDR_SI, INPUT); pinMode (LDR_II, INPUT); pinMode (LDR_ID, INPUT); pinMode (SPV, INPUT); /**************************** Motors *************************************** * Horizontal motor step by step Vertical motor step by step * * * * Microcontroller Driver ULN2003 Microcontroller Driver ULN2003 * * =============== ============== =============== ============== * * 2 IN1 6 IN1 * * 3 IN2 7 IN2 * * 4 IN3 8 IN3 * * 5 IN4 9 IN4 * ***********************************************************************************/ pinMode (5, OUTPUT); // Config the microcontroller pins as an output pins. pinMode (4, OUTPUT); pinMode (3, OUTPUT); pinMode (2, OUTPUT); pinMode (9, OUTPUT); pinMode (8, OUTPUT); pinMode (7, OUTPUT); pinMode (6, OUTPUT); pinMode (sunrise_pin, INPUT); // Config the microcontroller pin as an input pin. switch_sunrise = digitalRead(sunrise_pin); while (switch_sunrise == HIGH) { // Check of the sunrise limit switch for initialization. Serial.println("Inicializando motor horizontal, espere ......"); // Message on OLED display. inicializacion_motor_horizontal(); // Call to the initialize horizontal motor method. switch_sunrise = digitalRead(sunrise_pin); // Sunrise limit switch check, initial status must be LOW to exit the loop. } } void loop() { switch_sunrise = digitalRead(sunrise_pin); // Sunrise limit switch check. SD = analogRead(LDR_SD); // Config the microcontroller pins how analogics. SI = analogRead(LDR_SI); II = analogRead(LDR_II); ID = analogRead(LDR_ID); solar_panel_read = analogRead(SPV); // Config the microcontroller solar panel pin how analogic solar_panel_voltaje = (solar_panel_read*5.0)/1023.0; // Analog-to-digital conversion of the voltage obtained by the solar panel. 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.print("SD: "); // Messages on the serial monitor of the LDR value. Serial.println(SD); Serial.print("SI: "); Serial.println(SI); Serial.print("II: "); Serial.println(II); Serial.print("ID: "); Serial.println(ID); Serial.println(); Serial.print("Superior Average : "); // Messages on the serial monitor of the averages value. Serial.println(sup_aver); Serial.print("Inferior Average : "); Serial.println(inf_aver); Serial.print("Right Average : "); Serial.println(right_aver); Serial.print("Left Average : "); Serial.println(left_aver); Serial.println(); Serial.print("Solar Panel Voltaje: "); // Message on the serial monitor of the Analog-to-digital conversion voltage value. Serial.print(solar_panel_voltaje, 2); Serial.println(" volts"); Serial.println(); Serial.print("Final de carrera sunrise: "); // Message on the serial monitor of the sunrise limit switch state. Serial.println(switch_sunrise); /***************** Horizontal motor movements **************************/ if (right_aver == left_aver) { // With similar measure, the motor is off. apagado_hor(); // Calling the motor stop method. } if (right_aver > left_aver && (right_aver-left_aver) > tolerance) { // When a measurement is higher and the difference is greater than the tolerance, paso_izq(); // moves the horizontal motor in the corresponding direction by method call. } if (left_aver > right_aver && (left_aver-right_aver) > tolerance) { paso_der(); } apagado_hor(); // Calling the motor stop method. delay(500); /**************** Vertical motor movements ****************************/ if (sup_aver == inf_aver) { // With similar measure, the motor is off. apagado_ver(); // Calling the motor stop method. } if (sup_aver > inf_aver && (sup_aver-inf_aver) > tolerance) { // When a measurement is higher and the difference is greater than the tolerance, paso_up(); // moves the horizontal motor in the corresponding direction by method call. } if (inf_aver > sup_aver && (inf_aver-sup_aver) > tolerance) { paso_down(); } apagado_ver(); // Calling the motor stop method. delay(500); /*************** End of motors movement methods **********************/ oled_message(); // Method call to display the voltage of the solar panel on the OLED screen. } void paso_der(){ // Method for moving the motor horizontally to the right. digitalWrite(5, LOW); digitalWrite(4, LOW); digitalWrite(3, HIGH); digitalWrite(2, HIGH); delay(retardo); digitalWrite(5, LOW); digitalWrite(4, HIGH); digitalWrite(3, HIGH); digitalWrite(2, LOW); delay(retardo); digitalWrite(5, HIGH); digitalWrite(4, HIGH); digitalWrite(3, LOW); digitalWrite(2, LOW); delay(retardo); digitalWrite(5, HIGH); digitalWrite(4, LOW); digitalWrite(3, LOW); digitalWrite(2, HIGH); delay(retardo); } void paso_izq() { // Method for moving the motor horizontally to the left. digitalWrite(5, HIGH); digitalWrite(4, HIGH); digitalWrite(3, LOW); digitalWrite(2, LOW); delay(retardo); digitalWrite(5, LOW); digitalWrite(4, HIGH); digitalWrite(3, HIGH); digitalWrite(2, LOW); delay(retardo); digitalWrite(5, LOW); digitalWrite(4, LOW); digitalWrite(3, HIGH); digitalWrite(2, HIGH); delay(retardo); digitalWrite(5, HIGH); digitalWrite(4, LOW); digitalWrite(3, LOW); digitalWrite(2, HIGH); delay(retardo); } void apagado_hor() { // Horizontal motor off method. digitalWrite(5, LOW); digitalWrite(4, LOW); digitalWrite(3, LOW); digitalWrite(2, LOW); } void paso_up(){ // Method for moving the motor vertically upward. digitalWrite(9, LOW); digitalWrite(8, LOW); digitalWrite(7, HIGH); digitalWrite(6, HIGH); delay(retardo); digitalWrite(9, LOW); digitalWrite(8, HIGH); digitalWrite(7, HIGH); digitalWrite(6, LOW); delay(retardo); digitalWrite(9, HIGH); digitalWrite(8, HIGH); digitalWrite(7, LOW); digitalWrite(6, LOW); delay(retardo); digitalWrite(9, HIGH); digitalWrite(8, LOW); digitalWrite(7, LOW); digitalWrite(6, HIGH); delay(retardo); } void paso_down() { // Method for moving the motor vertically downward. digitalWrite(9, HIGH); digitalWrite(8, HIGH); digitalWrite(7, LOW); digitalWrite(6, LOW); delay(retardo); digitalWrite(9, LOW); digitalWrite(8, HIGH); digitalWrite(7, HIGH); digitalWrite(6, LOW); delay(retardo); digitalWrite(9, LOW); digitalWrite(8, LOW); digitalWrite(7, HIGH); digitalWrite(6, HIGH); delay(retardo); digitalWrite(9, HIGH); digitalWrite(8, LOW); digitalWrite(7, LOW); digitalWrite(6, HIGH); delay(retardo); } void apagado_ver() { // Vertical motor off method. digitalWrite(9, LOW); digitalWrite(8, LOW); digitalWrite(7, LOW); digitalWrite(6, LOW); } void oled_message() { // Solar panel voltage message on the OLED screen. display.clearDisplay(); 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(); } void inicializacion_motor_horizontal() { // Method for initializing horizontal motor. digitalWrite(5, LOW); digitalWrite(4, LOW); digitalWrite(3, HIGH); digitalWrite(2, HIGH); delay(retardo_inicializacion); digitalWrite(5, LOW); digitalWrite(4, HIGH); digitalWrite(3, HIGH); digitalWrite(2, LOW); delay(retardo_inicializacion); digitalWrite(5, HIGH); digitalWrite(4, HIGH); digitalWrite(3, LOW); digitalWrite(2, LOW); delay(retardo_inicializacion); digitalWrite(5, HIGH); digitalWrite(4, LOW); digitalWrite(3, LOW); digitalWrite(2, HIGH); delay(retardo_inicializacion); }