本帖最后由 superw 于 2023-10-16 01:06 编辑
内容一、演示视频
演示视频
内容二、 项目总结报告
任务0:准备工作
本期follow me活动使用的是来自Adafruit的ESP32-S3 TFT Feather,可以在arduino和circuitpython环境下开发,也可以使用乐鑫官方的esp-idf进行开发,由于circuitpython本身也是由adafruit开发维护的,所以本着适配性和兼容性,选择使用circuitpython进行学习。
首先需要将板子刷上circuitpython的固件,让circuitpython在开发板上跑起来。
在https://circuitpython.org/board/adafruit_feather_esp32s3_tft/下载基于ESP32-S3 TFT Feather的circuitpython UF2文件。
然后双击板上的reset按键,这个时候电脑上会出现一个叫FTHRS3BOOT的磁盘驱动器,把UF2文件直接拖到里面,磁盘驱动器会消失,并自动加载UF2文件,之后会出现一个叫CIRCUITPY的磁盘驱动器。这样就代表circuitpython的固件成功刷入,可以在板上进行circuitpython学习开发。具体刷入过程以及过程中LED状态的变化,可以根据官方文档操作
https://learn.adafruit.com/adafruit-esp32-s3-tft-feather/circuitpython
任务1:控制屏幕显示中文
任务要求:完成屏幕的控制,并且能显示中文
Circuitpython内嵌的只有一种字体,可以通过terminalio模块实现调用,进而操控TFT屏幕,但是调用这个模块只能显示英文。具体代码如下:
import board
import terminalio
from adafruit_display_text import label
text = "Hello world"
text_area = label.Label(terminalio.FONT, text=text)
text_area.x = 10
text_area.y = 10
board.DISPLAY.show(text_area)
while True:
pass
通过terminalio.FONT设置字体,并显示text中的文本。现象如下:
进一步要想显示中文,需要有一个中文字库。根据直播中老师的介绍讲解以及其他坛友分享的经验,通过下面的代码可以在屏幕上显示元素周期表中前20位元素的中文。
import board
import displayio
from adafruit_display_text import label
from adafruit_bitmap_font import bitmap_font
display = board.DISPLAY
font = bitmap_font.load_font("fonts/wenquanyi_13px.pcf")
text_group = displayio.Group()
text = "氢氦锂铍硼\n碳氮氧氟氖\n钠镁铝硅磷\n硫氯氩钾钙"
text_area = label.Label(font,text=text,color=0x00FF00,x=10,y=10)
text_group.append(text_area)
display.show(text_group)
while True:
pass
此段代码中导入了一个新的模块bitmap_font,通过这个模块可以将添加进来的字库文件加载进来并进一步使用。现象如下:
任务2:网络功能使用
任务要求:完成网络功能的使用,能够创建热点和连接到WiFi
根据官方提供的文档https://learn.adafruit.com/adafruit-esp32-s3-tft-feather/circuitpython-internet-test,可以使用板子连接到附近的WiFi,此种状态下,板子作为station连接附件的AP。根据Circuitpython的内嵌WiFi模块的文档https://docs.circuitpython.org/en/8.2.x/shared-bindings/wifi/index.html,可以将板子设为AP模式,等待附件的设备连接。具体代码如下:
import board
import time
import digitalio
import wifi
import os
import ipaddress
ssid = "Adafruit"
password = "12344321"
led = digitalio.DigitalInOut(board.LED)
led.direction = digitalio.Direction.OUTPUT
button = digitalio.DigitalInOut(board.BUTTON)
button.switch_to_input(pull=digitalio.Pull.UP)
button_count = 0
def AP_Mode(status):
if status:
print("ESP32-S3 AP Mode Open")
print(f"My AP MAC address: {[hex(i) for i in wifi.radio.mac_address_ap]}")
#wifi.radio.set_ipv4_address_ap
wifi.radio.start_ap(ssid,password)
if wifi.radio.ap_active:
print("ap_active")
else:
print("restart")
else:
print("ESP32-S3 AP Mode Close")
wifi.radio.stop_ap()
def Station_Mode(status):
if status:
print("ESP32-S3 Station Mode Open")
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('CIRCUITPY_WIFI_SSID')}")
wifi.radio.connect(os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD"))
print(f"Connected to {os.getenv('CIRCUITPY_WIFI_SSID')}")
print(f"My IP address: {wifi.radio.ipv4_address}")
ping_ip = ipaddress.IPv4Address("8.8.8.8")
ping = wifi.radio.ping(ip=ping_ip)
# retry once if timed out
if ping is None:
ping = wifi.radio.ping(ip=ping_ip)
if ping is None:
print("Couldn't ping 'google.com' successfully")
else:
# convert s to ms
print(f"Pinging 'google.com' took: {ping * 1000} ms")
if wifi.radio.connected:
print("station connected")
else:
print("restart")
else:
print("ESP32-S3 Station Mode Close")
wifi.radio.stop_station()
while True:
if not button.value:
button_count += 1
if button_count%2:
AP_Mode(False)
Station_Mode(True)
else:
Station_Mode(False)
AP_Mode(True)
else:
a=1
led.value = not led.value
time.sleep(0.5)
当第一次按下按键时,会先关闭板子的AP模式,启动板子的station模式,连接附近的WiFi;当第二次按下按键时,会先关闭板子的station模式,启动板子的AP模式,等待附件的设备连接。现象如下:
任务3:控制WS2812B
任务要求:使用按键控制板载Neopixel LED的显示和颜色切换
使用按键进行计数,当第一次按下时,控制Neopixel LED显示红色,第二次显示绿色,第三次显示蓝色,依次是红绿蓝青紫黄白黑,当按键的值超过8之后,使用random模块生成随机数控制Neopixel LED显示的颜色,同时用random模块控制Neopixel LED显示的亮度。具体代码如下:
import board
import digitalio
import time
import random
import neopixel
led = digitalio.DigitalInOut(board.LED)
led.direction = digitalio.Direction.OUTPUT
button = digitalio.DigitalInOut(board.BUTTON)
button.switch_to_input(pull=digitalio.Pull.UP)
button_count = 0
pixel = neopixel.NeoPixel(board.NEOPIXEL,1)
pixel.brightness = 0.3
while True:
if not button.value:
button_count += 1
pixel.brightness = random.random()
if button_count == 1:
pixel.fill((255,0,0))
elif button_count == 2:
pixel.fill((0,255,0))
elif button_count == 3:
pixel.fill((0,0,255))
elif button_count == 4:
pixel.fill((0,255,255))
elif button_count == 5:
pixel.fill((255,0,255))
elif button_count == 6:
pixel.fill((255,255,0))
elif button_count == 7:
pixel.fill((255,255,255))
elif button_count == 8:
pixel.fill((0,0,0))
else:
pixel.fill((random.randint(0,255),random.randint(0,255),random.randint(0,255)))
else:
a=1
led.value = not led.value
time.sleep(0.5)
现象如图:
任务4:WS2812B效果控制
任务要求:完成一个Neopixel(12灯珠或以上)控制器,通过按键和屏幕切换显示效果
通过按键控制12灯珠Neopixel显示不同的灯效,并在TFT屏幕上做相应的显示。具体代码如下:
import time
import board
import digitalio
import neopixel
import terminalio
import displayio
from adafruit_display_text import label
button = digitalio.DigitalInOut(board.BUTTON)
button.switch_to_input(pull=digitalio.Pull.UP)
button_count =0
BORDER = 20
FONTSCALE = 2
BACKGROUND_COLOR = 0x00FF00 # Bright Green
FOREGROUND_COLOR = 0xAA0088 # Purple
RED_COLOR = 0xFF0000
GREEN_COLOR = 0x00FF00
BLUE_COLOR = 0x0000FF
TEXT_COLOR = 0xFFFF00
display = board.DISPLAY
# On CircuitPlayground Express, and boards with built in status NeoPixel -> board.NEOPIXEL
# Otherwise choose an open pin connected to the Data In of the NeoPixel strip, i.e. board.D1
pixel_pin = board.D5
# The number of NeoPixels
num_pixels = 12
# The order of the pixel colors - RGB or GRB. Some NeoPixels have red and green reversed!
# For RGBW NeoPixels, simply change the ORDER to RGBW or GRBW.
ORDER = neopixel.GRB
pixels = neopixel.NeoPixel(
pixel_pin, num_pixels, brightness=0.2, auto_write=False, pixel_order=ORDER
)
def wheel(pos):
# Input a value 0 to 255 to get a color value.
# The colours are a transition r - g - b - back to r.
if pos < 0 or pos > 255:
r = g = b = 0
elif pos < 85:
r = int(pos * 3)
g = int(255 - pos * 3)
b = 0
elif pos < 170:
pos -= 85
r = int(255 - pos * 3)
g = 0
b = int(pos * 3)
else:
pos -= 170
r = 0
g = int(pos * 3)
b = int(255 - pos * 3)
return (r, g, b) if ORDER in (neopixel.RGB, neopixel.GRB) else (r, g, b, 0)
def rainbow_cycle(wait):
for j in range(255):
for i in range(num_pixels):
pixel_index = (i * 256 // num_pixels) + j
pixels[i] = wheel(pixel_index & 255)
pixels.show()
time.sleep(wait)
def TFT_show(color,color_text):
splash = displayio.Group()
display.show(splash)
inner_bitmap = displayio.Bitmap(display.width - BORDER * 2, display.height - BORDER * 2, 1)
inner_palette = displayio.Palette(1)
inner_palette[0] = color
inner_sprite = displayio.TileGrid(inner_bitmap, pixel_shader=inner_palette, x=BORDER, y=BORDER)
splash.append(inner_sprite)
text = color_text
text_area = label.Label(terminalio.FONT, text=text, color=TEXT_COLOR)
text_width = text_area.bounding_box[2] * FONTSCALE
text_group = displayio.Group(scale=FONTSCALE,x=display.width // 2 - text_width // 2,
y=display.height // 2,)
text_group.append(text_area) # Subgroup for text scaling
splash.append(text_group)
def switch_color_show(count):
if count == 1:
pixels.fill((255, 0, 0))
pixels.show()
TFT_show(RED_COLOR,"Red")
elif count == 2:
pixels.fill((0, 255, 0))
pixels.show()
TFT_show(GREEN_COLOR,"Green")
elif count == 3:
pixels.fill((0, 0, 255))
pixels.show()
TFT_show(BLUE_COLOR,"Blue")
elif count == 4:
rainbow_cycle(0.001) # rainbow cycle with 1ms delay per step
#else:
while True:
if not button.value:
time.sleep(0.2)
button_count += 1
print("button_count %d" %button_count)
switch_color_show(button_count)
if button_count == 4:
button_count = 0
else:
pass
心得体会
从第一期的RP2040的micropython,到这期ESP32-S3的circuitpython,得捷和eeworld真的有用心在帮大家打基础,这些MCU都是市面上非常常见的,在这些上面可以学习到很多基于MCU的微型python语言,非常棒,期待下期的新板卡!
内容三、可编译下载的代码
|