Or anything else. ( idea from a reddit post )
UPDATE: 20250523
Combining a GPS module, compass, a LED ring and some code, I want to make a little device which shows you the way to the nearest … something.
To make it completely standalone, I have to use a SIM module. (Same as I have used before) This POC will use my phone as hotspot.
The LED ring will show the direction to go.
Edit: Maybe not a LED ring but a little display.



As previously posted, I was playing with Overpass turbo.
Using an API, I can use code to query this.
- Arduino sends latitude, longitude to my webserver
- Webserver queries API for neastest POIs and calculates distance.
- Send data from webserver to arduino
- Arduino uses heading data to light up direction LED
(also on secondary display with distance info?)
edit: and shop info
Test code for my web server to query the data
import overpy import math api = overpy.Overpass() # This location will be filled with data from GPS module on Arduino. latitude = 52.2270745 # Center latitude (e.g. Berlin) longitude = 5.177519 # Center longitude box_size = 0.05 # Box size in degrees (about ~5 km) south = latitude - box_size north = latitude + box_size west = longitude - box_size east = longitude + box_size def haversine(lat1, lon1, lat2, lon2): R = 6371 # Earth radius in km phi1 = math.radians(lat1) phi2 = math.radians(lat2) d_phi = math.radians(lat2 - lat1) d_lambda = math.radians(lon2 - lon1) a = math.sin(d_phi / 2)**2 + math.cos(phi1) * math.cos(phi2) * math.sin(d_lambda / 2)**2 c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) return R * c # Distance in kilometers # Calculate bearing in degrees (0-360) def bearing(lat1, lon1, lat2, lon2): phi1 = math.radians(lat1) phi2 = math.radians(lat2) delta_lon = math.radians(lon2 - lon1) x = math.sin(delta_lon) * math.cos(phi2) y = math.cos(phi1) * math.sin(phi2) - math.sin(phi1) * math.cos(phi2) * math.cos(delta_lon) initial_bearing = math.atan2(x, y) compass_bearing = (math.degrees(initial_bearing) + 360) % 360 # Normalize to 0–360 return compass_bearing # Overpass QL query query = f""" [out:json]; node ["shop"="alcohol"] ({south}, {west}, {north}, {east}); out body; >; out skel qt; """ try: result = api.query(query) # Collect and sort places by distance places = [] for node in result.nodes: node_lat = float(node.lat) node_lon = float(node.lon) distance = haversine(latitude, longitude, node_lat, node_lon) direction = bearing(latitude, longitude, node_lat, node_lon) name = node.tags.get("name", "Unnamed") places.append((distance, direction, name, node_lat, node_lon)) places.sort() print(f"Found {len(places)} alcohol-related places sorted by distance:") for dist, dir_deg, name, lat, lon in places: print(f"- {name} at ({lat:.5f}, {lon:.5f}) — {dist:.2f} km, {dir_deg:.0f}°") except Exception as e: print(f"Error: {e}")
Output:
Found 10 alcohol-related places sorted by distance:
- The Skiff at (52.22583, 5.17860) — 0.16 km, 152°
- Onzewijnen at (52.22612, 5.17045) — 0.49 km, 258°
- Gall & Gall at (52.23244, 5.19204) — 1.15 km, 59°
- Gall & Gall at (52.21536, 5.16735) — 1.48 km, 208°
- Eric's Beer Craft at (52.21549, 5.16632) — 1.50 km, 211°
- Slijterij at (52.21082, 5.15692) — 2.29 km, 218°
- Gall & Gall at (52.21590, 5.14074) — 2.80 km, 244°
- Gall & Gall at (52.25422, 5.22705) — 4.53 km, 48°
- Gall & Gall at (52.26808, 5.18348) — 4.58 km, 5°
- Il DiVino at (52.27507, 5.16414) — 5.41 km, 350°
Example using Overpass Turbo to find breweries
Other ideas
- Geocaching (Thanks Vincent)
- Find each other at festivals?
UPDATE
Building the hardware : First design
Some test code
#include "SPI.h" #include "Adafruit_GFX.h" #include "Adafruit_GC9A01A.h" // Overrule stuff #define TFT_CS 18 // Chip select #define TFT_DC 5 // Data/command mode #define TFT_BL 4 // Backlight control #define TFT_MOSI 12 // SPI Out AKA SDA #define TFT_SCLK 13 // Clock out AKA SCL #define TFT_MISO -1 // pin not used #define TFT_RST 23 // Reset ################# IMPORTANT, won't work without!! Took me a hour! // Need this changed from example also Adafruit_GC9A01A tft(TFT_CS, TFT_DC,TFT_MOSI,TFT_SCLK,TFT_RST,TFT_MISO); float angle = 0; void setup() { tft.begin(); tft.setRotation(0); tft.fillScreen(GC9A01A_BLACK); drawCompassFace(); } void loop() { drawNeedle(angle, GC9A01A_RED); delay(1000); drawNeedle(angle, GC9A01A_BLACK); // Erase previous needle angle += 15; if (angle >= 360) angle = 0; tft.setCursor(60, 100); tft.setTextColor(GC9A01A_WHITE); tft.setTextSize(2); tft.println("230 Meters"); } // Draw static compass face void drawCompassFace() { int cx = tft.width() / 2; int cy = tft.height() / 2; int radius = 100; tft.drawCircle(cx, cy, radius, GC9A01A_WHITE); tft.setTextColor(GC9A01A_WHITE); tft.setTextSize(1); tft.setCursor(cx - 3, cy - radius + 5); tft.print("N"); tft.setCursor(cx - 3, cy + radius - 10); tft.print("S"); tft.setCursor(cx - radius + 5, cy - 3); tft.print("W"); tft.setCursor(cx + radius - 10, cy - 3); tft.print("E"); } // Draw compass needle void drawNeedle(float angleDeg, uint16_t color) { int cx = tft.width() / 2; int cy = tft.height() / 2; float angleRad = angleDeg * DEG_TO_RAD; int x = cx + cos(angleRad) * 90; int y = cy + sin(angleRad) * 90; tft.drawLine(cx, cy, x, y, color); }