第一部分 (3—5分钟短视频)
第二部分 (任务/项目总结报告)
必做任务1:使用MicroPython系统
任务目标:熟悉Seeed Studio XIAO ESP32C3开发板基本操作,安装esptool,并给开发板刷写MicroPython系统,完成入门程序的运行。
本任务主要是学会搭建Micro Python开发环境,并能运行第一个Micro Python程序。
包括Micro Python固件的烧录和PC端软件的安装。
ESP32C3支持使用MicroPython开发,但是出厂固件并不是MicroPython固件。
所以,需要先将开发板烧写成Micro Python固件。
根据官方资料显示,烧录MicroPython固件可以使用esptool。
环境搭建简要步骤如下,更加详细的环境搭建教程详见帖子:https://bbs.eeworld.com.cn/thread-1264550-1-1.html
1、安装esptool工具,如果电脑里已经有了esptool的同学可以跳过
2、下载MicroPython固件,网址:https://micropython.org/download/esp32c3/
3、将下载的固件放入到esptool工具目录下进行烧录
在esptool目录下运行cmd命令行
并运行如下命令:
esptool.exe --chip esp32c3 --port COM10 --baud 921600 --before default_reset --after hard_reset --no-stub write_flash --flash_mode dio --flash_freq 80m 0x0 esp32c3-usb-20230426-v1.20.0.bin
其中,COM10需要替换为电脑实际使用的串口号,esp32c3-usb-20230426-v1.20.0.bin替换为实际使用的。
正常下载完成后,重启开发板,就运行的是Micro Python固件了。
4、运行第一个MicroPython程序
运行MircorPython代码就有很多工具了,我习惯使用Thonny进行MicroPython的开发,Thonny软件的安装没有什么特殊性,按照普通软件的安装方法安装即可,这里不再做介绍了。
下面直接使用Thonny连接ESP32C3运行第一个Hello World程序
心得体会:MicroPython固件下载的过程还是相对比较复杂,必须要使用esptool功能才能下载,希望后期可以使用更简单的方式来下载固件,比如usb 拖拽模式。
必做任务2:驱动扩展板上的OLED屏幕
任务目标:利用OLED屏幕显示文字图形图片等信息
根据seeed官网的信息,XIAO扩展板上集成了一块0.96寸的I2C接口的oled屏幕,使用的引脚是GPIO6和GPIO7。
对于OLED的驱动,网上已经有很多大神写的开源库了,这里也就不再重复造轮子了
因为OLED屏幕的驱动芯片是SSD1306,所以在网上找到ssd1306的micropython库即可,多如牛毛,随便找一个都能用。
这里直接上链接:https://github.com/timotet/SSD1306/tree/master
文本和图形显示比较简单,直接调用ssd1306的库函数就能实现了
例如下面的显示文本代码:
# 显示文字
oled.fill(0) # Clear the screen
oled.text("Hello, ESP32C3!", 10, 15)
oled.text("EEWORLD!", 30, 40)
oled.text("TEXT TESET...", 20, 55)
oled.show() # Show the text
time.sleep(2)
图形显示也可以直接调用oled库函数:
#显示图形
oled.fill(0) # Clear the screen
oled.line(0, 0, 100, 100, 1) # 画线
oled.rect(60, 10, 50, 30, 1) # 画矩形
oled.show()
time.sleep(2)
最后就是图片显示,图片显示会稍微复杂一点,会涉及到图片的简单处理。
第一步,准备一张128*64以内的图片,因为oled的屏幕像素大小是128*64的,所以不能超过这个尺寸
第二步,将图片设置为单色图片,也就是黑白的图片
第三步,将图片转为为.pbm格式并上传到ESP32C3设备中备用
图片格式转换的网址为:https://convertio.co/zh/
完成后如下:
第四步,编写代码显示上面准备的图片,代码中会用到famebuf库,步熟悉这个库的同学可以取看看这个库的详细介绍
# 显示图片
with open('MicroPython.pbm', 'rb') as f: # 读取图片文件
f.readline() # 读取文件第一行,图片格式
width, height = [int(v) for v in f.readline().split()] # 读取图片像素大小
data = bytearray(f.read()) # 读取图片数据
f.close()
fbuf = framebuf.FrameBuffer(data, width, height, framebuf.MONO_HLSB) # 指定图片数据,大小及格式
oled.fill(0) # 清屏
oled.blit(fbuf, 0, 0) # 数据放入缓冲区
oled.show() # 显示
time.sleep(2)
心得体会:OLED屏幕的使用在ssd1306库的加持下还是比较简单的,显示英文文本,图形,图片都不是一件很难的事情。
但是无法直接支持中文的显示,中文显示需要另外处理,在有中文显示需求的情况下需要研究一下怎么显示中文的问题。
必做任务3:控制蜂鸣器播放音乐
任务目标:学会使用控制蜂鸣器,并能根据音乐简谱让蜂鸣器播放对应的音乐
XIAO扩展板上集成了一颗蜂鸣器,根据seeed官方的资料显示,蜂鸣器接在扩展板上的A3引脚,在对应到ESP32C3的引脚是GPIO5。
于是,就可以根据引脚信息来对引脚进行配置。
由于我们需要使用蜂鸣器发出不同频率的声音,所以这里就使用pwm功能来进行调整变频率。
GPIO5引脚初始化:
from machine import PWM,Pin
# Buzzer settings
buzzer = PWM(Pin(5),freq=1024,duty=512)
初始频率指定为1024Hz,占空比参数为512,即50% (范围0~1023),初始freq和duty可以随意指定,因为后面会根据音符来动态调整。
这样初始化完成后,蜂鸣器就能发出声音了,但是这个声音是固定不变的。
要想让蜂鸣器根据乐谱来播放音乐,就必须将乐谱量化成代码可以识别的数字,那么对于乐谱来说,基本上量化出来的参数就是两个,一个是频率,一个是时长。
每一个音符(1,2,3,4,5,6,7)对应了一种频率,这些频率都是知道的,可以在网络上查找相关的资料。
补充一点的是,每个音符又分为高音,中音和低音,分别对应不同的频率,也就是每个音符可以对应三种频率,具体要根据音乐简谱来定
对于时长,就需要根据实际的音乐简谱来对应了,每一个歌曲都是不一样的。
下面就是歌曲《沧海一声笑》的简朴,根据这个简朴就可以知道每个音符的频率和时长
量化后的频率和时长:
X0 = -1 # 休止符
D5 = 262 # 低音(5)
D6 = 294 # 低音(6)
Z1 = 349 # 中音(1)
Z2 = 392 # 中音(2)
Z3 = 440 # 中音(3)
Z5 = 523 # 中音(5)
Z6 = 587 # 中音(6)
# 频率
tune = [ Z6,Z5,Z3,Z2,Z1, Z3,Z2,Z1,D6,D5,X0, D5,D6,D5,D6,Z1,Z2,Z3,Z5, Z6,Z5,Z3,Z2,Z1,Z2,
Z6,Z6,Z5,Z3,Z2,Z1, Z3,Z2,Z1,D6,D5,X0, D5,D6,D5,D6,Z1,Z2,Z3,Z5, Z6,Z5,Z3,Z2,Z1,Z2,
Z6,Z6,Z5,Z3,Z2,Z1, Z3,Z2,Z1,D6,D5,X0, D5,D6,D5,D6,Z1,Z2,Z3,Z5, Z6,Z5,Z3,Z2,Z1,Z2,
Z6,Z6,Z5,Z3,Z2,Z1, Z3,Z2,Z1,D6,D5,X0, D5,D6,D5,D6,Z1,Z2,Z3,Z5, Z6,Z5,Z3,Z2,Z1
]
# 时长
duration = [ 0.75,0.25,0.5,0.5,2, 0.75,0.25,0.5,0.5,1.8,0.2, 0.75,0.25,0.75,0.25,0.75,0.25,0.5,0.5, 0.75,0.25,0.5,0.25,0.25,2,
0.75,0.25,0.25,0.5,0.5,2, 0.75,0.25,0.5,0.5,1.8,0.2, 0.75,0.25,0.75,0.25,0.75,0.25,0.5,0.5, 0.75,0.25,0.5,0.25,0.25,2,
0.75,0.25,0.25,0.5,0.5,2, 0.75,0.25,0.5,0.5,1.8,0.2, 0.75,0.25,0.75,0.25,0.75,0.25,0.5,0.5, 0.75,0.25,0.5,0.25,0.25,2,
0.75,0.25,0.25,0.5,0.5,2, 0.75,0.25,0.5,0.5,1.8,0.2, 0.75,0.25,0.75,0.25,0.75,0.25,0.5,0.5, 0.75,0.25,0.5,0.5,2
]
根据这两张表去设置pwm的频率和时长就能让蜂鸣器播放出歌曲《沧海一声笑》了。
如下就是根据这两张表动态设置pwm参数的程序,来源于seeed官方例程,稍作修改:
def buzzer_play():
total_notes = len(tune)
for i in range(total_notes):
current_note = tune[i]
wait = duration[i]
if current_note != -1:
buzzer.duty(512) # Set duty cycle for sound
buzzer.freq(current_note) # Set frequency of the note
else:
buzzer.duty(0) # Turn off the sound
time.sleep_ms(int(wait * 800))
buzzer.duty(0) # Turn off the sound
另外,代码里面time.sleep_ms(int(wait * 800))是用来控制播放速度的,可以根据实际情况做调整。
其实,更确切地说,这个地方实际上是控制音乐每一拍的时长。
必做任务4:连接WiFi网络
任务目标:使用开发板连接wifi网络并访问互联网
ESP32最大的优势就联网,再加上MicroPython,联网就更加方便了。
使用network库来进行联网是真的好用
调用接口network.WLAN(network.STA_IF)设置network的模式
调用接口station.scan()来进行wifi热点扫描
调用接口station.connect(wifi_ssid, wifi_password)来连接到wifi网络
对,联网就是如此简单。
import network
import utime as time
# Network settings
wifi_ssid = "CMCC-eP9M"
wifi_password = "y634ybku"
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])
联网以后,就可以获取到互联网上的一些信息,比如时间还有天气等等。
使用urequests库可以方便的请求互联网信息
获取时间,日期和时区:
import urequests
import ujson
import oled
url = "http://worldtimeapi.org/api/timezone/Asia/Shanghai"
def get_date_time():
# Perform HTTP GET request on a non-SSL web
response = urequests.get(url)
# Check if the request was successful
if response.status_code == 200:
# Parse the JSON response
data = ujson.loads(response.text)
# Extract the "datetime" field for New York
ny_datetime = data["datetime"]
# Split the date and time components
date_part, time_part = ny_datetime.split("T")
# Get only the first two decimal places of the time
time_part = time_part[:8]
# Get the timezone
timezone = data["timezone"]
print("Date:\r\n" + date_part)
print("Time:\r\n" + time_part)
print("Timezone:\r\n" + timezone)
oled.oled.fill(0)
oled.oled.text("Date:", 0, 0)
oled.oled.text(date_part, 0, 10)
oled.oled.text("Time:", 0, 20)
oled.oled.text(time_part, 0, 30)
oled.oled.text("Timezone:", 0, 40)
oled.oled.text(timezone, 0, 50)
# Update the display
oled.oled.show()
else:
print("Failed to get the time")
获取天气信息也是同样的道理:
import urequests
import ujson
import oled
url = 'https://api.seniverse.com/v3/weather/now.json?key={}&location={}&language=en&unit=c'
key = 'your key'
city = 'shanghai'
def get_weather():
result1=urequests.get(url.format(key, city))
j1=ujson.loads(result1.text)
city_name = "City:" + j1['results'][0]['location']['name']
weather = "Weather:" + j1['results'][0]['now']['text']
temp = "Temp:" + j1['results'][0]['now']['temperature'] + " C"
oled.oled.fill(0)
oled.oled.text(city_name, 0, 0)
# oled.oled.text(date_part, 0, 10)
oled.oled.text(weather, 0, 20)
# oled.oled.text(time_part, 0, 30)
oled.oled.text(temp, 0, 40)
# oled.oled.text(timezone, 0, 50)
# Update the display
oled.oled.show()
print(j1['results'][0]['location']['name'],end=' ')
print(j1['results'][0]['now']['text'],end=' ')
print(j1['results'][0]['now']['temperature'],end='℃ ')
print(j1['results'][0]['last_update'])
必做任务5:使用外部传感器
任务目标:连接环境光传感器和温湿度传感器,获取传感器的数值,并转换成真实的物理量。
本次follow me选配了2个外部传感器模块,分别是温湿度传感器模块AHT20和环境光传感器模块。
前者可以测量环境的温度和湿度,为I2C接口,后者可以测量环境的光强度,为模拟量接口。
需要注意的是AHT20有现成的库可以使用,只需简单的调用读温度/湿度的接口就能获取到温度/湿度,使用非常简单。
AHT20库下载地址:https://github.com/targetblank/micropython_ahtx0.git
环境的光强度是通过AD口测量的,调用ADC的读取接口就能获取到数字量或者电压值,也很简单。
温湿度读取:
import utime
from machine import Pin, I2C
import oled
import ahtx0
i2c = I2C(scl=Pin(7), sda=Pin(6))
# Create the sensor object using I2C
sensor = ahtx0.AHT10(i2c)
def get_temp_humi():
print("\nTemperature: %0.2f C" % sensor.temperature)
print("Humidity: %0.2f %%" % sensor.relative_humidity)
oled.oled.fill(0)
oled.oled.text("Temp: %0.2f C" % sensor.temperature, 0, 20)
oled.oled.text("Humi: %0.2f %%" % sensor.relative_humidity, 0, 40)
# Update the display
oled.oled.show()
光强度读取:
from machine import ADC,Pin
import utime
import oled
adc = ADC(2,atten = ADC.ATTN_11DB)
def get_light_voltage():
voltage = adc.read_uv() / 1000000
print("{}v ".format(voltage))
oled.oled.fill(0)
oled.oled.text(f'Voltage:{voltage:.3f}V', 0, 30)
# Update the display
oled.oled.show()
可选任务6:3选1即可(选做,非必做):从以下任务要求中,任选一个完成,也可以根据自己的兴趣爱好和能力特长,自定义难度相仿的任务并完成。
■ 分任务1:寻找WiFi发射源的位置
■ 分任务2:温湿度数据记录仪
■ 分任务3:开灯提醒器
任务目标:实现开灯提醒器
开灯提醒器实际上就是利用环境光传感器检测周围的环境光的强度,如果光线很暗检测到的光强度就会很低,如果光线很亮检测到的光强度就会很高,通过这种方式可以在光线很暗的情况下给出提醒,提醒用户开灯。报警方式有屏幕显示和声音提醒。
有前面任务5的传感器使用作为基础,开灯提醒器其实就非常简单了,拿到传感器的数据后只需做简单的判读处理就可以实现了。
from machine import ADC,Pin
import utime
import oled
import buzzer
VOLTAGE_THRESHOLD = 50
adc = ADC(2,atten = ADC.ATTN_11DB)
def light_check():
voltage = adc.read_uv() / 1000 # 获取电压mv
print("{}mv ".format(voltage))
if voltage < VOLTAGE_THRESHOLD:
buzzer.buzzer_alarm_on()
# oled.oled.fill(0)
oled.oled.text('Dim Light', 24, 50)
# Update the display
# oled.oled.show()
else:
buzzer.buzzer_alarm_off()
oled.oled.show()
单电压小于50mv时认为光线比较暗,显示“Dim Light”,同时蜂鸣器发出声音,提醒光线太暗,需要开灯。
除了这个功能以外,还提供了AHT的温湿度和wifi获取到的天气信息的循环显示。
当然了,这三个任务在MicroPython的加持下都不是很难。
第三部分 (可编译下载的代码)
https://download.eeworld.com.cn/detail/xinmeng_wit/630259
本帖最后由 xinmeng_wit 于 2023-12-14 21:02 编辑