Tinkers Projects

Imagine | Develop | Create

Sun/Moon TrackerMain
Sun/Moon Tracker0
Sun/Moon Tracker1

This is a device that can point to the sun or moon within the sky. This device could be used to track the sun, moon, planets, satellites or other celestial objects.

The device

The device uses 28BYI-48 stepper motors to move into the correct to point into the sky and is controlled by an ESP8266. The device uses https://ipgeolocation.io/ to get the correct angles from the longitude and latitude.

Code for Project

GNU General Public License v3.0
#include <Arduino.h>
#include <AccelStepper.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>
#include <ArduinoJson.h>
#include <TimeLib.h>

#define SePinA 4
#define SePinB 0
#define SePinC 2
#define SePinInput 15

#define Speed 7000 //200
#define Acceleration 5000000000.0

#define DIR_PIN 16
#define STEP_R_PIN 14
#define STEP_A_PIN 12
#define Home_R_PIN 1
#define Home_A_PIN 2
#define ENA_PIN 5

#define LATITUDE  "LATITUDE_OF_TRACKER"
#define LONGITUDE  "LONGITUDE_OF_TRACKER"
#define API_KEY  "API_KEY_FROM_ipgeolocation.io"
#define URL "https://api.ipgeolocation.io/astronomy"
#define TrueNothOffset 0


double sun_azimuth;
double sun_altitude;
unsigned long lastGet;
unsigned long lastupdate;
unsigned long countloop;


AccelStepper stepperR;
AccelStepper stepperA;

const uint8_t fingerprint[20] = {0x40, 0xaf, 0x00, 0x6b, 0xec, 0x90, 0x22, 0x41, 0x8e, 0xa3, 0xad, 0xfa, 0x1a, 0xe8, 0x25, 0x41, 0x1d, 0x1a, 0x54, 0xb3};
ESP8266WiFiMulti wifiMulti;

const size_t capacity = 512;
DynamicJsonDocument doc(capacity);


void setup() 
{
  delay(1000);
  Serial.begin(115200);
  Serial.println("Starting");
  pinMode(SePinInput,INPUT);
  pinMode(SePinA, OUTPUT);
  pinMode(SePinB, OUTPUT);
  pinMode(SePinC, OUTPUT);
  pinMode(ENA_PIN, OUTPUT);
  digitalWrite(ENA_PIN,HIGH);

  wifiMulti.addAP("WIFI_NAME", "WIFI_PASS");
  wifiMulti.addAP("WIFI_NAME", "WIFI_PASS");
  wifiMulti.addAP("WIFI_NAME", "WIFI_PASS");
  
  stepperR = AccelStepper(1,STEP_R_PIN,DIR_PIN);
  stepperR.setMaxSpeed(Speed);
  stepperR.setCurrentPosition(0);
  stepperR.setAcceleration(Acceleration);
  stepperR.setPinsInverted(1,0,0);
  
  stepperA = AccelStepper(1,STEP_A_PIN,DIR_PIN);
  stepperA.setMaxSpeed(Speed);
  stepperA.setCurrentPosition(0);
  stepperA.setAcceleration(Acceleration);
  
  home();
  
  delay(3000);
  unsigned long startTestComs = millis();
  while(wifiMulti.run() != WL_CONNECTED && startTestComs+3000>millis())
  {
    delay(100);
  }
  
  if (wifiMulti.run() == WL_CONNECTED) 
  {
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
    postData();
  }

  gotoLocation(sun_azimuth, sun_altitude);
  lastGet = 0;
  lastupdate = 0;
}

void loop()
{
  delay(1000);
  
  if(lastGet+86400 < countloop)
  {
    postData();
    gotoLocation(sun_azimuth, sun_altitude);
    lastGet = countloop;
    lastupdate = countloop;
  }
  
  if(lastupdate+60 < countloop)
  {
    gotoLocation(sun_azimuth, sun_altitude);
    lastupdate = countloop;
  }
  if(lastupdate>countloop || lastGet>countloop )
  {
    lastupdate = countloop;
    lastGet = countloop;
  }
  countloop++;
}


void gotoLocation(double Rotation, double angle)
{    
  Serial.println("Rotation: "+String(Rotation)+" angle: "+String(angle));
  
  stepperR.moveTo(Rotation * 91.0222222222);
  stepperA.moveTo(angle * 91.0222222222);
  digitalWrite(ENA_PIN,LOW);

  while(stepperR.distanceToGo()!=0 )
  {
    delay(0);
      stepperR.run();
  }
  
  while(stepperA.distanceToGo()!=0 )
  {
    delay(0);
      stepperA.run();
  }
  
  digitalWrite(ENA_PIN,HIGH);
}


void SetLocation(double Rotation, double angle)
{
   stepperR.setCurrentPosition(Rotation * 91.0222222222);
   stepperA.setCurrentPosition(angle * 91.0222222222);
}

void home()
{
  Serial.println("Homing");
  digitalWrite(ENA_PIN,LOW);
  while (select(Home_R_PIN) == LOW)
  {
    delay(0);
    stepperR.move(-10);
    stepperR.run();
  }
  Serial.println("Homed R");

  while (select(Home_A_PIN) == LOW)
  {
    delay(0);
    stepperA.move(-10);
    stepperA.run();
  }
  Serial.println("Homied A");

  SetLocation((2.5 - TrueNothOffset),45);
  digitalWrite(ENA_PIN,HIGH);
  Serial.println("Homing finished");
}



bool select(byte A)
{
  switch (A) {
    case 8:
      digitalWrite(SePinA, LOW);
      digitalWrite(SePinB, LOW);
      digitalWrite(SePinC, LOW);
      break;
    case 0:
      digitalWrite(SePinA, LOW);
      digitalWrite(SePinB, LOW);
      digitalWrite(SePinC, LOW);
      break;
    case 1:
      digitalWrite(SePinA, HIGH);
      digitalWrite(SePinB, LOW);
      digitalWrite(SePinC, LOW);
      break;
    case 2:
      digitalWrite(SePinA, LOW);
      digitalWrite(SePinB, HIGH);
      digitalWrite(SePinC, LOW);
      break;
    case 3:
      digitalWrite(SePinA, HIGH);
      digitalWrite(SePinB, HIGH);
      digitalWrite(SePinC, LOW);
      break;
    case 4:
      digitalWrite(SePinA, LOW);
      digitalWrite(SePinB, LOW);
      digitalWrite(SePinC, HIGH);
      break;
    case 5:
      digitalWrite(SePinA, HIGH);
      digitalWrite(SePinB, LOW);
      digitalWrite(SePinC, HIGH);
      break;
    case 6:
      digitalWrite(SePinA, LOW);
      digitalWrite(SePinB, HIGH);
      digitalWrite(SePinC, HIGH);
      break;
    case 7:
      digitalWrite(SePinA, HIGH);
      digitalWrite(SePinB, HIGH);
      digitalWrite(SePinC, HIGH);
      break;
  }
  return digitalRead(SePinInput);
}




bool postData() 
{
    std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);
    //client->setFingerprint(fingerprint);
    client->setInsecure();
    
    HTTPClient http;
    if(http.begin(*client,(String(URL)+"?apiKey="+String(API_KEY)+"&lat="+String(LATITUDE)+"&long="+String(LONGITUDE))))
    {
      int httpCode = http.GET();
       
      if (httpCode > 0)
      {
          Serial.printf("[HTTP] POST... code: %d\n", httpCode);
          Serial.println(http.getString());
          if(httpCode == HTTP_CODE_OK) 
          {
              DeserializationError error = deserializeJson(doc, http.getString());
              if (error) 
              {
                Serial.print(F("deserializeJson() failed: "));
                Serial.println(error.c_str());
                return false;
              }  
              else
              {
                if(doc.containsKey("sun_azimuth"))
                {
                  sun_azimuth = doc["sun_azimuth"].as<double>();
                  Serial.print("sun_azimuth: ");
                  Serial.println(sun_azimuth);
                }
                if(doc.containsKey("sun_altitude"))
                {
                  sun_altitude = doc["sun_altitude"].as<double>();
                  Serial.print("sun_altitude: ");
                  Serial.println(sun_altitude);
                }
              }           
              http.end();
              return true;
          }
      } 
      else 
      {
          Serial.printf("[HTTP] POST... failed, error: %s\n", http.errorToString(httpCode).c_str());
          Serial.println(http.getString());
      }
      
      http.end();
    } 
    else 
    {
      Serial.printf("[HTTPS] Unable to connect\n");
    }
    return false;
}

This is a device that can point to the sun or moon within the sky. This device could be used to track the sun, moon, planets, satellites or other celestial objects.

The device

The device uses 28BYI-48 stepper motors to move into the correct to point into the sky and is controlled by an ESP8266. The device uses https://ipgeolocation.io/ to get the correct angles from the longitude and latitude.