#include <AccelStepper.h>
// -------------------- MOTORS --------------------
// Horizontal motor
AccelStepper motorH(
AccelStepper::HALF4WIRE,
2, 4, 3, 5
);
// Vertical motor
AccelStepper motorV(
AccelStepper::HALF4WIRE,
6, 8, 7, 9
);
// -------------------- LDR --------------------
const int TL_PIN = A0; // Top Left
const int TR_PIN = A1; // Top Right
const int BL_PIN = A2; // Bottom Left
const int BR_PIN = A3; // Bottom Right
// -------------------- SETTINGS --------------------
const int tolerance = 30;
// Horizontal limits
const long H_MIN = -1024;
const long H_MAX = 1024;
// Vertical limits
const long V_MIN = -680;
const long V_MAX = 680;
// Target positions
long targetH = 0;
long targetV = 0;
// Sensor timing
unsigned long lastSensorRead = 0;
const unsigned long sensorInterval = 80;
// -------------------- SMOOTH LDR --------------------
int readSmooth(int pin) {
long total = 0;
for (int i = 0; i < 10; i++) {
total += analogRead(pin);
}
return total / 10;
}
// -------------------- SETUP --------------------
void setup() {
Serial.begin(9600);
// Horizontal motor
motorH.setMaxSpeed(150);
motorH.setAcceleration(40);
// Vertical motor
motorV.setMaxSpeed(150);
motorV.setAcceleration(40);
// Starting position = centre
motorH.setCurrentPosition(0);
motorV.setCurrentPosition(0);
targetH = 0;
targetV = 0;
Serial.println("DUAL AXIS SOLAR TRACKER READY");
}
// -------------------- LOOP --------------------
void loop() {
// Motors must run continuously
motorH.run();
motorV.run();
if (millis() - lastSensorRead >= sensorInterval) {
lastSensorRead = millis();
// Read LDRs
int TL = readSmooth(TL_PIN);
int TR = readSmooth(TR_PIN);
int BL = readSmooth(BL_PIN);
int BR = readSmooth(BR_PIN);
// Calculate averages
int left = (TL + BL) / 2;
int right = (TR + BR) / 2;
int top = (TL + TR) / 2;
int bottom = (BL + BR) / 2;
int diffH = right - left;
int diffV = top - bottom;
// ---------------- HORIZONTAL ----------------
if (diffH > tolerance) {
// Right is brighter
targetH -= 4;
if (targetH < H_MIN) {
targetH = H_MIN;
}
}
else if (diffH < -tolerance) {
// Left is brighter
targetH += 4;
if (targetH > H_MAX) {
targetH = H_MAX;
}
}
// ---------------- VERTICAL ----------------
if (diffV > tolerance) {
// Top is brighter
targetV -= 4;
if (targetV < V_MIN) {
targetV = V_MIN;
}
}
else if (diffV < -tolerance) {
// Bottom is brighter
targetV += 4;
if (targetV > V_MAX) {
targetV = V_MAX;
}
}
// Set motor targets
motorH.moveTo(targetH);
motorV.moveTo(targetV);
// ---------------- SERIAL MONITOR ----------------
Serial.print("L=");
Serial.print(left);
Serial.print(" R=");
Serial.print(right);
Serial.print(" | T=");
Serial.print(top);
Serial.print(" B=");
Serial.print(bottom);
Serial.print(" | H=");
Serial.print(diffH);
Serial.print(" V=");
Serial.print(diffV);
Serial.print(" | HPOS=");
Serial.print(motorH.currentPosition());
Serial.print(" VPOS=");
Serial.println(motorV.currentPosition());
}
}