本帖最后由 eew_gz8e7C 于 2023-12-9 17:03 编辑
第一部分
第二部分
本节任务目标:熟悉Seeed Studio XIAO ESP32C3开发板基本操作,安装esptool,并给开发板刷写MicroPython系统,完成入门程序的运行。
- 安装好python环境,需要安装的包esptool、mpremote
- 通过USB接入Seeed Studio XIAO ESP32C3,查看新增COM口,使用esptool刷入固件v1.21.0 (2023-10-05) .bin
esptool.py --chip esp32-c3 -p COM* write_flash -z 0x0 ESP32_GENERIC_C3-20231005-v1.21.0.bin
- 重启ESP32后,使用mpremote 连接ESP32进入REPL
mpremote connect COM*
- 打印系统信息,看到输出的mpy版本,至此mpy刷入成功,且可正常运行代码!
print(os.uname())
-
心得体会建议
在ESP32接入电脑前,提前打开设备管理器以便及时确认对应COM口。
本节任务目标:使用扩展板上的OLED屏幕显示文字和图形。
- 首先确定扩展板上的屏幕引脚信息,从第一部分硬件介绍可以确认IIC引脚6:SDA,7:SCL。
- 为了能便捷高效调用OLED屏幕,这里调用大神的库来实现屏幕的各种显示功能,它是一个轻量化的显示界面库,基于FrameBuffer驱动的屏幕均可使用,包含了label、dial、textbox等多种显示控件可供调用。
- 下载好后,使用thony将按下图文件夹将文件上传至esp32:
- 使用需要在color_setup.py中配置屏幕引脚及宽高信息:
from machine import Pin, I2C
import gc
from drivers.ssd1306.ssd1306 import SSD1306_I2C as SSD
# seeed studio ESP32-C3,OLED连接到 I2C0
i2c = I2C(0, scl=Pin(7), sda=Pin(6), freq=400000)
# 屏幕大小定义
oled_width = 128
oled_height = 64
# 内存回收清理
gc.collect()
# 实例SSD对象
ssd = SSD(oled_width, oled_height, i2c)
- 如果要显示中文,需要提前将显示的中文字符转为mpy专用字库以便调用,采用可以快速生成所需字库,并上传至lib/gui/fonts文件夹以供调用。
- 创建3个Lable实例化对象显示中英文,调用FrameBuffer基类中的图形方法绘制图形。
# 1. 屏幕调用基础配置
from color_setup import ssd
from gui.core.nanogui import refresh
from gui.core.writer import Writer
from gui.widgets import label
from gui.widgets.label import Label
# 2.字库调用
import gui.fonts.arial10 as arial10
import gui.fonts.font10 as font10
import gui.fonts.font6 as font6
import gui.fonts.cn16 as zh
import time
# 3.任务2
def task2_1():
# 清屏
ssd.fill(0)
refresh(ssd)
# 在屏幕上显示中英文字符
wri1 = Writer(ssd, font6, verbose=False)
txt1 = Label(writer=wri1, row=2, col=0, text=127,invert=True,align=label.ALIGN_CENTER) #此处text参数为Label的宽度
wri2 = Writer(ssd, font10, verbose=False)
txt2 = Label(writer=wri2, row=20, col=0,text=127,align=label.ALIGN_CENTER)
wri3 = Writer(ssd, zh, verbose=False)
txt3 = Label(writer=wri3, row=40, col=0, text=127,align=label.ALIGN_CENTER)
txt1.value("Task2")
txt2.value("EEWorld")
txt3.value("得捷第三期")
# 输出显示
refresh(ssd)
def task2_2():
#清除屏幕
ssd.fill(0)
refresh(ssd)
#图形显示
ssd.rect(2,2,20,20,1)
ssd.ellipse(40,12,10,10,1)
ssd.ellipse(80,12,20,10,1)
# 输出显示
refresh(ssd)
if __name__=="__main__":
task2_1()
time.sleep(5)
task2_2()
- 效果展示:
2
- 心得体会建议:通过调用库可以大幅缩短屏幕类应用开发所需时间。
本节任务目标:使用Seeed Studio XIAO ESP32C3控制蜂鸣器发出不同频率的声音,并播放一段音乐。
- 从第一部分硬件介绍可以确认蜂鸣器的引脚为GPIO5
- 声音的大小与发生体的振幅有关,声音的音调与发声体的振动频率有关。使用PWM控制蜂鸣器,通过调节PWM波的频率来控制音调,调节PWM波的占空比来调整声音大小,将蜂鸣器引脚设置为PWM输出
from machine import Pin, PWM
import utime
# 设置D3(GPIO 5)口为PWM
beeper = PWM(Pin(5))
- 常见的音调频率见下图
- 创建字典保存音调与频率对应关系
# 定义音调频率
tones = {'1': 262, '2': 294, '3': 330, '4': 349, '5': 392, '6': 440, '7': 494, '-': 0,
'a':523, 'b': 587, 'c': 659, 'd': 698, 'e': 784, 'f': 880, 'g': 988,' ':0,',':0,
'A':1046, 'B': 1175, 'C': 1318, 'D': 1397, 'E': 1568, 'F': 1760, 'G': 1976}
- 创建乐谱
# 定义小星星旋律
melody = "1155665-4433221-5544332-5544332-1155665-4433221"
# 定义沧海一声笑旋律
chysx="fecba-cba65-5656abcefecbab-65321-cba65-5656abcefecba"
- 定义播放函数,并运行试听
def buzzer(disc):
for tone in disc:
freq = tones[tone]
if freq:
beeper.init(duty=20, freq=freq) # 调整PWM的频率,使其发出指定的音调
else:
beeper.duty(0) # 空拍时一样不上电
# 停顿一下 (四四拍每秒两个音,每个音节中间稍微停顿一下)
utime.sleep_ms(400)
beeper.duty(0) # 设备占空比为0,即不上电
utime.sleep_ms(100)
beeper.deinit() # 释放PWM
if __name__=="__main__":
buzzer(melody)
utime.sleep_ms(500)
buzzer(chysx)
- 效果展示
3
- 心得体会建议:通过本次任务不仅熟悉了蜂鸣器的使用,对ESP32的PWM输出也有了基本掌握。
本节任务目标:将Seeed Studio XIAO ESP32C3连接到WiFi网络,并访问互联网信息。
- 通过micropython库连接wifi网络非常简单,使用network模块可以方便地进行WIFI网络/AP热点的配置
- 使用network.WLAN()进行wifi连接或者ap热点的配置
import network
import time
class WLAN():
def __init__(self,mode='ap',ssid='ESP-AP',key='esp32666'):
if mode=='ap':
self.setAp(ssid,key)
elif mode=='wlan':
self.connect(ssid,key)
def connect(self,ssid:str,key:str):
self.wlan = network.WLAN(network.STA_IF)
self.wlan.active(True)
msg=""
if self.wlan.isconnected():
self.wlan.disconnect()
time.sleep(1)
if not self.wlan.isconnected():
print('connecting to network...')
self.wlan.connect(ssid, key)
wait_time=0
while not self.wlan.isconnected():
time.sleep(1)
wait_time+=1
msg=f"wait for {wait_time} s"
print(msg)
if wait_time>10:
msg=f"connect failed!"
print(msg)
return msg
msg=f"connected! ssid={ssid} ip={self.wlan.ifconfig()[0]}"
print(msg)
return msg
def scan(self):
return self.wlan.scan()
def setAp(self,apssid='ESP-AP',apkey='esp32666'):
self.ap=network.WLAN(network.AP_IF)
if apkey:
self.ap.config(ssid=apssid,password=apkey,authmode=4)
else:
self.ap.config(ssid=apssid,authmode=0)
self.ap.active(True)
if __name__=='__main__':
w=WLAN('wlan','xxx','xxxxxx')
- 进行https访问测试
import urequests
response = urequests.get("https://www.baidu.com/")
print(response.text)
-
效果展示 4
-
心得体会建议:换用本次活动推荐的PCB天线能够取得更好的WIFI信号效果。
本节任务目标:连接环境光传感器或温湿度传感器,获取传感器的数值,并转换成真实的物理量。
- AHT20温湿度传感器采用IIC总线传输数据,光线传感器通过ADC采集,光线传感器接入扩展板A0接口,温湿度传感器接入IIC接口。
- AHT20温湿度需要ahtx0驱动可以通过两个渠道下载安装: https://pypi.org/project/micropython-ahtx0/。
- 另外需要注意,ESP32 adc默认采集电压范围0~1.1V,可以通过配置衰减来扩大量程。
from machine import Pin, I2C, ADC
import utime
from ahtx0 import AHT20
import gui.fonts.font6 as font6
import gui.fonts.cn16 as cn
from gui.core.nanogui import refresh
from gui.core.writer import Writer
from gui.widgets import label
from gui.widgets.label import Label
from color_setup import ssd
import _thread
adcLight=ADC(Pin(2),atten=ADC.ATTN_11DB)#atten=ADC.ATTN_11DB配置衰减
i2cHumiture=I2C(0, scl=Pin(7), sda=Pin(6), freq=400000)
huSensor = AHT20(i2cHumiture)
wri1 = Writer(ssd, font6, verbose=False)
txt1 = Label(writer=wri1, row=2, col=0, text=127,invert=True,align=label.ALIGN_CENTER) #此处text参数为Label的宽度
wri2 = Writer(ssd, cn, verbose=False)
txt2 = Label(writer=wri2, row=17, col=0,text=127,align=label.ALIGN_LEFT)
wri3 = Writer(ssd, cn, verbose=False)
txt3 = Label(writer=wri3, row=32, col=0, text=127,align=label.ALIGN_LEFT)
wri4 = Writer(ssd, cn, verbose=False)
txt4 = Label(writer=wri3, row=47, col=0, text=127,align=label.ALIGN_LEFT)
lightVal=None
def sensorLoop():
global lightVal
while True:
light_adc = adcLight.read_uv()
lightVal = light_adc / 1000.0
print("Light{:.2f} mV".format(lightVal))
print("Temperature{:.2f}".format(huSensor.temperature))
print("Humidity{:.2f}\n".format(huSensor.relative_humidity))
utime.sleep(1)
def sensorLoopThread():
_thread.start_new_thread( sensorLoop, () )
def showSensorData():
while True:
ssd.fill(0)
txt1.value("Task5")
txt2.value("光:{:.1f}".format(lightVal))
txt3.value("温:{:.1f}℃".format(huSensor.temperature))
txt4.value("湿:{:.1f}%".format(huSensor.relative_humidity))
refresh(ssd)
utime.sleep(2)
def task5():
sensorLoopThread()
utime.sleep(0.5)
showSensorData()
if __name__=="__main__":
task5()
- 效果展示:
5
- 心得体会建议:温湿度信号采集频率不要超过1s/次,否则自身发热可能导致温度采集结果偏差。
任务目标:监测环境光强度,如果光线太暗,通过屏幕和蜂鸣器提醒用户开灯,达到保护视力的效果。
- 实现思路:循环读取光线传感器电压值,并在屏幕显示,当传感器输出电压值低于50mv时,通过蜂鸣器及屏幕提示开灯并点亮LED,当传感器输出电压高于200mV时关闭LED。
- 关键代码
from machine import Pin, I2C, ADC, PWM
import utime
from ahtx0 import AHT20
import gui.fonts.font6 as font6
import gui.fonts.cn16 as cn
from gui.core.nanogui import refresh
from gui.core.writer import Writer
from gui.widgets import label
from gui.widgets.label import Label
from color_setup import ssd
import _thread
adcLight=ADC(Pin(2),atten=ADC.ATTN_11DB)
i2cHumiture=I2C(0, scl=Pin(7), sda=Pin(6), freq=400000)
huSensor = AHT20(i2cHumiture)
# 设置D3(GPIO 5)口为PWM
beeper = PWM(Pin(5),duty=0)
# 设置D2(GPIO 4)口为LED负载
led=Pin(4,Pin.OUT)
led.off()
wri1 = Writer(ssd, font6, verbose=False)
txt1 = Label(writer=wri1, row=2, col=0, text=127,invert=True,align=label.ALIGN_CENTER) #此处text参数为Label的宽度
wri2 = Writer(ssd, cn, verbose=False)
txt2 = Label(writer=wri2, row=17, col=0,text=127,align=label.ALIGN_LEFT)
wri3 = Writer(ssd, cn, verbose=False)
txt3 = Label(writer=wri3, row=32, col=0, text=127,align=label.ALIGN_LEFT)
wri4 = Writer(ssd, cn, verbose=False)
txt4 = Label(writer=wri3, row=47, col=0, text=127,align=label.ALIGN_LEFT)
lightVal=None
def sensorLoop():
global lightVal
while True:
light_adc = adcLight.read_uv()
lightVal = light_adc/1000.0
print("Light:{:.2f}".format(lightVal))
# print("Temperature:{:.2f}".format(huSensor.temperature))
# print("Humidity:{:.2f}\n".format(huSensor.relative_humidity))
utime.sleep(0.5)
def sensorLoopThread():
_thread.start_new_thread( sensorLoop, () )
def showSensorData():
while True:
ssd.fill(0)
txt1.value("Task6")
txt2.value("光:{:.1f}".format(lightVal))
if lightVal<50.0:
txt3.value("光线暗!请开灯!")
beeper.init(duty=20, freq=1000)
utime.sleep_ms(200)
beeper.duty(0)
utime.sleep_ms(50)
beeper.init(duty=20, freq=1000)
utime.sleep_ms(200)
beeper.duty(0)
led.on()
else:
if lightVal>200.0:
led.off()
txt3.value("")
refresh(ssd)
utime.sleep(2)
def task6():
sensorLoopThread()
utime.sleep(0.5)
showSensorData()
if __name__=="__main__":
task6()
- 效果展示
task6
- 心得体会建议:PIN口负载能力有限,控制灯带开关可以通过三极管开关电路实现。
第三部分
可执行的任务代码
总结
通过本期活动,学习了ESP32 Micropython的基本使用方法,掌握了SSD1306的LCD屏幕的中英文及图形显示、PWM驱动蜂鸣器播放简单的音乐、ESP32的WIFI连接与网络访问、光线及温湿度传感器的信号读取。最后感谢得捷电子和EEWORLD举办的本次活动。
|