Feerick ISS Tracker issues with PIO

This is another file that worked great when I put it away. This the esteemed Mr. Feerick’s revision of an ISS tracker program I found online.

I’m getting a lot of errors that interrupt compiling. It’s saying “display” wasn’t declared anywhere display is used. And this is how it’s declared, universally at the top:

#ifdef USE_OLED
Adafruit_SSD1306 display(128, 64, &Wire, 8);
#endif

Also a lot of “Expected a declaration” and “this declaration has no storage class or type specifier”,

Seems like it must come from PIO, since display is correctly declared, etc.

Can you zip up and post your project please, or, if it’s on github etc, post a link. I suspect that since you last looked at it, the Adafruit stuff (technical Term) has been updated and may work differently.

However, I’d need to see a compilation output to be sure as those messages you mention are from the compiler, not from PlatformIO, whihc only calls out to the compileres etc when you build or upload a project.

Hope you are well Joe.

Cheers,
Norm.

Hi Norm, Feeling much more secure knowing you’re still here.
When I opened it, PIO had like fifty library updates.

I’ll build it again and share all the dialog. Which is actually monologue.

I don’t see a way to share a zipped folder. The Ukraine banner at the bottom covers the menu.

ISS Feerick:
This is almost identical to yours. I modified the display fonts.

/**
 * Original code written by pollux labs, 2020
 * URL: https://gist.github.com/polluxlabs/1ba7824175c5e011565bd61af2fd1c6b
 */
#define USE_OLED
#define SCREEN_WIDTH 128   // OLED display width, in pixels
#define SCREEN_HEIGHT 32   // OLED display height, in pixels
#define OLED_RESET -1      // Reset pin # (-1 if sharing Arduino reset pin or no reset pin)
#define OLED_I2C_ADDR 0x3C // Displays I2C address
#define OLED_ROTATION 0    // 0 = 0, 1 = 90, 2 = 180 or 3 = 270 (degree rotation)

#define NEOPIXEL_PIN D3
#define NUM_OF_NEOPIXELS 12
#define STATUS_LED LED_BUILTIN
#define STATUS_LED_INVERTED true

#include <Arduino.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
#include <Adafruit_NeoPixel.h>
#ifdef USE_OLED
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include "Fonts/FreeSansBold9pt7b.h"
#include "Fonts/Org_01.h"
#include <Adafruit_SSD1306.h>
#endif

#include <TimeLib.h>
#include <Timezone.h>

#include "secrets.h"

#ifdef USE_OLED
Adafruit_SSD1306 display(128, 64, &Wire, 8);
#endif

long riseTime = 0;                 // Time the ISS will rise for current position
long currentTime = 0;              // Current time (UTC)
long flyoverDuration = 0;          // Duration of ISS pass for current position
long timeUntilFlyover = 0;         // How long it will be until the next flyover
long timeUntilFlyoverComplete = 0; // How long it will be until the current flyover is complete

enum machineStates
{
  WIFI_INIT,
  START,
  GET_TIME,
  GET_NEXT_PASS,
  WAIT_FOR_PASS,
  PASS_START,
  PASSING,
  PASS_COMPLETE
};

enum machineStates currentState = WIFI_INIT;

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_OF_NEOPIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
WiFiClient client;

void success()
{
  pixels.fill(pixels.Color(0, 255, 0));
  pixels.show();

  delay(500);

  pixels.clear();
  pixels.show();
}

void fail()
{
  pixels.fill(pixels.Color(255, 0, 0));
  pixels.show();

  delay(500);

  pixels.clear();
  pixels.show();
}

// Current time (UTC)
bool getCurrentTime()
{
  HTTPClient http;
  http.begin(client, "http://worldtimeapi.org/api/timezone/America/New_York"); // URL for getting the current time

  int httpCode = http.GET();
  if (httpCode > 0)
  {
    if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY)
    { //Check for the returning code
      String payload = http.getString();

      const size_t capacity = JSON_OBJECT_SIZE(15) + 550;
      DynamicJsonDocument doc(capacity);
      DeserializationError error = deserializeJson(doc, payload);
      http.end();

      if (error)
      {
        Serial.print(F("deserializeJson() failed(current time): "));
        Serial.println(error.c_str());
        return false;
      }

      currentTime = doc["unixtime"]; //save current time
      return true;
    }
    else
    {
      Serial.printf("getCurrentTime(): HTTP request failed, server response: %03i\n", httpCode);
      return false;
    }
  }
  else
  {
    Serial.printf("getCurrentTime(): HTTP request failed, reason: %s\n", http.errorToString(httpCode).c_str());
    return false;
  }
}

bool getNextPass()
{
  HTTPClient http;

  http.begin(client, "http://api.open-notify.org/iss-pass.json?lat=" + String(37.25) + "&lon=" + String(-121.9) + "&alt=" + String(260.00) + "&n=5"); //URL for API call

  int httpCode = http.GET();
  if (httpCode > 0)
  {
    if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY)
    {
      String payload = http.getString(); //save response

      const size_t capacity = JSON_ARRAY_SIZE(5) + 5 * JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(5) + 190;
      DynamicJsonDocument doc(capacity);
      DeserializationError error = deserializeJson(doc, payload);
      http.end();

      if (error)
      {
        Serial.print(F("deserializeJson() failed: "));
        Serial.println(error.c_str());
        return false;
      }

      JsonArray response = doc["response"];
      flyoverDuration = response[0]["duration"]; // save duration of the next flyover
      riseTime = response[0]["risetime"];        // save start time of the next flyover

      if (riseTime < currentTime)
      { //If ISS has already passed, take the next flyover
        flyoverDuration = response[1]["duration"];
        riseTime = response[1]["risetime"];
      }

      return true;
    }
    else
    {
      Serial.printf("getNextPass(): HTTP request failed, server response: %03i\n", httpCode);
      return false;
    }
  }
  else
  {
    Serial.printf("getNextPass(): HTTP request failed, reason: %s\n", http.errorToString(httpCode).c_str());
    return false;
  }
}

void setup()
{
  Serial.begin(9600);
  pinMode(STATUS_LED, OUTPUT); //LED Pin
  digitalWrite(STATUS_LED, (STATUS_LED_INVERTED == true) ? HIGH : LOW);

  pixels.begin();
  pixels.setBrightness(100);
  pixels.show();

  Serial.println("");
  Serial.println(F("ISS Flyover Notifier"));
  Serial.println("");

/*#ifdef USE_OLED
  if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_I2C_ADDR))
  {
    Serial.println(F("SSD1306 initalisation failed"));
  }
  display.setRotation(OLED_ROTATION);
  display.clearDisplay();
#endif
}*/

void loop()
{
  switch (currentState)
  {
  case WIFI_INIT:
  {
    WiFi.begin("TP-Link_7C28", "64411811");
    Serial.print(F("WiFi Connecting..."));

#ifdef USE_OLED
    display.clearDisplay();
    display.setTextSize(2);
    display.setTextColor(WHITE);
    display.setCursor(20, 0);
    // Display static text
    display.print("Connect");
    display.setCursor(20, 16);
    display.print("to WiFi");
    display.display();
#endif

    int waitTime = 0;
    while ((WiFi.status() != WL_CONNECTED) && (waitTime < 300))
    {
      Serial.print(".");
      digitalWrite(STATUS_LED, !digitalRead(STATUS_LED));
      delay(100);
      waitTime++;
    }

    digitalWrite(STATUS_LED, (STATUS_LED_INVERTED == true) ? HIGH : LOW);

    if (WiFi.status() == WL_CONNECTED)
    {
      success();
      Serial.println("CONNECTED!");
      currentState = START;
    }
    else
    {
      Serial.println("FAIL!");
      Serial.print(F("Device will restart in "));
      for (int i = 5; i >= 1; i--)
      {
        Serial.print(i);
        Serial.print("...");
        fail();
        delay(500);
      }
      ESP.restart();
    }
    break;
  }
  case START:
  {
    if (WiFi.status() == WL_CONNECTED)
    {
      currentState = GET_TIME;
    }
    else
    {
      currentState = WIFI_INIT;
    }

    break;
  }
  case GET_TIME:
  {
    Serial.println(F("Getting the current time (UTC)..."));

#ifdef USE_OLED
    display.clearDisplay();
    display.setTextSize(2);
    display.setTextColor(WHITE);
    display.setCursor(20, 0);
    // Display static text
    display.println("Get UTC");
    display.setCursor(20, 16);
    display.println("Time");
    display.display();
#endif

    if (!getCurrentTime())
    {
      fail();
      delay(1000);
    }
    else
    {
      success();

      Serial.print(F("Current time (UTC) = "));
      Serial.println(currentTime);
      display.println(currentTime);
      display.display();

      currentState = GET_NEXT_PASS;
    }
    break;
  }
  case GET_NEXT_PASS:
  {
    Serial.println(F("Looking up next ISS flyover time..."));

#ifdef USE_OLED
    display.clearDisplay();
    display.setTextSize(2);
    display.setTextColor(WHITE);
    display.setCursor(20, 0);
    display.println("Get Next");
    display.setCursor(20, 16);
    display.println("ISS Pass");
    display.display();
#endif

    if (!getNextPass())
    {
      fail();
      delay(1000);
    }
    else
    {
      success();

      //compute time until rise
      timeUntilFlyover = riseTime - currentTime;

      Serial.print("Risetime = ");
      Serial.println(riseTime);

      Serial.print(F("Time until flyover (in seconds): "));
      Serial.println(timeUntilFlyover);

      uint32_t t = timeUntilFlyover;
      int s = t % 60;
      t = (t - s) / 60;
      int m = t % 60;
      t = (t - m) / 60;
      int h = t;
      Serial.printf("That's %02i hours, %02i minutes and %02i seconds from now\n", h, m, s);

      t = flyoverDuration;
      s = t % 60;
      t = (t - s) / 60;
      m = t % 60;
      Serial.printf("Estimated pass duration will be %02i minutes and %02i second(s)\n", m, s);

      timeUntilFlyoverComplete = flyoverDuration;
      currentState = WAIT_FOR_PASS;
    }
    break;
  }
  case WAIT_FOR_PASS:
  {
    if (timeUntilFlyover > 0)
    { // while the ISS isn't overhead

      uint32_t t = timeUntilFlyover;
      int s = t % 60;
      t = (t - s) / 60;
      int m = t % 60;
      t = (t - m) / 60;
      int h = t;
      Serial.printf("Next ISS flyover in %02i:%02i:%02i\n", h, m, s);

#ifdef USE_OLED
      display.clearDisplay();
      display.setTextSize(1);
      display.setTextColor(WHITE);
      display.setCursor(5, 5);
      display.setFont(&Org_01);
      display.print("Next flyover:");
      display.setTextSize(3);
      display.setFont(&Org_01);
      display.setCursor(5, 25);
      display.printf("%02i:%02i:%02i", h, m, s);
      display.display();
#endif

      timeUntilFlyover--;
      delay(1000);
    }
    else
    {
      currentState = PASS_START;
    }
    break;
  }
  case PASS_START:
  {
    //when ISS rises  above the horizon
    Serial.println(F("ISS overhead!"));

    uint32_t t = timeUntilFlyoverComplete;
    int s = t % 60;
    t = (t - s) / 60;
    int m = t % 60;
    Serial.printf("Estimated pass duration %02i minutes and %02i second(s)\n", m, s);

    currentState = PASSING;
    break;
  }
  case PASSING:
  {
    if (timeUntilFlyoverComplete > 0)
    {
      //map remaining flyover time on a color gradient
      int colorRed = map(timeUntilFlyoverComplete, 0, flyoverDuration, 200, 0);
      int colorBlue = map(timeUntilFlyoverComplete, 0, flyoverDuration, 0, 200);

      //show the current color on all LEDs
      pixels.fill(pixels.Color(colorRed, 0, colorBlue));
      pixels.show();

      timeUntilFlyoverComplete--;

      uint32_t t = timeUntilFlyoverComplete;
      int s = t % 60;
      t = (t - s) / 60;
      int m = t % 60;
      Serial.printf("Pass time remaining: %02i minutes and %02i second(s)\n", m, s);

#ifdef USE_OLED
      display.clearDisplay();
      display.setTextSize(1);
      display.setTextColor(WHITE);
      display.setCursor(20, 5);
      display.print("Overhead!");
      display.setTextSize(2);
      display.setCursor(20, 28);
      display.printf("%02i:%02i", m, s);
      display.display();
#endif

      delay(1000);
    }
    else
    {
      currentState = PASS_COMPLETE;
    }
    break;
  }
  case PASS_COMPLETE:
  {
    //shut down the NeoPixel until next ISS flyover
    pixels.clear();
    pixels.show();

    currentState = START;
    break;
  }
  }
}
lib_deps =

    ESP8266WiFi

    ArduinoJson

    ESP8266HTTPClient

    adafruit/Adafruit NeoPixel@^1.6.0

    Wire

    SPI

    https://github.com/adafruit/Adafruit-GFX-Library.git

    https://github.com/adafruit/Adafruit_SSD1306.git

    https://github.com/adafruit/Adafruit_BusIO.git

    https://github.com/PaulStoffregen/Time.git

    https://github.com/JChristensen/Timezone.git
Building in debug mode
Compiling .pio\build\esp12e\src\main.cpp.o
Compiling .pio\build\esp12e\lib239\ESP8266WiFi\ESP8266WiFiMulti.cpp.o
Compiling .pio\build\esp12e\lib239\ESP8266WiFi\ESP8266WiFiSTA-WPS.cpp.o
Compiling .pio\build\esp12e\lib239\ESP8266WiFi\ESP8266WiFiSTA.cpp.o
src\main.cpp:37:1: error: expected ',' or ';' before 'Adafruit_SSD1306'
   37 | Adafruit_SSD1306 display(128, 64, &Wire, 8);
      | ^~~~~~~~~~~~~~~~
src\main.cpp: In function 'void setup()':
src\main.cpp:201:1: error: a function-definition is not allowed here before '{' token
  201 | {
      | ^
src\main.cpp:452:1: error: expected '}' at end of input
  452 | }
      | ^
src\main.cpp:177:1: note: to match this '{'
  177 | {
      | ^
*** [.pio\build\esp12e\src\main.cpp.o] Error 1
==================================== [FAILED] 

Thanks Joe. I’ll have a try to compile when I get a chance. Give me a kick if you don’t hear back say, in a couple of days. I’m changing to a new laptop, from the 16+ year old one, and It’s taking some time. :frowning_face:

Oh, the Ukraine banner will vanish if you refresh the page three times. :wink:

Cheers,
Norm.

First thing I spotted. In setup, you’ve commented out some code at the end. You have mistakenly commented out the closing ‘{’ to end the setup function. Oops!

Cheers,
Norm.

Hi Joe,

that was indeed the problem. The closing brace, }, for the setup() function had been commented out. Shift the closing comment marker to after the #endif so it looks like this:

...
  display.clearDisplay();
#endif 
*/
}

and definitely not like this:

...
  display.clearDisplay();
#endif
}*/

You will then get a clean compile:

...
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [====      ]  35.2% (used 28812 bytes from 81920 bytes)
Flash: [===       ]  28.9% (used 301652 bytes from 1044464 bytes)
Building .pio/build/d1_mini/firmware.bin
Creating BIN file ".pio/build/d1_mini/firmware.bin" using "/home/norman/.platformio/packages/framework-arduinoespressif8266/bootloaders/eboot/eboot.elf" and ".pio/build/d1_mini/firmware.elf"
========================= [SUCCESS] Took 3.21 seconds ...

Cheers,
Norm.

Thanks!
I’d commented out the OLED, because it isn’t letting me use the OLED:
src\main.cpp:37:1: error: expected ‘,’ or ‘;’ before ‘Adafruit_SSD1306’
37 | Adafruit_SSD1306 display(128, 64, &Wire, 8);
| ^~~~~~~~~~~~~~~~
src\main.cpp: In function ‘void setup()’:
src\main.cpp:191:8: error: ‘display’ was not declared in this scope; did you mean ‘delay’?
191 | if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_I2C_ADDR))
| ^~~~~~~
| delay

‘display’ was not declared in this scope; did you mean ‘delay’?

(This is sorta moot, because the ISS doesn’t fly over me. It doesn’t cross the east coast of US. It’s over the Caribbean when it crosses my longitude. Boo.

Hey Joe,

I just copied your lib_deps, and source into a project and uncommented the bit you commented out and it compiled just file.

I’m not sure what your board is, but mine’s a D1_Mini using the Expressif8266 platform and the Arduino framework. Is this the same as yours?

[env]
board = d1_mini
platform = espressif8266@2.6.2
framework = arduino
...

Cheers,
Norm.

I’m using the D1 Mini 8266.
I really want the display. Value without the display is a small non-zero number.
It won’t accept the declaration. The declaration doesn’t raise an error, but ‘display’ does.

I wanted to see if it would compile without the OLED. I made a /* typo, so the test wasn’t valid. But the display is the most important part. Even if I won’t be able to see the ISS from here. It’ll be visible for 45 seconds.