solar_light_tracker_Armin3.ino


1
/***************************************************************************
2
*    Solar light tracker project with Mega 2560 R3 Board microcontroller,  *
3
*    Solar panel, LDR resistors, 0.96 inch OLED 128X64 pixels display,     *
4
*    2 TB6600 modules and 2 NEMA17 step by step motors.                    *
5
*                                                                          *
6
*    Armin Rolfes / Wilfried Meyer                                         *
7
*    Last revisión 04.10.2024                                              *
8
***************************************************************************/
9
#include <AccelStepper.h>
10
/**************   OLED display library and configuration    *************/
11
#include <Wire.h>                     // I2C communication library.
12
#include <Adafruit_GFX.h>             // Core graphics library for screen.
13
#include <Adafruit_SSD1306.h>         // SSD1306 oled driver library for monochrome 128x64 display.
14
15
#define SCREEN_WIDTH 128                                             // 128 pixels width screen. 
16
#define SCREEN_HEIGHT 64                                             // 64 pixels height screen.
17
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);     // Screen object declaration.
18
19
/*******************    LDR config    *********************/
20
int LDR_UpR = A0;          // Upper right LDR connected to the analog pin 0 of the microcontroller.
21
int LDR_UpL = A1;          // Upper left  LDR connected to the analog pin 1 of the microcontroller.
22
int LDR_LoL = A2;          // Lower left  LDR connected to the analog pin 2 of the microcontroller.
23
int LDR_LoR = A3;          // Lower right LDR connected to the analog pin 3 of the microcontroller.
24
25
int upperRightLdrVal = 0;  // Upper right LDR resistor voltage (AD)
26
int upperLeftLdrVal  = 0;  // Upper left  LDR resistor voltage (AD) 
27
int lowerLeftLdrVal  = 0;  // Lower left  LDR resistor voltage (AD)
28
int lowerRightLdrVal = 0;  // Lower right LDR resistor voltage (AD)
29
30
int upperAverageLdr  = 0;  // Arithmetic mean of the upper LDR sensors
31
int lowerAverageLdr  = 0;  // Arithmetic mean of the lower LDR sensors
32
int rightAverageLdr  = 0;  // Arithmetic mean of the right LDR sensors
33
int leftAverageLdr   = 0;  // Arithmetic mean of the left LDR sensors
34
35
int toleranceAverageLdr  = 10;   // tolerance for the LDR average values
36
37
/*******************    Solar panel    ********************/
38
int SPV = A4;                       // Solar Panel connected to the analog pin 4 of the microcontroller.
39
int solarPanelAdVal     = 0;        // value of the direct voltage of the solar panel (AD).
40
float solarPanelVoltage = 0;        // Analog-to-Digital converted voltage value
41
42
/******************     Motors config    ******************/
43
int MOTOR_ENABLE  = HIGH; // value to enable  the motor (LOW or HIGH depending on hardware configuration)
44
int MOTOR_DISABLE = LOW; // value to disable the motor (LOW or HIGH depending on hardware configuration)
45
46
// config for horizontal movement
47
int MOTOR_LEFT_RIGHT_ENABLE      = 41; // enable Pin for Motor for left / right Motor movement / todo//
48
int MOTOR_LEFT_RIGHT_PULS        = 37; // Puls Pin for Motor left / right Motor movement / todo//
49
int MOTOR_LEFT_RIGHT_DIRECTION   = 39; // direction PIN for Motor left / right Motor movement  / todo//
50
51
int MOTOR_DIRECTION_LEFT  = 39 HIGH;  // value for which motor moves to the left  (LOW or HIGH depending on hardware configuration)   / todo//
52
int MOTOR_DIRECTION_RIGHT = 39 LOW;  // value for which motor moves to the right (LOW or HIGH depending on hardware configuration)   / todo//
53
54
// config for vertical movement
55
int MOTOR_UP_DOWN_ENABLE         = 35; // enable Pin for Motor up / down Motor movement / todo//
56
int MOTOR_UP_DOWN_PULS           = 31; // Puls Pin for Motor up / down Motor movement / todo//
57
int MOTOR_UP_DOWN_DIRECTION      = 33; // direction PIN for Motor up / down Motor movement / todo//
58
59
int MOTOR_DIRECTION_UP   = 33 HIGH;  // value for which motor moves to the up  (LOW or HIGH depending on hardware configuration)   / todo//
60
int MOTOR_DIRECTION_DOWN = 33 LOW;   // value for which motor moves to the down (LOW or HIGH depending on hardware configuration)   / todo//
61
62
/******************     Motors speed     ******************/
63
int motorMoveDelay     = 500;        // Delay between movement steps of the stepper motor [us] / todo//
64
int motorStepsToMoveLeftRight = 5;   // Number of steps to move in left or right direction / todo//
65
int motorStepsToMoveUpDown = 2;      // Number of steps to move in up   or down  direction / todo //
66
67
68
/******************    limit switches   *********************************
69
*   Normally closed Sunrise limit switch                                *                                                                
70
*   Normally opened Sunset limit switch                                 * 
71
***********************************************************************/
72
int LIMIT_SWITCH_LEFT   = 1;         // Pin Limit switch left // todo Pin Endschalter links West
73
int LIMIT_SWITCH_LEFT_PRESSED = HIGH;   // value for which the LEFT limit switch is pressed (LOW or HIGH depending on hardware configuration)   / todo//
74
75
int LIMIT_SWITCH_RIGHT  = 0;         // Pin Limit switch right // todo Pin Endschalter rechts Ost
76
int LIMIT_SWITCH_RIGHT_PRESSED = LOW;  // value for which the RIGHT limit switch is pressed (LOW or HIGH depending on hardware configuration)   / todo//
77
78
int LIMIT_SWITCH_UP     = 2;         // Pin Limit switch up // todo Pin Endschalter Oben Nord
79
int LIMIT_SWITCH_UP_PRESSED = HIGH;     // value for which the UP limit switch is pressed (LOW or HIGH depending on hardware configuration)   // todo//
80
81
int LIMIT_SWITCH_DOWN   = 3;         // Pin Limit switch down // todo Pin Endschalter unten Süd
82
int LIMIT_SWITCH_DOWN_PRESSED = HIGH;   // value for which the DOWN limit switch is pressed (LOW or HIGH depending on hardware configuration)   / todo//
83
84
int limitSwitchLeftStatus;          // current value for left  limit switch
85
int limitSwitchRightStatus;         // current value for right limit switch
86
int limitSwitchUpStatus;            // current value for up    limit switch
87
int limitSwitchDownStatus;          // current value for down  limit switch
88
89
void setup() 
90
{
91
  
92
      Serial.begin(9600);               // Serial monitor initialisation.
93
94
      if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) 
95
      {                                                         // OLED screen initialisation.
96
            Serial.println(F("SSD1306 allocation failed"));     // Message if display initialization fails.
97
            for(;;);
98
      }
99
        
100
      display.clearDisplay();                                   // Clear display.
101
      display.setTextColor(WHITE);                              // Set text to white color.
102
103
      // Config LDR Pins
104
      pinMode (LDR_UpR, INPUT);
105
      pinMode (LDR_UpL, INPUT);
106
      pinMode (LDR_LoL, INPUT);
107
      pinMode (LDR_LoR, INPUT); 
108
109
      pinMode (SPV, INPUT);
110
111
      // Config Motor Pins
112
      pinMode(MOTOR_LEFT_RIGHT_ENABLE, OUTPUT);    // Enable
113
      pinMode(MOTOR_LEFT_RIGHT_PULS, OUTPUT);      // Puls
114
      pinMode(MOTOR_LEFT_RIGHT_DIRECTION, OUTPUT); // Direction
115
      digitalWrite(MOTOR_LEFT_RIGHT_ENABLE, MOTOR_DISABLE);   // disable Motor left right
116
117
      pinMode(MOTOR_UP_DOWN_ENABLE, OUTPUT);    // Enable
118
      pinMode(MOTOR_UP_DOWN_PULS, OUTPUT);      // Puls
119
      pinMode(MOTOR_UP_DOWN_DIRECTION, OUTPUT); // Direction
120
      digitalWrite(MOTOR_UP_DOWN_ENABLE, MOTOR_DISABLE);   // disable Motor up down
121
122
      // Config limit switches
123
      pinMode (LIMIT_SWITCH_LEFT, INPUT);
124
      pinMode (LIMIT_SWITCH_RIGHT, INPUT);
125
      pinMode (LIMIT_SWITCH_UP, INPUT);
126
      pinMode (LIMIT_SWITCH_DOWN, INPUT);
127
128
      // set back to start position
129
      limitSwitchRightStatus = digitalRead(LIMIT_SWITCH_RIGHT);        
130
      while (limitSwitchRightStatus != LIMIT_SWITCH_RIGHT_PRESSED) 
131
      {                                                        // Check of the sunrise limit switch
132
            Serial.println("move Panel to Start position");    // Message on OLED display.
133
            movePanelRight();                                  // Call to the initialize horizontal motor method.
134
            limitSwitchRightStatus = digitalRead(LIMIT_SWITCH_RIGHT);         // Sunrise limit switch check, initial status must be LOW to exit the loop.
135
       }
136
           
137
}
138
139
void loop() 
140
{
141
   limitSwitchLeftStatus   = digitalRead(LIMIT_SWITCH_LEFT); // read limit switches  
142
   limitSwitchRightStatus  = digitalRead(LIMIT_SWITCH_RIGHT);    
143
   limitSwitchUpStatus     = digitalRead(LIMIT_SWITCH_UP);
144
   limitSwitchDownStatus   = digitalRead(LIMIT_SWITCH_DOWN);
145
   
146
   upperRightLdrVal = analogRead(LDR_UpR);                   // Config LDR microcontroller pins
147
   upperLeftLdrVal  = analogRead(LDR_UpL);
148
   lowerLeftLdrVal  = analogRead(LDR_LoL);
149
   lowerRightLdrVal = analogRead(LDR_LoR);
150
151
   solarPanelAdVal   = analogRead(SPV);                      // Config the microcontroller solar panel pin how analogic
152
   solarPanelVoltage = (solarPanelAdVal*5.0)/1023.0;         // Analog-to-digital conversion of the voltage obtained by the solar panel.
153
154
   upperAverageLdr = (upperRightLdrVal + upperLeftLdrVal) /2;  // Calculation of the average voltage value of the LDRs on each side.
155
   lowerAverageLdr = (lowerRightLdrVal + lowerLeftLdrVal) /2;
156
   rightAverageLdr = (upperRightLdrVal + lowerRightLdrVal)/2;
157
   leftAverageLdr  = (upperLeftLdrVal  + lowerLeftLdrVal) /2;
158
159
   Serial.print("upperRightLdrVal: ");                         // Messages on the serial monitor of the LDR value.
160
   Serial.println(upperRightLdrVal);
161
   Serial.print("upperLeftLdrVal: ");
162
   Serial.println(upperLeftLdrVal);
163
   Serial.print("lowerLeftLdrVal: ");
164
   Serial.println(lowerLeftLdrVal);
165
   Serial.print("lowerRightLdrVal: ");
166
   Serial.println(lowerRightLdrVal);
167
   Serial.println();
168
169
   Serial.print("Upper LDR Average : ");                        // Messages on the serial monitor of the averages value.
170
   Serial.println(upperAverageLdr);
171
   Serial.print("Lower LDR Average : ");
172
   Serial.println(lowerAverageLdr);
173
   Serial.print("Right LDR Average : ");
174
   Serial.println(rightAverageLdr);
175
   Serial.print("Left LDR Average : ");
176
   Serial.println(leftAverageLdr);
177
   Serial.println();
178
179
   Serial.print("Solar Panel Voltage: ");                      // Message on the serial monitor of the Analog-to-digital conversion voltage value.
180
   Serial.print(solarPanelVoltage, 2);
181
   Serial.println(" volts");
182
   Serial.println();
183
184
   Serial.print("limit switch left state: ");                  // Message on the serial monitor of the limit switch states.
185
   Serial.println(limitSwitchLeftStatus);
186
   Serial.print("limit switch right state: ");               
187
   Serial.println(limitSwitchRightStatus);
188
   Serial.print("limit switch up state: ");               
189
   Serial.println(limitSwitchUpStatus);
190
   Serial.print("limit switch down state: ");               
191
   Serial.println(limitSwitchDownStatus);
192
193
   /***************** Horizontal motor movements **************************/ 
194
   if (rightAverageLdr == leftAverageLdr)                      // With similar measure, the motor is off. 
195
   {                    
196
         stopMoveLeftOrRight();                                // Calling the motor stop method.
197
   }
198
199
   if (rightAverageLdr > leftAverageLdr && (rightAverageLdr-leftAverageLdr) > toleranceAverageLdr) 
200
   {                                                           // When a measurement is higher and the difference is greater than the toleranceAverageLdr,
201
         movePanelLeft();                                      // moves the horizontal motor in the corresponding direction by method call.
202
   }
203
204
   if (leftAverageLdr > rightAverageLdr && (leftAverageLdr-rightAverageLdr) > toleranceAverageLdr) 
205
   {
206
         movePanelRight();
207
   }
208
209
   stopMoveLeftOrRight();                                      // Calling the motor stop method.     
210
   delay(500);
211
212
   /**************** Vertical motor movements ****************************/
213
   if (upperAverageLdr == lowerAverageLdr) 
214
   {                   // With similar measure, the motor is off.
215
         stopMoveUpOrDown();                                   // Calling the motor stop method.
216
   }
217
218
   if (upperAverageLdr > lowerAverageLdr && (upperAverageLdr-lowerAverageLdr) > toleranceAverageLdr) 
219
   {       // When a measurement is higher and the difference is greater than the toleranceAverageLdr,
220
         movePanelUp();                                        // moves the horizontal motor in the corresponding direction by method call.
221
   }
222
223
   if (lowerAverageLdr > upperAverageLdr && (lowerAverageLdr-upperAverageLdr) > toleranceAverageLdr) 
224
   {
225
         movePanelDown();
226
   }
227
228
   stopMoveUpOrDown();                                         // Calling the motor stop method.    
229
   delay(500);
230
231
   /*************** End of motors movement methods **********************/
232
233
   oled_message();                                             // Method call to display the voltage of the solar panel on the OLED screen.
234
235
}
236
237
// Method for moving the motor horizontally to the right.
238
void movePanelRight() 
239
{
240
   for (int i = 0; i < motorStepsToMoveLeftRight; i++)
241
   {
242
      limitSwitchRightStatus = digitalRead(LIMIT_SWITCH_RIGHT);      // limit switch check.
243
      if (limitSwitchRightStatus != LIMIT_SWITCH_RIGHT_PRESSED)
244
      {
245
         digitalWrite(MOTOR_LEFT_RIGHT_ENABLE, MOTOR_ENABLE);        // Enable movement
246
         digitalWrite(MOTOR_LEFT_RIGHT_DIRECTION, MOTOR_DIRECTION_RIGHT);  // set direction for movement
247
248
         digitalWrite(MOTOR_LEFT_RIGHT_PULS, HIGH);
249
         delayMicroseconds(motorMoveDelay);
250
         digitalWrite(MOTOR_LEFT_RIGHT_PULS, LOW);
251
         delayMicroseconds(motorMoveDelay);
252
253
         digitalWrite(MOTOR_LEFT_RIGHT_ENABLE,MOTOR_DISABLE);         // Disable movement
254
      }
255
      else
256
      {
257
         Serial.println("Limit switch RIGHT pressed! Can't move further!");
258
         break;
259
      }
260
   }
261
}
262
263
// Method for moving the motor horizontally to the left.
264
void movePanelLeft() 
265
{               
266
   for (int i = 0; i < motorStepsToMoveLeftRight; i++)
267
   {
268
      limitSwitchLeftStatus = digitalRead(LIMIT_SWITCH_LEFT);      // limit switch check.
269
      if (limitSwitchLeftStatus != LIMIT_SWITCH_LEFT_PRESSED)
270
      {
271
         digitalWrite(MOTOR_LEFT_RIGHT_ENABLE, MOTOR_ENABLE);      // Enable movement
272
         digitalWrite(MOTOR_LEFT_RIGHT_DIRECTION, MOTOR_DIRECTION_RIGHT);  // set direction for movement
273
274
         digitalWrite(MOTOR_LEFT_RIGHT_PULS, HIGH);
275
         delayMicroseconds(motorMoveDelay);
276
         digitalWrite(MOTOR_LEFT_RIGHT_PULS, LOW);
277
         delayMicroseconds(motorMoveDelay);
278
279
         digitalWrite(MOTOR_LEFT_RIGHT_ENABLE,MOTOR_DISABLE);         // Disable movement
280
      }
281
      else
282
      {
283
         Serial.println("Limit switch LEFT pressed! Can't move further!");
284
         break;
285
      }
286
   }
287
}
288
289
// Horizontal motor off method.      
290
void stopMoveLeftOrRight() 
291
{            
292
   digitalWrite(MOTOR_LEFT_RIGHT_ENABLE,MOTOR_DISABLE);   // disable Motor left right 
293
}
294
295
// Method for moving the motor vertically upward.
296
void movePanelUp()
297
{
298
   for (int i = 0; i < motorStepsToMoveUpDown; i++)
299
   {
300
      limitSwitchUpStatus = digitalRead(LIMIT_SWITCH_UP);      // limit switch check
301
      if (limitSwitchUpStatus != LIMIT_SWITCH_UP_PRESSED)
302
      {
303
         digitalWrite(MOTOR_UP_DOWN_ENABLE, MOTOR_ENABLE);     // Enable movement
304
         digitalWrite(MOTOR_UP_DOWN_DIRECTION, MOTOR_DIRECTION_UP);  // set direction for movement
305
306
         digitalWrite(MOTOR_UP_DOWN_PULS, HIGH);
307
         delayMicroseconds(motorMoveDelay);
308
         digitalWrite(MOTOR_UP_DOWN_PULS, LOW);
309
         delayMicroseconds(motorMoveDelay);
310
311
         digitalWrite(MOTOR_UP_DOWN_ENABLE,MOTOR_DISABLE);         // Disable movement
312
      }
313
      else
314
      {
315
         Serial.println("Limit switch UP pressed! Can't move further!");
316
         break;
317
      }
318
   }
319
}
320
321
// Method for moving the motor vertically downward.
322
void movePanelDown() 
323
{            
324
   for (int i = 0; i < motorStepsToMoveUpDown; i++)
325
   {
326
      limitSwitchUpStatus = digitalRead(LIMIT_SWITCH_DOWN);      // limit switch check
327
      if (limitSwitchUpStatus != LIMIT_SWITCH_DOWN_PRESSED)
328
      {
329
         digitalWrite(MOTOR_UP_DOWN_ENABLE, MOTOR_ENABLE);       // Enable movement
330
         digitalWrite(MOTOR_UP_DOWN_DIRECTION, MOTOR_DIRECTION_DOWN);  // set direction for movement
331
332
         digitalWrite(MOTOR_UP_DOWN_PULS, HIGH);
333
         delayMicroseconds(motorMoveDelay);
334
         digitalWrite(MOTOR_UP_DOWN_PULS, LOW);
335
         delayMicroseconds(motorMoveDelay);
336
337
         digitalWrite(MOTOR_UP_DOWN_ENABLE,MOTOR_DISABLE);         // Disable movement
338
      }
339
      else
340
      {
341
         Serial.println("Limit switch UP pressed! Can't move further!");
342
         break;
343
      }
344
   }
345
}
346
347
// Vertical motor off method.        
348
void stopMoveUpOrDown() 
349
{           
350
  digitalWrite(MOTOR_UP_DOWN_ENABLE,MOTOR_DISABLE); 
351
}
352
353
void oled_message() {         // Solar panel voltage message on the OLED screen.
354
  display.clearDisplay();
355
  display.setTextSize(2);
356
  display.setCursor(7,0);
357
  display.print("Solar Vols");
358
  display.setTextSize(3);
359
  display.setCursor(20, 30);
360
  display.print(solarPanelVoltage, 2);
361
  display.display();
362
}