非常高兴能继续参与到第二期的followme活动中,本次活动我体会到了circuitpython的开发便捷性,同时终于能亲自动手练习机器识别,按照现有例程进行实践一遍,收获颇丰,虽然还有很多不懂的地方,但总算迈出了第一步。
我使用了两块开发板,Adafruit ESP32-S3 TFT Feather和xiao ble sense(自带六轴传感器,省去接线烦恼)。
根据楚大佬的教学视频,我试着生成了中文字体,感谢大佬。
任务1:控制屏幕显示中文(必做任务)
任务主要用到了displayio、text、font等模块和库,官方都有现成的提供,只需调用即可
'''
任务1:控制屏幕显示中文(必做任务)
完成屏幕的控制,并且能显示中文
'''
import displayio
import board
from adafruit_bitmap_font import bitmap_font
from adafruit_display_text import label
import time
display = board.DISPLAY
display.show(None)
font_file = "font/Fontquan-XinYiGuanHeiTi-Regular.pcf"
font = bitmap_font.load_font(font_file)
hanzi = label.Label(font, color=0xff22ff, scale=1)
hanzi.anchor_point = (0.5, 0.5)
hanzi.anchored_position = (display.width//2, display.height//2)
hanzi.text = "Follow me 第2期\n与得捷电子一起解锁开发板超能力!"
main_group = displayio.Group()
main_group.append(hanzi)
display.show(main_group)
n=0
while True :
n=(n+255) & 0xffffff
hanzi.color = n
time.sleep(0.05)
# print(n)
任务2:网络功能使用(必做任务)
主要使用了wifi模块,从setting.toml读取wifi的ssid和pwd,然后连接路由器,最后切换到ap模式
'''
任务2:网络功能使用(必做任务)
完成网络功能的使用,能够创建热点和连接到WiFi
'''
import wifi,time,os
import displayio
import board
from adafruit_bitmap_font import bitmap_font
from adafruit_display_text import label
import time
display = board.DISPLAY
display.show(None)
font_file = "font/Fontquan-XinYiGuanHeiTi-Regular.pcf"
font = bitmap_font.load_font(font_file)
hanzi = label.Label(font, color=0xff22ff, scale=1)
hanzi.anchor_point = (0.5, 0.5)
hanzi.anchored_position = (display.width//2, display.height//2)
hanzi.text = "连接wifi中"
main_group = displayio.Group()
main_group.append(hanzi)
display.show(main_group)
while not wifi.radio.connected:
try:
wifi.radio.connect(os.getenv("WIFI_SSID"), os.getenv("WIFI_PASSWORD"))
except Exception as ex:
print(ex)
time.sleep(0.5)
print('.')
print(f"My IP address: {wifi.radio.ipv4_address}")
hanzi.text = f"已连接 WiFi\n我的IP地址: {wifi.radio.ipv4_address}"
wifi.radio.stop_station()
time.sleep(1.0)
hanzi.text = "关闭station模式\n开启AP模式"
wifi.radio.start_ap("ap")
time.sleep(1.0)
hanzi.text = "已开启AP模式\n请连接"
任务3:控制WS2812B(必做任务)
主要使用到内置的neopixel模块,按下按键,屏幕和灯同时切换颜色
'''
**任务3:控制WS2812B(必做任务)**
使用按键控制板载Neopixel LED的显示和颜色切换
'''
import displayio
import board
from adafruit_bitmap_font import bitmap_font
from adafruit_display_text import label
from adafruit_display_shapes.rect import Rect
import time
import keypad
import neopixel
import digitalio
GREEN = 0x00ff00
RED = 0xff0000
BLUE = 0x0000ff
YELLOW = 0xffff00
color = [GREEN,RED,BLUE,YELLOW]
power = digitalio.DigitalInOut(board.NEOPIXEL_POWER)
power.direction = digitalio.Direction.OUTPUT
power.value = True
pixel = neopixel.NeoPixel(board.NEOPIXEL,1)
pixel.brightness = 0.5
pixel.fill(color[0])
display = board.DISPLAY
display.show(None)
font_file = "font/Fontquan-XinYiGuanHeiTi-Regular.pcf"
font = bitmap_font.load_font(font_file)
background = Rect(0,0,display.width-1,display.height-1,fill = color[0])
hanzi = label.Label(font, color=0x000000, scale=1)
hanzi.anchor_point = (0.5, 0.5)
hanzi.anchored_position = (display.width//2, display.height//2)
hanzi.text = "Follow me 第2期\n与得捷电子一起解锁开发板超能力!"
main_group = displayio.Group()
main_group.append(background)
main_group.append(hanzi)
display.show(main_group)
keys = keypad.Keys((board.BUTTON,), value_when_pressed=False, pull = True)
event = keypad.Event()
def getkey():
if keys.events.get_into(event):
if event.pressed:
# print(event)
return event.key_number
if event.released:
return event.key_number+10
# print(event)
pass
return -1
i=0
while True:
time.sleep(0.1)
key = getkey()
if key == 0:
i=(i+1 )%4
background.fill = color[i]
pixel.fill(color[i])
任务4:■ 分任务1:日历&时钟——完成一个可通过互联网更新的万年历时钟,并显示当地的天气信息
这时一个对前面任务的一个综合应用,需要用到displayio、wifi、socketpool等模块,使用wifi进行时间同步,从心知天气获取天气信息并更新到屏幕上
'''
**分任务1:日历&时钟**——
完成一个可通过互联网更新的万年历时钟,并显示当地的天气信息
'''
import wifi
import socketpool
import os , gc
import rtc
import time
import board
from adafruit_display_text import label
from adafruit_display_text import bitmap_label
import adafruit_ntp
import displayio
import terminalio
import adafruit_requests
import ssl
import adafruit_imageload
display = board.DISPLAY
display.show(None)
# if not wifi.Radio.connected:
print(f"Connecting to \r\n[ {os.getenv('WIFI_SSID')} ]")
while not wifi.radio.connected:
try:
wifi.radio.connect(os.getenv("WIFI_SSID"), os.getenv("WIFI_PASSWORD"))
except Exception as ex:
print(ex)
time.sleep(0.5)
print('.')
print(f"My IP address: {wifi.radio.ipv4_address}")
TIME_API = "http://worldtimeapi.org/api/ip"
pool = socketpool.SocketPool(wifi.radio)
ntp = adafruit_ntp.NTP(pool, tz_offset=8, server = "ntp1.aliyun.com")
try:
rtc.RTC().datetime = ntp.datetime
except Exception as e:
print(e)
pass
time_now = time.localtime()
print(time_now)
requests = adafruit_requests.Session(pool, ssl.create_default_context())
WEATHERKEY = os.getenv("WEATHER_KEY")
if WEATHERKEY =="":
WEATHERKEY = 'ctpe2272nswh94og'
LOCATION = os.getenv("LOCATION")
if LOCATION=="":
LOCATION = 'sanya'
UNITS = "c"
LANGUAGE = 'en'
print("Getting weather for {}".format(LOCATION))
# Set up the URL for fetching weather data
DATA_SOURCE = (
"http://api.seniverse.com/v3/weather/now.json?"
+ "key="
+ WEATHERKEY
+ "&location="
+ LOCATION
+ "&language="
+ LANGUAGE
+ "&unit="
+ UNITS
)
# Define time interval between requests
time_interval = 1800 # set the time interval to 30 minutes
# Set up display a default image
#image, 8bit png
image, palette = adafruit_imageload.load("/images/weather/icons8-sunny-64_.png")
# Set the transparency index color to be hidden
palette.make_transparent(0)
tile_grid = displayio.TileGrid(image,pixel_shader = palette)
tile_grid.x = display.width // 2 - tile_grid.tile_width // 2-10
tile_grid.y = display.height // 2 - tile_grid.tile_height // 2
display.show(None)
main_group = displayio.Group()
from adafruit_bitmap_font import bitmap_font
font_file = "font/LeagueSpartan-Bold-16.bdf"
font = bitmap_font.load_font(font_file)
# font = terminalio.FONT
# label
hour_label = label.Label(terminalio.FONT, color=0x00ff00, scale=6)
hour_label.anchor_point = (1.0, 0.0)
hour_label.anchored_position = (display.width-1, 0)
hour_label.text = "{:0>2d}".format(time_now.tm_hour)
minute_label = label.Label(terminalio.FONT, color=0x00ffff, scale=6)
minute_label.anchor_point = (1.0, 0.0)
minute_label.anchored_position = (display.width-1, 64)
minute_label.text = "{:0>2d}".format(time_now.tm_min)
main_group.append(hour_label)
main_group.append(minute_label)
# main_group.append(gc_label)
WEEK_COLOR_NOW = 0xCCCCCC
WEEK_COLOR_NOTNOW=0x444444
week_id = time_now.tm_wday
week_label=[]
weeks = ("MON","TUE","WED","THU","FRI","SAT","SUN")
for i in range(7):
wlabel = label.Label(font, color=WEEK_COLOR_NOTNOW, scale=1)
wlabel.anchor_point = (0.0, 0.0)
wlabel.anchored_position = (0, i*19)
wlabel.text = f"{weeks[i]}"
week_label.append(wlabel)
main_group.append(wlabel)
week_label[week_id].color = WEEK_COLOR_NOW
main_group.append(tile_grid)
# Create label for displaying temperature data
text_area = bitmap_label.Label(terminalio.FONT, scale=2)
text_area.anchor_point = (0.5, 0.5)
text_area.anchored_position = (display.width // 2-10, display.height // 2)
main_group.append(text_area)
display.show(main_group)
now = time.monotonic()
old = now
# Define function to get the appropriate weather icon
def get_weather_condition_icon(weather_condition):
if "cloud" in weather_condition.lower():
return "/images/weather/icons8-cloudy-64_.png"
elif "rain" in weather_condition.lower():
return "/images/weather/icons8-rain-64_.png"
elif "snow" in weather_condition.lower():
return "/images/weather/icons8-snowy-64_.png"
elif "clear" in weather_condition.lower():
return "/images/weather/icons8-sunny-64_.png"
else:
return "/images/weather/icons8-sunny-64_.png"
# Define function to update the background image based on weather conditions
def set_background(weather_condition, background_tile_grid):
bitmap_path = get_weather_condition_icon(weather_condition)
image, palette = adafruit_imageload.load(bitmap_path)
palette.make_transparent(0)
background_tile_grid.bitmap = image
background_tile_grid.pixel_shader = palette
def get_weather():
# Fetch weather data from OpenWeatherMap API
print("Fetching json from", DATA_SOURCE)
response = requests.get(DATA_SOURCE)
print(response.json())
# Extract temperature and weather condition data from API response
current_weather_condition = response.json()["results"][0]["now"]["text"]
current_temp = response.json()["results"][0]["now"]["temperature"]
print("Weather condition: ", current_weather_condition)
# Update label for displaying temperature data
text_area.text = "{}\n\n\n {} C".format(LOCATION, current_temp)
# Update background image
set_background(current_weather_condition, tile_grid)
get_weather()
old_w = time.monotonic()
while True:
now = time.monotonic()
if (now-old) >= 10.0:
old = time.monotonic()
time_now = time.localtime()
gc.collect()
hour_label.text = "{:0>2d}".format(time_now.tm_hour)
minute_label.text = "{:0>2d}".format( time_now.tm_min)
if time_now.tm_wday != week_id:
week_label[week_id].color = WEEK_COLOR_NOTNOW
week_label[time_now.tm_wday].color = WEEK_COLOR_NOW
weekid = time_now.tm_wday
if (now-old_w) >= time_interval:
old_w = time.monotonic()
get_weather()
gc.collect()
time.sleep(0.2)
任务4:■ 分任务5:AI功能应用——结合运动传感器,完成手势识别功能,至少要识别三种手势(如水平左右、前后、垂直上下、水平画圈、垂直画圈,或者更复杂手势
本次任务,选用了xiao ble sense开发板,此板自带6轴传感器,非常方便进行手势识别的开发,省去接线的烦恼,主要使用arduino进行开发,使用了tinyml进行动作的识别。
本次代码主要是基于原来的例程进行实践,作为学习使用。原本只有两个动作,我修改成了其他的三个动作。
采集到数据后,在上位机进行训练,获得模型文件,然后再编译进开发板,串口输出识别的结果。
在过程中,主要是提供动作的训练数据,分别保存到csv文件,并分别命名。
在classifier中,定义手势即可
// array to map gesture index to a name
const char* GESTURES[] = {
"circle",
"h2left",
"h2right"
};
|