[作品提交] 【得捷电子Follow me第2期】任务5:通过网络控制WS2812B

sipower   2023-9-2 19:02 楼主

 

本次任务是结合123,在手机上通过网络控制板载Neopixel LED的显示和颜色切换,屏幕同步显示状态。

本来我原计划采用APP Inventor配合板子进行TCP通讯实现任务要求的功能,但是这个只适合安卓手机,普适性差。后来看见坛友大佬ttxiaotaoge的帖子《【得捷电子Follow me第2期】CircuitPython入门到完成任务1-5详细教程》后,感觉这个网页的方法非常棒,只需浏览器就能操作,不挑系统,索性可耻的抄作业了。大佬帖子链接:

https://bbs.eeworld.com.cn/thread-1253916-1-1.html

抄作业第一步,就是学习分析代码。由于大佬用的板子不是这次官方要求的Adafruit ESP32-S3 TFT Feather,需要适配硬件参数。

第一步修改屏幕,这个改起来很简单,原来的屏蔽掉,直接用系统原配即可。如下代码。

190023sbkkhqoxyzxox51i.png

然后添加WiFi连接,我猜测大佬的板子是支持WiFi记忆的,所以上电不需要再做连接设置。

190023f7pzl7rr7b7rypg7.png

接下来修改按键和RGB灯的配置信息,其中按键不要忘了设置上拉哦,如下图红框所示。

190023nx5dtqg8p8d2i5p2.png

最后就是调整显示文字的格式,不然会显示不全。

190023lhoorfhxnyotjxql.png

代码改好后直接运行就OK了,效果如下图所示。

190023buuk9ihoikihf0zt.jpg

然后用电脑浏览器打开网址:

http://192.168.31.110:1080/client

就可在网页中改变RGB灯颜色了,如下图。

190023vi0z9dk0rr9pch6z.png

当然也可以在手机浏览器中打开这个网页,如下图。

190023fbd21pm2bb2mp2cb.jpg

最后的最后,我对代码进行小幅修改,删掉了天气和时间显示,只显示RGB灯的状态,录了一段视频,放在下面了。

感谢得捷电子和EEWORLD提供的这次机会,也希望在接下来的活动中,提供更多好玩的板子和题目,让大家一起快乐搞机。

具体代码如下。

import board
import digitalio
import terminalio
import busio
import neopixel
import rtc
import time
#网络相关库
import wifi
import socketpool
import ssl
import adafruit_requests
from adafruit_httpserver import Server, Request, Response, Websocket, GET
#显示相关库
import displayio
from adafruit_bitmap_font import bitmap_font
from adafruit_display_text.label import Label


display = board.DISPLAY
board.DISPLAY.brightness = 0.5
board.DISPLAY.rotation = 0

my_display_group = displayio.Group()
print("Display Init Success\n")
# displayDriver_End

wifi.radio.connect('xxxxxxxxxxxxxxxxxx', 'xxxxxxxxxxxxxxxxxxxxxx')
print(f"My IP address: {wifi.radio.ipv4_address}")
# WiFi状态查询,未连接WIFI则不联网更新数据,开启AP模式
wificonnect_State = wifi.radio.connected
print("wificonnect_State",wificonnect_State)
if(wificonnect_State == False):
    wifi.radio.start_ap(ssid = 'Esp32', password = '')
Wifi_Mode = 'STA' if(wificonnect_State == True) else 'AP'
Wifi_ip = wifi.radio.ipv4_address if(wificonnect_State == True) else wifi.radio.ipv4_address_ap


#构造函数——按键控制RGB
i = 0
Enter_flag = False
def Button0_Work():
    global i
    global Enter_flag
    global RGBr, RGBg, RGBb
    if(Button0.value == False and Enter_flag == False):
        time.sleep(0.05)#延时消抖
        if(Button0.value == False and Enter_flag == False):
            i+=1
            RGBr, RGBg, RGBb = 8*i, 8*i, 8*i
            pixels.fill((RGBr, RGBg, RGBb))
            Enter_flag = True
            print("pixels change\n",i)
            if(i>20):
                i = 0            
    elif(Button0.value == True and Enter_flag == True):
        time.sleep(0.05)#延时消抖
        if(Button0.value == True and Enter_flag == True):
            Enter_flag = False
        
 
# RGBDriver_Begin
pixel_pin = board.NEOPIXEL
num_pixels = 1
pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.2, auto_write=True)
pixels.fill((8, 8, 8))
print("RGBDriver Init Success\n")
# RGBDriver_End

# ButtonDriver_Begin
Button0 = digitalio.DigitalInOut(board.BUTTON)
Button0.direction = digitalio.Direction.INPUT
Button0.pull = digitalio.Pull.UP
print("Button0 Init Success\n")
# ButtonDriver_End

# 添加中文字体
font_file = "opposans_m_12.pcf"
font_Chinese = bitmap_font.load_font(font_file)
print("fonts Init Success\n")

# 显示WiFi IP 和 Mode
text_Wifi = "WiFi状态:{}\n{}:1080/client".format(Wifi_Mode,Wifi_ip)#更新RGB状态
text_Wifi_title = Label(font_Chinese, text=text_Wifi, color = 0xffffff)
text_Wifi_title.x = 5
text_Wifi_title.y = 10
my_display_group.append(text_Wifi_title)

# 显示RGB状态,和按键状态,RGB文字同RGB灯颜色
RGBr, RGBg, RGBb = 255,255,255
text_RGB = "RGB灯颜色:{:03}:{:03}:{:03}\n按键次数:{:02}".format(RGBr, RGBg, RGBb, i)#更新RGB状态
text_RGB_title = Label(font_Chinese, text=text_RGB, color = (RGBr, RGBg, RGBb))
text_RGB_title.x = 5
text_RGB_title.y = 70
my_display_group.append(text_RGB_title)
# ShowChinese_End

# GetandSetHttp_Begin
pool = socketpool.SocketPool(wifi.radio) # 网络管理,触发http操作
server = Server(pool, debug=True)

websocket: Websocket = None
next_message_time = time.monotonic()#数据更新时钟,以秒为单位变化

HTML_TEMPLATE = """
<html lang="en">
    <head>
    <!--注释:强制html使用utf-8编码-->
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
        <title>Web控制中心</title>
    </head>
    <body>
        <p>按键状态: <strong>-</strong></p>
        <p>RGB 颜色: <input type="color"></p>
        <script>
            const Button_count = document.querySelector('strong');
            const colorPicker = document.querySelector('input[type="color"]');

            let ws = new WebSocket('ws://' + location.host + '/connect-websocket');

            ws.onopen = () => console.log('WebSocket connection opened');
            ws.onclose = () => console.log('WebSocket connection closed');
            ws.onmessage = event => Button_count.textContent = event.data;
            ws.onerror = error => Button_count.textContent = error;

            colorPicker.oninput = debounce(() => ws.send(colorPicker.value), 200);
            <!--注释:创建一个延时函数,消除RGB调整抖动-->
            function debounce(callback, delay = 1000) {
                let timeout
                return (...args) => {
                    clearTimeout(timeout)
                    timeout = setTimeout(() => {
                    callback(...args)
                  }, delay)
                }
            }
        </script>
    </body>
</html>
"""
#创建Http服务器
@server.route("/client", GET)
def client(request: Request):
    return Response(request, HTML_TEMPLATE, content_type="text/html")
#创建websocket服务
@server.route("/connect-websocket", GET)
def connect_client(request: Request):
    global websocket  # pylint: disable=global-statement
    if websocket is not None:
        print("websocket.close")
        websocket.close()  # Close any existing connection
    websocket = Websocket(request)
    return websocket

#UI show Begin
display.show(my_display_group)
print("display show Success\n")
#UI show End

#判断网络模式,设定location.host
if(wificonnect_State == True):
    server.start(str(wifi.radio.ipv4_address), port = 1080)
else:
    server.start(str(wifi.radio.ipv4_address_ap), port = 1080)   
# GetandSetHttp_Begin
time.sleep(2)#等待2秒进入循环
while True:
    #httpSeverLoop_Begin
    server.poll()
    # Check for incoming messages from client
    if websocket is not None:
        if (data := websocket.receive(True)) is not None:
            RGBr, RGBg, RGBb = int(data[1:3], 16), int(data[3:5], 16), int(data[5:7], 16)
            pixels.fill((RGBr, RGBg, RGBb))

    # Send a message every second
    if websocket is not None and next_message_time < time.monotonic():
        time.sleep(0.2)
        if websocket is not None:
            Button_count = i
            websocket.send_message(str(Button_count))
            next_message_time = time.monotonic() + 1
    #httpSeverLoop_End
    
    #Other_Loop
    text_RGB_title.color = (RGBr, RGBg, RGBb)
    text_RGB_title.text = "RGB灯颜色:{:03}:{:03}:{:03}\n按键次数:{:02}".format(RGBr, RGBg, RGBb, i)#更新RGB状态
    Button0_Work()

实际效果如下视频。

004

 

还有一个问题,我的板子每次启动都先花屏一下,如下图,然后再正常显示,不知道是不是被修过的原因,已经收到板子的同学们,你们的板子有这个情况吗?

190023je2qq26hghtyzzhx.jpg

回复评论 (2)

进入系统后,先清一下屏,可能就不会出现花屏的现象了。

点赞  2023-9-5 09:52

666大佬,牛逼

点赞  2023-9-8 09:43
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复