diff --git a/lib/vl53l1x/examples/radar_screen.py b/lib/vl53l1x/examples/radar_screen.py index 4965ef66..ca1c9c2e 100644 --- a/lib/vl53l1x/examples/radar_screen.py +++ b/lib/vl53l1x/examples/radar_screen.py @@ -2,77 +2,80 @@ Displays a real-time distance bar on the screen. The closer the object, the longer and brighter the bar, similar to a car parking sensor. -Adapted for a round display bezel. +Adapted for a round display bezel using steami_screen widgets. """ from time import sleep_ms +import micropython import ssd1327 from machine import I2C, SPI, Pin +from steami_screen import DARK, GRAY, LIGHT, RED, Screen, SSD1327Display from vl53l1x import VL53L1X +# === Constants === MAX_DISTANCE_MM = 1000 -# Layout constants for the round screen -BAR_X = 24 -BAR_Y = 70 -BAR_MAX_WIDTH = 80 -BAR_HEIGHT = 15 -TEXT_LBL_X = 28 -TEXT_LBL_Y = 35 -TEXT_VAL_X = 36 -TEXT_VAL_Y = 50 -TEXT_OUT_X = 16 # Shifted left to fit the longer "Out of range" text - -i2c = I2C(1) -tof = VL53L1X(i2c) - +# === Display === spi = SPI(1) dc = Pin("DATA_COMMAND_DISPLAY") res = Pin("RST_DISPLAY") cs = Pin("CS_DISPLAY") +display = SSD1327Display(ssd1327.WS_OLED_128X128_SPI(spi, dc, res, cs)) +screen = Screen(display) + +# === Sensor === +i2c = I2C(1) +tof = VL53L1X(i2c) + + +@micropython.native +def compute_display(distance): + """Compute proximity and color from distance value. + + Returns (proximity, color) or (None, None) if out of range. + """ + if distance > MAX_DISTANCE_MM: + return None, None + proximity = MAX_DISTANCE_MM - distance + if proximity > 700: + color = RED + elif proximity > 400: + color = LIGHT + else: + color = GRAY + return proximity, color -display = ssd1327.WS_OLED_128X128_SPI(spi, dc, res, cs) try: while True: distance = tof.read() - # Clear the display frame buffer - display.fill(0) - - # Clamp distance to maximum range and compute integer proximity - clamped_dist = max(0, min(distance, MAX_DISTANCE_MM)) - proximity = MAX_DISTANCE_MM - clamped_dist + screen.clear() - # Map proximity to bar width (max 80px) and brightness (max 15) - bar_width = (80 * proximity) // MAX_DISTANCE_MM - brightness = (15 * proximity) // MAX_DISTANCE_MM + proximity, color = compute_display(distance) - # If the object is within the detection range, ensure minimum visibility - if distance <= MAX_DISTANCE_MM: - bar_width = max(1, bar_width) - brightness = max(1, brightness) + # Draw gauge first so that title/value text layers on top of the arc + if proximity is None: + screen.gauge(0, min_val=0, max_val=MAX_DISTANCE_MM, color=DARK) + else: + screen.gauge(proximity, min_val=0, max_val=MAX_DISTANCE_MM, color=color) - # Draw the outline box (1 pixel larger than the max bar size) at max brightness - display.framebuf.rect(BAR_X - 1, BAR_Y - 1, BAR_MAX_WIDTH + 2, BAR_HEIGHT + 2, 15) - # Draw the distance bar centered: x=24, y=70, max_width=80, height=15 - display.framebuf.fill_rect(BAR_X, BAR_Y, bar_width, BAR_HEIGHT, brightness) + screen.title("RADAR") - # Display distance or "Out of range" - if distance > MAX_DISTANCE_MM: - display.text("Out of range", TEXT_OUT_X, TEXT_VAL_Y, 15) + if proximity is None: + screen.value("----", unit="mm") + screen.subtitle("Out of range") else: - display.text("{} mm".format(distance), TEXT_VAL_X, TEXT_VAL_Y, 15) - - # Send the buffer to the physical screen - display.show() + screen.value(str(distance), unit="mm") + screen.subtitle("Proximity") + screen.show() sleep_ms(50) except KeyboardInterrupt: pass + finally: - # Clear the screen on exit or error - display.fill(0) - display.show() + screen.clear() + screen.show()