【得捷电子Follow me第2期】+ 提交帖:基于ESP32-S3的万年历
[复制链接]
本帖最后由 liuvx 于 2023-11-21 17:04 编辑
最近完成了本期活动的全部内容,本次活动中使用的Adafruit ESP32-S3 TFT Feather开发板,支持WiFi和蓝牙功,自带高清TFT彩色显示屏。完成了屏幕显示中文,连接WiFi,驱动RGB,制作万年历等任务。
内容一:演示视频
这次实现的是基于ESP32-S3的万年历,可以连接上网络,并在屏幕上显示现在的时间,日期,天气和温度。
得捷电子 Follow me 第2期任务-得捷电子 Follow me 第2期任务-EEWORLD大学堂
内容二:项目总结报告
任务1:控制屏幕显示中文
首先,将效果图呈现在这
图 1 效果图
前期准备工作:
- 拿到Adafruit ESP32-S3 TFT Feather开发板上电,进入UF2模式,并安装CircuitPython环境。
CircuitPython固件UF2下载页面:
Feather ESP32-S3 TFT Download (circuitpython.org)
- 将下载好的UF2固件直接拖进Adafruit ESP32-S3 TFT Feather自带的盘中,等待自动重启即可。
- 当你的屏幕显示如图2一样时,CircuitPython即安装好。
图 2
正式开始:
图 3 CircuitPython
我是使用VScode进行配置,可以先安装这个插件后再进行后面的操作。
本次任务所需要3个库
我们可以在vscode里执行这一个命令
然后在输入
之后就可以查找并安装自己所需要的库了。
可以在进入命令执行时,输入
可以查询到自己所下载的库
本节还需要额外添加字库
字库链接:
我所使用的是wenquanyi_13px.pcf,下载好之后直接拖进开发板所带的盘就行。
然后是代码部分
这一部分是导入所必要的库
import board
import displayio
from adafruit_display_text import label, wrap_text_to_lines
from adafruit_bitmap_font import bitmap_font
然后设定屏幕参数
display = board.DISPLAY
board.DISPLAY.brightness = 0.2 # 设置显示屏亮度为0.35
board.DISPLAY.rotation = 0 # 设置显示屏旋转为0度
然后设置需要在屏幕上显示的字
# 加载自定义字体文件
font = bitmap_font.load_font("wenquanyi_13px.pcf")
# 设置文本颜色
color = 0xFF0000 # 这里的颜色为红色
# 初始化文本变量
text_change = 0
# 创建显示组和文本标签
text_group = displayio.Group()
text_area = label.Label(font, text="test", color=color) # 创建文本标签对象
text_area.x = 0 # 设置文本的X坐标
text_area.y = 55 # 设置文本的Y坐标
text_area.line_spacing = 0.5 # 设置文本行间距
text_area.scale = 2 # 设置文本放大倍数
# 设置文本内容
text_area.text = "WIFI:ESP\n密码:00000000" # 这里设置文本内容
text_area.ass = "w"
text_group.append(text_area) # 将文本标签添加到显示组中
display.show(text_group) # 在显示设备上显示文本
任务2:连接WiFi和创建热点
这个任务的要求是完成网络功能的使用,能够创建热点和连接到WiFi。
并且代码比较简单
先说下连接WIFI:
在我们刷入固件后,可以在盘中看到一个settings.toml的文件,我们只需要修改它即可实现WIFI的链接
然后修改里面的代码
#配置WIFI的ID
CIRCUITPY_WIFI_SSID = "Liuv"
#配置WiFi密码
CIRCUITPY_WIFI_PASSWORD = "12345678"
#配置网页工作流密码
CIRCUITPY_WEB_API_PASSWORD = "123456"
#配置网页工作流端口
CIRCUITPY_WEB_API_PORT = 80
在我们连上WIFI后,屏幕会显示出ip地址
这样我们的WIFI就链接上了。
然后是开启热点
导入必须的库
import wifi
然后开启热点
wifi.radio.start_ap('ESP', '00000000')
名字和密码。
任务完成
任务3:RGB灯的使用
本次任务所要使用的是板上自带的RGB灯和按键
我打算先不用按键来切换颜色,先使用time库来使它达到每0.5秒切换一次颜色的效果。
板上所带的RGB灯型号为WS2812b,可使用Adafruit提供的neopixe库来使用它。
import neopixel
导入time库
import time
修改brightn可改变RGB灯最大亮度。
然后进入循环
while True:
pixel.brightness = 0.6
pixel.fill((255, 0, 0))
time.sleep(0.5)
pixel.brightness = 0.5
pixel.fill((0, 255, 0))
time.sleep(0.5)
pixel.brightness = 0.1
pixel.fill((0, 0, 255))
time.sleep(0.5)
中的
pixel.fill((255, 0, 0))
分别是Red,Green,Blue的颜色控制。
time.sleep(0.5)
表示延时0.5s
当你烧入代码后就能观察到rgb在红色,绿色,蓝色来回切换,且每个的亮度不同。
完整代码如下
import time
import board
import neopixel
pixel = neopixel.NeoPixel(board.NEOPIXEL, 1)#初始化rgb引脚
pixel.brightness = 0.6#更改亮度
while True:
pixel.brightness = 0.6
pixel.fill((255, 0, 0))
time.sleep(0.5)
pixel.brightness = 0.5
pixel.fill((0, 255, 0))
time.sleep(0.5)
pixel.brightness = 0.1
pixel.fill((0, 0, 255))
time.sleep(0.5)
这样,你就掌握了最基本的RGB灯的控制,再让我们看看如何用按键操作它吧
当你使用按键时,就要调用基本数字库了
import digitalio
然后再初始化按键
button = digitalio.DigitalInOut(board.BUTTON)
button.switch_to_input(pull=digitalio.Pull.UP)
表示上拉输入
然后进入循环
while True:
if not button.value:
if n % 3 == 1:
pixel.brightness = 0.6
pixel.fill((255, 0, 0))
elif n % 3 == 2:
pixel.brightness = 0.5
pixel.fill((0, 255, 0))
elif n % 3 == 0:
pixel.brightness = 0.3
pixel.fill((0, 0, 255))
n = n+1
仅仅这样写,也是有效果的,但是可能无法达到我们想要的结果。
因为按键在按下的时候会产生抖动,会对我们造成影响.
因此我们要加入延时函数来进行消抖
while True:
if not button.value:
time.sleep(0.1)
if not button.value:
if n % 3 == 1:
pixel.brightness = 0.6
pixel.fill((255, 0, 0))
elif n % 3 == 2:
pixel.brightness = 0.5
pixel.fill((0, 255, 0))
elif n % 3 == 0:
pixel.brightness = 0.3
pixel.fill((0, 0, 255))
n = n+1
这样,就能满足我们的一个想要的效果了。
完整代码如下
import time
import board
import neopixel
import digitalio
n = 0
button = digitalio.DigitalInOut(board.BUTTON)
button.switch_to_input(pull=digitalio.Pull.UP)
pixel = neopixel.NeoPixel(board.NEOPIXEL, 1)#初始化rgb引脚
pixel.brightness = 0.6#更改亮度
while True:
if not button.value:
time.sleep(0.1)
if not button.value:
if n % 3 == 1:
pixel.brightness = 0.6
pixel.fill((255, 0, 0))
elif n % 3 == 2:
pixel.brightness = 0.5
pixel.fill((0, 255, 0))
elif n % 3 == 0:
pixel.brightness = 0.3
pixel.fill((0, 0, 255))
n = n+1
else:
pass
任务4:日历和时钟
在本次任务中,我们需要完成在我们的屏幕上显示时间与天气等信息
先放张效果图
我们来分步进行
首先是先完成文字部分
屏幕显示部分
需要的库可以自行查看之前的任务一
先设置屏幕的一些基本参数
# 设置板子的亮度和是否翻转
board.DISPLAY.brightness = 0.5 #
board.DISPLAY.rotation = 0 #
word_font = bitmap_font.load_font("wenquanyi_13px.pcf")
咱们可以在这个任务中增加一张图片来使其更加美观
需要这个库
import adafruit_imageload
然后引入图片,注意图片需要是bmp格式的
# 引入图片
image, palette = adafruit_imageload.load(
'/images/ysqd.bmp', bitmap=displayio.Bitmap, palette=displayio.Palette)
tile_grid = displayio.TileGrid(image, pixel_shader=palette)
group = displayio.Group()
group.append(tile_grid)
然后再显示其他文字,如时间,温度啥的
# 日期的设置
date = label.Label(word_font, text="test", color=0x000000)
date.x = 10 #
date.y = 20
date.scale = 2 #
group.append(date)
# 周几的设置
week = label.Label(word_font, text="周五", color=0x000000)
week.x = 120
week.y = 20
week.scale = 2
group.append(week)
# 时间的设置
timer = label.Label(word_font, text='10:17', color=0x779649)
timer.x = 15
timer.y = 65
timer.scale = 2 #
group.append(timer)
# 天气文字的设置
weather = label.Label(word_font, text='阴', color=0x3271ae)
weather.x = 10
weather.y = 110
weather.scale = 2 #
group.append(weather)
# 温度文字的设置
temperature = label.Label(word_font, text='10度-15度', color=0x3271ae)
temperature.x = 60
temperature.y = 110
temperature.scale = 2
group.append(temperature)
# 事实温度文字的设置
tem_now = label.Label(word_font, text='10度', color=0x3271ae)
tem_now.x = 150
tem_now.y = 65
tem_now.scale = 2
group.append(tem_now)
最后再显示即可
board.DISPLAY.show(group)
WIFI连接
和之前类似,在SETTING这个文件中配置ssid和password
# 连接WIFI,若连接失败会报错
print("Connecting to", ssid)
wifi.radio.connect(ssid, password)
time.sleep(1)
print("Connected to", ssid)
延时1s的目的为了使能够连接WiFi后再进行后面的操作
获取信息
相关库介绍
adafruit_ntp
adafruit_requests
rtc
获得天气这个需要从其他地方返回数据获得
我这里使用的是易客云API,比较方便和稳定
代码部分
# 周几文字的数据
def get_wday(week_today):
if week_today == 0:
return "周一"
elif week_today == 1:
return "周二"
elif week_today == 2:
return "周三"
elif week_today == 3:
return "周四"
elif week_today == 4:
return "周五"
elif week_today == 5:
return "周六"
elif week_today == 6:
return "周日"
再利用RTC来获得时间
# 使用rtc
rtc.RTC().datetime = adafruit_ntp.NTP(socketpool.SocketPool(
wifi.radio), tz_offset=8, server='ntp.aliyun.com').datetime
从API获取天气情况
def get_weather():
requests = adafruit_requests.Session(
socketpool.SocketPool(wifi.radio), ssl.create_default_context())
appid = os.getenv("appid")
appsecret = os.getenv("appsecret")
res = requests.get(
'https://v0.yiketianqi.com/free/day?appid=%s&appsecret=%s&unescape=1&city=南阳' % (appid, appsecret)).json()
return res['wea'], res['tem_night'], res['tem_day'], res['tem']
注意这里的appid和appsecret需要从易客云获取并写入settings这个文件中
否则会无法正常获得温度
再进行循环之前先获取一遍信息
# 获得时间
time_now = time.localtime()
timer.text = '%02d:%02d' % (time_now.tm_hour, time_now.tm_min)
date.text = '%d月%d日' % (time_now.tm_mon, time_now.tm_mday)
week.text = get_wday(time_now.tm_wday)
wea, tem_night, tem_day, tem = get_weather()
weather.text = wea
temperature.text = '%s℃-%s℃' % (tem_night, tem_day)
tem_now.text = '%s度' % (tem)
进入循环后需要对获取信息的速度加以限制
while True:
time_now = time.localtime()
timer.text = '%02d:%02d' % (time_now.tm_hour, time_now.tm_min)
if time_now.tm_min == 0:
wea, tem_night, tem_day, tem = get_weather()
weather.text = wea
temperature.text = '%d℃-%d℃' % (tem_night, tem_day)
tem_now.text = '%s度' % (tem)
if time_now.tm_hour == 0:
date.text = '%d月%d日' % (time_now.tm_mon, time_now.tm_mday)
week.text = get_wday(time_now.tm_wday)
pass
这样就OK了
完整代码如下
import board
import displayio
import os
import wifi
import ssl
import socketpool
import adafruit_ntp
import rtc
import time
import ipaddress
import adafruit_requests
import adafruit_imageload
from adafruit_display_text import label, wrap_text_to_lines
from adafruit_bitmap_font import bitmap_font
# 获得WIFI名字和密码
ssid = os.getenv("CIRCUITPY_WIFI_SSID")
password = os.getenv("CIRCUITPY_WIFI_PASSWORD")
# 周几文字的数据
def get_wday(week_today):
if week_today == 0:
return "周一"
elif week_today == 1:
return "周二"
elif week_today == 2:
return "周三"
elif week_today == 3:
return "周四"
elif week_today == 4:
return "周五"
elif week_today == 5:
return "周六"
elif week_today == 6:
return "周日"
# 连接WIFI,若连接失败会报错
print("Connecting to", ssid)
wifi.radio.connect(ssid, password)
time.sleep(10)
print("Connected to", ssid)
# 获得天气情况
def get_weather():
requests = adafruit_requests.Session(
socketpool.SocketPool(wifi.radio), ssl.create_default_context())
appid = os.getenv("appid")
appsecret = os.getenv("appsecret")
res = requests.get(
'https://v0.yiketianqi.com/free/day?appid=%s&appsecret=%s&unescape=1&city=南阳' % (appid, appsecret)).json()
return res['wea'], res['tem_night'], res['tem_day'], res['tem']
# 使用rtc
rtc.RTC().datetime = adafruit_ntp.NTP(socketpool.SocketPool(
wifi.radio), tz_offset=8, server='ntp.aliyun.com').datetime
# 引入图片
image, palette = adafruit_imageload.load(
'/images/ysqd.bmp', bitmap=displayio.Bitmap, palette=displayio.Palette)
tile_grid = displayio.TileGrid(image, pixel_shader=palette)
group = displayio.Group()
group.append(tile_grid)
# 设置板子的亮度和是否翻转
board.DISPLAY.brightness = 0.5 #
board.DISPLAY.rotation = 0 #
word_font = bitmap_font.load_font("wenquanyi_13px.pcf")
# 日期的设置
date = label.Label(word_font, text="test", color=0x000000)
date.x = 10 #
date.y = 20
date.scale = 2 #
group.append(date)
# 周几的设置
week = label.Label(word_font, text="周五", color=0x000000)
week.x = 120
week.y = 20
week.scale = 2
group.append(week)
# 时间的设置
timer = label.Label(word_font, text='10:17', color=0x779649)
timer.x = 15
timer.y = 65
timer.scale = 2 #
group.append(timer)
# 天气文字的设置
weather = label.Label(word_font, text='阴', color=0x3271ae)
weather.x = 10
weather.y = 110
weather.scale = 2 #
group.append(weather)
# 温度文字的设置
temperature = label.Label(word_font, text='10度-15度', color=0x3271ae)
temperature.x = 60
temperature.y = 110
temperature.scale = 2
group.append(temperature)
# 事实温度文字的设置
tem_now = label.Label(word_font, text='10度', color=0x3271ae)
tem_now.x = 150
tem_now.y = 65
tem_now.scale = 2
group.append(tem_now)
# 获得时间
time_now = time.localtime()
timer.text = '%02d:%02d' % (time_now.tm_hour, time_now.tm_min)
date.text = '%d月%d日' % (time_now.tm_mon, time_now.tm_mday)
week.text = get_wday(time_now.tm_wday)
wea, tem_night, tem_day, tem = get_weather()
weather.text = wea
temperature.text = '%s℃-%s℃' % (tem_night, tem_day)
tem_now.text = '%s度' % (tem)
board.DISPLAY.show(group)
while True:
time_now = time.localtime()
timer.text = '%02d:%02d' % (time_now.tm_hour, time_now.tm_min)
if time_now.tm_min == 0:
wea, tem_night, tem_day, tem = get_weather()
weather.text = wea
temperature.text = '%d℃-%d℃' % (tem_night, tem_day)
tem_now.text = '%s度' % (tem)
if time_now.tm_hour == 0:
date.text = '%d月%d日' % (time_now.tm_mon, time_now.tm_mday)
week.text = get_wday(time_now.tm_wday)
pass
内容三:任务总结
本次活动是我真正意义上接触ESP32,之前只接触过STM32,51之类的单片机。通过本次活动,我学到了许多ESP32的使用方法以及CircuitPython的操作。明白了esp32在某些地方使用上确实比32简单些。这次任务带我进入了嵌入式的新领域,使我的技能得到了训练,也使得之前一知半解的知识得到了补充,收获满满,非常感谢得捷电子和ee对本次活动的支持。
代码资源链接
follow me 第二期全套代码-嵌入式开发相关资料下载-EEWORLD下载中心
|