[Digi-Key Follow me Issue 2] Play with Adafruit ESP32-S3 TFT Feather (Full Process Comprehensive Post)
[Copy link]
This post was last edited by QuaX_Chow on 2023-10-14 16:18
2023.8.19 (start construction, save a draft first)
2023.10.6
This time I bring you a quick tutorial for the second phase of Follow Me (I have been waiting for a long time
This activity can be basically checked by referring to the manual
Thanks to the organizers eeworld and Digi-Key Electronics for their support, and thanks to all the great forum friends who posted in advance.
Content 1: 3-5 minutes short video
Content 2: Main article
Content 3: The data package compiled by myself (including sample code, task code, official information, and some external libraries. If you can't open it, it means it has not been reviewed yet. You can use the old data package first)
1、Quick Start
First, let's quickly build the development environment we need. This time we use the officially recommended Mu Editor to write CircuitPython.
Connect the development board to the computer using a data cable and press the reset button twice (as shown below)
When the Neo light turns green and the red LED light flashes, the computer will show that a new disk is connected. Drag adafruit-circuitpython-adafruit_feather_esp32s3_tft-en_US-8.2.3.uf2 from the data package-other into the root directory of the new disk to quickly add the circuitpython support package for the development board.
After the file is moved, the development board information and UID will be displayed on the development board screen (as shown below) and a new USB flash drive will appear.
PS: CircuitPython actually has a Chinese package, but what is displayed on the screen is pinyin. (Adafruit-circuitpython-adafruit_feather_esp32s3_tft-zh_Latn_pinyin-8.2.3.uf2 is shown below)
If we want to edit the code, just open the code.py in the root directory (as shown below) and edit it.
First, we will run two test programs. The programs can be found in the manual or in the sample code of the corresponding library.
The first one is a lighting program that can be used directly. Just cv it into code.py.
If the download is successful, you can see the onboard LED flashing.
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)
Test code ①
灯
The second is the image display code, which can be achieved by adding the imageload library in other-lib in the data package .
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
Test code ②
How to add an external library : open the compressed package of the external library and copy the corresponding folder into the lib folder in the root directory of the development board USB disk (such as the imageload library)
This code needs to create an image folder in the root directory and paste the following converted image in the folder↓
Test image
2. Task 1: Control the screen to display Chinese (mandatory task)
If we want to control the screen to display Chinese, we need to use the bitmap library to load the dot matrix font into displayio. We can use bdf, pcf and other formats. It is very simple.
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
- Initialize the display module and set the brightness and rotation angle
- Load the required font files
- Create group and label objects to display text, and set the text content, color, position, and scale
- Add a text label object to the group that displays the text
- Use display.show to add the group that displays the text to the display for display
- Enter a continuous display loop to keep the text displayed on the screen
3. Task 2: Use of network functions (mandatory task)
First, we configure the information required for the network function for the development board.
Create a new text document in the root directory, name it settings , save it and change the suffix to .toml (the result is as shown below).
If you want to edit it, open it in text format and edit it directly, or if you have VS Code, you can edit it directly.
It is also very simple to realize the network function of Adafruit ESP32-S3 TFT Feather . Just refer to P143 of the manual (as shown below). However, unlike the manual method, our configuration information is stored in the settings.toml file.
Screenshot from Manual P143
Let’s connect to WiFi first
In settings.toml , configure the ID and password of the WiFi you want to connect to.
PS: Only supports 2.4G frequency band, just open a hotspot on your phone
details as follows:
WIFI_SSID = "HOMO"
WIFI_PASSWORD = "1145141919810"
After the configuration is complete, just use the sample code in 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}")
Connect to WiFi
Recreate hotspot
In settings.toml , configure the ID and password of the development board AP.
details as follows:
AP_SSID = "HOMO"
AP_PASSWORD = "1145141919810"
The following code is based on the built-in library
#创建热点
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
Create Hotspot
ap
4. Task 3: Control WS2812B (required task)
To control WS2812B, just add the external library neopixel.py in lib (see other-lib for details )
Let’s refer to the sample code again (laughing)
Slightly change it to use an array to store color information
The button is directly replaced by Dupont wire, anyway, the principle is the same. At the same time, add software to eliminate jitter, the effect is good
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
Colorful cycle:
5. Task 4.1: Calendar & Clock (optional task)
Import the required libraries and modules, including wifi, os, ssl, socketpool, adafruit_requests.
Connect to wifi and send HTTP request to obtain JSON data of Wuxi's weather information.
Parse JSON data and extract weather information to be displayed, including city information, current time, air quality, temperature range, humidity, PM2.5, etc.
Display, end (
##连接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显示天气信息 ---------------------------------------------------
- Use the WiFi module to connect to the wireless network, the SocketPool and Requests libraries to access the API, and obtain the JSON data of the weather forecast
- Then, parse the JSON data and extract the required weather information
- Use the Displayio library to display weather information on the TFT display
rili
6. Task 4.2: WS2812B effect control (optional task)
Let’s take a look at the task requirements first:
Complete a Neopixel (12 or more LEDs) controller and display the effects by pressing buttons and switching the screen
By chance , I got a DFRobot 8*8 RGB light board at the end of last semester
If you have the hardware, you can start
For the control part, just refer to the neo program above.
Cycle through 7 colors
To display the color on the screen, just add a judgment in the loop
#以下是一起动捏
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
-
Initialize Neopixel by setting the number and pins of LEDs and define the rainbow color array
-
DigitalInOut to control the LED and button pins. Set the LED pin to output mode, the button pin to input mode, and enable the pull-up resistor
-
Use the time module to perform delay and debounce operations. Delay a period of time to debounce when a key is pressed to ensure that only valid keys are triggered
-
Loop through the button states. When the button is pressed, toggle the LED state and set the Neopixel pixel color to a rainbow color. Each time the button is pressed, the rainbow color index increases by one, and starts over when the maximum index is reached.
8864
7. Task 5: Control WS2812B via the network (optional task, not required)
Flip the manual Flip the manual Flip the manual
Official Manual P148
Direct link to Adafruit IO: Link
To be honest, this is my first time to use MQTT, but it's no problem to follow the example
(The second half has been modified)
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()
- Use the WiFi module to connect to a wireless network and display the connection status on the TFT display
- Connect to Adafruit IO using MQTT protocol and subscribe to the "neopixel" feed
- When a new value from the "neopixel" feed is received, the color of the NeoPixel is updated and the color information is displayed on the TFT display.
wlanneo
My experience with this activity
I think this event is very meaningful to me, because the development board +1 because I have come into contact with a new syntax and added my own ddl
The overall difficulty of the task is moderate, and there is less Chinese information available, which can help cultivate good habits of rtfm
It is recommended that you get a small Linux development board for the next event.
(END)2023/10/14
|