1.承诺:所提交的任务/项目内容为参与者在EEWorld原创首发
2. 项目介绍
项目 主要使用Seeed Studio XIAO ESP32C3 以及 扩展版,利用 温湿度传感器和 光度传感器,来实现 对环境的感知。利用Wi-Fi 技术 从网络获取文本,并显示在扩展版的显示屏。利用扩展版的板载蜂鸣器,实现了播放音乐的功能。在综合实践任务种,对比了常见的“高增益”天线的无线接收能力。
硬件部分:
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上。
扩展版:主要包含 OLED屏幕(ssd1306 驱动),包括蜂鸣器 SD卡槽 等等
3. 各任务功能对应的主要代码片段及说明
3.1 Wi-Fi 部分
import network
# 连接WiFi网络
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect('Wi-Fi SSID', 'Wi-Fi WPD')
# 等待连接成功
while not wlan.isconnected():
loading_circle.loading_circle(oled)
这段代码,主要使用network 模块,首先设置STA_IF 模式,然后 激活wlan,最后带入Wi-Fi 名称和密码,在等待连接种,让屏幕显示一个loading 的图案。
3.2 I2C的使用
from machine import Pin, SoftI2C
# 创建SoftI2C实例
i2c = SoftI2C(scl=Pin(7), sda=Pin(6))
# 扫描I2C设备
devices = i2c.scan()
#MPY: soft reboot
#Found I2C device at address: 0x38 #ATH20
#Found I2C device at address: 0x3c
#Found I2C device at address: 0x51
#Found I2C device at address: 0x44 #SHT35
# 打印找到的设备地址
for device in devices:
print("Found I2C device at address: %s" % hex(device))
温湿度传感器,使用前,可以使用这个脚本,来检查I2C 总线上的设备是否正常连接,对下一步有排查的作用。
3.3 温湿度传感器
from machine import Pin, SoftI2C
from ahtx0 import AHT20
import utime
# 创建SoftI2C实例
i2c = SoftI2C(scl=Pin(7), sda=Pin(6), freq=400_000)
# 创建AHT20实例
aht = AHT20(i2c)
while True:
# 读取温度和湿度
temp = aht.temperature
humi = aht.relative_humidity
print(f"温度: {temp:.2f} °C, 湿度: {humi:.2f} %")
utime.sleep(2)
首先,导入驱动,然后实例化一个I2C,使用的是 7 和 6 号针脚(这里扩展版上写的SCL 5 和 SDA4,不要混淆了),最后在大循环种,每隔2秒,收集并在调试器种打印当前的温度和湿度。
3.4 光度传感器
import utime
from machine import Pin, ADC
def readLight():
photoRes = ADC(Pin(2))
light = photoRes.read_u16()
print('light ',light)
light = round(light/65535*100,2)
return light
while True:
print("light: " + str(readLight()) +"%")
utime.sleep(3)
与I2C上的温湿度传感器不同,光照是通过ACD上的电压值来表示当前光线度,而且需要通过公式转化,转化成 光照百分比。连接口,选择的是左下方的 GND-3V3-N/A-0 这个接口使用。
3.5 蜂鸣器播放音乐
from buzzer_music import music
from time import sleep
#nokia
song = '0 E6 1 0;0 G6 1 0;1 F6 1 0;2 A5 1 0;4 B5 1 0;7 D6 1 0;8 F5 1 0;10 G5 1 0;12 D6 1 0;13 C6 1 0;14 E5 1 0;16 G5 1 0;18 C6 1 0;23 G6 1 0;24 F6 1 0;25 A5 1 0;27 B5 1 0;29 E6 1 0;30 D6 1 0;31 F5 1 0;33 G5 1 0;35 D6 1 0;36 C6 1 0;37 E5 1 0;39 G5 1 0;41 C6 1 0;69 G6 1 0;70 F6 1 0;71 A5 1 0;73 B5 1 0;75 E6 1 0;76 D6 1 0;77 F5 1 0;79 G5 1 0;81 D6 1 0;82 C6 1 0;83 E5 1 0;85 G5 1 0;87 C6 1 0;46 G6 1 0;47 F6 1 0;48 A5 1 0;50 B5 1 0;52 E6 1 0;53 D6 1 0;54 F5 1 0;56 G5 1 0;58 D6 1 0;59 C6 1 0;60 E5 1 0;62 G5 1 0;64 C6 1 0;161 G6 1 0;162 F6 1 0;163 A5 1 0;165 B5 1 0;167 E6 1 0;168 D6 1 0;169 F5 1 0;171 G5 1 0;173 D6 1 0;174 C6 1 0;175 E5 1 0;177 G5 1 0;179 C6 1 0;138 G6 1 0;139 F6 1 0;140 A5 1 0;142 B5 1 0;144 E6 1 0;145 D6 1 0;146 F5 1 0;148 G5 1 0;150 D6 1 0;151 C6 1 0;152 E5 1 0;154 G5 1 0;156 C6 1 0;92 G6 1 0;93 F6 1 0;94 A5 1 0;96 B5 1 0;98 E6 1 0;99 D6 1 0;100 F5 1 0;102 G5 1 0;104 D6 1 0;105 C6 1 0;106 E5 1 0;108 G5 1 0;110 C6 1 0;115 G6 1 0;116 F6 1 0;117 A5 1 0;119 B5 1 0;121 E6 1 0;122 D6 1 0;123 F5 1 0;125 G5 1 0;127 D6 1 0;128 C6 1 0;129 E5 1 0;131 G5 1 0;133 C6 1 0'
"""
Find a piece of music on onlinesequencer.net, click edit,
then select all notes with CTRL+A and copy them with CTRL+C
Paste string as shown above after removing ";:" from
the end and "Online Sequencer:120233:" from the start
"""
from machine import Pin
#One buzzer on pin 5
mySong = music(song, pins=[Pin(5)])
#Four buzzers
#mySong = music(song, pins=[Pin(0),Pin(1),Pin(2),Pin(3)])
while True:
mySong.tick()
sleep(0.04)
播放库buzzer_music 使用的是https://github.com/james1236/buzzer_music 这个,音乐选择是诺基亚经典铃声,希望可以给大家带来记忆中的感觉。蜂鸣器,接入的针脚是5号,需要修改后才能使用开源库的功能。
3.6 Wi-Fi 信号检测
import network
import time
from time import sleep
import machine
from machine import Pin, SoftI2C
import ssd1306_v2 as ssd1306
import math
# ESP32C3 Pin assignment
i2c = SoftI2C(scl=Pin(7), sda=Pin(6)) # Adjust the Pin numbers based on your connections
oled_width = 128
oled_height = 64
oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)
# Network settings
wifi_ssid = "Wi-Fi SSID"
wifi_password = "Wi-Fi WPD"
machine.freq(160000000) # Set CPU frequency to 160 MHz (ESP8266 specific)
oled.text("Starting up...", 0, 0)
oled.show()
station = network.WLAN(network.STA_IF)
station.active(True)
station.connect(wifi_ssid, wifi_password)
time.sleep(1)
while not station.isconnected():
time.sleep(1)
oled.fill(0)
oled.text("Connecting to", 0, 0)
oled.text(wifi_ssid, 0, 20)
oled.show()
time.sleep(2)
oled.fill(0)
ip_address = station.ifconfig()[0] # Get the IP address
oled.text("Connected! ", 0, 0)
oled.text("IP Address:", 0, 20)
oled.text(ip_address, 0, 40)
oled.show()
time.sleep(2)
# Buzzer settings
buzzer_pin = machine.Pin(5, machine.Pin.OUT)
buzzer = machine.PWM(buzzer_pin)
buzzer.freq(1047)
buzzer.duty(0)
center_x = oled_width // 2
center_y = oled_height // 2
square_size = 6 # Size of each square
num_squares = 12 # Number of squares
angle_increment = 2 * math.pi / num_squares
x_pos = [12, 38, 64, 90]
statuses = ["poor", "normal", "good", "excellent"]
def calculate_block_count(rssi):
# Determine the number of blocks based on RSSI values
if -80 <= rssi < -60:
return 1
elif -60 <= rssi < -40:
return 2
elif -40 <= rssi < -20:
return 3
elif -20 <= rssi <= 10:
return 4
def draw_blocks(count):
for i in range(count):
y_pos = 50 - calculate_block_height(i)
oled.fill_rect(x_pos[i], y_pos, 24, calculate_block_height(i), 1)
for i in range(count, 4): # Clear unused area
y_pos = 50 - calculate_block_height(i)
oled.fill_rect(x_pos[i], y_pos, 24, calculate_block_height(i), 0)
def calculate_block_height(index):
return 10 * (index + 1)
loop_count = 0 # Initialize loop count
while loop_count < 2: # Execute the loop 24 times
oled.fill(0) # Clear the screen
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))
# Draw all squares
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) # Draw the square
oled.fill_rect(x, y, square_size, square_size, 0) # Erase the current square
oled.show()
time.sleep_ms(100) # Pause before next iteration
loop_count += 1 # Increase loop count
oled.fill(0) # Clear the screen after finishing the loops
oled.show()
while True:
oled.fill(0)
station = network.WLAN(network.STA_IF)
time.sleep(0.1)
rssi = station.status('rssi')
rssi_duty = 160 + 2 * int(rssi)
rssi_duty_2 = int(rssi_duty / 2)
rssi_abs = abs(int(rssi)) / 100
block_count = calculate_block_count(rssi)
status = statuses[block_count - 1] # Get the status text based on block count
draw_blocks(block_count)
oled.text(status, 11, 56)
oled.text("RSSI:", 0, 0)
oled.text(str(rssi), 40, 0)
# Update the display
oled.show()
buzzer.duty(rssi_duty)
time.sleep(rssi_abs)
buzzer.duty(0)
time.sleep(rssi_abs)
buzzer.duty(rssi_duty_2)
time.sleep(rssi_abs)
buzzer.duty(0)
time.sleep(rssi_abs)
接入代码后,会自动接入设定号的Wi-Fi ,然后再循环种检测信号强度,并根据信号强度,然后使用蜂鸣器给我不同音色的报警音。在综合时间项目中,我依次测试4种5款天线,并整理到对比结果种。
4. 各任务功能展示及说明
4.1 烧入Micropython 固件(任务1)
分为下载固件,安装esptool 模块,和刷入三个部分。
下载页面 : https://micropython.org/download/ESP32_GENERIC_C3/
安装方法: python -m pip install esptool
刷入方法: (端口和文件路径记得替换)
python -m esptool --chip esp32c3 --port COM21 --baud 921600 --before default_reset --after hard_reset --no-stub write_flash --flash_mode dio --flash_freq 80m 0x0 E:\ESP32_GENERIC_C3-20231005-v1.21.0.bin
成功结果:
4.2 连接Wi-Fi 显示文本(任务2+ 任务4)
import network
import urequests
import ujson
import loading_circle
import oled_init
from show_lines import print_lines,truncate_string
oled = oled_init.oled_init()
oled.text("Starting up...", 0, 0)
oled.show()
# 连接WiFi网络
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect('Wi-Fi SSID', 'Wi-Fi WPD')
# 等待连接成功
while not wlan.isconnected():
loading_circle.loading_circle(oled)
# 连接成功后访问互联网信息
response = urequests.get('https://api.quotable.io/random')
json_data = response.json()
print(json_data)
print('type(json_data)',type(json_data))
print(json_data['content'],json_data['author'])
oled.fill(0)
#oled.text(json_data['author'], 0, 0)
#oled.text(json_data['content'], 0, 10)
print_lines(oled,json_data['content'])
auther_str = truncate_string('-' + json_data['author'],15,1)
auther_str_px_len = len(auther_str)*8
auther_float_right_x = 128 - auther_str_px_len #oled_width = 128
oled.text(auther_str, auther_float_right_x, 55)
oled.show()
# 断开连接
wlan.disconnect()
接入网络后,从https://api.quotable.io/random 获取随机英文名人名言,显示在屏幕上
其中对于长文本的截取函数
from machine import Pin, SoftI2C
import ssd1306
# 定义OLED屏幕的宽度和高度
oled_width = 128
oled_height = 64
# 初始化I2C总线和OLED对象
i2c = SoftI2C(scl=Pin(7), sda=Pin(6))
oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)
# 长字符串
long_string = "This is a long string that needs to be wrapped when displayed on the OLED screen."
# 16 *6 = 96 字符
# 16 *5 = 80 内容
# 16 *1 作者
def truncate_string(s, n,dot_m=3):
if len(s) > n:
return s[:n-3] + "."*dot_m
else:
return s
def print_lines(oled, text, width=16, height=10):
# 长字符串处理
text = truncate_string(text,80)
lines = text.split('\n')
line_number = 0
for i, line in enumerate(lines):
for j in range(0, len(line), width):
segment = line[j:j+width]
oled.text(segment, 0, line_number*height)
line_number += 1
oled.show()
if __name__ == '__main__':
print_lines(oled,long_string)
成功结果:
4.3 蜂鸣器播放(任务3)
代码参考 3.5 章节
成功结果: 参考视频
4.4 温湿度传感器(任务5)
代码参考 3.3 章节
成功结果:
4.5 光度传感器(任务5)
代码参考 3.4 章节
成功结果:
4.6 “高增益”天线接收信号对比(综合实践)
代码参考 3.6 章节
所用硬件和结果
5. 对本活动的心得体会(包括意见或建议)
- XIAO ESP32 C3 确实 迷你可爱,性能尚可
- 加入扩展板后,更加全能,而且尺寸还是在众多开发板占有优势(与RPi对比)
- Grove 接口,还需要进一步的完善和发展,目前普及度还不是那么高
- 感谢EEWORLD,和群里的lightxixi 管理很负责,有问必答,还有各位小伙伴
- 项目有不对的地方,欢迎留言交流
附件
1.视频
https://training.eeworld.com.cn/video/38586
2. 源代码
https://download.eeworld.com.cn/detail/disk0/630249