from machine import Pin, I2C
import ssd1306
import time
import uasyncio as asyncio
from umenu import ValueItem, Menu, EnumItem, MenuScreen, CustomItem, SubMenuItem, BackItem, CallbackItem, InfoItem
from rotary_irq_rp2 import RotaryIRQ
import framebuf
import icons
i2c = I2C(1, scl=Pin(7), sda=Pin(6))
display = ssd1306.SSD1306_I2C(128, 64, i2c)
# ======= 显示封面 =======
cover_fb = framebuf.FrameBuffer(icons.cover, 115, 17, framebuf.MONO_HLSB)
display.fill(0)
display.blit(cover_fb, 6, 20)
display.show()
time.sleep(2) # 停 2 秒
class RcState:
def __init__(self):
self.fire_temp = 200 # 火温
self.bean_temp = 180 # 风温
self.wind_lev = 100 # 风速等级
self.des_temp = 220 # 目标温度
self.time = 100 # 时钟
self.wifi_status = False
class WifiScreen(CustomItem):
def __init__(self, name):
super().__init__(name)
self.status = False
def select(self):
return self.parent
def draw(self):
self.display.fill(0)
self.display.rect(0, 0, self.display.width, self.display.height, 1)
self._centered_text('MODE: WIFI', 12, 1)
self._centered_text_limit('freewolf_wifiabcd', 26, 1)
self._centered_text('225.210.110.230', 40, 1)
self.display.show()
def get_status(self):
return self.status
def activate(self):
self.status = not self.status
self.get_status()
def _centered_text(self, text, y, c):
# text = text[:10] + "..." if len(text) > 10 else text
x = int(self.display.width/2 - len(text)*8/2)
self.display.text(text, x, y, c)
def _centered_text_limit(self, text, y, c):
text = text[:10] + "..." if len(text) > 10 else text
x = int(self.display.width/2 - len(text)*8/2)
self.display.text(text, x, y, c)
class HomeScreen:
def __init__(self, controller):
self.controller = controller
def draw(self):
# 清屏
self.controller.display.fill(0)
fire_fb = framebuf.FrameBuffer(icons.fire, 12, 12, framebuf.MONO_HLSB)
temp_fb = framebuf.FrameBuffer(icons.temp, 12, 12, framebuf.MONO_HLSB)
clock_fb = framebuf.FrameBuffer(icons.clock, 12, 12, framebuf.MONO_HLSB)
wind_fb = framebuf.FrameBuffer(icons.wind, 12, 12, framebuf.MONO_HLSB)
# 在不同位置绘制
self.controller.display.blit(temp_fb, 0, 2) # 温度
self.controller.display.blit(fire_fb, 0, 48) # 左上角
self.controller.display.blit(clock_fb, 64, 26) # 再画一个 fire
self.controller.display.blit(wind_fb, 0, 26) # 再画一个 fire
self.controller.display.text(f"{self.controller.state.fire_temp} / {self.controller.state.bean_temp}", 20, 4, 1)
self.controller.display.text(f"{self.controller.state.wind_lev} {self.controller.state.time}", 20, 28, 1)
self.controller.display.text(f"{self.controller.state.des_temp}", 20, 51, 1)
# 一次性刷新
self.controller.display.show()
class Controller :
def __init__(self, display, menu):
self.state = RcState() # 状态
self.menu = menu
self.memu_lev = 0
self.display = display
self.rotary = RotaryIRQ(pin_num_clk=2, pin_num_dt=3, min_val=0, max_val=10, incr=1, pull_up=True)
self.home_screen = HomeScreen(self)
def click(self, pin):
print('click')
time.sleep_ms(50)
if self.memu_lev == 0:
print(self.menu)
self.menu.draw()
self.memu_lev = 1
print('进入菜单')
elif self.memu_lev == 1:
self.menu.click()
async def run(self):
self.home_screen.draw()
r = RotaryIRQ(14, 15, reverse=True)
val_old = r.value()
while True:
val_new = r.value()
if val_old != val_new:
print(f"Rotary value changed: {-1 if val_old > val_new else 1}")
if self.memu_lev is not 0:
self.menu.move(-1 if val_old > val_new else 1)
val_old = val_new
asyncio.sleep_ms(50)
# ======= 菜单 =======
menu = Menu(display, 4, 12)
controller = Controller(display, menu)
def stop():
time.sleep_ms(50)
print("Stopping...")
controller.home_screen.draw()
controller.memu_lev = 0
controller.menu.reset_only()
def back():
time.sleep_ms(50)
controller.home_screen.draw()
controller.memu_lev = 0
controller.menu.reset_only()
menu.set_screen(MenuScreen('Main Menu')
.add(CallbackItem("Back", back, return_home=True))
.add(CallbackItem("Stop", stop, return_home=True))
.add(ValueItem('Fire', 0, 50, 250, 1, print))
.add(ValueItem('Wind', 0, 0, 10, 1, print))
.add(EnumItem("ROR", ['Manual', 'C1', 'C2'], print, 0))
.add(WifiScreen('Wifi'))
.add(InfoItem('Version', 'v1.0'))
)
sw = Pin(11, Pin.IN, Pin.PULL_UP)
def btn_click(pin):
time.sleep_ms(50)
if pin.value() == 0:
controller.click(pin)
sw.irq(btn_click, Pin.IRQ_FALLING)
asyncio.run(controller.run())