Makestreme
Published © GPL3+

ISS Antenna - Indicates When the ISS Is Overhead

This is a miniature desktop antenna that indicates how far the International Space Station is from your location!

IntermediateFull instructions provided5 hours229
ISS Antenna - Indicates When the ISS Is Overhead

Things used in this project

Hardware components

Wemos D1 Mini
Espressif Wemos D1 Mini
×1
RGB Diffused Common Cathode
RGB Diffused Common Cathode
×1
Through Hole Resistor, 470 ohm
Through Hole Resistor, 470 ohm
×3
Hook Up Wire Kit, 22 AWG
Hook Up Wire Kit, 22 AWG
×3

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Custom parts and enclosures

Truss sides

Sketchfab still processing.

Base plate

Sketchfab still processing.

Bridge

Sketchfab still processing.

Dish

Sketchfab still processing.

Housing

Sketchfab still processing.

LED base

Sketchfab still processing.

Truss middle

Sketchfab still processing.

Schematics

Circuit

Circuit

Code

Main arduino code

Arduino
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ArduinoJson.h>

#define RED_PIN D5
#define GREEN_PIN D6
#define BLUE_PIN D7

//  USER CONFIG 
// Your Wi-Fi credentials
const char* WIFI_SSID = "YOUR_SSID";
const char* WIFI_PASS = "YOUR_PASSWORD";

// Your location (in decimal degrees)
const double MY_LAT = 11.1101; 
const double MY_LON = 20.2202;

// Distance thresholds (km)
const double VISIBLE_RADIUS   = 500.0;
const double SLIGHTLY_FAR_RADIUS = 1000.0;

// API endpoint
const char* ISS_API_URL = "http://api.open-notify.org/iss-now.json";

//  HELPER FUNCTIONS 
double deg2rad(double deg) {
  return deg * (PI / 180.0);
}

double haversine(double lat1, double lon1, double lat2, double lon2) {
  double dLat = deg2rad(lat2 - lat1);
  double dLon = deg2rad(lon2 - lon1);
  lat1 = deg2rad(lat1);
  lat2 = deg2rad(lat2);

  double a = sin(dLat/2) * sin(dLat/2) +
             sin(dLon/2) * sin(dLon/2) * cos(lat1) * cos(lat2);
  double c = 2 * atan2(sqrt(a), sqrt(1-a));
  const double R = 6371.0; // Earth radius in km
  return R * c;
}

// Function for steady pure red color
void steadyRed(unsigned long duration) {
  unsigned long startTime = millis();
  
  // Pure red values
  analogWrite(RED_PIN, 100);     // Full red
  analogWrite(GREEN_PIN, 0);     // No green for pure red
  analogWrite(BLUE_PIN, 0);      // No blue
  
  while (millis() - startTime < duration) {
    // Just keep the color steady for the duration
    delay(10);
  }
}

// Function for pulsing yellow color
void pulsingDeepYellow(unsigned long duration) {
  unsigned long startTime = millis();
  int brightness = 0;
  int fadeAmount = 5;
  
  while (millis() - startTime < duration) {
    // Deep yellow/amber - more red, less green
    int redValue = brightness;
    int greenValue = brightness * 0.3;  // Only 30% green to make a deep amber/yellow
    
    analogWrite(RED_PIN, redValue);
    analogWrite(GREEN_PIN, greenValue);
    analogWrite(BLUE_PIN, 0);  // No blue
    
    // Change brightness for next time through the loop
    brightness = brightness + fadeAmount;
    
    // Reverse direction of fading at the limits
    if (brightness <= 0 || brightness >= 100) {
      fadeAmount = -fadeAmount;
    }
    
    // Slow pulse - longer delay
    delay(30);
  }
}

// Function for pulsing green color (fast)
void pulsingGreen(unsigned long duration) {
  unsigned long startTime = millis();
  int brightness = 0;
  int fadeAmount = 10;  // Faster change for quicker pulse
  
  while (millis() - startTime < duration) {
    // Pure green
    analogWrite(RED_PIN, 0);     // No red
    analogWrite(GREEN_PIN, brightness);  // Green only
    analogWrite(BLUE_PIN, 0);    // No blue
    
    // Change brightness for next time through the loop
    brightness = brightness + fadeAmount;
    
    // Reverse direction of fading at the limits
    if (brightness <= 0 || brightness >= 100) {
      fadeAmount = -fadeAmount;
    }
    
    // Fast pulse - shorter delay
    delay(15);
  }
  
}

//  SETUP & LOOP 
void setup() {
  pinMode(RED_PIN, OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(BLUE_PIN, OUTPUT);

  Serial.begin(115200);
  WiFi.begin(WIFI_SSID, WIFI_PASS);

  Serial.print("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nConnected!");
}

void loop() {
  if (WiFi.status() == WL_CONNECTED) {
    WiFiClient client;
    HTTPClient http;
    http.begin(client, ISS_API_URL); 

    int httpCode = http.GET();

    if (httpCode == HTTP_CODE_OK) {
      String payload = http.getString();
      StaticJsonDocument<256> doc;
      DeserializationError err = deserializeJson(doc, payload);

      if (!err) {
        double issLat = doc["iss_position"]["latitude"].as<double>();
        double issLon = doc["iss_position"]["longitude"].as<double>();
        double dist = haversine(MY_LAT, MY_LON, issLat, issLon);

        // Decide visibility
          if (dist <= VISIBLE_RADIUS) {
            // Fast pulsing green for 30 seconds
            pulsingGreen(30000);
          }
          else if (dist <= SLIGHTLY_FAR_RADIUS) {
            // Slow pulsing deep yellow for 30 seconds
            pulsingDeepYellow(30000);
          }
          else {
            // Pure red color for 30 seconds
            steadyRed(30000);
          }
      } else {
        Serial.println("Failed to parse JSON");
      }
    } else {
      Serial.printf("HTTP GET failed, code: %d\n", httpCode);
    }

    http.end();
  } else {
    Serial.println("WiFi not connected!");
  }

  delay(200);  
}

Credits

Makestreme
11 projects • 12 followers
I make DIY projects that are fun and interesting! An engineer by profession :) youtube.com/@makestreme

Comments