Using SolarPosition Library for Solar Tracking Robot Project

I am working on a solar tracking robot project using 2 servo motors and 4 LDRs with an Arduino Uno. I am excited about this project, but I am struggling to use the SolarPosition library for the project. I have experience working with the servo motor and the LDR, but I have no prior knowledge of the SolarPosition library.

I am reaching out to the community to ask for help and guidance on how to use the SolarPosition library effectively for my project. I would appreciate any resources or tips on how to get started and make the most of this library for my project.

Thank you in advance for your help and support. I am looking forward to learning from the community and making progress on my project......

#include <Servo.h>

// Define servo motors
Servo servo1;
Servo servo2;

// Define LDR pins
const int ldrPin1 = A0;
const int ldrPin2 = A1;
const int ldrPin3 = A2;
const int ldrPin4 = A3;

// Define servo motor positions
int servoPos1 = 90; // starting position
int servoPos2 = 90; // starting position

void setup() {
  // Initialize servo motors
  servo1.attach(9);
  servo2.attach(10);
}

void loop() {
  // Read LDR sensor values
  int ldrVal1 = analogRead(ldrPin1);
  int ldrVal2 = analogRead(ldrPin2);
  int ldrVal3 = analogRead(ldrPin3);
  int ldrVal4 = analogRead(ldrPin4);

  // Calculate average LDR sensor value
  int avgLdrVal = (ldrVal1 + ldrVal2 + ldrVal3 + ldrVal4) / 4;

  // Determine which direction to move the servo motors
  if (avgLdrVal > 500) {
    // Sun is on the right side, move servos to the right
    servoPos1 += 1;
    servoPos2 -= 1;
  } else {
    // Sun is on the left side, move servos to the left
    servoPos1 -= 1;
    servoPos2 += 1;
  }

  // Ensure servo positions stay within range
  if (servoPos1 < 0) {
    servoPos1 = 0;
  }
  if (servoPos1 > 180) {
    servoPos1 = 180;
  }
  if (servoPos2 < 0) {
    servoPos2 = 0;
  }
  if (servoPos2 > 180) {
    servoPos2 = 180;
  }

  // Move servo motors to new positions
  servo1.write(servoPos1);
  servo2.write(servoPos2);

  // Delay before next loop
  delay(50);
}

I always start by surveying the public Internet to determine if another may have already created a project on which I can

  • incorporate concepts and code snippets
  • improve

solar tracker project + "robot" at DuckDuckGo

IF the tracker library you referenced is utilized, maybe a graphic of how to connect 4 LDR will be shown. Is this library a requirement or just a suggestion???

Looking over the library code,
SolarPosition/SolarPosition.cpp at master · KenWillmott/SolarPosition · GitHub

it appears fairly straightforward; similar to
How to build a DIY solar/sun tracker using Arduino Projects (thestempedia.com)

But you wish to utilize LDRs to set the platform position which feeds the necessary "position" data to the library.

Thought: just mentally playing around with the "accuracy" of a completed system, I do not believe you can reliably know the (absolute) position of robot to any reasonable position ... maybe within a few kilometers at best.

IMO, as stated, you will need to build a prototype, write code, and come back with specific question regarding the codebase. At this point, you are in research mode.

A PDF on Arduino Solar Positioning sans library:
ArduinoUnoSolarCalculations.pdf (instesre.org)

A forum reference to past project:
Solar Tracker based on Sun Position Calculation - Using Arduino / Project Guidance - Arduino Forum

2 Likes

This is another ephemeris

will be needed when the robot goes to Mars...

1 Like

Using LDRs, there is no need for the SolarPosition library. That library calculates sun position based on location (latitude/longitude) and time, for which you need an accurate way of determining time, generally a real-time clock (RTC). If your "robot" is mobile, you also need some way of telling the exact orientation of the robot, because the SolarPosition library gives an angle and elevation, and you need a fixed reference of which direct the robot is facing and what angle it is sitting at.

2 Likes

Astute observations. I wouldn't sweat about the RTC though. Probably, any robot should know the time.

Please post a picture of your solar tracker platform.

How will you determine the commands to send to the servos, in order to point the platform at a certain position in the sky?

1 Like

One could use this library SolarCalculator library for Arduino. I use the library to determine when the sun comes up and where the sun will be to point a solar array at the sun. Then I use the library to get sun position once every 6 minutes to move the array to the suns new position.

How?

Did you try the example sketches that come with the SolarPosition library? It would be relatively easy to just take the real time az/el values that it produces, and scale them to servo input values. Disclaimer, I'm the library author. I never made any examples specific to any hardware, for the obvious reason that end users would have diverse applications. If you make a reasonable effort to do that, and post the results here, I will help you.

It was originally written for lighting control, but is definitely generic enough for the application you outline in your first post.

There are no fancy mathematical tasks, as both sun and servo platform use a two dimensional polar coordinate system.

Have you been able to get a current sun angle from the library? Take the azimuth value of the sun and rotate the servo to match the angle. Take the elevation value of the sun and rotate the servo to match the angle. Position the unit so that it points North, so that the angles produced by the calculator relate to the servo torque angle.

1 Like

To sharpen my point, we are not getting any feedback about what the OP has actually tried. Just some boilerplate code with, and followed by, one drawing and some questions.

It is necessary to see some activity, in order to guide the activities.

I have tested the library you have given and it works, thanks for this.

#include <SolarCalculator.h>
#include <TimeLib.h>
#include <Servo.h>

// Location
double latitude = 10.3195;
double longitude = 123.0198;
int utc_offset = +8;

// Servo pins
int az_pin = 9;  // azimuth servo control pin
int el_pin = 10; // elevation servo control pin

// Servo limits (in degrees)
int az_min = 0;  // minimum azimuth angle
int az_max = 180; // maximum azimuth angle
int el_min = 0;  // minimum elevation angle
int el_max = 90; // maximum elevation angle

// Refresh interval, in seconds
int interval = 10;

// Servo objects
Servo az_servo;
Servo el_servo;

void setup()
{
  Serial.begin(9600);
  
  // Attach servo pins
  az_servo.attach(az_pin);
  el_servo.attach(el_pin);

  // Set system time to compile time
  setTime(toUtc(compileTime()));

  // Set time manually (hr, min, sec, day, mo, yr)
  //setTime(0, 0, 0, 1, 1, 2022);
}

void loop()
{
  static unsigned long next_millis = 0;

  // At every interval
  if (millis() > next_millis)
  {
    time_t utc = now();
    double az, el;

    // Calculate the solar position, in degrees
    calcHorizontalCoordinates(utc, latitude, longitude, az, el);

    // Print results
    Serial.print(F("Az: "));
    Serial.print(az);
    Serial.print(F("°  El: "));
    Serial.print(el);
    Serial.println(F("°"));

    // Move servos to match azimuth and elevation angles
    int az_angle = map(az, 0, 360, az_min, az_max);
    int el_angle = map(el, 0, 90, el_min, el_max);
    az_servo.write(az_angle);
    el_servo.write(el_angle);

    next_millis = millis() + interval * 1000L;
  }
}

time_t toUtc(time_t local)
{
  return local - utc_offset * 3600L;
}

// Code from JChristensen/Timezone Clock example
time_t compileTime()
{
  const uint8_t COMPILE_TIME_DELAY = 8;
  const char *compDate = __DATE__, *compTime = __TIME__, *months = "JanFebMarAprMayJunJulAugSepOctNovDec";
  char chMon[4], *m;
  tmElements_t tm;

  strncpy(chMon, compDate, 3);
  chMon[3] = '\0';
  m = strstr(months, chMon);
  tm.Month = ((m - months) / 3 + 1);

  tm.Day = atoi(compDate + 4);
  tm.Year = atoi(compDate + 7) - 1970;
  tm.Hour = atoi(compTime);
  tm.Minute = atoi(compTime + 3);
  tm.Second = atoi(compTime + 6);
  time_t t = makeTime(tm);
  return t + COMPILE_TIME_DELAY;
}


2 Likes

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