238 lines
6.6 KiB
Python
238 lines
6.6 KiB
Python
import time
|
||
import uasyncio as asyncio
|
||
import machine
|
||
import gc
|
||
import neopixel
|
||
|
||
from config import *
|
||
from wifi import connect_wifi
|
||
from timeutil import setup_rtc
|
||
from sensors import Sensors
|
||
from display import OLED
|
||
from webserver import WebServer
|
||
|
||
|
||
# Set CPU speed
|
||
machine.freq(CPU_FREQ)
|
||
|
||
#HOSTNAME = "Testname"
|
||
|
||
# Connect WiFi
|
||
print("Version = ", VERSION)
|
||
print("Hostname = ", HOSTNAME)
|
||
wlan = connect_wifi(SSID, PASSWORD, HOSTNAME)
|
||
rtc = setup_rtc(TZ_OFFSET)
|
||
print("Server running on http://" + wlan.ifconfig()[0])
|
||
|
||
#TANK_CAPACITY_L = 3000
|
||
print("Heart Beat =", HEARTBEAT)
|
||
print("Tank Volume =", TANK_CAPACITY_L)
|
||
# Init sensors and display
|
||
sensors = Sensors()
|
||
if DISPLAY_ON:
|
||
oled = OLED()
|
||
|
||
sensors.test_pin1.on()
|
||
sensors.test_pin2.on()
|
||
sensors.test_pin0.on()
|
||
# Capture boot time
|
||
start_time = time.time()
|
||
|
||
# print("Boot timestamp:", start_time)
|
||
|
||
# Set tank full reference from current reading at boot
|
||
|
||
#MAX_PRESSURE_KPA = sensors.read_pressure()
|
||
time.sleep_ms(250)
|
||
sensors.test_pin1.off()
|
||
sensors.test_pin2.off()
|
||
sensors.test_pin0.off()
|
||
|
||
print("✔ Config loaded.")
|
||
print("Initial MAX_PRESSURE_KPA =", MAX_PRESSURE_KPA, "KPA")
|
||
print("Initial Known Depth =", KNOWN_DEPTH_M, "m")
|
||
#print("Initial Known Pressure =", MAX_PRESSURE_KPA)
|
||
|
||
def rssi_percent():
|
||
rssi = wlan.status("rssi")
|
||
rssi = max(-100, min(-50, rssi))
|
||
return int((rssi + 100) * 2)
|
||
|
||
class HeartbeatFadeNeoPixel:
|
||
def __init__(self, neopixel_obj, pixel_index=0, color=(255, 0, 0),
|
||
min_brightness=5, max_brightness=100,
|
||
step=2, interval_ms=20):
|
||
|
||
self.np = neopixel_obj
|
||
self.index = pixel_index
|
||
self.color = color
|
||
|
||
self.min_brightness = min_brightness
|
||
self.max_brightness = max_brightness
|
||
self.step = step
|
||
self.interval = interval_ms
|
||
|
||
self.brightness = min_brightness
|
||
self.direction = 1 # 1 = fade up, -1 = fade down
|
||
self.last_time = time.ticks_ms()
|
||
|
||
def apply_brightness(self, c, level):
|
||
r, g, b = c
|
||
factor = level / 100
|
||
return (int(r * factor), int(g * factor), int(b * factor))
|
||
|
||
def update(self):
|
||
now = time.ticks_ms()
|
||
if time.ticks_diff(now, self.last_time) >= self.interval:
|
||
self.last_time = now
|
||
|
||
# Update brightness
|
||
self.brightness += self.direction * self.step
|
||
|
||
# Bounce at limits
|
||
if self.brightness >= self.max_brightness:
|
||
self.brightness = self.max_brightness
|
||
self.direction = -1
|
||
|
||
if self.brightness <= self.min_brightness:
|
||
self.brightness = self.min_brightness
|
||
self.direction = 1
|
||
|
||
# Apply brightness
|
||
self.np[self.index] = self.apply_brightness(self.color, self.brightness)
|
||
self.np.write()
|
||
|
||
|
||
# ============================================================
|
||
# NEOPIXEL SETUP
|
||
# ============================================================
|
||
|
||
STRIP_PIN = 17
|
||
STRIP_LEDS = 3
|
||
strip = neopixel.NeoPixel(machine.Pin(STRIP_PIN), STRIP_LEDS)
|
||
|
||
SINGLE_PIN = 28
|
||
single = neopixel.NeoPixel(machine.Pin(SINGLE_PIN), 1)
|
||
|
||
# ============================================================
|
||
# BUTTONS
|
||
# ============================================================
|
||
|
||
button_pins = [20, 21, 22]
|
||
buttons = [machine.Pin(pin, machine.Pin.IN, machine.Pin.PULL_UP) for pin in button_pins]
|
||
|
||
# ============================================================
|
||
# COLOR PALETTE
|
||
# ============================================================
|
||
|
||
colors = [
|
||
(0, 0, 0), # Off
|
||
(255, 0, 0), # Red
|
||
(0, 255, 0), # Green
|
||
(0, 0, 255), # Blue
|
||
(255, 255, 255), # White
|
||
]
|
||
|
||
# ============================================================
|
||
# STRIP STATE
|
||
# ============================================================
|
||
|
||
color_index = [0, 0, 0]
|
||
brightness = [50, 50, 50]
|
||
last_state = [1, 1, 1]
|
||
press_time = [0, 0, 0]
|
||
|
||
# ============================================================
|
||
# HEARTBEAT CONFIG (NOW HAS MIN + MAX)
|
||
# ============================================================
|
||
|
||
FLASH_COLOR_INDEX = 1 # Palette color
|
||
FLASH_MIN = 1 # << lowest brightness (0–100)
|
||
FLASH_MAX = 10 # << highest brightness
|
||
FLASH_STEP = 0.2 # fade speed
|
||
FLASH_INTERVAL_MS = 20 # smoothness
|
||
|
||
heartbeat = HeartbeatFadeNeoPixel(
|
||
neopixel_obj=single,
|
||
pixel_index=0,
|
||
color=colors[FLASH_COLOR_INDEX],
|
||
min_brightness=FLASH_MIN,
|
||
max_brightness=FLASH_MAX,
|
||
step=FLASH_STEP,
|
||
interval_ms=FLASH_INTERVAL_MS
|
||
)
|
||
|
||
# ============================================================
|
||
# HELPERS
|
||
# ============================================================
|
||
|
||
def apply_brightness(color, level):
|
||
r, g, b = color
|
||
factor = level / 100
|
||
return (int(r * factor), int(g * factor), int(b * factor))
|
||
|
||
def update_strip():
|
||
for i in range(STRIP_LEDS):
|
||
strip[i] = apply_brightness(colors[color_index[i]], brightness[i])
|
||
strip.write()
|
||
|
||
# ============================================================
|
||
# INITIAL
|
||
# ============================================================
|
||
|
||
update_strip()
|
||
|
||
async def sensor_task():
|
||
global MAX_PRESSURE_KPA
|
||
while True:
|
||
gc.collect()
|
||
sensors.check_buttons()
|
||
# heartbeat.update()
|
||
if AVERAGE:
|
||
pressure = sensors.read_pressure_avg()
|
||
else:
|
||
pressure = sensors.read_pressure()
|
||
#sensors.test_pin1.on()
|
||
if sensors.tank_full:
|
||
sensors.tank_full = False
|
||
MAX_PRESSURE_KPA = sensors.read_pressure()
|
||
|
||
if HEARTBEAT:
|
||
# sensors.test_pin2.on()
|
||
# time.sleep_ms(100)
|
||
# sensors.test_pin2.off()
|
||
# color_index[i] = 0
|
||
i=0
|
||
color_index[i] = (color_index[i] + 1) % len(colors)
|
||
update_strip()
|
||
# time.sleep_ms(100)
|
||
|
||
else:
|
||
# sensors.test_pin2.off()
|
||
# color_index[i] = 3
|
||
update_strip()
|
||
# time.sleep_ms(100)
|
||
|
||
percent = pressure / MAX_PRESSURE_KPA
|
||
depth_mm = percent * MAX_DEPTH_M * 1000
|
||
sensors.tank_percentage = percent * 100
|
||
|
||
if DISPLAY_ON:
|
||
oled.show(
|
||
rtc,
|
||
pressure,
|
||
sensors.tank_percentage,
|
||
sensors.cpu_temp(),
|
||
rssi_percent(),
|
||
depth_mm
|
||
)
|
||
await asyncio.sleep(1)
|
||
|
||
async def main():
|
||
asyncio.create_task(sensor_task())
|
||
server = WebServer(wlan, sensors, start_time, MAX_CONNECTIONS)
|
||
srv = await asyncio.start_server(server.handle, "0.0.0.0", 80)
|
||
async with srv:
|
||
await asyncio.Event().wait()
|
||
|
||
asyncio.run(main()) |