Solar tracker, newbie project

So i want to build this 2 axis tracker on arduino using LDR's and L297 driver.
I want to try and keep it as simple as i can using least components possible.
The idea at the moment is to use single IR sensor for axis limit switch. Would that be hard to program? I am novice in programming and always had hard time with it :slight_smile:
There are many sample i can work with to adapt sketches to my needs but i would like to have 2 knobs for pan/tilt tuning. I don't know what's better to use, pot or some sort of rotary encoder to offset LDR data. The idea is to use this solar tracker with mirror to direct some sunlight to my north west rooms.
Any ideas appreciated. Thanks

As a beginner you need to start simple and write bits of code to deal with the individual
Aspects - eg the IR sensor, the motor driving, analog inputs etc - and get those working on their own .

Try to avoid adapting something you’ve down loaded unless you fully understand it , bodge exercises are fraught with difficulties

I have got simple dc toy motor working with dual relays and IR limit switch to reverse the motor. So far that much as i dont have other parts. Tomorrow my L297 and photoresistors come in along with geared 12V dc motors. I have rough imagination how to program basic tracking, i only need to figure out how to offset input data so by turning one pot i could pan the tracker and the other - tilt.

So i think i have the code for motors and LDR's reworked, compiles fine. Just need to setup test rig and test it. I have scrapped the idea of using POT's or encoders for adjustment and instead will use mechanical bracket to position sensor. Less parts and it will be more reliable.
Can someone suggest how to code IR sensor for limit switch? Again, to keep part count minimal i would like to use single per axis with a disc with and extrusion to engage sensor. What i need is when the sensor is triggered it reverses that axis. That way it will work both ways. Here is the code so far:

//set constant pin numbers
int eldr = A1; //LDR sensor east
int wldr = A2; //LDR sensor west
int tldr = A3; //LDR sensor top
int bldr = A4; //LDR sensor bottom
int IN1 = 2; //PAN Motor 
int IN2 = 3;  //PAN Motor 
int IN3 = 4; //TILT Motor 
int IN4 = 5; //TILT Motor
int PANsw = A5; //PAN limit switch
int TILTsw = A6; //TILT limit switch
int eastldr = 0; //east LDR sensor state
int westldr = 0; //west LDR sensor state
int topldr = 0; //top LDR sensor state
int botldr = 0; //bottom LDR sensor state
int PANlim = 0; //PAN limmit switch state
int TILTlim = 0; // TILT limit switch state
int error = 0;
int poserror = 0;
int tberror = 0;
int tbposerror = 0;

void setup() {
  //LDR sensors
  pinMode (A1, INPUT);
  pinMode (A2, INPUT);
  pinMode (A3, INPUT);
  pinMode (A4, INPUT);
  //Limit switches
  pinMode (A5, INPUT);
  pinMode (A6, INPUT);
  //Motor output
  pinMode (2, OUTPUT);
  pinMode (3, OUTPUT);
  pinMode (4, OUTPUT);
  pinMode (5, OUTPUT);
  Serial.begin(9600);
}

void loop() {Serial.print("start programm");
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
  
//automaticaly rotating of the panel
//check east-west orientation first
  eastldr = analogRead(A1);
          westldr = analogRead(A2);
          topldr = analogRead(A3);
          botldr = analogRead(A4);
                    error = (((eastldr+topldr)/2) - ((westldr+botldr)/2));
                            poserror = abs(error);
                                     if (poserror > 10){
 if (error > 0) {
   digitalWrite(IN2, HIGH);

//  Serial.print("IN2 HIGH");
  }
  else if (error < 0)    {
   digitalWrite(IN1, HIGH);
//Serial.print("IN1 HIGH");
  }}
  else if (poserror <= 10 )  {
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, LOW);
//Serial.print("LOW BOTH");
    }
Serial.println(eastldr);
Serial.println(westldr);
Serial.println(topldr);
Serial.println(botldr);

         topldr = analogRead(A3);
         botldr = analogRead(A4);
         eastldr = analogRead(A1);
         westldr = analogRead(A2);
                  tberror = (((topldr+westldr)/2) - ((botldr+eastldr)/2));
                            tbposerror = abs(tberror);
                  error = (((eastldr+topldr)/2) - ((westldr+botldr)/2));
                            poserror = abs(error);
                                     if (poserror > 10){
 if (error > 0) {
   digitalWrite(IN2, HIGH);
//  Serial.print("IN2 HIGH");
  }
  else if (error < 0)    {
   digitalWrite(IN1, HIGH);
//Serial.print("IN1 HIGH");
  }}
  else if (poserror <= 10 )  {
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, LOW);
    }
Serial.println(eastldr);
Serial.println(westldr);
   if (tbposerror > 10)
{ if (tberror > 0) {
    digitalWrite(IN4, HIGH);
}    else if (tberror < 0)    {
      digitalWrite(IN3, HIGH);
    }
  }
  else if (poserror <= 10 )  {
    digitalWrite(IN4, LOW);
    digitalWrite(IN3, LOW);
  }
    delay(200);
}

I use a solar tracking library to calculate the angles of the sun to do the solar tracking thingy. GitHub - KenWillmott/SolarPosition: Arduino Library to calculate the position of the sun relative to geographic coordinates

Reduced component count and lowered current draw from the battery. Also, can check for sun rise. When sunrise apply motor power, move panels to position, remove motor power. I torque the solar panels position once every 6 minutes. Using actuators the panel position is held without the need the keep the motors powered.

Mine is a bit different. I am building heliostat to bring some light into northern rooms. With LDR's its easy to direct sunlight where its needed and I don't need to program offsets if I install additional ones, just adjust LDR on the bracket.

When I built a solar tracker using photo diodes, I placed the photo diodes at each end of the panel and used code to keep the panel centered to the sun. What limit are you trying to achieve?

I am trying to design in axis motion limit switches so it does not brake or twist wires. Usually its 2 switches per axis. I want to use single IR limit sensor per axis with rotating disc.
I want to reverse the motor when limit switch is trigered. It will work for both, CC and CCW motion.

Looks like my programming deficiencies are thing of the past. Tried ChatGPT and it probably did the code i need. Have not tested it but looks alright:

#include <L298N.h>
#include <Encoder.h>

const int ldrPin1 = A0; // pin for first LDR (East/West)
const int ldrPin2 = A1; // pin for second LDR (East/West)
const int ldrPin3 = A2; // pin for third LDR (Tilt)
const int ldrPin4 = A3; // pin for fourth LDR (Tilt)
const int motorPin1 = 3; // pin for motor driver input 1
const int motorPin2 = 4; // pin for motor driver input 2
const int enablePin = 5; // pin for motor driver enable
const int encoderPin1 = 6; // pin for rotary encoder input 1
const int encoderPin2 = 7; // pin for rotary encoder input 2
const int switchPin = 8; // pin for encoder switch
const int xEndStop = 9; // pin for the x-axis end stop
const int yEndStop = 10; // pin for the y-axis end stop

L298N motor(motorPin1, motorPin2, enablePin);
Encoder encoder(encoderPin1, encoderPin2);

// variables to store the current position and last position of the encoder
long currentPosition, lastPosition;

// variable to store the state of the encoder switch
boolean switchState;

void setup() {
  motor.begin();
  encoder.attach();

  // set the initial state of the encoder switch
  switchState = digitalRead(switchPin);

  // set the initial position of the encoder
  currentPosition = encoder.read();

  // set the initial state of the end stops
  pinMode(xEndStop, INPUT);
  pinMode(yEndStop, INPUT);
}

void loop() {
  // read the values from the LDRs
  int ldrValue1 = analogRead(ldrPin1);
  int ldrValue2 = analogRead(ldrPin2);
  int ldrValue3 = analogRead(ldrPin3);
  int ldrValue4 = analogRead(ldrPin4);

  // check if the sun is to the left or right of the panel
  if (ldrValue1 > ldrValue2) {
    // move the panel to the left
    motor.left();
  } else if (ldrValue1 < ldrValue2) {
    // move the panel to the right
    motor.right();
  } else {
    // stop the motor if the sun is directly in front of the panel
    motor.stop();
  }

  //Check if the sun is in tilt direction using the other two LDRs.
  if(ldrValue3 > ldrValue4) {
// tilt the panel up
motor.up();
} else if (ldrValue3 < ldrValue4) {
// tilt the panel down
motor.down();
} else {
// stop the motor if the sun is directly in front of the panel
motor.stop();
}

// read the current position of the encoder
currentPosition = encoder.read();

// check if the encoder has been turned
if (currentPosition != lastPosition) {
// check if the encoder switch is in the horizontal position
if (switchState == LOW) {
// check if the x-axis end stop is engaged
if (digitalRead(xEndStop) == LOW) {
// reverse the x-axis
motor.setSpeed(255); // set the motor speed to full reverse
motor.reverse(); // reverse the motor
delay(500); // wait for the motor to stop
motor.stop(); // stop the motor
}
} else {
// check if the y-axis end stop is engaged
if (digitalRead(yEndStop) == LOW) {
// reverse the y-axis
motor.setSpeed(255); // set the motor speed to full reverse
motor.reverse(); // reverse the motor
delay(500); // wait for the motor to stop
motor.stop(); // stop the motor
}
}
// update the last position of the encoder
lastPosition = currentPosition;
}
}

Tried with simple thermometer code with LCD key shield and generated code worked first time. Note how AI inserts comments as well.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.