这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » [Let'sDo第3期]DIY一个电子测光表-自由发挥贴-感应舵机监控日历时钟物

共2条 1/1 1 跳转至

[Let'sDo第3期]DIY一个电子测光表-自由发挥贴-感应舵机监控日历时钟物联网光照测光表(妈妈说标题长的帖子才有人看)

菜鸟
2024-12-05 15:52:49     打赏

在上一个帖子[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秒

IMG_20241205_142730.jpg


高工
2024-12-06 07:07:54     打赏
2楼

原来你是如此的优秀


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]