601|0

11

帖子

1

TA的资源

一粒金砂(中级)

楼主
 

【得捷电子Follow me第2期】CircuitPython完成任务1-5作业提交 [复制链接]

  本帖最后由 ttxiaotaoge 于 2023-10-11 21:30 编辑

根据要求本项目完成如下功能:

完成任务:

任务1:控制屏幕显示中文(必做任务)----- 完成屏幕的控制,并且能显示中文

任务2:网络功能使用(必做任务)----- 完成网络功能的使用,能够创建热点和连接到WiFi

任务3:控制WS2812B(必做任务)---- 使用按键控制板载Neopixel LED的显示和颜色切换

任务4:从下方5个分任务中选择1个感兴趣的完成即可(必做任务)

■  分任务1:日历&时钟——完成一个可通过互联网更新的万年历时钟,并显示当地的天气信息

■  分任务2:WS2812B效果控制——完成一个Neopixel(12灯珠或以上)控制器,通过按键和屏幕切换展示效果

任务5:通过网络控制WS2812B(可选任务,非必做)----- 结合123,在手机上通过网络控制板载Neopixel LED的显示和颜色切换,屏幕同步显示状态

在未收到板子之前,我有写个一篇介绍如何实现上述功能的文档,热度还蛮高的,贴在下方供大家参考。

【得捷电子Follow me第2期】CircuitPython入门到完成任务1-5详细教程 - DigiKey得捷电子技术专区 - 电子工程世界-论坛 (eeworld.com.cn)

本篇文章为任务提交贴,下面将按照要求进行任务完成的说明介绍与建议。

第一部分

任务一:3-5分钟短视频

视频链接如下:

follow me第二期任务演示-follow me第二期任务演示-EEWORLD大学堂


 

第二部分

任务二:任务/项目总结报告

任务1:控制屏幕显示中文(必做任务)----- 完成屏幕的控制,并且能显示中文

功能对应的主要代码片段及说明

 

 

上述为软件的整体结构,由于我们需要显示中文,所以我们需要添加字库文件,按照我之前的文章,我们创建了一款16尺寸的测试字体,并存放在fonts文件夹下,待代码调用。

#通用库
import board
#屏幕显示库
import displayio
#字体导入库
from adafruit_bitmap_font import bitmap_font
#显示标签库
from adafruit_display_text.label import Label
显示图片库
import adafruit_imageload

# displayDriver_Begin 显示驱动
display = board.DISPLAY
# 创建一个显示组件
my_display_group = displayio.Group()
print("Display Init Success\n")
# displayDriver_End

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

# DrawTimeandTemp_Beign 文字显示
# 标签中文字的内容
time_label_text = "{}-{:02}-{:02}\n"\
                  "时间:{:02}:{:02}:{:02}\n"\
                  "地区:{}\n"\
                  "温度:{}\t"\
                  "天气:{}\n".format(r.datetime.tm_year, r.datetime.tm_mon, r.datetime.tm_mday, \
                                      r.datetime.tm_hour, r.datetime.tm_min, r.datetime.tm_sec, \
                                      current_area, current_temp, current_weather)
# 标签的属性:字体,文字内容,颜色,位置
time_label = Label(font = font_Chinese, text=time_label_text, color = 0xff00ff)
time_label.x = 10
time_label.y = 60
# 将标签添加到显示组件中
my_display_group.append(time_label)
# DrawTimeandTemp_End

功能展示及说明

根据代码的功能,我们实现了在屏幕上使用我们设定的字体显示中文汉字,如下图所示。

 

心得体会建议

本任务最大的困难点,可能是创建中文字库了,建议官方可以提供一些不同语言的字库文件,便于开发者使用。

任务2:网络功能使用(必做任务)----- 完成网络功能的使用,能够创建热点和连接到WiFi

功能对应的主要代码片段及说明

本任务要求我们创建热度和连接wifi,circuitpython固件的优势就是本身boot支持连接wifi,因此我们在seting中配置宏定义即可,同时我们在代码中进行判断,如果未连接wifi,我们就创建一个esp32名称的热点,同时我们将它的相关信息打印在屏幕上,相关代码如下:

settings.toml中的配置

CIRCUITPY_WIFI_SSID = "ttxiaotaoge"
CIRCUITPY_WIFI_PASSWORD = "zt123321"
CIRCUITPY_WEB_API_PASSWORD= "123"
#网络相关库
import wifi

# 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

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

功能展示及说明

连接wifi状态:

 

未连接wifi状态:

 

心得体会建议

circuitpython固件支持wifi自动连接,这种性质非常不错,同时我们可以直接访问ip来进入在线编程模式,非常方便使用,相关界面如下:

 

任务3:控制WS2812B(必做任务)---- 使用按键控制板载Neopixel LED的显示和颜色切换

 

功能对应的主要代码片段及说明

根据该要求,我们需要控制2个东西,第一个是按键,第二个是LED,按键本身就是输入,我们直接使用输入状态读取即可;NeopixelLED我们需要导入相关的库来实现控制,相关代码如下:

# RGBLED显示库
import neopixel

#构造函数——按键控制RGB, 实现每次按键让LED的rgb属性提高,直到最亮再复位至0
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

# 板载RGB
pixels = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2, auto_write=True)
# 拓展RGB16路灯珠
pixels16 = neopixel.NeoPixel(board.A0, 16, brightness=0.2, auto_write=True)
# pixels.fill((8, 8, 8))
pixels[0] = 0xff0000
pixels.show()
print("RGBDriver Init Success\n")
# RGBDriver_End

while True:

# 按键控制LED始终循环使能
    Button0_Work()

功能展示及说明

相关展示如下:

 

心得体会建议

Neopixel的库让我们可以非常容易的驱动rgbLED,但我们最好也要了解下RGB是如何实现驱动,一串带有编码性质的方波可以让RGB为我闪耀。

任务4:分任务1:日历&时钟——完成一个可通过互联网更新的万年历时钟,并显示当地的天气信息

 

功能对应的主要代码片段及说明

该任务为本期任务最核心的任务,相关代码如下:

代码运行后将自动联网,如联网成功会自动同步网络时间和获取天气信息并显示在LCD屏幕上,时间显示为经过同步的RTC内部时钟,天气地区配置在代码中设定,使用知心天气API

若未成功联网将会开启AP模式,默认为SSID为ESP32无密码。显示屏会显示当前网络模式和访问ip,同时显示本地时间(RTC内部时钟)

其中API获取网络天气和时间,需要根据自身的需求进行修改,包含知心天气的KEY和地区

TIME_DATA_SOURCE = "http://worldtimeapi.org/api/timezone/Asia/Shanghai"
WEATHER_DATA_SOURCE = "http://api.seniverse.com/v3/weather/now.json?key=SBmmNRnXdiTFi8UQw&location=nanjing&language=zh-Hans&unit=c"

#网络相关库
import wifi
import socketpool
import ssl
import adafruit_requests
from adafruit_httpserver import Server, Request, Response, Websocket, GET
#构造函数——解码天气
def parse_weather(weather_str):
    # Extract the time part from the datetime string
    area = weather_str['results'][0]['location']['name']
    temp = weather_str['results'][0]['now']['temperature']
    weather = weather_str['results'][0]['now']['text']
    return area, temp, weather

#构造函数——解码时间
def parse_time(datetime_str):
    # Extract the time part from the datetime string
    date_str = datetime_str.split("T")[0]
    time_str = datetime_str.split("T")[1].split(".")[0]
    hour, minute, second = map(int, time_str.split(":"))
    date = date_str
    return hour, minute, second, date

#构造函数——更新网络数据
def Update_Data():
    global r
    global current_area, current_temp, current_weather
    current_area = current_temp = current_weather = None
    r = rtc.RTC()
    
    if(wificonnect_State == True):       
        #WeatherUpdate Begin
        requests = adafruit_requests.Session(pool, ssl.create_default_context())
        response_Weather = requests.get(WEATHER_DATA_SOURCE)
        data_Weather = response_Weather.json()
        response_Weather= requests.get(WEATHER_DATA_SOURCE)
        response_Weather.socket.close()
        current_area, current_temp, current_weather = parse_weather(data_Weather)
        print("WeatherUpdate Success\n")
        #WeatherUpdate End

        #ClockTimeUpdate Begin
        requests = adafruit_requests.Session(pool, ssl.create_default_context())
        response_clock = requests.get(TIME_DATA_SOURCE)
        data_clock = response_clock.json()
        response_clock= requests.get(WEATHER_DATA_SOURCE)
        response_clock.socket.close()
        current_hour, current_minute, current_second, current_date = parse_time(data_clock["datetime"])
        r.datetime = time.struct_time((int(current_date[0:4]), int(current_date[5:7]), int(current_date[8:10]), \
                                   current_hour, current_minute, current_second, 0, -1, -1))
        print("ClockTimeUpdate Success\n")
        #ClockTimeUpdate Begin

# GetandSetHttp_Begin
TIME_DATA_SOURCE = "http://worldtimeapi.org/api/timezone/Asia/Shanghai"
WEATHER_DATA_SOURCE = "http://api.seniverse.com/v3/weather/now.json?key=SBmmNRnXdiTFi8UQw&location=nanjing&language=zh-Hans&unit=c"
pool = socketpool.SocketPool(wifi.radio) # 网络管理,触发http操作
server = Server(pool, debug=True)



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

# GetTimeandTemp_Beign
Update_Data()
# GetTimeandTemp_End

# DrawTimeandTemp_Beign
time_label_text = "{}-{:02}-{:02}\n"\
                  "时间:{:02}:{:02}:{:02}\n"\
                  "地区:{}\n"\
                  "温度:{}\t"\
                  "天气:{}\n".format(r.datetime.tm_year, r.datetime.tm_mon, r.datetime.tm_mday, \
                                      r.datetime.tm_hour, r.datetime.tm_min, r.datetime.tm_sec, \
                                      current_area, current_temp, current_weather)
time_label = Label(font = font_Chinese, text=time_label_text, color = 0xff00ff)
time_label.x = 10
time_label.y = 60
my_display_group.append(time_label)
# DrawTimeandTemp_End

#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}\nKEY:{:02}".format(RGBr, RGBg, RGBb, i)#更新RGB状态
    time_label.text = "{}-{:02}-{:02}\n"\
                      "时间:{:02}:{:02}:{:02}\n"\
                      "地区:{}\n"\
                      "温度:{}\t"\
                      "天气:{}\n".format(r.datetime.tm_year, r.datetime.tm_mon, r.datetime.tm_mday, \
                                          r.datetime.tm_hour, r.datetime.tm_min, r.datetime.tm_sec, \
                                          current_area, current_temp, current_weather)
    Button0_Work()

上述代码中,我们通过访问对应网站,获取其json数据,并通过json库,解析其中的数据。

功能展示及说明

相关演示如下:

 

心得体会建议

本任务的重点是从网络上获取对应的天气和时间信息,以及通过json解析其中的关键数据。

任务4:分任务2:WS2812B效果控制——完成一个Neopixel(12灯珠或以上)控制器,通过按键和屏幕切换展示效果

 

功能对应的主要代码片段及说明

相关代码如下:

#构造函数——屏幕跑马灯
set_colour = 0
set_colour1 = 0
set_colour2 = 1
set_colour3 = 2
time_count = 0
def ColourRun_Work():
    global set_colour, set_colour1, set_colour2, set_colour3
    global time_count
    time_count += 1
    if(time_count >= 5):
        time_count = 0
        if(i%2 == 0):
            for x in range(150, 170):
                for y in range(100, 110):
                    bitmap[x, y] = set_colour1 # Set pixel at (x, y) to blue
            if (set_colour1 < 4):
                set_colour1 += 1
            else:
                set_colour1 = 0
            for x in range(175, 195):
                for y in range(100, 110):
                    bitmap[x, y] = set_colour2 # Set pixel at (x, y) to blue
            if (set_colour2 < 4):
                set_colour2 += 1
            else:
                set_colour2 = 0
            for x in range(200, 220):
                for y in range(100, 110):
                    bitmap[x, y] = set_colour3 # Set pixel at (x, y) to blue
            if (set_colour3 < 4):
                set_colour3 += 1
            else:
                set_colour3 = 0
        else:
            for x in range(150, 170):
                for y in range(100, 110):
                    bitmap[x, y] = set_colour # Set pixel at (x, y) to blue
            for x in range(175, 195):
                for y in range(100, 110):
                    bitmap[x, y] = set_colour # Set pixel at (x, y) to blue
            for x in range(200, 220):
                for y in range(100, 110):
                    bitmap[x, y] = set_colour # Set pixel at (x, y) to blue
            if (set_colour < 4):
                set_colour += 1
            else:
                set_colour = 0
            pixels16[0 + set_colour] = 0xff0000
            pixels16[1 + set_colour] = 0x00FF00
            pixels16[2 + set_colour] = 0x0000FF
            pixels16.show()

我们在代码中实现了一个屏幕上的跑马灯,以及让灯珠也按照上述方式进行跑动闪烁

功能展示及说明

通过按键实现切换不同的炫彩流水灯效果如下:

 

心得体会建议

该功能同任务3,不过我们增加了对多个灯珠的驱动显示效果,实际看起来非常优雅。

任务5:通过网络控制WS2812B(可选任务,非必做)----- 结合123,在手机上通过网络控制板载Neopixel LED的显示和颜色切换,屏幕同步显示状态

 

功能对应的主要代码片段及说明

该功能我们使用网页端来完成,该方法有多个优势,既让代码更佳见解,也同时适配了多端访问的问题,本质上我们是使用websocket来访问esp32s3

相关代码如下:

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

功能展示及说明

相关展示如下,我们可以很轻松的获取按键的状态,以及控制esp32的板载RGBLED

 

心得体会建议

由于circuitpython本身带了网页端,为了避免冲突,我们需要重新定义网页的端口号,避开使用http默认的80端口

 

 

第三部分

任务三:可编译下载的代码

代码下载地址链接:

followme第二期任务代码-嵌入式开发相关资料下载-EEWORLD下载中心

感谢得捷电子提供的本次follow me活动,上述为本次活动的全部完成内容,感谢观看。

 

 

 

 

 

 

 

 

点赞 关注
 
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/6 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表