一 任务汇总视频
视频链接:https://training.eeworld.com.cn/video/38575
二 开发板介绍
本次采用的是 Adafruit ESP32-S3 开发板带TFT屏幕,开发板采用的是上海乐鑫的ESP32-S3芯片。芯片是支持蓝牙(CircuitPython 不支持),wifi。据了解esp32-s3 及其衍生产品主要用于物联网产品中。
三 项目介绍
本次follow 2 是需要完成4个任务。我选择的是完成:1.控制屏幕显示中文 2.网络功能(包括创建wifi热点与连接wifi)3. 利用按键控制板载led的显示与颜色切换 4. 日历&时钟的显示。经过对比选择CircuitPython 来进行开发。看过“忙碌的死龙”的视频,结合自己实际使用的情况。发现如下问题:
1.选择采用web 的方式连接串口进行调试,时常会出现web页面连接串口不成功的情况。
2.选择vscode 打开code.py 文件,但是却无法查看到串口 REPL 的信息。
因而,选择mu editor 编辑器。 可以编辑CircuitPython 代码文件,同时可以稳定的打开串口调试窗口。
任务一 控制屏幕显示中文
本任务是首个任务,首先要熟悉怎么烧录 CircuitPython 的固件。访问https://circuitpython.org/board/adafruit_feather_esp32s3_tft/ 选择uf2 固件下载。然后,连接按开发板上的rst键2次,进入烧录界面。然后把下载的adafruit-circuitpython-adafruit_feather_esp32s3_tft-en_US-8.2.6.uf2 固件复制到开发板中。即烧录成功。
接下来,是要完成中文字体显示。首先需要知道,要调用相应的库。库的下载地址为:https://circuitpython.org/libraries。 根据烧录的程序下载“Bundle for Version 8.x”版本的库。解压到本地后,进入解压文件夹的lib文件夹下 复制adafruit_bitmap_font文件夹,adafruit_imageload文件夹,adafruit_display_text文件夹,到开发板的lib的文件夹下。
需要显示相应的汉字则需要处理字库。首先可以选择在网上下载相应的字库ttf文件。然后利用Fontmin 软件打开相应的字库文件,选取相应的需要用到的字符及数字,保存为一个新的ttf文件,该文件仅仅包含了所选的字符。然后利用FontForge软件生成bdf文件。但是此文件加载会慢。于是,参考https://learn.adafruit.com/custom-fonts-for-pyportal-circuitpython-display中提到的相关内容,利用https://adafruit.github.io/web-bdftopcf/ 网址,在线把bdf文件转成pcf文件。请注意,bdf文件其实比pcf文件要小,只是加载的慢。pcf 文件稍大,但是加载的快。接下来编辑代码显示相关的汉字。
# 在这里写上你的代码 :-)
import board
import displayio
# 导入外部库adafruit_imageload
import adafruit_imageload
from adafruit_display_text import label
from adafruit_bitmap_font import bitmap_font
# 使用固件自带的屏幕设备
display = board.DISPLAY
# 创建本例程里像组
group = displayio.Group()
# 加载图片
image, palette = adafruit_imageload.load("/pic/bg2.png")
# 是否开启透明
palette.make_transparent(3)
# 创建图片布局
grid = displayio.TileGrid(image, pixel_shader=palette)
# 将图片布局添加到图像组,由于是第一个添加的,默认是最下层
group.append(grid)
# 显示当前图像组
display.show(group)
# 加载字体并定义字体颜色为黑色
font = bitmap_font.load_font("/font/myfont2.pcf")
color = 0x000000
slog = label.Label(font, text="很高兴参加得捷电子", color=color)
slog.x = 30
slog.y = 38
group.append(slog)
slog2 = label.Label(font, text="Follow me 第二期", color=color)
slog2.x = 40
slog2.y = 70
group.append(slog2)
display.show(group)
while True:
pass
任务二 网络功能(包括创建wifi热点与连接wifi)
1. 连接wifi
wifi连接只需要修改相应的配置文件即可。修改开发板文件夹根目录下的 settings.toml文件相应字段。
CIRCUITPY_WIFI_SSID = "当前要连接的WIFI名"
CIRCUITPY_WIFI_PASSWORD = "当前要连接的WiFi密码"
保存后按板上的rst键,开发板会自动连接wifi,并获取ip地址。
2. wifi热点
import wifi
wifi.radio.start_ap("rz", "12345678")
以上2行代码可以让手机搜索rz 进行连接。在实验中发现,尽量设置了settings.toml中wifi连接,且热点连接成功,但是所连接的手机仍然不能上网。
任务三 利用按键控制板载led的显示与颜色切换
任务一中下载的库文件,复制neopixel.mpy 文件, adafruit_led_animation文件夹到 开发板的lib 文件夹下。
导入相应的库文件,并有选择的导入需要显示的灯的颜色。本利用boot按键来切换led灯的颜色,查看开发板电路原理图,
boot按键是低电平有效。则在代码中我们设置boot 上拉,输入。
然后利用按键次数,与所显示的颜色求余, 每3次循环一次。
# 导入board内置库
import board
# 导入time内置库
import time
from digitalio import DigitalInOut, Direction, Pull
import neopixel
# 从adafruit_led_animation.animation.blink库导入Blink
from adafruit_led_animation.animation.blink import Blink
from adafruit_led_animation.color import BLUE, RED, JADE, BLACK, ORANGE, GOLD, OLD_LACE
# str1 = "Leo"
# print("Hello world!",str1)
# 初始化像素灯引脚
pixel_pin = board.NEOPIXEL
# 设置像素灯数量
num_pixels = 1
# 初始化像素灯
pixels = neopixel.NeoPixel(
pixel_pin, num_pixels, brightness=0.2, auto_write=False, pixel_order=neopixel.GRB
)
# 初始化blink动态效果,speed 闪烁频率0.5m
blink = Blink(pixels, speed=0.5, color=BLACK)
# 初始化btn按钮对象
btn = DigitalInOut(board.BOOT0)
# 设置btn引脚为输入
btn.direction = Direction.INPUT
# 设置btn引脚为上拉
btn.pull = Pull.UP
# 定义led_color变量,用于五种颜色切换
led_color = 0
# 进入while循环
while True:
# 判断按键是否按下
if not btn.value:
# 若按键按下,则对led_color求余数,根据余数指定led颜色
if led_color % 3 == 0:
blink = Blink(pixels, speed=0.5, color=RED)
print("LED is RED")
elif led_color % 3 == 1:
blink = Blink(pixels, speed=0.5, color=BLUE)
print("LED is BLUE")
elif led_color % 3 == 2:
blink = Blink(pixels, speed=0.5, color=GOLD)
print("LED is GOLD")
# led_color 增加1
led_color = led_color + 1
else:
# 按键未按下时啥也不干
pass
time.sleep(0.2)
blink.animate()
其中所导入的adafruit_led_animation 库,我们选择了blink(闪烁)动态效果,因为板子上面只有1个灯,所以这个想过容易显示出来。Blink函数第一个参数是led灯的初始函数。利用
neopixel.NeoPixel 函数进行处理化led灯。默认库在固件里就固化了板载像素灯和屏幕实例, 可以使用board.NEOPIXEL来给引脚赋值,由于板载只有1个像素灯,所以灯的数量也只设置成1。
任务四 日历&时钟的显示
首先通过网络访问获取当前的时间,有了当前的时间,才能显示日期,及温度,天气。通过调用 http://vv.video.qq.com/checktime?otype=json 获取实时时间。编写星期转换函数,把星期用汉字显示出来。然后,在高德api申请一个key,通过requests函数获取相应的城市及天气情况。然后通过每一个小时获取相应的天气情况,并显示出来。本功能可以通过外网获得本地的外网的ip地址,然后通过ip地址获取本地的城市代码,进而调用高德的天气显示。 在实验中发现,在家里获取的外网ip地址,无法通过高德api获取相应的天气信息。因而,此段代码未贴出。
import board
# 导入displayio库(内置的)
import displayio
# 导入外部库adafruit_imageload,如果没有就在教程附件下载
import adafruit_imageload
# 导入外部库adafruit_display_text里的lable,用于显示标签
from adafruit_display_text import label
# 导入外部库adafruit_bitmap_font里的lable
from adafruit_bitmap_font import bitmap_font
# 导入os库,用来获取wifi信息
import os
# 导入rtc库,实现RTC时钟
import rtc
# 导入wifi、time库备用
import wifi
import time
# 导入网络库备用
import ssl
import socketpool
import adafruit_ntp
import adafruit_requests
import json
from adafruit_datetime import datetime, date,timezone,timedelta
# 使用固件自带的屏幕设备,不需要另行初始化屏幕参数
display = board.DISPLAY
# 创建本例程里的唯一图像组
group = displayio.Group()
# 加载图片
image, palette = adafruit_imageload.load("/pic/bg2.png")
# 是否开启透明
palette.make_transparent(0)
# 创建图片布局
grid = displayio.TileGrid(image, pixel_shader=palette)
# 将图片布局添加到图像组,由于是第一个添加的,默认是最下层
group.append(grid)
# 显示当前图像组
display.show(group)
# 加载字体并定义字体颜色为黑色
font = bitmap_font.load_font("/font/myfont1.pcf")
nun_font = bitmap_font.load_font("/font/myfont2.pcf")
color = 0x000000
# 初始化日期标签并设置x,y轴绘图坐标,然后将标签添加到图像组
date = label.Label(font, text="00月00日", color=color)
date.x = 50
date.y = 20
group.append(date)
# 初始化星期标签并设置x,y轴绘图坐标,然后将标签添加到图像组
week = label.Label(font, text="周一", color=color)
week.x = 30
week.y = 120
group.append(week)
# 初始化时间标签并设置x,y轴绘图坐标,然后将标签添加到图像组
timeT = label.Label(nun_font, text="00:00", color=color)
timeT.x = 15
timeT.y = 60
group.append(timeT)
# 初始化温度标签并设置x,y轴绘图坐标,然后将标签添加到图像组
temp = label.Label(font, text="30°", color=color)
temp.x = 80
temp.y = 120
group.append(temp)
# 初始化天气标签并设置x,y轴绘图坐标,然后将标签添加到图像组
tempzh = label.Label(font, text="晴", color=color)
tempzh.x = 130
tempzh.y = 120
group.append(tempzh)
# 显示修改后的图像组
display.show(group)
# while True:
# pass
# 使用os.getenv函数,从setting.toml文件里获取wifi ssid和密码
ssid = os.getenv("CIRCUITPY_WIFI_SSID")
password = os.getenv("CIRCUITPY_WIFI_PASSWORD")
# 连接到 wifi
print("Connecting to", ssid)
wifi.radio.connect(ssid, password)
print("Connected to", ssid)
TEXT_URL= "http://vv.video.qq.com/checktime?otype=json"
pool = socketpool.SocketPool(wifi.radio)
requests = adafruit_requests.Session(pool, ssl.create_default_context())
response = requests.get(TEXT_URL)
timestamp = time.time()
txt = response.text.split("QZOutputJson=")[1]
print(txt)
#print(txt)
data = json.loads(txt.replace(";",""))
local_time = datetime.fromtimestamp(data["t"])
rtc.RTC().datetime=time.localtime(data["t"] + 8*3600)
def get_wday(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 "周日"
# 初始化requests对象
pool = socketpool.SocketPool(wifi.radio)
requests = adafruit_requests.Session(pool, ssl.create_default_context())
def get_weather():
# 设置城市id
city = "450900"
# 这个函数使用的是高德API,使用该API需要先去注册相关账户,申请key。
key = ""
# 拼接天气链接url
getweather_url = "https://restapi.amap.com/v3/weather/weatherInfo?city=" + city + "&key=" + key
# 获取天气json数据
response = requests.get(getweather_url)
json_resp = response.json()
# 关闭连接
response.close()
# 解析json数据,并返回温度和天气信息
for da in json_resp["lives"]:
#print(da["temperature"])
return da["temperature"], da["weather"]
# 先创建一个status变量,用来在设备启动时获取天气信息
status = "boot"
# 主循环
while True:
# 每秒获取一次本地RTC时间
t = time.localtime()
# 首次启动或者本地RTC时间的分钟属性为0时,更新日期标签和天气标签
if (status == "boot" or t.tm_min == 0):
# 更新日期标签
date.text = "%d月%d日" % (t.tm_mon, t.tm_mday)
week.text = get_wday(t.tm_wday)
# 获取天气信息
str_t, str_tz = get_weather()
# 更新温度标签
temp.text = "%s°" % (str_t)
# 更新天气标签
tempzh.text = str_tz
status = "updated"
# 每隔1秒 更新一次时钟标签,用于动态显示
if (t.tm_sec % 2 == 0):
timeT.text = "%02d:%02d" % ( t.tm_hour, t.tm_min)
timeT.color = 0x000000
else:
timeT.text = "%02d:%02d" % ( t.tm_hour, t.tm_min)
timeT.color = 0xD9D7C9
# 刷新屏幕
display.show(group)
# 休眠1秒
time.sleep(1)
# while True:
# pass
对本次活动的心得:
本次是我第一次参加得捷的follow 项目,也是我第一次用CircuitPython进行编程,原本计划用arduino进行实现,但是因为工作的原因,时间不够了。CircuitPython无蓝牙库是一个遗憾。在后续的学习中,我计划用arduino 来实现同样的功能。希望我能获取更多的单片机的知识。
代码下载链接:https://download.eeworld.com.cn/detail/java620/629883