ESP32 Satellite Tracker

Hi. I am trying to do this project i stumble from github. I have run the program onto my ESP32, but after zeroing, the serial monitor shows the value that i needed but the stepper motor does not rotate according to the value on the serial monitor. The stepper motor does not rotate at all. Can someone explain why this is happening? Below is the coding that i imported onto my ESP32


#include <WiFi.h> //1.2.7
#include <HTTPClient.h>
#include <AccelStepper.h>     // 1.64.0
#include <ESP32Time.h>        // 2.0.0
#include <Sgp4.h>             //https://github.com/Hopperpop/Sgp4-Library
#include "soc/soc.h"          // to disable ESP32 brownout detector
#include "soc/rtc_cntl_reg.h" // to disable ESP32 brownout detector
#include <HardwareSerial.h>
#include "time.h"
#include <SerLCD.h> // 1.0.9
#include <math.h>
#include <strings.h>
#include "secrets.h"
// Replace with your network credentials
const char *ssid = SECRET_SSID;
const char *password = SECRET_PASS;

char satnames[20][30] = {"A-SEANSAT-PG1"}; // Names of satellites.
char satURL[20][40] = {"/NORAD/elements/gp.php?CATNR=57985"}; // URL of Celestrak TLEs for satellites (In same order as names).
char TLE1[20][70];
char TLE2[20][70];
long upcomingPasses[20];
int numSats = 1; // Number of satellites to track.
float minPassElevation = 10.0;
float myLat = 1.9344;
float myLong = 103.358729;
float myAlt = 27; // Your latitude, longitude and altitude.
const int timeZone = -5;
// pins:
// EL motor: 26, 18, 19, 23 Limit: 32
// AZ motor: 22, 21, 17 ,16 Limit: 27
//  Azimuth stepper pins //
#define AZmotorPin1 22 // IN1 on the ULN2003 driver
#define AZmotorPin2 21 // IN2 on the ULN2003 driver
#define AZmotorPin3 17 // IN3 on the ULN2003 driver
#define AZmotorPin4 16 // IN4 on the ULN2003 driver
#define AZLimit 27
// Elevation stepper pins //
#define ELmotorPin1 26
#define ELmotorPin2 18
#define ELmotorPin3 19
#define ELmotorPin4 23
#define ELLimit 32
float oneTurn = 4096; // stepper steps/turn

int SAT;
int nextSat;
int AZstart;
long passEnd;
int satVIS;
int year;
int mon;
int day;
int hr;
int minute;
double sec;
int today;
long nextpassEpoch;
long nextpassEndEpoch;
long passDuration;

char satname[] = " ";
int passStatus = 0;

HardwareSerial LCD(2);
Sgp4 sat;

int satAZsteps;
int satELsteps;
int turns = 0;

#define MotorInterfaceType 8 // Define the AccelStepper interface type; 4 wire motor in half step mode:
AccelStepper stepperAZ = AccelStepper(MotorInterfaceType, AZmotorPin1, AZmotorPin3, AZmotorPin2, AZmotorPin4);
AccelStepper stepperEL = AccelStepper(MotorInterfaceType, ELmotorPin1, ELmotorPin3, ELmotorPin2, ELmotorPin4);

ESP32Time rtc(0);
unsigned long timeNow = 0;
const char *ntpServer = "pool.ntp.org";

unsigned long getTime()
{
  time_t now;
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo))
  {
    // Serial.println("Failed to obtain time");
    return (0);
  }
  time(&now);
  return now;
}

int nextSatPass(long _nextpassEpoch[20])
{
  for (int i = 0; i < numSats; ++i)
  {
    if (_nextpassEpoch[0] - timeNow >= _nextpassEpoch[i] - timeNow)
    {
      _nextpassEpoch[0] = _nextpassEpoch[i];
      nextSat = i;
    }
  }
  return nextSat;
}

void initMotors()
{
  // Setup stepper movements //
  stepperEL.setMaxSpeed(1000);
  stepperEL.setCurrentPosition(0); // Elevation stepper starts at -227 steps (20 degrees above horizon).
  stepperEL.setAcceleration(100);
  stepperAZ.setMaxSpeed(300);
  stepperAZ.setCurrentPosition(0); // Azimuth stepper starts at 0.
  stepperAZ.setAcceleration(100);

  unsigned long startTime = millis();
  unsigned long currentTime;

  // Zero //
  stepperAZ.runToNewPosition(-600);
  while (true)
  {
    currentTime = millis();
    if (currentTime - startTime > 40 * 1000)
    {
      Serial.print("Zeroing timed out");
      while (true)
        ;
    }
    if (digitalRead(AZLimit) == LOW)
    {
      stepperAZ.setCurrentPosition(0);
      stepperAZ.runToNewPosition(-200);
      stepperAZ.setCurrentPosition(0);
      break;
    }
    if (stepperAZ.distanceToGo() == 0)
    {                                  // if motor moved to the maximum position
      stepperAZ.setCurrentPosition(0); // reset position to 0
      stepperAZ.moveTo(2000);          // move the motor to maximum position again
    }
    stepperAZ.run();
  }
  digitalWrite(AZmotorPin1, LOW);
  digitalWrite(AZmotorPin2, LOW);
  digitalWrite(AZmotorPin3, LOW);
  digitalWrite(AZmotorPin4, LOW);

  stepperEL.runToNewPosition(-100);
  startTime = millis();
  while (true)
  {
    currentTime = millis();
    if (currentTime - startTime > 40 * 1000)
    {
      Serial.println("Zeroing timed out");
      while (true)
        ;
    }
    if (digitalRead(ELLimit) == LOW)
    {
      stepperEL.setCurrentPosition(0);
      stepperEL.runToNewPosition(-80);
      stepperEL.setCurrentPosition(0);
      break;
    }
    if (stepperEL.distanceToGo() == 0)
    {                                  // if motor moved to the maximum position
      stepperEL.setCurrentPosition(0); // reset position to 0
      stepperEL.moveTo(1000);          // move the motor to maximum position again
    }
    stepperEL.run();
  }

  digitalWrite(ELmotorPin1, LOW);
  digitalWrite(ELmotorPin2, LOW);
  digitalWrite(ELmotorPin3, LOW);
  digitalWrite(ELmotorPin4, LOW);
  delay(1000);
};

void clearLCD()
{
  LCD.write(0xFE); // send the special command
  LCD.write(0x01); // send the set cursor command
}

SerLCD lcd;

void setup()
{
  pinMode(ELLimit, INPUT_PULLUP); // init pins for limit switches
  pinMode(AZLimit, INPUT_PULLUP);
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // disable brownout detector
  Serial.begin(115200);
  LCD.begin(9600, SERIAL_8N1, 20, 25); // Rx pin not used
  lcd.begin(LCD);
  delay(1000);

  // Connect to Wi-Fi network
  clearLCD();
  lcd.print("Connecting to WiFi...");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(2000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi!");

  // Get Unix timestamp
  clearLCD();
  LCD.write("Fetching time...");
  while (timeNow == 0)
  {
    configTime(0, 0, ntpServer);
    timeNow = getTime();
  }
  Serial.println("unixtime: " + String(timeNow));
  rtc.setTime(timeNow);

  Serial.println("Zeroing");
  clearLCD();
  lcd.print("Zeroing...");
  initMotors();

  // Fetch TLE
  clearLCD();
  LCD.write("Fetching TLEs");
  HTTPClient http;
  sat.site(myLat, myLong, myAlt); // set location latitude[°], longitude[°] and altitude[m]
  for (SAT = 0; SAT < numSats; SAT++)
  {
    Serial.println("Request #: " + String(SAT) + " For: " + String(satnames[SAT]));
    http.begin("https://celestrak.org/" + String(satURL[SAT]));
    int httpCode = http.GET();
    String TLE;

    if (httpCode == HTTP_CODE_OK)
    {
      TLE = http.getString();
      TLE.substring(26, 96).toCharArray(TLE1[SAT], 70);
      TLE.substring(97, 167).toCharArray(TLE2[SAT], 70);
      Serial.println(TLE1[SAT]);
      Serial.println(TLE2[SAT]);

      sat.init(satname, TLE1[SAT], TLE2[SAT]);                  // initialize satellite parameters
      upcomingPasses[SAT] = Predict(timeNow, minPassElevation); // find next pass and store it array
    }
    else
    {
      Serial.println("Failed to fetch TLE data for " + String(satnames[SAT]));
    }
    delay(100);
  }
  http.end();

  nextSat = nextSatPass(upcomingPasses); // find earliest pass and track that sat
  Serial.println("Next satellite: " + String(nextSat));
  sat.init(satname, TLE1[nextSat], TLE2[nextSat]);
  Predict(timeNow, 0.0);
}

String printHHmmss(unsigned long _secondsIn)
{
  unsigned int _hour = floor(_secondsIn / 60 / 60);
  unsigned int _minute = floor((_secondsIn / 60) % 60);
  unsigned int _seconds = _secondsIn % 60;
  char _DateAndTimeString[20]; // 19 digits plus the null char
  sprintf(_DateAndTimeString, "%02d:%02d:%02d", _hour, _minute, _seconds);
  return _DateAndTimeString;
}

void loop()
{
  timeNow = rtc.getEpoch();
  sat.findsat(timeNow);
  satAZsteps = -round(sat.satAz * oneTurn / 360); // Convert degrees to stepper steps
  satELsteps = -round(sat.satEl * oneTurn / 360);

  invjday(sat.satJd, timeZone, true, year, mon, day, hr, minute, sec);
  Serial.println("\nLocal time: " + String(day) + '/' + String(mon) + '/' + String(year) + ' ' + String(hr) + ':' + String(minute) + ':' + String(sec));
  Serial.println("azimuth = " + String(sat.satAz) + " elevation = " + String(sat.satEl) + " distance = " + String(sat.satDist));
  Serial.println("latitude = " + String(sat.satLat) + " longitude = " + String(sat.satLon) + " altitude = " + String(sat.satAlt));
  Serial.println("AZsteps = " + String(satAZsteps));

  if (nextpassEpoch - timeNow < 300 && nextpassEpoch + 5 - timeNow > 0)
  {
    Serial.println("Status: Pre-pass");
    Serial.println("Next satellite is #: " + String(satnames[nextSat]) + " in: " + String(nextpassEpoch - timeNow));
    clearLCD();
    lcd.print(satnames[nextSat]);
    lcd.print(" " + printHHmmss(nextpassEpoch - timeNow));
    lcd.setCursor(0, 1);
    lcd.print("AZ:" + String(int(sat.satAz)) + " EL:" + String(int(sat.satEl)));
    prepass();
  }
  else if (sat.satVis != -2)
  {
    Serial.println("Status: In pass");
    clearLCD();
    lcd.print(satnames[nextSat]);
    unsigned int timeToLOS = nextpassEndEpoch - timeNow;
    unsigned int _minute = floor((timeToLOS / 60) % 60);
    unsigned int _seconds = timeToLOS % 60;
    char DateAndTimeString[20]; // 19 digits plus the null char
    sprintf(DateAndTimeString, "%02d:%02d", _minute, _seconds);
    lcd.print(" LOS");
    lcd.print(DateAndTimeString);
    lcd.setCursor(0, 1);
    lcd.print("AZ:" + String(int(sat.satAz)) + " EL:" + String(int(sat.satEl)));
    inPass();
  }
  else if (timeNow - passEnd < 60)
  {
    Serial.println("Status: Post-pass");
    clearLCD();
    lcd.print("Post-pass:" + String(passEnd + 60 - timeNow));
    postpass();
  }
  else if (sat.satVis == -2)
  {
    Serial.println("Status: Standby");
    Serial.println("Next satellite is: " + String(satnames[nextSat]) + " in: " + String(nextpassEpoch - timeNow));
    clearLCD();
    lcd.print(satnames[nextSat]);
    lcd.print(" " + printHHmmss(nextpassEpoch - timeNow));
    lcd.setCursor(0, 1);
    lcd.print("AZ:" + String(int(sat.satAz)) + " EL:" + String(int(sat.satEl)));
    standby();
  }
  delay(500);
}

void standby()
{

  // Azimuth //
  stepperAZ.runToNewPosition(0);
  // ELEVATION //
  stepperEL.runToNewPosition(-280); // Standby at 20 degrees above horizon

  digitalWrite(AZmotorPin1, LOW);
  digitalWrite(AZmotorPin2, LOW);
  digitalWrite(AZmotorPin3, LOW);
  digitalWrite(AZmotorPin4, LOW);

  digitalWrite(ELmotorPin1, LOW);
  digitalWrite(ELmotorPin2, LOW);
  digitalWrite(ELmotorPin3, LOW);
  digitalWrite(ELmotorPin4, LOW);
}

void prepass()
{
  // Pass is less than 300 seconds (5 mins) away, move antenna to start location and wait.
  if (AZstart < 360 && AZstart > 180)
  {
    AZstart = AZstart - 360; // Goes to start counter-clockwise if closer.
  }
  stepperAZ.runToNewPosition(-AZstart * oneTurn / 360);
  stepperEL.runToNewPosition(0);

  digitalWrite(AZmotorPin1, LOW);
  digitalWrite(AZmotorPin2, LOW);
  digitalWrite(AZmotorPin3, LOW);
  digitalWrite(AZmotorPin4, LOW);

  digitalWrite(ELmotorPin1, LOW);
  digitalWrite(ELmotorPin2, LOW);
  digitalWrite(ELmotorPin3, LOW);
  digitalWrite(ELmotorPin4, LOW);
}

void inPass()
{

  // Handle zero crossings
  if (AZstart > 0)
  {
    satAZsteps = satAZsteps - oneTurn;
  }
  if (satAZsteps - stepperAZ.currentPosition() > 100)
  {
    stepperAZ.setCurrentPosition(stepperAZ.currentPosition() + oneTurn);
    turns--;
  }
  if (satAZsteps - stepperAZ.currentPosition() < -100)
  {
    stepperAZ.setCurrentPosition(stepperAZ.currentPosition() - oneTurn);
    turns++;
  }

  // Update stepper position
  stepperAZ.runToNewPosition(satAZsteps);
  stepperEL.runToNewPosition(satELsteps);
  passEnd = timeNow;
  passStatus = 1;
}

void postpass()
{
  Serial.println("Post pass time left: " + String(passEnd + 60 - timeNow));
  if (timeNow - passEnd > 30)
  {
    if (turns > 0)
    {
      stepperAZ.setCurrentPosition(stepperAZ.currentPosition() + oneTurn);
      turns--;
    }
    if (turns < 0)
    {
      stepperAZ.setCurrentPosition(stepperAZ.currentPosition() - oneTurn);
      turns++;
    }
  }
  if (passStatus == 1 && timeNow - passEnd > 50)
  {
    for (SAT = 0; SAT < numSats; SAT++)
    {
      sat.init(satname, TLE1[SAT], TLE2[SAT]);
      upcomingPasses[SAT] = Predict(timeNow + 200, minPassElevation); // + 200 seconds so next pass is for sure not the one just ending.
      Serial.println("Next pass for Satellite #: " + String(SAT) + " in: " + String(upcomingPasses[SAT] - timeNow));
    }
    nextSat = nextSatPass(upcomingPasses);
    sat.init(satname, TLE1[nextSat], TLE2[nextSat]);
    Predict(timeNow, 0.0);
    passStatus = 0;
  }
}

What stepper motors?
What driver?
What schematics?

Please read and use the topic "How to get the best out of this forum.".

1 Like

Sorry for not mentioning the hardware that i use

Stepper motors = 28byj-48
Driver = ULN2003

Below are the schematics design of the project

Untitled

Update.

I already tried rotate the stepper motor using this coding and it rotate. So i presume my coding for the project have issue.

#include <Stepper.h>

const int steps_per_rev = 2048;  

#define IN1 26
#define IN2 25
#define IN3 33
#define IN4 32

Stepper motor(steps_per_rev, IN1, IN3, IN2, IN4);

void setup() {
  motor.setSpeed(10);
  Serial.begin(115200);
}

void loop() {
  Serial.println("Rotating Clockwise...");
  motor.step(steps_per_rev);
  delay(1000); 
  Serial.println("Rotating Anti-clockwise...");
  motor.step(-steps_per_rev);
  delay(1000);
}

There is no power supplied in the picture.

I use my laptop to connect to the ESP32. Does that mean that the stepper motor should have separate power supply?

Have You tried connecting only one stepper?
The Fritzing picture does not tell much, only the fysical positions where wires are connected. Proper schematics would tell the pin designations. In general it is bad design to power any motor from any controller pin. The tiny strips on the board might get overloaded.

1 Like

The stepper example that worked used a different stepper library. Why did you switch?

Get the stepper working with the stepper library you want to use, before adding any other code.

1 Like

Hi, @akmalfariz
Welcome to the forum.

https://forum.arduino.cc/t/how-to-get-the-best-out-of-this-forum

Where??? Please post a link?

What platform was the code originally coded for?

Can you please tell us your electronics, programming, arduino, hardware experience?

Thanks... Tom... :grinning: :+1: :coffee: :australia:

1 Like

Hi, here are the link that get this code from

I am currently in my final year of electronic engineering degree. My project are somewhat similar to this. Thanks in advance

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