本帖最后由 EPTmachine 于 2023-12-17 22:42 编辑
很荣幸能获得Follow Me第三期的活动资格,本次使用的板卡是Seeed Studio XIAO ESP32C3。是一款基于 Espressif ESP32-C3 Wi-Fi/蓝牙双模芯片的 IoT 迷你开发板。ESP32-C3 是一款32 位 RISC-V CPU,具有强大的计算能力,包含FPU(浮点运算单元),可进行32 位单精度运算。它具有出色的射频性能,支持IEEE 802.11 b/g/n Wi-Fi和蓝牙 5 (LE)协议。正如其名,Seeed Studio XIAO ESP32C3具有小巧精致的外形,还可通过表面贴装整合到更复杂的PCB上。
本次活动指定的配件都是Seeed Studio出品的,在其官网上可以找到详细的板卡资料。
XIAO ESP32C3介绍界面。
除了XIAO ESP32C3外,本次选购的配件包括了XIAO系列的通用拓展板(板载OLED、蜂鸣器、用户按键、SD卡插槽等外设)、外接天线、AHT20温湿度传感器、光照传感器等模块,可以用于实现常见的IOT应用。
开发板各个组件的实物连接图如下。
开发板的整体设计很紧凑,而且官网提供资料很丰富,便于开发者使用。
主要完成了以下几个任务,相应的代码如下
介绍视频:[https://training.eeworld.com.cn/video/38742]
任务一:使用MicroPython系统
安装Thonny
使用MicroPython进行编程需要在开发板和PC上安装和配置MicroPython环境。
在PC端,安装Thonny IDE,安装过程十分简单,安装选项选择默认即可。
Thonny 还提供了免安装的版本,两者的使用方式很简单,大家可以自行选择适合自己的版本。
烧写ESP32C3固件
XIAO ESP32C3需要烧录相应的MicroPython镜像来支持MicroPython程序运行。在win10环境中需要安装Python和esptool支持程序的烧写。
在Python官网下载Python3.11的安装包。在命令行中输入python --version
查看安装的Python版本。
接下来安装esptool工具
pip install esptool
从github上拉取esptool的仓库(这里感觉有点怪,win10的Python环境太乱了,我的电脑安装了很多Python版本,这里虽然运行成功了,不保证能复现。。。)
git clone https:
在第一次烧录MicroPython的镜像时,需要进行全片的flash擦除,这里的COM23根据自己系统和端口不同更换为合适的参数。
./esptool.py
从MicroPython的官网下载ESP32C3的固件,将固件放到epstool仓库的根目录。
然后从地址0x00开始烧写固件。
./esptool.py
开发环境使用
Thonny 启动后提示环境配置,选择默认即可。
在View选项卡中选择需要显示的菜单,帮助开发者开发。
烧写的固件中自带了常用的测试工具,只需要编写几行代码就可以开始编写应用程序了。
Thonny中提供了可以用于输入命令行的Shell,可用于数据不同的Python指令。
在烧写的micropython固件中集成了系统功能函数,可用于查看系统的信息,了解运行的硬件平台的参数和固件的信息。通过输入help('modules')
可以查看安装好的库。
使用import os导入系统功能函数,在shell调用相关的函数,比如os.uname即可得到系统的信息。
在Thonny操作界面的右侧可以看到本地文件和开发板上的文件系统,对其进行管理。
开发板上要自动运行程序,至少需要一个boot.py文件,该文件会在开发板上电后自动运行。编写下列函数并上传到开发板中。
import os
import gc
BOARD_NAME = os.uname().machine
gc.collect()
print("开发板:%s" % BOARD_NAME)
print("剩余内存: %0.2fM" % (gc.mem_free()/1024/1024))
输出结果如图
任务2:驱动扩展板上的OLED屏幕
任务二的目标是是使用扩展板上的OLED屏幕显示文字信息。该屏幕的驱动芯片为SSD1306,通讯协议为I2C,在官方提供的固件中提供了I2C的驱动函数,但是没有SSD1306的驱动函数。需要添加额外的驱动库,本文使用官方提供的ssd1306驱动库。
硬件介绍
ESP32C3模组的IO引脚分布以及扩展板的引脚和功能分布如下图。
由图中信息可知IO引脚使用的是GPIO6(SDA)和GPIO7(SCL)。
驱动库上传
在micropython中,第三方的驱动库一般都放在根目录下的lib文件夹中。

软件编写
确定了OLED屏幕的驱动接口和驱动库,在此基础上就可以编写相应的应用程序了。
首先是显示文字,以下代码实现在OLED屏幕上显示文字
import time
from machine import Pin, SoftI2C
import ssd1306
import math
i2c = SoftI2C(scl=Pin(7), sda=Pin(6))
oled_width = 128
oled_height = 64
oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)
oled.fill(0)
oled.text("Hello, Seeder!", 10, 15)
oled.text("/////", 30, 40)
oled.text("(`3`)y", 30, 55)
oled.show()
效果如图所示。
接下来是在屏幕上显示图形。
import time
from machine import Pin, SoftI2C
import ssd1306
import math
i2c = SoftI2C(scl=Pin(7), sda=Pin(6))
oled_width = 128
oled_height = 64
oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)
center_x = oled_width
center_y = oled_height
square_size = 6
num_squares = 12
angle_increment = 2 * math.pi / num_squares
while True:
oled.fill(0)
for i in range(num_squares):
angle = i * angle_increment
x = int(center_x + (center_x - square_size-30) * math.cos(angle))
y = int(center_y + (center_x - square_size-30) * math.sin(angle))
for j in range(num_squares):
angle_j = j * angle_increment
x_j = int(center_x + (center_x - square_size-30) * math.cos(angle_j))
y_j = int(center_y + (center_x - square_size-30) * math.sin(angle_j))
oled.fill_rect(x_j, y_j, square_size, square_size, 1)
oled.fill_rect(x, y, square_size, square_size, 0)
oled.show()
time.sleep_ms(100)
效果如图所示
任务3:使用蜂鸣器播放音乐
硬件介绍
ESP32C3模组的IO引脚分布以及扩展板的引脚和功能分布如下图。
由图中信息可知控制蜂鸣器的引脚是GPIO5(PWM)
软件编写
蜂鸣器的控制GPIO或者PWM即可实现控制,以下代码实现简单的蜂鸣器提示
import time
from time import sleep
import machine
from machine import Pin, SoftI2C
buzzer_pin = machine.Pin(5, machine.Pin.OUT)
buzzer = machine.PWM(buzzer_pin)
buzzer.freq(1047)
while True:
buzzer.duty(10)
time.sleep(1)
buzzer.duty(0)
time.sleep(1)
以下代码实现控制蜂鸣器播放音乐
import machine
import time
buzzer_pin = machine.Pin(5, machine.Pin.OUT)
buzzer = machine.PWM(buzzer_pin)
buzzer.freq(1047)
NOTE_C4 = 262
NOTE_D4 = 294
NOTE_E4 = 330
NOTE_F4 = 349
NOTE_G4 = 392
NOTE_A4 = 440
NOTE_B4 = 494
NOTE_C5 = 523
NOTE_D5 = 587
NOTE_E5 = 659
NOTE_F5 = 698
NOTE_G5 = 784
NOTE_A5 = 880
NOTE_B5 = 988
notes = [
NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0,
NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0,
NOTE_C5, NOTE_D5, NOTE_B4, NOTE_B4, 0,
NOTE_A4, NOTE_G4, NOTE_A4, 0,
NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0,
NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0,
NOTE_C5, NOTE_D5, NOTE_B4, NOTE_B4, 0,
NOTE_A4, NOTE_G4, NOTE_A4, 0,
NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0,
NOTE_A4, NOTE_C5, NOTE_D5, NOTE_D5, 0,
NOTE_D5, NOTE_E5, NOTE_F5, NOTE_F5, 0,
NOTE_E5, NOTE_D5, NOTE_E5, NOTE_A4, 0,
NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0,
NOTE_D5, NOTE_E5, NOTE_A4, 0,
NOTE_A4, NOTE_C5, NOTE_B4, NOTE_B4, 0,
NOTE_C5, NOTE_A4, NOTE_B4, 0,
NOTE_A4, NOTE_A4,
NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0,
NOTE_C5, NOTE_D5, NOTE_B4, NOTE_B4, 0,
NOTE_A4, NOTE_G4, NOTE_A4, 0,
NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0,
NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0,
NOTE_C5, NOTE_D5, NOTE_B4, NOTE_B4, 0,
NOTE_A4, NOTE_G4, NOTE_A4, 0,
NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0,
NOTE_A4, NOTE_C5, NOTE_D5, NOTE_D5, 0,
NOTE_D5, NOTE_E5, NOTE_F5, NOTE_F5, 0,
NOTE_E5, NOTE_D5, NOTE_E5, NOTE_A4, 0,
NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0,
NOTE_D5, NOTE_E5, NOTE_A4, 0,
NOTE_A4, NOTE_C5, NOTE_B4, NOTE_B4, 0,
NOTE_C5, NOTE_A4, NOTE_B4, 0,
NOTE_E5, 0, 0, NOTE_F5, 0, 0,
NOTE_E5, NOTE_E5, 0, NOTE_G5, 0, NOTE_E5, NOTE_D5, 0, 0,
NOTE_D5, 0, 0, NOTE_C5, 0, 0,
NOTE_B4, NOTE_C5, 0, NOTE_B4, 0, NOTE_A4,
NOTE_E5, 0, 0, NOTE_F5, 0, 0,
NOTE_E5, NOTE_E5, 0, NOTE_G5, 0, NOTE_E5, NOTE_D5, 0, 0,
NOTE_D5, 0, 0, NOTE_C5, 0, 0,
NOTE_B4, NOTE_C5, 0, NOTE_B4, 0, NOTE_A4
]
durations = [
125, 125, 250, 125, 125,
125, 125, 250, 125, 125,
125, 125, 250, 125, 125,
125, 125, 375, 125,
125, 125, 250, 125, 125,
125, 125, 250, 125, 125,
125, 125, 250, 125, 125,
125, 125, 375, 125,
125, 125, 250, 125, 125,
125, 125, 250, 125, 125,
125, 125, 250, 125, 125,
125, 125, 125, 250, 125,
125, 125, 250, 125, 125,
250, 125, 250, 125,
125, 125, 250, 125, 125,
125, 125, 375, 375,
250, 125,
125, 125, 250, 125, 125,
125, 125, 250, 125, 125,
125, 125, 375, 125,
125, 125, 250, 125, 125,
125, 125, 250, 125, 125,
125, 125, 250, 125, 125,
125, 125, 375, 125,
125, 125, 250, 125, 125,
125, 125, 250, 125, 125,
125, 125, 250, 125, 125,
125, 125, 125, 250, 125,
125, 125, 250, 125, 125,
250, 125, 250, 125,
125, 125, 250, 125, 125,
125, 125, 375, 375,
250, 125, 375, 250, 125, 375,
125, 125, 125, 125, 125, 125, 125, 125, 375,
250, 125, 375, 250, 125, 375,
125, 125, 125, 125, 125, 500,
250, 125, 375, 250, 125, 375,
125, 125, 125, 125, 125, 125, 125, 125, 375,
250, 125, 375, 250, 125, 375,
125, 125, 125, 125, 125, 500
]
def play_song():
total_notes = len(notes)
for i in range(total_notes):
current_note = notes<i>
wait = durations<i>
if current_note != 0:
buzzer.duty(512)
buzzer.freq(current_note)
else:
buzzer.duty(0)
time.sleep_ms(wait)
buzzer.duty(0)
while True:
play_song()
任务4:连接WiFi网络
ESP32C3支持Wifi功能,可以连接互联网,从网上获取信息,比如网络时间信息。
连接网络
参考官方提供的代码,填入自己的wifi名称和密码,即可实现联网。
import network
import urequests
import utime as time
wifi_ssid = "user_wifi"
wifi_password = "user_passwd"
def scan_and_connect():
station = network.WLAN(network.STA_IF)
station.active(True)
print("Scanning for WiFi networks, please wait...")
for ssid, bssid, channel, RSSI, authmode, hidden in station.scan():
print("* {:s}".format(ssid))
print(" - Channel: {}".format(channel))
print(" - RSSI: {}".format(RSSI))
print(" - BSSID: {:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}".format(*bssid))
print()
while not station.isconnected():
print("Connecting...")
station.connect(wifi_ssid, wifi_password)
time.sleep(10)
print("Connected!")
print("My IP Address:", station.ifconfig()[0])
scan_and_connect()
串口输出的结果如下:
Scanning for WiFi networks, please wait...
.....
Connected!
My IP Address: 192.168.170.168
获取网络时间并显示
网络时间的获取是通过向网络时间服务器发起请求,在返回的json字符串中提取相关的信息,配合之前实现的ssd1306显示功能,从而实现获取网络时间并显示的功能。
代码如下
from machine import Pin, SoftI2C
import ssd1306
from time import sleep
import time
import network
import urequests
import ujson
i2c = SoftI2C(scl=Pin(7), sda=Pin(6))
oled_width = 128
oled_height = 64
oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)
station = network.WLAN(network.STA_IF)
station.active(True)
wifi_ssid = "user_wifi"
wifi_password = "user_passwd"
url = "http://worldtimeapi.org/api/timezone/America/New_York"
print("Scanning for WiFi networks, please wait...")
authmodes = ['Open', 'WEP', 'WPA-PSK' 'WPA2-PSK4', 'WPA/WPA2-PSK']
for (ssid, bssid, channel, RSSI, authmode, hidden) in station.scan():
print("* {:s}".format(ssid))
print(" - Channel: {}".format(channel))
print(" - RSSI: {}".format(RSSI))
print(" - BSSID: {:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}".format(*bssid))
print()
while not station.isconnected():
print("Connecting...")
station.connect(wifi_ssid, wifi_password)
time.sleep(10)
print("Connected!")
print("My IP Address:", station.ifconfig()[0])
while True:
response = urequests.get(url)
if response.status_code == 200:
data = ujson.loads(response.text)
ny_datetime = data["datetime"]
date_part, time_part = ny_datetime.split("T")
time_part = time_part[:8]
timezone = data["timezone"]
oled.fill(0)
oled.text("New York Date:", 0, 0)
oled.text(date_part, 0, 10)
oled.text("New York Time:", 0, 20)
oled.text(time_part, 0, 30)
oled.text("Timezone:", 0, 40)
oled.text(timezone, 0, 50)
oled.show()
else:
oled.text("Failed to get the time for New York!")
oled.show()
显示效果如图
任务5:使用外部传感器
了解硬件
扩展板上提供了I2C和模拟转换接口,分别对应了ATH20温湿度传感器和模拟关线传感器。
Grove AHT20介绍页面温湿度传感器的接口为I2C。其与扩展板的连接如图所示。
Grove Light Sensor v1.2对其进行了详细的介绍。模块与拓展板的连接如图所示。
添加驱动库
AHT20驱动库地址为:[https://github.com/targetblank/micropython_ahtx0],调用以下指令拉取相关的代码。
git clone https:
将代码仓库中的ahtx0.py复制到设备的lib文件夹中,就可以在代码中使用温湿度传感器了。
软件编写
首先编写读取温湿度传感器的代码,以下代码实现对温湿度传感器数据的读取。
import utime
from machine import Pin, I2C
import ahtx0
i2c = I2C(0, scl=Pin(7), sda=Pin(6), freq=400000)
sensor = ahtx0.AHT10(i2c)
while True:
print("\nTemperature: %0.2f C" % sensor.temperature)
print("Humidity: %0.2f %%" % sensor.relative_humidity)
utime.sleep(1)
通过串口打印出来的数据如下所示:
接下来通过ADC读取光照传感器的模拟信号,得到当前的光照强度。代码如下:
import utime
from machine import Pin, ADC
sensor_dev = ADC(Pin(2))
sensor_dev.atten(ADC.ATTN_11DB)
while True:
sensor_value = 0
for i in range(0,16):
sensor_value = sensor_value + sensor_dev.read()
sensor_value = sensor_value / 16
Vbattf = 2 * sensor_value / 1000.0
print("\nLight value is: %0.2f C" % Vbattf)
utime.sleep(1)
光照强度的读取结果如下图所示:
总结
本次活动提供的ESP32C3是为物联网应用设计的,配合MicroPython可以快速实现物联网应用的快速开发。