1247|1

18

帖子

6

TA的资源

一粒金砂(中级)

楼主
 

【得捷电子Follow me第2期】玩转Adafruit ESP32-S3 TFT Feather (全流程综合贴) [复制链接]

  本帖最后由 QuaX_Chow 于 2023-10-14 16:18 编辑

2023.8.19(开始动工,存个草稿先)


2023.10.6

这次给大家带来的是Follow Me第二期任务的速通教学(鸽了很久

本次活动基本查阅查阅手册就可以通过

感谢主办方eeworld得捷电子的支持,感谢各位提前发帖的大神坛友

内容一:3-5分钟短视频

内容二:本篇

内容三:本人整理的资料包(包含示例代码、任务代码、官方资料、部分外部库,打不开就是还没审核,可以先用老的资料包)

 


1、Quick Start

首先我们快速搭建一下我们所需的开发环境,本次使用的是官方推荐的Mu Editor编写CircuitPython。

使用数据线将开发板与电脑相连,并连按两次reset键(如下所示)

当Neo灯绿灯常亮,红色LED呼吸灯闪烁时,电脑就会显示连接到了一个新磁盘。将资料包-other中的adafruit-circuitpython-adafruit_feather_esp32s3_tft-en_US-8.2.3.uf2拖入新磁盘的根目录即可为开发板快速添加circuitpython支持包。
或者直接去官网下载,下载链接:circuitpy包
待文件移动完成后开发板屏幕上即会显示开发板信息和uid(如下图)同时出现一个新u盘

PS:circuitpython其实还有个中文包,但在屏幕上显示的是拼音。。(adafruit-circuitpython-adafruit_feather_esp32s3_tft-zh_Latn_pinyin-8.2.3.uf2如下所示)

再在电脑上安装好Mu Editor(下载地址),当然如thonny啥的也是可以的。
 
我们想要编辑代码的话,直接打开根目录(如下所示)下的code.py并编辑即可
 

首先我们先刷两个测试程序,程序都可以在手册或者对应库的示例代码里找到

第一个是可以直接使用的点灯程序,直接cv进code.py即可。
下载成功即可看见板载LED闪烁。
import board
import digitalio
import time
led = digitalio.DigitalInOut(board.LED)
led.direction = digitalio.Direction.OUTPUT
while True:
    led.value = True
    time.sleep(0.5)
    led.value = False
    time.sleep(0.5)

测试代码①


 

第二个是图片显示代码,添加资料包中other-lib中的imageload库即可实现。

import board
import displayio
import adafruit_imageload


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.show(group)
#
while True:
    pass

测试代码②

添加外部库的方法:打开外部库的压缩包,将对应文件夹复制进开发板u盘根目录下的lib文件夹即可(如imageload库)

 

 

本代码需在根目录下创建image文件夹,并在该文件夹下粘贴下面这张已转格式的图片↓

测试图片
ys

 
2、任务1:控制屏幕显示中文(必做任务)
我们想要控制屏幕显示中文的话,需要使用bitmap库将点阵字体加载到displayio中,可以使用bdf、pcf等格式,非常简单
 
import board
import displayio
from adafruit_display_text import label, wrap_text_to_lines
from adafruit_bitmap_font import bitmap_font

# 设置要显示的字符串
dis_str = "完成屏幕的控制并且能显示中文"

def screen_dispstr(str):
    # 根据屏幕旋转角度确定每行显示的字符数
    if board.DISPLAY.rotation % 180 == 0:
        char_num = 23  # 横屏
    else:
        char_num = 13  # 竖屏

    strbuf = ""
    for i in range(len(str) / char_num):
        # 将字符串按每行字符数拆分,并添加换行符
        strbuf = strbuf + str[i * char_num:(i + 1) * char_num] + "\n"
    return strbuf

# 初始化显示屏
display = board.DISPLAY
board.DISPLAY.brightness = 0.35
board.DISPLAY.rotation = 0

# 加载字体和设置颜色
font = bitmap_font.load_font("wenquanyi_10pt.pcf")
color = 0x00FFFF

# 创建显示文本的组和标签
text_group = displayio.Group()
text_area = label.Label(font, text=screen_dispstr(dis_str), color=color)
text_area.x = 2
text_area.y = 6
text_area.line_spacing = 0.8
text_area.scale = 1

text_group.append(text_area)
display.show(text_group)

# 持续显示
while True:
    pass

 
 
  1. 初始化显示屏模块,并设置亮度和旋转角度
  2. 加载所需的字体文件
  3. 创建显示文本的组和标签对象,并设置文本内容、颜色、位置和缩放
  4. 将文本标签对象添加到显示文本的组中
  5. 使用display.show将显示文本的组添加到显示屏上进行显示
  6. 进入持续显示的循环,保持文本显示在屏幕上
 
 
xszw

 
 
 
3、任务2:网络功能使用(必做任务)
首先我们为开发板配置一下网络功能所需的信息。
在根目录下新建一个文本文档,命名为settings,保存后将后缀改为.toml(结果如下图)。
想要编辑的话以文本格式打开直接编辑或者有VS Code的话也可以直接编辑。

 

想实现Adafruit ESP32-S3 TFT Feather的网络功能也十分简单,参考手册P143(如下图所示)就行,但与手册方法不同的是,我们的配置信息存在了settings.toml文件中。
手册P143截图

我们先连接WiFi

settings.toml中,配置你想要连接的WiFi的ID和密码。

PS:只支持2.4G频段,手机开个热点就行

具体如下:

WIFI_SSID = "HOMO"
WIFI_PASSWORD = "1145141919810"

配置完成后,直接在code.py中使用示例代码即可

# SPDX-FileCopyrightText: 2020 Brent Rubell for Adafruit Industries
#
# SPDX-License-Identifier: MIT

import os
import wifi

print("ESP32-S3 Station Test")

print(f"My MAC address: {[hex(i) for i in wifi.radio.mac_address]}")

print("Available WiFi networks:")
for network in wifi.radio.start_scanning_networks():
    print("\t%s\t\tRSSI: %d\tChannel: %d" % (str(network.ssid, "utf-8"),
                                             network.rssi, network.channel))
wifi.radio.stop_scanning_networks()

print(f"Connecting to {os.getenv('WIFI_SSID')}")
wifi.radio.connect(os.getenv("WIFI_SSID"), os.getenv("WIFI_PASSWORD"))
print(f"Connected to {os.getenv('WIFI_SSID')}")
print(f"My IP address: {wifi.radio.ipv4_address}")
连接WiFi
 
wifi

 
 

再创建热点

settings.toml中,配置开发板AP的ID和密码。

具体如下:

AP_SSID = "HOMO"
AP_PASSWORD = "1145141919810"

以下代码基于自带的库

 
#创建热点
import os
import wifi
import adafruit_requests

print("ESP32-S3 Access Point Test")

print(f"My MAC address: {[hex(i) for i in wifi.radio.mac_address]}")

wifi.radio.start_ap(os.getenv("AP_SSID"), os.getenv("AP_PASSWORD"))

#显示网络信息
print(f"My SSID: {"HOMO"}")

print(f"My PASSWORD: {"1145141919810"}")

while True:
    pass

创建热点

 

ap

 

 

 

 
4、任务3:控制WS2812B(必做任务)
要控制WS2812B,只需在lib中添加外部库neopixel.py(详见other-lib
再再参考一下示例代码(笑
稍微改一下,用数组存储颜色信息
按钮直接用杜邦线代替,反正原理是一样的。同时添加软件消抖,效果不错
import time
import board
import digitalio
import neopixel

button_pin = board.D5

Color_Num = 0

# 彩虹数组
RAINBOW_COLORS = [
    (255, 0, 0),     # 红
    (255, 165, 0),   # 橙
    (255, 255, 0),   # 黄
    (0, 255, 0),     # 绿
    (0, 0, 255),     # 蓝
    (75, 0, 130),    # 靛蓝
    (238, 130, 238)  # 紫
]

#初始为红
Color = RAINBOW_COLORS[0]

button = digitalio.DigitalInOut(button_pin)
button.direction = digitalio.Direction.INPUT
button.pull = digitalio.Pull.UP

debounce_delay = 0.1  # 消抖延迟,单位为秒
button_pressed = False

pixel = neopixel.NeoPixel(board.NEOPIXEL, 1)
pixel.brightness = 0.3

while True:
    if not button.value and not button_pressed:  # 按键被按下且之前未被按下
        button_pressed = True
        time.sleep(debounce_delay)  # 延迟一段时间进行消抖
        if not button.value:  # 确认按键仍然被按下
            Color = RAINBOW_COLORS[Color_Num]
            # 设置led颜色
            pixel.fill(Color)
            Color_Num += 1
            if Color_Num == 7:
                Color_Num -= 7
    elif button.value:  # 按键未被按下
        button_pressed = False

 

neo(1)

 

七彩循环:
xunhuan

 
 
 
5、任务4.1:日历&时钟(选做任务)

 

导入所需的库和模块,包括wifi、os、ssl、socketpool、adafruit_requests。

连接wifi,发送HTTP请求获取无锡的天气信息的JSON数据。

解析JSON数据,提取需要显示的天气信息,包括城市信息、当前时间、空气质量、温度范围、湿度、PM2.5等。

显示,结束(

 

##连接wifi --------------------------------------------------------------------------------------
# SPDX-FileCopyrightText: 2020 Brent Rubell for Adafruit Industries
#
# SPDX-License-Identifier: MIT

import os
import wifi

print("ESP32-S3 Station Test")

print(f"My MAC address: {[hex(i) for i in wifi.radio.mac_address]}")

print("Available WiFi networks:")
for network in wifi.radio.start_scanning_networks():
    print("\t%s\t\tRSSI: %d\tChannel: %d" % (str(network.ssid, "utf-8"),
                                             network.rssi, network.channel))
wifi.radio.stop_scanning_networks()

print(f"Connecting to {os.getenv('WIFI_SSID')}")
wifi.radio.connect(os.getenv("WIFI_SSID"), os.getenv("WIFI_PASSWORD"))
print(f"Connected to {os.getenv('WIFI_SSID')}")
print(f"My IP address: {wifi.radio.ipv4_address}")


## END连接wifi --------------------------------------------------------------------------------------




## 访问网络 --------------------------------------------------------------------------------------
import ssl
import socketpool
import adafruit_requests
# 请求获取JSON
## api  http://t.weather.sojson.com/api/weather/city/101280601
JSON_TIME_URL = "http://t.weather.itboy.net/api/weather/city/101190201"


pool = socketpool.SocketPool(wifi.radio)
requests = adafruit_requests.Session(pool, ssl.create_default_context())


## END访问网络 --------------------------------------------------------------------------------------




## 读取解析Json ---------------------------------------------------------------------------------------
print(f"Fetching and parsing json from {JSON_TIME_URL}")
response = requests.get(JSON_TIME_URL)
print("-" * 40)
## print(f"Time: {response.json()['sysTime2']}")
print("-" * 40)
print(response.json())


weather = response.json()
cityInfo  = weather['cityInfo']
city_weather = weather['data']
forecast = city_weather['forecast']

dis_str = ""+cityInfo['parent']+' '+cityInfo['city'] +' '+weather['time'][:11] + forecast[0]['week']
dis_str += '\n 空气质量:'+city_weather['quality'] +" " +forecast[0]['type']
dis_str += "\n 最"+forecast[0]['high']+' 最'+forecast[0]['low']
dis_str += "\n 湿度: "+city_weather['shidu']
dis_str += "\n PM2.5:"+str(city_weather['pm25']) +' PM10:'+str(city_weather['pm10'])
dis_str += "\n 注意!!  "+forecast[0]['notice']

## END读取解析Json ---------------------------------------------------------------------------------------




## 显示天气信息	---------------------------------------------------
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.9
board.DISPLAY.rotation = 0

font = bitmap_font.load_font("wenquanyi_10pt.pcf")

## 字体颜色
color = 0x9499CA



text_group = displayio.Group()
text_area = label.Label(font, text=dis_str, color=color)
text_area.x = 0
text_area.y = 10
text_area.line_spacing = 0.8
text_area.scale = 1


text_group.append(text_area)
display.show(text_group)
while True:
    pass

## END显示天气信息	---------------------------------------------------

 
 
  1. 使用WiFi模块连接到无线网络,SocketPool和Requests库访问API,获取天气预报的JSON数据
  2. 然后,解析JSON数据并提取所需的天气信息
  3. 使用Displayio库在TFT显示屏上显示天气信息

 

rili

 

 

 
6、任务4.2:WS2812B效果控制(选做任务)
先瞅一眼任务要求:
完成一个Neopixel(12灯珠或以上)控制器,通过按键和屏幕切换展示效果
凑巧上学期末整了块DFRobot 8*8的RGB灯板👇

硬件有了那直接开整

控制部分直接参考上面neo的程序就行

循环切换7个颜色

屏幕显示颜色只要在循环加个判断就行

 
#以下是一起动捏
import board
import digitalio
import time
import neopixel

led_pin = board.D13
button_pin = board.D5

# 设置LED数量和引脚
NUM_LEDS = 64
LED_PIN = board.D12
Color_Num = 0


# 初始化Neopixel对象
pixels = neopixel.NeoPixel(LED_PIN, NUM_LEDS, brightness=0.2, auto_write=False)

# 彩虹数组
RAINBOW_COLORS = [
    (255, 0, 0),     # 红
    (255, 165, 0),   # 橙
    (255, 255, 0),   # 黄
    (0, 255, 0),     # 绿
    (0, 0, 255),     # 蓝
    (75, 0, 130),    # 靛蓝
    (238, 130, 238)  # 紫
]

#初始为红
Color = RAINBOW_COLORS[0]

led = digitalio.DigitalInOut(led_pin)
led.direction = digitalio.Direction.OUTPUT

button = digitalio.DigitalInOut(button_pin)
button.direction = digitalio.Direction.INPUT
button.pull = digitalio.Pull.UP

debounce_delay = 0.1  # 消抖延迟,单位为秒
button_pressed = False

while True:
    if not button.value and not button_pressed:  # 按键被按下且之前未被按下
        button_pressed = True
        time.sleep(debounce_delay)  # 延迟一段时间进行消抖
        if not button.value:  # 确认按键仍然被按下
            led.value = not led.value
            # 在每个LED上设置彩虹颜色
            for i in range(NUM_LEDS):
                Color = RAINBOW_COLORS[Color_Num]
                pixels[i] = Color
                pixels.show()
                time.sleep(0.001)
            Color_Num += 1
            if Color_Num == 7:
                Color_Num -= 7
    elif button.value:  # 按键未被按下
        button_pressed = False

 

  1. 通过设置LED的数量和引脚,初始化Neopixel,定义彩虹颜色数组

  2. DigitalInOut来控制LED和按钮的引脚。将LED引脚设置为输出模式,按钮引脚设置为输入模式,启用上拉电阻

  3. 使用time模块来进行延迟和消抖操作。在按键按下时延迟一段时间进行消抖,确保只有有效的按键触发

  4. 循环检测按钮状态。当按钮被按下时,切换LED的状态并设置Neopixel的像素颜色为彩虹颜色。每次按下按钮,彩虹颜色的索引加一,当达到最大索引时重新开始

 

8864

 

 

 
7、任务5:通过网络控制WS2812B(可选任务,非必做)
翻手册翻手册翻手册
官方手册P148
链接直达Adafruit IO:链接
说实话,我还是第一次接触mqtt,但跟着例程走一遍也是没啥问题的
(后半段有所修改)
 
import time
import ssl
import os
from random import randint
import microcontroller
import socketpool
import wifi
import board
import neopixel
import displayio
import terminalio
import adafruit_minimqtt.adafruit_minimqtt as MQTT
from adafruit_io.adafruit_io import IO_MQTT
from adafruit_display_text import bitmap_label, label

# WiFi
try:
    print("Connecting to %s" % os.getenv("WIFI_SSID"))
    wifi.radio.connect(os.getenv("WIFI_SSID"), os.getenv("WIFI_PASSWORD"))
    print("Connected to %s!" % os.getenv("WIFI_SSID"))
# Wi-Fi connectivity fails with error messages, not specific errors, so this except is broad.
except Exception as e:  # pylint: disable=broad-except
    print("Failed to connect to WiFi. Error:", e, "\nBoard will hard reset in 30 seconds.")
    time.sleep(30)
    microcontroller.reset()

# Initialise NeoPixel
pixel = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.3)

# Set up TFT display
display = board.DISPLAY
board.DISPLAY.brightness = 0.35
board.DISPLAY.rotation = 0

group = displayio.Group()

weather_color=0x00FF00

neopixel_area = label.Label(terminalio.FONT, text="NeoPixel", color=weather_color)
neopixel_area.x = 2
neopixel_area.y = 30
neopixel_area.line_spacing = 0.8
neopixel_area.scale = 1

main_group = displayio.Group()
main_group.append(group)
main_group.append(neopixel_area)

# Show the main group on the display
display.show(main_group)

# Define callback functions which will be called when certain events happen.
def connected(client):
    print("Connected to Adafruit IO!  Listening for NeoPixel changes...")
    # Subscribe to Adafruit IO feed called "neopixel"
    client.subscribe("neopixel")


def message(client, feed_id, payload):  # pylint: disable=unused-argument
    print("Feed {0} received new value: {1}".format(feed_id, payload))
    #neopixel_area.text = "Feed {0} received new value: {1}".format(feed_id, payload)
    if feed_id == "neopixel":
        pixel.fill(int(payload[1:], 16))


# Create a socket pool
pool = socketpool.SocketPool(wifi.radio)

# Initialize a new MQTT Client object
mqtt_client = MQTT.MQTT(
    broker="io.adafruit.com",
    username=os.getenv("AIO_USERNAME"),
    password=os.getenv("AIO_KEY"),
    socket_pool=pool,
    ssl_context=ssl.create_default_context(),
)

# Initialize Adafruit IO MQTT "helper"
io = IO_MQTT(mqtt_client)

# Set up the callback methods above
io.on_connect = connected
io.on_message = message

timestamp = 0
while True:
    try:
        # 如果Adafruit IO未连接...
        if not io.is_connected:
            # 连接到MQTT代理
            print("Connecting to Adafruit IO...")
            io.connect()

        # 显示颜色信息

        neopixel_area.text = "Color: #{:02X}{:02X}{:02X}".format(*pixel[0])  # 更新文本显示

        # 显示更新后的屏幕
        display.refresh()

        # 显示延迟
#        time.sleep(0.5)

        # 显式处理消息循环
        io.loop()

    # 处理可能的失败
    except Exception as e:  # pylint: disable=broad-except
        print("Failed to get or send data, or connect. Error:", e,
              "\nBoard will hard reset in 30 seconds.")
        time.sleep(30)
        microcontroller.reset()

 

  1. 使用WiFi模块连接到无线网络,并在TFT显示屏上显示连接状态
  2. 使用MQTT协议连接到Adafruit IO,并订阅"neopixel"的feed
  3. 当接收到"neopixel" feed的新值时,更新NeoPixel的颜色,并在TFT显示屏上显示颜色信息

 

wlanneo

 

 

 

对本活动的心得体会

 

我觉得本次活动对我来说十分有意义,因为开发板+1因为新接触了一种语法,并且增加了自己的ddl

 

任务总体难度适中,且可查的中文资料较少,可以培养rtfm的好习惯

 

建议下次活动直接来块小Linux开发板

 

(完)2023/10/14

 

 

最新回复

用bitmap库将点阵字体加载到displayio中,可以使用bdf、pcf等格式,是比较方便   详情 回复 发表于 2023-10-15 08:04
点赞 关注
 
 

回复
举报

6861

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

用bitmap库将点阵字体加载到displayio中,可以使用bdf、pcf等格式,是比较方便

 
 
 

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

查找数据手册?

EEWorld Datasheet 技术支持

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

 
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
快速回复 返回顶部 返回列表