Dual-Axis Solar Tracker – Arduino Nano Code - Bambu3Design – 3D Printing & Design
Dual-Axis Solar Tracker – Arduino Nano Code

Dual-Axis Solar Tracker – Arduino Nano Code

#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());
  }
}

Scroll to Top