168 lines
6.2 KiB
Python
168 lines
6.2 KiB
Python
import time
|
|
import machine
|
|
from machine import Pin, SPI, I2C
|
|
import rlcd
|
|
|
|
# Import our utility classes
|
|
from shtc3_util import SHTC3
|
|
from rtc_util import PCF85063
|
|
from battery_util import BatteryMonitor
|
|
from button_util import BoardButtons
|
|
from rgb_led_util import BoardLED
|
|
|
|
# LED state management
|
|
led_modes = [
|
|
("Red (Breathing)", lambda led: led.set_color(40, 0, 0), "breath"),
|
|
("Green (Breathing)", lambda led: led.set_color(0, 40, 0), "breath"),
|
|
("Blue (Breathing)", lambda led: led.set_color(0, 0, 40), "breath"),
|
|
("Cyan (Breathing)", lambda led: led.set_color(0, 30, 30), "breath"),
|
|
("Magenta (Breathing)", lambda led: led.set_color(30, 0, 30), "breath"),
|
|
("Rainbow Cycle", lambda led: led.set_color(30, 30, 30), "rainbow"), # Dummy base color, handled by cycle
|
|
("LED Off", lambda led: led.off(), "off")
|
|
]
|
|
current_mode_idx = 1 # Start on Green (Breathing)
|
|
|
|
def main():
|
|
global current_mode_idx
|
|
print("=== Initializing ESP32-S3-RLCD-4.2 Demo ===")
|
|
|
|
# 1. Initialize shared I2C bus and SPI display
|
|
print("Initializing I2C (SDA=13, SCL=14)...")
|
|
i2c = I2C(0, sda=Pin(13), scl=Pin(14))
|
|
|
|
print("Initializing SPI and Display...")
|
|
spi = SPI(1, baudrate=20000000, polarity=0, phase=0, sck=Pin(11), mosi=Pin(12))
|
|
display = rlcd.RLCD(spi, cs=Pin(40), dc=Pin(5), rst=Pin(41))
|
|
|
|
# Enable the speaker amplifier power control pin (just to show how, set low for now to save power/avoid hum)
|
|
print("Configuring Audio Amp control pin...")
|
|
amp_pin = Pin(46, Pin.OUT, value=0)
|
|
|
|
# 2. Initialize Utilities
|
|
print("Initializing hardware utilities...")
|
|
sensor = SHTC3(i2c)
|
|
rtc_chip = PCF85063(i2c)
|
|
battery = BatteryMonitor()
|
|
led = BoardLED(38)
|
|
buttons = BoardButtons()
|
|
|
|
# Sync system clock from hardware RTC on startup
|
|
rtc_chip.sync_to_system()
|
|
|
|
# Set initial LED mode (Green breathing)
|
|
led_modes[current_mode_idx][1](led)
|
|
|
|
# 3. Setup Button Event Callbacks
|
|
last_action_str = "System Started"
|
|
trigger_screen_update = True
|
|
|
|
def on_key_click():
|
|
global current_mode_idx
|
|
current_mode_idx = (current_mode_idx + 1) % len(led_modes)
|
|
mode_name = led_modes[current_mode_idx][0]
|
|
# Apply color settings
|
|
led_modes[current_mode_idx][1](led)
|
|
print(f"KEY clicked! Switched LED mode to: {mode_name}")
|
|
nonlocal last_action_str, trigger_screen_update
|
|
last_action_str = f"LED: {mode_name}"
|
|
trigger_screen_update = True
|
|
|
|
def on_boot_click():
|
|
print("BOOT clicked! Triggering manual refresh.")
|
|
nonlocal last_action_str, trigger_screen_update
|
|
last_action_str = "Manual Screen Refresh"
|
|
trigger_screen_update = True
|
|
|
|
# Register callbacks
|
|
buttons.key.on_click(on_key_click)
|
|
buttons.boot.on_click(on_boot_click)
|
|
|
|
# 4. Main execution loop
|
|
print("Starting Main Loop...")
|
|
last_screen_update = 0
|
|
screen_update_interval_ms = 5000 # Update display every 5 seconds or on button triggers
|
|
|
|
screenshot_saved = False
|
|
|
|
while True:
|
|
current_time_ms = time.ticks_ms()
|
|
|
|
# Check if we should update the screen
|
|
if trigger_screen_update or (time.ticks_diff(current_time_ms, last_screen_update) >= screen_update_interval_ms):
|
|
trigger_screen_update = False
|
|
last_screen_update = current_time_ms
|
|
|
|
# Read sensor values
|
|
temp, hum = sensor.read_sensor()
|
|
temp_str = f"{temp} C" if temp is not None else "Error"
|
|
hum_str = f"{hum} %" if hum is not None else "Error"
|
|
|
|
# Read RTC time
|
|
dt = rtc_chip.get_datetime()
|
|
if dt:
|
|
time_str = f"{dt[0]:04d}-{dt[1]:02d}-{dt[2]:02d} {dt[4]:02d}:{dt[5]:02d}:{dt[6]:02d}"
|
|
else:
|
|
time_str = "RTC Error"
|
|
|
|
# Read battery info
|
|
bat_v = battery.read_voltage()
|
|
bat_p = battery.read_percentage()
|
|
bat_str = f"{bat_v:.2f}V ({bat_p}%)" if bat_v is not None else "Error"
|
|
|
|
print(f"[{rtc_chip.get_time_string()}] T={temp_str}, H={hum_str}, Battery={bat_str}")
|
|
|
|
# Draw display
|
|
display.clear(0) # Clear to white (standard background)
|
|
|
|
# Title
|
|
display.text("WAVESHARE ESP32-S3-RLCD-4.2", 10, 10, 1)
|
|
display.line(10, 20, 390, 20, 1)
|
|
|
|
# Sensor Readings block
|
|
display.text_large("ENVIRONMENT", 15, 30, scale=2, c=1)
|
|
display.text(f"Temperature : {temp_str}", 25, 55, 1)
|
|
display.text(f"Humidity : {hum_str}", 25, 70, 1)
|
|
|
|
display.line(10, 95, 390, 95, 1)
|
|
|
|
# Device Status block
|
|
display.text_large("DEVICE STATUS", 15, 105, scale=2, c=1)
|
|
display.text(f"RTC Time : {time_str}", 25, 130, 1)
|
|
display.text(f"Battery : {bat_str}", 25, 145, 1)
|
|
|
|
display.line(10, 170, 390, 170, 1)
|
|
|
|
# Interactions block
|
|
display.text_large("INTERACTIVE CONTROLS", 15, 180, scale=2, c=1)
|
|
display.text("Press [KEY] button to cycle NeoPixel LED", 25, 205, 1)
|
|
display.text("Press [BOOT] button to force display refresh", 25, 220, 1)
|
|
|
|
# Footer / Last action
|
|
display.line(10, 245, 390, 245, 1)
|
|
display.text(f"Event: {last_action_str}", 15, 255, 1)
|
|
|
|
# Send buffer to screen
|
|
display.show()
|
|
|
|
# Capture the first frame as a screenshot so we can verify it
|
|
if not screenshot_saved:
|
|
try:
|
|
display.save_screenshot('screenshot_demo.pbm')
|
|
screenshot_saved = True
|
|
except Exception as e:
|
|
print(f"Failed to save screenshot_demo: {e}")
|
|
|
|
# Update NeoPixel animation smoothly (runs every 50ms)
|
|
mode_type = led_modes[current_mode_idx][2]
|
|
if mode_type == "breath":
|
|
led.update_breathing(1.5)
|
|
elif mode_type == "rainbow":
|
|
led.update_rainbow(0.4)
|
|
else:
|
|
led.off()
|
|
|
|
time.sleep_ms(50)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|