[作品提交] 【得捷电子Follow me第2期】+ 任务合集

XAndxiang   2023-10-18 16:55 楼主

第一次参加带此类活动中还是很兴奋的,过程也是一波三折,登陆两个多月板子才陆续到手里,马上就开始紧张的交作业环节了,首先我们先回顾一下本次的活动有那些作业需要交。

任务1:控制屏幕显示中文(必做任务)

完成屏幕的控制,并且能显示中文

搭配器件:Adafruit ESP32-S3 TFT Feather

 

任务2:网络功能使用(必做任务)

完成网络功能的使用,能够创建热点和连接到WiFi

搭配器件:Adafruit ESP32-S3 TFT Feather

 

任务3:控制WS2812B(必做任务)

使用按键控制板载Neopixel LED的显示和颜色切换

搭配器件:Adafruit ESP32-S3 TFT Feather

 

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

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

建议搭配器件:Adafruit ESP32-S3 TFT Feather

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

建议搭配器件:Adafruit ESP32-S3 TFT Feather、可寻址RGB LED

■  分任务3:数据检测与记录——按一定时间间隔连续记录温度/亮度信息,保存到SD卡,并可以通过按键调用查看之前的信息,并在屏幕上绘图

建议搭配器件:Adafruit ESP32-S3 TFT Feather、光传感器、温度传感器、微型 SD卡模块

■  分任务4:音乐播放功能——实现音乐播放器功能,可以在屏幕上显示列表信息和音乐信息,使用按键进行切换,使用扬声器进行播放

建议搭配器件:Adafruit ESP32-S3 TFT Feather、音频放大器、扬声器

■  分任务5:AI功能应用——结合运动传感器,完成手势识别功能,至少要识别三种手势(如水平左右、前后、垂直上下、水平画圈、垂直画圈,或者更复杂手势

建议搭配器件:Adafruit ESP32-S3 TFT Feather、运动传感器

 

任务5:通过网络控制WS2812B(可选任务,非必做)

 

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

搭配器件:Adafruit ESP32-S3 TFT Feather

可以看到1,2,3,4任务都是必做的,5可以选择做或者不做。

那么就挨个来不着急。

 

接下来先给大家讲解一下各个任务的实现:
//内容一:3-5分钟短视频//


补充视频

视频补充说明

 

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

任务一:

因为要显示中文,这边找了一个免费的中文字库
epcxt-20221115.zip (1.75 MB)
(下载次数: 3, 2023-10-17 17:56 上传)
,本身体积非常小,很适合这个小内存的设备,目前固件只能识别到bdf和pcf格式的字库,需要将ttf格式的字库转换为pcf格式的,这里需要用到一个字库转换工具otf2bdf,

第1步:安装otf2bdf工具,找了一圈发现win平台是没有的,这里就在linux上操作了,如下图所示就安装成功了。

1697536917217.png  

第2步:我们执行转换命令: otf2bdf 一品创享体1.20.ttf -p 16 -o yipingchuangxiang_v1.2_16.bdf

-p的意思就是指定生成的字库文字大小 -o 指定生成的文件名

1697537059416.png  

可以看到我这里箭头指的已经生成了,还有一个文字大小48的就不演示了。

第3步:现在已经得到了bdf格式的字库了,这个文件大小有1M多,如果还嫌大放不进去可以使用官方推荐的工具进一步转换为pcf格式。

https://adafruit.github.io/web-bdftopcf/

点击进去将刚才生成的bdf文件上传上去既可以自动转换为pcd文件,这个转换后文件只有500多k了。

第4步:在u盘里面新建文件夹font,images,将字库文件丢到font后面就可以调用了,同样,后面调用图片也是需要我们丢图片到images文件夹

第5步:在u盘里面新建文件settings.toml,填上如下内容,板子就可以自动连接到wifi了

# SPDX-FileCopyrightText: 2023 Adafruit Industries
#
# SPDX-License-Identifier: MIT

# This is where you store the credentials necessary for your code.
# The associated demo only requires WiFi, but you can include any
# credentials here, such as Adafruit IO username and key, etc.
CIRCUITPY_WIFI_SSID = "you ssid"
CIRCUITPY_WIFI_PASSWORD = "you password"
CIRCUITPY_WEB_API_PASSWORD = "you password"
CIRCUITPY_WEB_API_PORT = 80

第6步:在编写的时候需要用到一些库,可以从这个https://circuitpython.org/libraries网站上下载,需要用到那个直接在lib文件夹拷贝到u盘里面的lib文件夹即可,没有就创建一个。

第7步:在u盘里面新建文件code.py,在里面填上如下内容我们就可以完成任务1了。

import board  # 导入board库,用于访问硬件板上的引脚和设备
import displayio  # 导入displayio库,用于管理和控制显示器
from vectorio import Rectangle  # 导入vectorio库,用于创建和管理矩形图形
import adafruit_imageload  # 导入adafruit_imageload库,用于加载图像文件


# 导入外部库adafruit_display_text里的lable,用于显示标签
from adafruit_display_text import label
# 导入外部库adafruit_bitmap_font里的lable,用于显示字体
from adafruit_bitmap_font import bitmap_font

# 加载字体并定义字体颜色为黑色
font = bitmap_font.load_font("/font/yipingchuangxiang_v1.2_16.pcf")
color = 0x000000

# 获取内置显示器对象
display = board.DISPLAY

# 加载PNG图像
image, palette = adafruit_imageload.load("images/bg.png")

# 将透明色设置为隐藏
palette.make_transparent(0)

# 创建用于加载的图像瓦片网格
tile_grid = displayio.TileGrid(image, pixel_shader=palette)
tile_grid.x = display.width // 2 - tile_grid.tile_width // 2
tile_grid.y = display.height // 2 - tile_grid.tile_height // 2

# 创建空白背景
bg_palette = displayio.Palette(1)
bg_palette[0] = 0xFFFFFF
rect = Rectangle(
    pixel_shader=bg_palette, width=display.width, height=display.height, x=0, y=0
)

# 创建显示器组对象
group = displayio.Group()

# 添加背景
group.append(rect)
# 添加加载的图像瓦片网格
group.append(tile_grid)

# 初始化日期标签并设置x,y轴绘图坐标,然后将标签添加到图像组
date = label.Label(font, text="      电子工程世界\n  www.eeworld.com.cn\n    简称EEWORLD", color=color)
date.x = 0
date.y = 20
group.append(date)

# 在显示器上显示组
board.DISPLAY.show(group)

# 持续循环,使程序保持在显示器上显示
while True:
    pass

最后我们来看一下,完成效果。

1417cb5d4a19350d55472322a268628.jpg  

任务二:

这个作业非常简单,我们只需要在程序中导入wifi库即可,然后在程序中调用wifi.radio.start_ap就行了,直接上代码

import wifi  #这个是内部库
import board  # 导入board库,用于访问硬件板上的引脚和设备
import displayio  # 导入displayio库,用于管理和控制显示器
import adafruit_imageload  # 导入adafruit_imageload库,用于加载图像文件

from vectorio import Rectangle  # 导入vectorio库,用于创建和管理矩形图形
from adafruit_display_text import label  # 导入外部库adafruit_display_text里的lable,用于显示标签
from adafruit_bitmap_font import bitmap_font  # 导入外部库adafruit_bitmap_font里的lable,用于显示字体

# 加载字体并定义字体颜色为黑色
font = bitmap_font.load_font("/font/yipingchuangxiang_v1.2_16.pcf")
color = 0x000000

# 获取内置显示器对象
display = board.DISPLAY

# 加载PNG图像
image, palette = adafruit_imageload.load("images/bg.png")

# 将透明色设置为隐藏
palette.make_transparent(0)

# 创建用于加载的图像瓦片网格
tile_grid = displayio.TileGrid(image, pixel_shader=palette)
tile_grid.x = display.width // 2 - tile_grid.tile_width // 2
tile_grid.y = display.height // 2 - tile_grid.tile_height // 2

# 创建空白背景
bg_palette = displayio.Palette(1)
bg_palette[0] = 0xFFFFFF
rect = Rectangle(
    pixel_shader=bg_palette, width=display.width, height=display.height, x=0, y=0
)

# 创建显示器组对象
group = displayio.Group()

# 添加背景
group.append(rect)
# 添加加载的图像瓦片网格
group.append(tile_grid)

# 初始化日期标签并设置x,y轴绘图坐标,然后将标签添加到图像组
date = label.Label(font, text="      电子工程世界\n  www.eeworld.com.cn\n    简称EEWORLD", color=color)
date.x = 0
date.y = 20
group.append(date)

wifi.radio.start_ap("eeworld", "www.eeworld.com.cn")
print(f"SSID: eeworld")
print(f"PASSWORD: www.eeworld.com.cn")

# 在显示器上显示组
board.DISPLAY.show(group)

# 持续循环,使程序保持在显示器上显示
while True:
    pass

f5a1e414b15762a3a9c08c3a81073af.jpg  

   0f3097ecc0997b8cd5f8ed229151df6.jpg  

可以看到已经生成了一个名字叫eeworld的wifi,我们输入密码也是可以连接上去的。

连接wifi的话其实我们在settings.toml配置一下就可以连接到wifi了。

 

任务三:

这个作业需要我们控制ws2812,所以我们需要再导入一个库neopixel,这个库是外部库,需要我们拷贝到u盘lib目录里面去

然后我这边刚好有一个圆形灯板,有30灯,可以利用板子上的boot按钮切换灯的颜色,具体看代码。

import time  # 这个是内部库
import wifi  # 这个是内部库
import board  # 导入board库,用于访问硬件板上的引脚和设备
import neopixel  # 这个是驱动ws2812BRGB灯所需要的库
import digitalio # 这个是内部库,数字io需要的库
import displayio  # 导入displayio库,用于管理和控制显示器
import adafruit_imageload  # 导入adafruit_imageload库,用于加载图像文件

from vectorio import Rectangle  # 导入vectorio库,用于创建和管理矩形图形
from adafruit_display_text import label  # 导入外部库adafruit_display_text里的lable,用于显示标签
from adafruit_bitmap_font import bitmap_font  # 导入外部库adafruit_bitmap_font里的lable,用于显示字体

# 加载字体并定义字体颜色为黑色
font = bitmap_font.load_font("/font/yipingchuangxiang_v1.2_16.pcf")
color = 0x000000

# 获取内置显示器对象
display = board.DISPLAY

# 加载PNG图像
image, palette = adafruit_imageload.load("images/bg.png")

# 将透明色设置为隐藏
palette.make_transparent(0)

# 创建用于加载的图像瓦片网格
tile_grid = displayio.TileGrid(image, pixel_shader=palette)
tile_grid.x = display.width // 2 - tile_grid.tile_width // 2
tile_grid.y = display.height // 2 - tile_grid.tile_height // 2

# 创建空白背景
bg_palette = displayio.Palette(1)
bg_palette[0] = 0xFFFFFF
rect = Rectangle(
    pixel_shader=bg_palette, width=display.width, height=display.height, x=0, y=0
)

# 创建显示器组对象
group = displayio.Group()

# 添加背景
group.append(rect)
# 添加加载的图像瓦片网格
group.append(tile_grid)

# 初始化日期标签并设置x,y轴绘图坐标,然后将标签添加到图像组
date = label.Label(font, text="      电子工程世界\n  www.eeworld.com.cn\n    简称EEWORLD", color=color)
date.x = 0
date.y = 20
group.append(date)

wifi.radio.start_ap("eeworld", "www.eeworld.com.cn")
print(f"SSID: eeworld")
print(f"PASSWORD: www.eeworld.com.cn")


pixel_pin = board.D13  #设置ws2812控制引脚
num_pixels = 30  # 设置灯珠数量
ORDER = neopixel.GRB  #颜色排列顺序

pixels = neopixel.NeoPixel(
    pixel_pin, num_pixels, brightness=0.05, auto_write=False, pixel_order=ORDER
)

button = digitalio.DigitalInOut(board.BUTTON)
button.switch_to_input(pull=digitalio.Pull.UP)

# 在显示器上显示组
board.DISPLAY.show(group)

button_state = False
led_state = 1

# 持续循环,使程序保持在显示器上显示
while True:
    if not button.value and button_state == False:
        button_state = True
        led_state = led_state + 1;
        time.sleep(0.2)
        if led_state == 3:
            led_state = 0;
        print("Hello World",led_state)
    else:
        time.sleep(0.2)
        button_state = False
    
    if led_state == 0:
        pixels.fill((255, 0, 0))
        pixels.show()
    elif led_state == 1:
        pixels.fill((0, 255, 0))
        pixels.show()
    elif led_state == 2:
        pixels.fill((0, 0, 255))
        pixels.show()

可以看下效果

ws2812

控制板载的灯的画只需要将IO改为:

pixel_pin = board.NEOPIXEL  #设置ws2812控制引脚
num_pixels = 1  # 设置灯珠数量

效果如下:

ws

 

任务四:
这个作业我们需要完成一共网络时钟,我们的去一些第三方平台申请一共获取天气的接口,我这里用的是高德的api,然后调用接口去请求数据即可,然后直接套用前面显示的程序显示到屏幕即可,看代码

import board  # 导入board库,用于访问硬件板上的引脚和设备
import os
import rtc
import ssl
import time as Time
import wifi  # 这个是内部库

import neopixel  # 这个是驱动ws2812BRGB灯所需要的库
import digitalio # 这个是内部库,数字io需要的库
import displayio  # 导入displayio库,用于管理和控制显示器
import socketpool

import adafruit_ntp
# import adafruit_datetime 000
import adafruit_requests
import adafruit_imageload  # 导入adafruit_imageload库,用于加载图像文件

from vectorio import Rectangle  # 导入vectorio库,用于创建和管理矩形图形
from adafruit_display_text import label  # 导入外部库adafruit_display_text里的lable,用于显示标签
from adafruit_bitmap_font import bitmap_font  # 导入外部库adafruit_bitmap_font里的lable,用于显示字体

# 加载字体并定义字体颜色为黑色
font = bitmap_font.load_font("/font/yipingchuangxiang_v1.2_16.pcf")
time_font = bitmap_font.load_font("/font/DingTalk_ncn_60.pcf")
color = 0x000000

# 获取当前设备的rtc时钟
pool = socketpool.SocketPool(wifi.radio) #初始化
ntp = adafruit_ntp.NTP(pool, tz_offset=8, server="ntp.aliyun.com") #校正时间
rtc.RTC().datetime = ntp.datetime #校正时间

# 获取内置显示器对象
display = board.DISPLAY

# 加载PNG图像
image, palette = adafruit_imageload.load("images/bg.png")

# 将透明色设置为隐藏
palette.make_transparent(0)

# 创建用于加载的图像瓦片网格
tile_grid = displayio.TileGrid(image, pixel_shader=palette)
tile_grid.x = display.width // 2 - tile_grid.tile_width // 2
tile_grid.y = display.height // 2 - tile_grid.tile_height // 2

# 创建空白背景
bg_palette = displayio.Palette(1)
bg_palette[0] = 0xFFFFFF
rect = Rectangle(
    pixel_shader=bg_palette, width=display.width, height=display.height, x=0, y=0
)

# 创建显示器组对象
group = displayio.Group()

# 添加背景
group.append(rect)
# 添加加载的图像瓦片网格
group.append(tile_grid)

wifi.radio.start_ap("eeworld", "www.eeworld.com.cn")
print(f"SSID: eeworld")
print(f"PASSWORD: www.eeworld.com.cn")


# pixel_pin = board.D13  #设置ws2812控制引脚
# num_pixels = 30  # 设置灯珠数量
pixel_pin = board.NEOPIXEL  #设置ws2812控制引脚
num_pixels = 1  # 设置灯珠数量
ORDER = neopixel.GRB  #颜色排列顺序

pixels = neopixel.NeoPixel(
    pixel_pin, num_pixels, brightness=0.05, auto_write=False, pixel_order=ORDER
)

button = digitalio.DigitalInOut(board.BUTTON)
button.switch_to_input(pull=digitalio.Pull.UP)

label_city = label.Label(font, text="上海市", color=color)
label_city.x = 20
label_city.y = 20
group.append(label_city)

label_weather = label.Label(font, text="晴", color=color)
label_weather.x = 160
label_weather.y = 20
group.append(label_weather)

label_time = label.Label(time_font, text="00:00", color=color)
label_time.x = 20
label_time.y = 60
group.append(label_time)

label_temperature = label.Label(font, text="温度:", color=color)
label_temperature.x = 20
label_temperature.y = 120
group.append(label_temperature)

label_winddirection = label.Label(font, text="风向:", color=color)
label_winddirection.x = 120
label_winddirection.y = 120
group.append(label_winddirection)

# 在显示器上显示组
board.DISPLAY.show(group)

button_state = False
led_state = 0

weather_info = None
province = None
city = None
weather = None
temperature = None
wind_direction = None
wind_power = None
humidity = None
report_time = None

sys_init = 1
get_weather_flag = 0
former_time = 0

print("start")

def get_weather():
    # 调用天气接口API
    JSON_URL = "https://restapi.amap.com/v3/weather/weatherInfo?key="+os.getenv("CIRCUITPY_WEATHER_API_KEY")+"&city="+os.getenv("CIRCUITPY_WEATHER_API_CITY")
    print(JSON_URL)
    pool = socketpool.SocketPool(wifi.radio)
    requests = adafruit_requests.Session(pool, ssl.create_default_context())
    response = requests.get(JSON_URL)

    # 解析JSON数据
    JSON_DATA = response.json()
    # 获取天气信息
    weather_info = JSON_DATA["lives"][0]
    province = weather_info["province"]
    city = weather_info["city"]
    weather = weather_info["weather"]
    temperature = weather_info["temperature"]
    wind_direction = weather_info["winddirection"]
    wind_power = weather_info["windpower"]
    humidity = weather_info["humidity"]
    report_time = weather_info["reporttime"]

    # 打印天气信息
    print("Province: {}".format(province))
    print("City: {}".format(city))
    print("Weather: {}".format(weather))
    print("Temperature: {}°C".format(temperature))
    print("Wind Direction: {}".format(wind_direction))
    print("Wind Power: {}".format(wind_power))
    print("Humidity: {}%".format(humidity))
    print("Report Time: {}".format(report_time))
    now_time = Time.localtime()
    label_time.text = "%d:%d" % (now_time.tm_hour, now_time.tm_min)
    label_city.text = city
    label_temperature.text = "温度:"+temperature
    label_winddirection.text = "风向:"+wind_direction


# 持续循环,使程序保持在显示器上显示
while True:
    if not button.value and button_state == False:
        button_state = True
        led_state = led_state + 1;
        Time.sleep(0.2)
        if led_state == 3:
            led_state = 0;
        print("Hello World",led_state)
    else:
        Time.sleep(0.2)
        button_state = False
    
    if led_state == 0:
        pixels.fill((255, 0, 0))
        pixels.show()
    elif led_state == 1:
        pixels.fill((0, 255, 0))
        pixels.show()
    elif led_state == 2:
        pixels.fill((0, 0, 255))
        pixels.show()

    now_time = Time.localtime()
    if (sys_init == 1):                                         #第一次上电读取一下天气
        sys_init = 0
        print("sys_init",now_time)
        try:
            get_weather()
        except:
            print("get_weather An exception occurred")

    if (get_weather_flag == 1 and now_time.tm_hour == 0):       #一小时更新一次天气
        try:
            get_weather()
        except:
            print("get_weather An exception occurred")
        get_weather_flag = 0
    if (now_time.tm_sec == 10):
        get_weather_flag = 1

    if(former_time != now_time.tm_min):                         #一分钟刷新一下时间
        label_time.text = "%d:%d" % (now_time.tm_hour, now_time.tm_min)
        former_time = now_time.tm_min

 

 

看下最后效果:

35f9c594411763ef335e0c55f3f71d1.jpg  

最后上传一下可运行的u盘打包文件,里面配置文件需要自己新建一下。

 

//内容三:可编译下载的代码//

CircuitPython.rar (243.21 KB)
(下载次数: 3, 2023-10-18 17:00 上传)
 
在这次活动中,CircuitPython的编程给我最直观的感觉就是直观和简单:CircuitPython的语法和结构与标准Python非常相似,
因此对于已经熟悉Python的开发者来说,CircuitPython的学习曲线相对较低,
虽然我也是第一次使用类python的语言编程,但是上手起来也很快,直接在编辑器里面编辑就可以了
编辑完保存程序就自动运行了,无需在搭建环境什么的实在是太有好友了,而且有很多写好了的库可以使用,
不用再去做重复造轮子的了,这点必须给一个赞,得益于这些简单易用的库,使得此次活动的开发过程顺利完成。
在本次活动中也有好多小伙伴可以一起交流,这点给咱们的组织同学也必须点一个赞,有啥问题都能在群里一一解答。
对于本次活动都很满意,要说有啥意见的话那就是有些规则和可操作的范围规定的不是很明白,我个人理解没有完全写明白,最后希望活动越办越好。
 
 

回复评论 (4)

eeworld的logo都整出来了

image.png  

点赞  2023-10-19 07:29

效果相当不错啊,这个背景图片很好看

在爱好的道路上不断前进,在生活的迷雾中播撒光引
点赞  2023-10-19 08:47
引用: 火辣西米秀 发表于 2023-10-19 07:29 eeworld的logo都整出来了 强  

哈哈,整了个完整的中文字库,想显示什么就显示什么了

点赞  2023-10-19 22:55
引用: 秦天qintian0303 发表于 2023-10-19 08:47 效果相当不错啊,这个背景图片很好看

女朋友给做的背景图

点赞  2023-10-19 22:57
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复