'''
MAX7219 Weather Display using Google Current Weather API
* Uses Google Current Weather API for real-time conditions
* Fetches CURRENT weather data including "feels like" temperature
* Four MAX7219 devices connected in daisy chain
* 8x8 dot matrix modules (256 LEDs total) forming 8 rows x 32 columns
* Updates weather data every 5 minutes
* Raspberry Pi Pico W pin connections to MAX7219:
* MAX7219 VCC pin to VBUS
* MAX7219 GND pin to GND
* MAX7219 DIN pin to digital GPIO3
* MAX7219 CS pin to digital GPIO5
* MAX7219 CLOCK pin to digital GPIO2
Google-powered CURRENT weather display for real-time conditions
'''
# Import MicroPython libraries
from machine import Pin, SPI
import max7219
import time
import network
import urequests
import ujson
import math
# WiFi Credentials for Wokwi testing
WIFI_SSID = 'Wokwi-GUEST'
WIFI_PASSWORD = ''
# Google Weather API Configuration
GOOGLE_API_KEY = 'AIzaSyCBgDPnIbQC2hPjB2hu7DOSoHIlK1xwYIk' # Paste your actual Google Weather API key here
LOCATION_NAME = 'Ashburnham, MA, USA'
# Coordinates for Google Weather API
latitude = 42.6355
longitude = -71.9097
WEATHER_UPDATE_INTERVAL = 300 # 5 minutes in seconds
# Initialize SPI for MAX7219
spi = SPI(0, baudrate=10000000, polarity=0, phase=1, sck=Pin(2), mosi=Pin(3))
ss = Pin(5, Pin.OUT)
# Create matrix display with four MAX7219 devices
display = max7219.Matrix8x8(spi, ss, 16)
# Set display brightness (1-15)
display.brightness(6)
# Global variables for weather data
current_temp = None
feels_like_temp = None
weather_description = None
last_update = 0
scrolling_message = "Starting Weather Display..."
print(f"Location: {LOCATION_NAME}")
print(f"Coordinates: {latitude}, {longitude}")
def connect_wifi():
"""Connect to WiFi network"""
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print('Connecting to WiFi...')
wlan.connect(WIFI_SSID, WIFI_PASSWORD)
# Wait for connection with timeout
timeout = 20
while not wlan.isconnected() and timeout > 0:
time.sleep(1)
timeout -= 1
print('.', end='')
if wlan.isconnected():
print(f'\nWiFi connected! IP: {wlan.ifconfig()[0]}')
return True
else:
print('\nWiFi connection failed!')
return False
return True
def fetch_weather_data():
"""Fetch weather data using Google Weather API Current Conditions"""
global current_temp, feels_like_temp, weather_description, last_update, scrolling_message
try:
print("Fetching current weather data from Google Weather API...")
print(f"Using coordinates: {latitude}, {longitude}")
# Google Weather API Current Conditions URL - using HTTP to avoid SSL issues
base_url = "http://weather.googleapis.com/v1/currentConditions:lookup"
params = f"?key={GOOGLE_API_KEY}&location.latitude={latitude}&location.longitude={longitude}&units_system=IMPERIAL"
url = base_url + params
print(f"Fetching from Google: {url}")
response = urequests.get("https://weather.googleapis.com/v1/forecast/days:lookup?key=AIzaSyCBgDPnIbQC2hPjB2hu7DOSoHIlK1xwYIk&location.latitude=42.6&location.longitude=-71.9&units_system=IMPERIAL&days=2")
if response.status_code == 200:
doc = ujson.loads(response.text)
response.close()
print("Google Weather API response received")
print(f"Temperature: {doc.get('temperature', 'MISSING')}")
print(f"FeelsLike: {doc.get('feelsLikeTemperature', 'MISSING')}")
print(f"Weather: {doc.get('weatherCondition', 'MISSING')}")
# Parse like your working C++ code
try:
current_temp = round(float(doc["temperature"]["degrees"]))
feels_like_temp = round(float(doc["feelsLikeTemperature"]["degrees"]))
weather_description = doc["weatherCondition"]["description"]["text"]
except KeyError as ke:
print(f"Missing key in response: {ke}")
print(f"Full response: {doc}")
return False
except Exception as pe:
print(f"Parse error: {pe}")
return False
print(f"Google Current Weather: {current_temp}F, Feels like: {feels_like_temp}F, {weather_description}")
# Update timestamp
last_update = time.time()
# Create scrolling message
scrolling_message = f"Current Weather: {current_temp}F - Feels Like: {feels_like_temp}F - {weather_description} - {LOCATION_NAME} - "
print(f"Weather updated: {current_temp}F (feels like {feels_like_temp}F) - {weather_description}")
return True
elif response.status_code == 401:
print("Google API Error: Invalid API key or permissions")
response.close()
scrolling_message = "Invalid Google API key - Check key and enable Weather API - "
return False
elif response.status_code == 403:
print("Google API Error: Access forbidden - check API permissions")
response.close()
scrolling_message = "Google API access denied - Enable Weather API - "
return False
else:
print(f"Google Weather API Error: {response.status_code}")
response.close()
scrolling_message = f"Google Weather API error {response.status_code} - "
return False
except Exception as e:
print(f"Error fetching Google weather: {e}")
scrolling_message = "Google Weather fetch failed - Check connection - "
return False
def get_weather_description(weather_code):
"""Convert weather code to description"""
weather_codes = {
0: "Clear Sky",
1: "Mainly Clear", 2: "Partly Cloudy", 3: "Overcast",
45: "Fog", 48: "Rime Fog",
51: "Light Drizzle", 53: "Drizzle", 55: "Heavy Drizzle",
61: "Light Rain", 63: "Rain", 65: "Heavy Rain",
71: "Light Snow", 73: "Snow", 75: "Heavy Snow",
80: "Light Showers", 81: "Showers", 82: "Heavy Showers",
95: "Thunderstorm", 96: "Thunderstorm with Hail"
}
return weather_codes.get(weather_code, "Unknown Weather")
def get_weather_display():
"""Get weather data for display, update if needed"""
global last_update, scrolling_message
current_time = time.time()
# Check if we need to update weather data
if last_update == 0 or (current_time - last_update) > WEATHER_UPDATE_INTERVAL:
if connect_wifi():
if not fetch_weather_data():
if GOOGLE_API_KEY == 'YOUR_GOOGLE_API_KEY_HERE':
scrolling_message = "Please set your Google Weather API key - "
else:
scrolling_message = "Google Weather service unavailable - "
else:
scrolling_message = "WiFi connection failed - Check Wokwi connection - "
return scrolling_message
def display_startup():
"""Display startup messages"""
startup_messages = [
"Weather Display Starting...",
"Connecting to Wokwi WiFi...",
f"Location: {LOCATION_NAME}",
"Fetching weather data..."
]
for message in startup_messages:
print(message)
# Calculate message dimensions
length = len(message)
column = length * 8
# Quick scroll of startup message
for x in range(32, -column, -2): # Faster scroll for startup
display.fill(0)
display.text(message, x, 0, 1)
display.show()
time.sleep(0.02)
time.sleep(0.3)
def test_display():
"""Test the MAX7219 display"""
print("Testing display...")
test_messages = [
"Display Test",
"Google Weather",
"Wokwi Ready"
]
for message in test_messages:
length = len(message)
column = length * 8
for x in range(32, -column, -1):
display.fill(0)
display.text(message, x, 0, 1)
display.show()
time.sleep(0.04)
time.sleep(0.5)
def test_google_current_weather_api():
"""Test Google Current Weather API"""
print("Testing Google Current Weather API...")
print(f"API Key: {GOOGLE_API_KEY[:10]}..." if GOOGLE_API_KEY != 'YOUR_GOOGLE_API_KEY_HERE' else "No API key set")
print(f"Coordinates: {latitude}, {longitude}")
if GOOGLE_API_KEY == 'YOUR_GOOGLE_API_KEY_HERE':
print("ERROR: Please set your Google Weather API key!")
print("1. Use your existing Google Cloud Console account")
print("2. Enable Weather API")
print("3. Get your API key")
return False
if connect_wifi():
success = fetch_weather_data()
if success:
print("✓ Google Current Weather API successful!")
print(f" Current: {current_temp}F")
print(f" Feels Like: {feels_like_temp}F")
print(f" Conditions: {weather_description}")
print(f" Message: {scrolling_message}")
return True
else:
print("✗ Google Current Weather API failed")
return False
else:
print("✗ WiFi connection failed")
return False
def test_with_fake_data():
"""Test display with fake Google weather data"""
global current_temp, feels_like_temp, weather_description, scrolling_message
print("Testing display with fake Google weather data...")
# Set fake weather data
current_temp = 68
feels_like_temp = 72
weather_description = "Partly Cloudy"
scrolling_message = f"Google Weather: {current_temp}F - Feels Like: {feels_like_temp}F - {weather_description} - {LOCATION_NAME} - "
print(f"Fake Google weather: {current_temp}F (feels like {feels_like_temp}F) - {weather_description}")
# Test scrolling display
for cycle in range(2): # 2 complete scrolls
length = len(scrolling_message)
column = length * 8
for x in range(32, -column, -1):
display.fill(0)
display.text(scrolling_message, x, 0, 1)
display.show()
time.sleep(0.05)
time.sleep(0.5)
print("Fake Google weather test complete!")
def main():
"""Main program loop"""
global scrolling_message
print("MAX7219 Google Current Weather API Display")
print("=" * 45)
print("Features: REAL Google Current Weather API + Feels Like Temperature")
print("Platform: Wokwi Simulator")
print(f"Location: {LOCATION_NAME}")
print(f"Coordinates: {latitude}, {longitude}")
print(f"API Endpoint: weather.googleapis.com/v1/currentConditions")
# Check API key
if GOOGLE_API_KEY == 'YOUR_GOOGLE_API_KEY_HERE':
print("WARNING: Please set your Google Weather API key!")
print("You already have a Google Cloud account - just enable Weather API!")
scrolling_message = "Set Google Weather API key - Enable Weather API in Cloud Console - "
# Clear display
display.fill(0)
display.show()
time.sleep(1)
# Initial weather fetch
if GOOGLE_API_KEY != 'YOUR_GOOGLE_API_KEY_HERE':
get_weather_display()
print("Starting Google Current Weather API display loop...")
print("Weather updates every 5 minutes")
print("Press Ctrl+C to stop")
# Main display loop
while True:
try:
# Get current weather message (auto-updates if needed)
current_message = get_weather_display()
# Calculate message dimensions
length = len(current_message)
column = length * 8 # 8 pixels per character
# Scroll the message across the display
for x in range(32, -column, -1): # Start from right edge
display.fill(0)
display.text(current_message, x, 0, 1)
display.show()
time.sleep(0.05) # Scrolling speed
# Small pause between message repeats
time.sleep(0.3)
except KeyboardInterrupt:
print("\nShutting down Google Weather display...")
display.fill(0)
display.text("Goodbye!", 0, 0, 1)
display.show()
time.sleep(2)
display.fill(0)
display.show()
break
except Exception as e:
print(f"Display error: {e}")
scrolling_message = "Display error - Restarting... - "
time.sleep(3)
if __name__ == '__main__':
# Uncomment these lines for testing:
# test_display() # Test MAX7219 hardware
# test_with_fake_data() # Test display with fake weather
# test_google_current_weather_api() # Test real current weather API
# Run main weather display
main()