[作品提交] 【得捷Follow me第3期】XIAO ESP32 C3 基于 MicroPthon 的IoT 项目报告

disk0   2023-12-9 22:18 楼主

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卡槽 等等

 

444.png

 

 

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

    成功结果:

101_epsl.png  

 

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)

 

成功结果:

image.png  

 

4.3 蜂鸣器播放(任务3)

    代码参考 3.5 章节

    成功结果: 参考视频

 

4.4 温湿度传感器(任务5)

    代码参考 3.3 章节

    成功结果:

image.png  

 

4.5 光度传感器(任务5)

    代码参考 3.4 章节

    成功结果:

image.png  

 

4.6 “高增益”天线接收信号对比(综合实践)

代码参考 3.6 章节

所用硬件和结果

image.png  


5. 对本活动的心得体会(包括意见或建议)

- XIAO ESP32 C3 确实 迷你可爱,性能尚可

- 加入扩展板后,更加全能,而且尺寸还是在众多开发板占有优势(与RPi对比)

image.png     - Seeed 官网资料比较丰富

    - Grove 接口,还需要进一步的完善和发展,目前普及度还不是那么高

    - 感谢EEWORLD,和群里的lightxixi 管理很负责,有问必答,还有各位小伙伴

    - 项目有不对的地方,欢迎留言交流

 

附件

1.视频

https://training.eeworld.com.cn/video/38586

 

2. 源代码

https://download.eeworld.com.cn/detail/disk0/630249

 

 

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复