Now that we know where to get the current (lat, lon) for the ISS and how to convert that to (x, y) we can write a little program to display this in near real time. The general idea for the program is pretty simple:
- Load a background map (map.bmp)
- Every ~10 seconds:
- Get the current (lat, lon) location
- Compute screen (x, y) from (lat, lon)
- Draw a marker at (x,y)
- Add location trail
That's it.
Download the Project Files
Here's the complete code that does this. Click on the Download Project Bundle button to get all the files for this project:
# SPDX-FileCopyrightText: 2019 Carter Nelson for Adafruit Industries # # SPDX-License-Identifier: MIT import time import math import board import displayio from terminalio import FONT from adafruit_pyportal import PyPortal from adafruit_display_shapes.circle import Circle from adafruit_display_text.label import Label #--| USER CONFIG |-------------------------- MARK_SIZE = 10 # marker radius MARK_COLOR = 0xFF3030 # marker color MARK_THICKNESS = 5 # marker thickness TRAIL_LENGTH = 200 # trail length TRAIL_COLOR = 0xFFFF00 # trail color DATE_COLOR = 0x111111 # date color TIME_COLOR = 0x111111 # time color LAT_MAX = 80 # latitude (deg) of map top/bottom edge UPDATE_RATE = 10 # update rate in seconds #------------------------------------------- DATA_SOURCE = "http://api.open-notify.org/iss-now.json" DATA_LOCATION = ["iss_position"] WIDTH = board.DISPLAY.width HEIGHT = board.DISPLAY.height # determine the current working directory needed so we know where to find files cwd = ("/"+__file__).rsplit('/', 1)[0] pyportal = PyPortal(url=DATA_SOURCE, json_path=DATA_LOCATION, status_neopixel=board.NEOPIXEL, text_font=None, default_bg=cwd+"/map.bmp") # Connect to the internet and get local time pyportal.get_local_time() # Date and time label date_label = Label(FONT, text="0000-00-00", color=DATE_COLOR, x=165, y=223) time_label = Label(FONT, text="00:00:00", color=TIME_COLOR, x=240, y=223) pyportal.splash.append(date_label) pyportal.splash.append(time_label) # ISS trail trail_bitmap = displayio.Bitmap(3, 3, 1) trail_palette = displayio.Palette(1) trail_palette[0] = TRAIL_COLOR trail = displayio.Group() pyportal.splash.append(trail) # ISS location marker marker = displayio.Group() for r in range(MARK_SIZE - MARK_THICKNESS, MARK_SIZE): marker.append(Circle(0, 0, r, outline=MARK_COLOR)) pyportal.splash.append(marker) def get_location(width=WIDTH, height=HEIGHT): """Fetch current lat/lon, convert to (x, y) tuple scaled to width/height.""" # Get location try: location = pyportal.fetch() except RuntimeError: return None, None # Compute (x, y) coordinates lat = float(location["latitude"]) # degrees, -90 to 90 lon = float(location["longitude"]) # degrees, -180 to 180 # Scale latitude for cropped map lat *= 90 / LAT_MAX # Mercator projection math # https://stackoverflow.com/a/14457180 # https://en.wikipedia.org/wiki/Mercator_projection#Alternative_expressions x = lon + 180 x = width * x / 360 y = math.radians(lat) y = math.tan(math.pi / 4 + y / 2) y = math.log(y) y = (width * y) / (2 * math.pi) y = height / 2 - y return int(x), int(y) def update_display(current_time, update_iss=False): """Update the display with current info.""" # ISS location if update_iss: x, y = get_location() if x and y: marker.x = x marker.y = y if len(trail) >= TRAIL_LENGTH: trail.pop(0) trail.append(displayio.TileGrid(trail_bitmap, pixel_shader=trail_palette, x = x - 1, y = y - 1) ) # Date and time date_label.text = "{:04}-{:02}-{:02}".format(current_time.tm_year, current_time.tm_mon, current_time.tm_mday) time_label.text = "{:02}:{:02}:{:02}".format(current_time.tm_hour, current_time.tm_min, current_time.tm_sec) try: board.DISPLAY.refresh(target_frames_per_second=60) except AttributeError: board.DISPLAY.refresh_soon() # Initial refresh update_display(time.localtime(), True) last_update = time.monotonic() # Run forever while True: now = time.monotonic() new_position = False if now - last_update > UPDATE_RATE: new_position = True last_update = now update_display(time.localtime(), new_position) time.sleep(0.5)
Plug your PyPortal into your computer with a known good USB data+power cable.
Copy all the files from the zip file on your computer to the PyPortal with the subdirectories noted below.
Your PyPortal CIRCUITPY drive should contain the following files in the correct folders:
Text editor powered by tinymce.