在上一个帖子[Let'sDo第3期]DIY一个电子测光表-自由发挥贴-光照物联网监控日历时钟-电子产品世界论坛
实现之后,反正线接都接了,再接个舵机吧。
通过光照感应控制舵机,比按键触发要省心一点。
另外在屏幕增加显示快门和光圈数据。
这里的快门和光圈需要计算,那么要增加数学计算库
import math
之后增加计算代码:
lux=loaded_data.get("photocell_val", 0) lux_text= "%.0fLux " % lux # print(lux_text) # EV ev = 2 + math.log(lux / 10, 2) ev_text= "%.0fev " % ev # print(ev_text) # 快门 km = (sets_gq[index_gq] * sets_gq[index_gq]) / (4 * (lux / 10)) km_text= "%.0fkm " % km # print(km_text) photocell_label.text = lux_text + ev_text + km_text
注意这里的photocell_val数据来自于另一个物联网设备ESP32-C6采集到的光照数据,推送过来的MQTT消息。
还需要引入两个库来控制舵机
import pwmio import adafruit_motor.servo
创建实例并指定初始值
servo_1 = adafruit_motor.servo.Servo(pwmio.PWMOut(board.A4, frequency=50), min_pulse=1000, max_pulse=2000) servo_1.angle = 0
可以看到,上面把舵机信号线接到了A4引脚,注意舵机需要用5V单独供电,用开发板供电是不行滴。
完整代码如下:
import time import board import terminalio import displayio import digitalio from adafruit_display_text import label from adafruit_bitmap_font import bitmap_font import json # 导入json库以解析JSON消息 import os import ssl import wifi import socketpool import adafruit_minimqtt.adafruit_minimqtt as MQTT import adafruit_ntp import rtc import pwmio import adafruit_motor.servo import math status = "boot" # 先创建一个status变量,用来在设备启动时获取天气信息 flash_screen = False # 刷新屏幕标志位 last_second = 61 # 记录上一秒的值,用来实现时间刷新 servo_1 = adafruit_motor.servo.Servo(pwmio.PWMOut(board.A4, frequency=50), min_pulse=1000, max_pulse=2000) servo_1.angle = 0 # WiFi和MQTT设置 aio_username = os.getenv("aio_username") aio_key = os.getenv("aio_key") wifi_ssid = os.getenv("CIRCUITPY_WIFI_SSID") wifi_password = os.getenv("CIRCUITPY_WIFI_PASSWORD") mqtt_broker = os.getenv('broker') mqtt_port = os.getenv('port') publish = os.getenv('publish') subscribe = os.getenv('subscribe') device = os.getenv('device') # 初始化LED和按钮 led = digitalio.DigitalInOut(board.LED) led.direction = digitalio.Direction.OUTPUT buttonD0 = digitalio.DigitalInOut(board.D0) buttonD0.switch_to_input(pull=digitalio.Pull.UP) #模拟启动拍摄 buttonD1 = digitalio.DigitalInOut(board.D1) buttonD1.switch_to_input(pull=digitalio.Pull.UP) #改变光圈 buttonD2 = digitalio.DigitalInOut(board.D2) buttonD2.switch_to_input(pull=digitalio.Pull.UP) # 初始化显示屏 display = board.DISPLAY display_group = displayio.Group() # display.root_group = display_group # 设置显示屏背景 width = board.DISPLAY.width height = board.DISPLAY.height color_bitmap = displayio.Bitmap(width, height, 1) # 1-bit color depth color_palette = displayio.Palette(4) # Need 2 colors for the palette (black and red) color_palette[0] = 0x000000 # Black (background color, but we won't use it since we're setting the whole bitmap to red) color_palette[1] = 0xFF0000 # Red (will be used as the background color) color_palette[2] = 0x00FF00 color_palette[3] = 0x0000FF # Fill the bitmap with the red color from the palette (index 1) color_bitmap.fill(1) bg_sprite = displayio.TileGrid(color_bitmap, pixel_shader=color_palette) display_group.append(bg_sprite) FONTSCALE = 2 # 文本缩放比例 oppo_sans_20 = bitmap_font.load_font("/font/OPlusSans3.0-Medium-20.bdf") oppo_sans_64 = bitmap_font.load_font("/font/OPlusSans3.0-Medium-64.bdf") # 创建一个用于显示文本对象 date_label = label.Label(font=oppo_sans_20, text="", color=color_palette[0]) date_label.x = 10 date_label.y = 10 display_group.append(date_label) device_label = label.Label(font=oppo_sans_20, text=device, color=color_palette[2]) device_label.x = 50 device_label.y = 10 display_group.append(device_label) week_label = label.Label(font=oppo_sans_20, text="", color=color_palette[0]) week_label.x = 100 # 移动到右侧以避免与date_label重叠 week_label.y = 10 display_group.append(week_label) publish_label = label.Label(font=oppo_sans_20, text=publish, color=color_palette[3]) publish_label.x = 148 publish_label.y = 10 # 下移到第四行 display_group.append(publish_label) # 第二行标签 timeL = label.Label(font=oppo_sans_64, text="00:00", color=color_palette[0]) timeL.x = (width // 2) - (timeL.width // 2) # 居中显示 timeL.y = 44 # 稍微下移以避免与第一行重叠 display_group.append(timeL) # 第三行标签 device_label = label.Label(font=oppo_sans_20, text="", color=color_palette[2]) device_label.x = 10 device_label.y = 80 # 下移到第三行 display_group.append(device_label) subscribe_label = label.Label(font=oppo_sans_20, text="To:"+subscribe, color=color_palette[2]) subscribe_label.x = 120 # 移动到右侧以避免与publish_label重叠 subscribe_label.y = 80 display_group.append(subscribe_label) # 第四行标签(考虑到字体大小,可能需要更多的垂直空间) time_rev = label.Label(font=oppo_sans_20, text="00:00:00", color=color_palette[0]) time_rev.x = 10 time_rev.y = 100 # 调整位置以避免重叠 display_group.append(time_rev) photocell_label = label.Label(font=oppo_sans_20, text="%.2f Lux"%0, color=0xD9D7C9) photocell_label.x =100 photocell_label.y = 110 display_group.append(photocell_label) state_label = label.Label(font=oppo_sans_20, text="", color=color_palette[0]) state_label.x = 5 state_label.y = 125 # 调整位置以避免重叠 display_group.append(state_label) #光圈可选参数 sets_gq = [2, 2.8, 4, 5.6] #默认光圈初始值为4 index_gq=2 def updateDisplay(): display.root_group = display_group updateDisplay() # 连接到WiFi print(f"Connecting to {wifi_ssid}") state_label.text="Con.ingSSID" time.sleep(0.05) updateDisplay() wifi.radio.connect(wifi_ssid, wifi_password) print(f"Connected to {wifi_ssid}!") state_label.text="SSID Get" updateDisplay() time.sleep(0.05) # 创建Socket池和SSL上下文 pool = socketpool.SocketPool(wifi.radio) ssl_context = ssl.create_default_context() ntp = adafruit_ntp.NTP(pool, server="ntp2.aliyun.com",tz_offset=8, cache_seconds=28800) rtc.RTC().datetime = ntp.datetime # 创建MQTT客户端并设置回调 mqtt_client = MQTT.MQTT( broker=mqtt_broker, port=mqtt_port, username=aio_username, password=aio_key, socket_pool=pool, ssl_context=ssl_context, ) def connected(client, userdata, flags, rc): print("Connected to MQTT Server!") state_label.text="MQTT Coned" updateDisplay() time.sleep(0.05) client.subscribe(subscribe) # 订阅主题 def disconnected(client, userdata, rc): print("Disconnected from MQTT Server!") state_label.text="MQTT Disc." updateDisplay() time.sleep(0.05) def message(client, topic, message): print(f"New message on topic {topic}: {message}") state_label.text="New msg" updateDisplay() try: loaded_data = json.loads(message) # print(loaded_data) device_label.text = "F:" + loaded_data.get("Device", "Unknown") lux=loaded_data.get("photocell_val", 0) lux_text= "%.0fLux " % lux # print(lux_text) # EV ev = 2 + math.log(lux / 10, 2) ev_text= "%.0fev " % ev # print(ev_text) # 快门 km = (sets_gq[index_gq] * sets_gq[index_gq]) / (4 * (lux / 10)) km_text= "%.0fkm " % km # print(km_text) photocell_label.text = lux_text + ev_text + km_text # print(photocell_label.text) time_rev.text = loaded_data.get("time", "%02d:%02d:%02d" % (t.tm_hour, t.tm_min, t.tm_sec)) if lux<30: servo_1.angle =0 else: servo_1.angle =180 except: pass def get_wday(wday): """ 根据时间结构体获取到的tm_wday属性,判断是星期几 """ if(wday == 0): return "周一" elif(wday == 1): return "周二" elif(wday == 2): return "周三" elif(wday == 3): return "周四" elif(wday == 4): return "周五" elif(wday == 5): return "周六" elif(wday == 6): return "周日" rtc.RTC().datetime = ntp.datetime # 使用ntp时间更新系统时间。 mqtt_client.on_connect = connected mqtt_client.on_disconnect = disconnected mqtt_client.on_message = message # 连接到MQTT服务器 print("Connecting to MQTT Server...") state_label.text="Co.ingMQTT" updateDisplay() mqtt_client.connect() last_time_update = time.monotonic() # 使用单调时间以避免时间跳跃 # 主循环 def update_ntp_time(): rtc.RTC().datetime = ntp.datetime while True: mqtt_client.loop(timeout=1) update_ntp_time() t = time.localtime() timeL.x = (width // 2) - (timeL.width // 2) # 居中显示 if (status == "boot" or t.tm_min%2 == 0): date_label.text = "%2d/%2d" % (t.tm_mon, t.tm_mday) # 更新日期标签 week_label.text = get_wday(t.tm_wday) # 更新星期标签 status = "updated" # 更新 status 为 updated flash_screen = True # 刷新屏幕标志位置位 # 如果过了1秒,刷新屏幕 if (t.tm_sec is not last_second): flash_screen = True # 刷新屏幕标志位置位 last_second = t.tm_sec # 更新last_second if (t.tm_sec %1 == 0): # 每隔1秒 更新一次时钟标签,用于动态显示 timeL.text = "%02d:%02d" % (t.tm_hour, t.tm_min) # timeL.text = "%02d:%02d:%02d" % (t.tm_hour, t.tm_min, t.tm_sec) timeL.color = 0x000000 else: timeL.text = "%02d:%02d" % (t.tm_hour, t.tm_min) # timeL.text = "%02d:%02d:%02d" % (t.tm_hour, t.tm_min, t.tm_sec) timeL.color = 0xD9D7C9 if (flash_screen): updateDisplay() # 刷新屏幕 flash_screen = False # time.sleep(0.05) # 休眠0.2秒