Tracking the Heavens: Building a Laser-Guided ISS Tracker
There is something inherently magical about watching the International Space Station (ISS) streak across the night sky. It is a football-field-sized laboratory hurtling at 17,500 mph, 250 miles above our heads. But unless you are constantly checking an app, it’s easy to miss.
To solve this, I built a dedicated, hardware-based ISS tracker using an ESP32. It doesn't just show data on an LCD; it physically tracks the station’s path. A high-intensity "cross" laser mounted on a motorized gimbal points directly at the ISS's position in real-time, projecting its location onto the roof of my study as it passes overhead.
The Hardware: Steppers, Servos, and Light
The project is built on the ESP32 platform, leveraging its dual-core processing and built-in Wi-Fi. To translate digital coordinates into physical movement, I used a hybrid motion system:
- Azimuth (Horizontal): A NEMA 17 stepper motor driven by a Pololu Tic controller. Steppers are ideal here because they allow for 360-degree rotation and precise micro-stepping.
- Elevation (Vertical): A high-torque servo motor that tilts the laser from 0° (horizon) to 90° (zenith).
- The Indicator: A "cross" laser module that provides a clear visual marker on the ceiling.
- Feedback: A NeoPixel ring provides color-coded status (e.g., green for an active pass, pulsing blue for standby) and an LCD displays the raw telemetry.

The Mathematics of the Sky
The core challenge of this project isn't just moving motors; it's the coordinate transformation. The ISS provides its location in Geodetic coordinates (Latitude, Longitude, and Altitude). However, my tracker lives at a fixed point on Earth. To point the laser, I need to convert those global coordinates into Topocentric coordinates: Azimuth and Elevation.
The Azimuth Calculation
Azimuth ($Az$) is the horizontal angle measured clockwise from North ($0^{\circ}$) to the object. To calculate this, we use the haversine formula and spherical trigonometry.

Given:
- $\phi_1, \lambda_1$: My local Latitude and Longitude.
- $\phi_2, \lambda_2$: The ISS Latitude and Longitude.
- $\Delta\lambda$: The difference in longitude ($\lambda_2 - \lambda_1$).
The formula for the initial bearing (Azimuth) is:
$$\theta = \operatorname{atan2}(\sin(\Delta\lambda) \cdot \cos(\phi_2), \cos(\phi_1) \cdot \sin(\phi_2) - \sin(\phi_1) \cdot \cos(\phi_2) \cdot \cos(\Delta\lambda))$$
Normalizing for the Stepper
The result of an atan2 function is typically in radians between $-\pi$ and $+\pi$. To drive a stepper motor, I first convert this to degrees ($0^{\circ}$ to $360^{\circ}$):
- Convert to Degrees: $Deg = \theta \cdot (180/\pi)$
- Normalize: $Azimuth = (Deg + 360) \pmod{360}$
Because the tracker uses a Pololu Tic via I2C, I can command the stepper to move to a specific "step" position that corresponds to that degree value, ensuring the laser always takes the shortest path.
The Software Stack: MQTT and Logic
The ESP32 doesn't calculate the ISS position itself (which involves complex TLE orbital mechanics). Instead, it acts as an MQTT client.
A separate script (running on a home server) calculates the ISS position every second and publishes it to an MQTT broker. The ESP32 subscribes to these topics:
stat/isstrack/azimuth: Rotates the stepper.cmnd/isstrack/altitude: Adjusts the servo.cmnd/isstrack/led: Toggles the laser when the ISS is actually "visible" (above the horizon and illuminated by the sun).
The "Loop"
The firmware is designed to be resilient. It handles Wi-Fi reconnections, syncs time via NTP to predict the next pass, and provides a local web interface for manual calibration. If the MQTT stream drops, the NeoPixels pulse red, and the motors return to a "home" docking position.
Bringing the Space Station Indoors
There is a profound sense of scale when you sit in a quiet room and see a laser cross slowly crawl across the ceiling. It represents six human beings living in a vacuum, traveling at five miles per second.
By bridging the gap between raw orbital data and physical movement, this tracker turns an abstract mathematical concept into a tangible, visual experience. Whether it's the middle of the night or a cloudy afternoon. Now to add a fog machine for maximum effect ;)