本帖最后由 Tristan_C 于 2023-12-11 23:58 编辑
DigiKey得捷电子技术Follow Me第3期 项目总结报告
任务1:使用MicroPython系统
本次的板子Seeed Studio XIAO ESP32C3要求使用MicroPython进行开发,任务一也自然要求搭建MicroPython系统了。这里使用了Thonny开发工具,改工具可以在如下路径下载, https://thonny.org/,因为在之前开发别的项目(如RP2040)已经安装,且安装简单,在此不再赘述。安装好打开为如下软件界面。
接下来让Seeed Studio XIAO ESP32C3板子进入烧录状态,进入的方式有两种:
- 按住板子上的BOOT 按钮,然后使用USB接到PC,再松开该按钮
- 先行将板子通过USB线接到PC,然后按住BOOT按钮不松开,再按下RESET按钮并松开,接着松开BOOT按钮
这里采用方式2进行,这样方便操作一些。板子上的按钮定义如下图。
此时在Thonny的右下角可以看到板子被识别了,如果未能正确识别,需要检查操作流程和接线是否正确。
设备管理器中也能发现该设备
此时在上述发现的设备列表中,点击最下方的配置解释器。
需要选择正确的解释器和端口
点击右下方的“安装或更新MicroPython(esptool)”按钮,在弹出的窗口中选择正确的配置项。点击“安装”开始安装
需要注意的是,首次安装MicroPython系统最好将上图中的Erase all flash before installi勾上。
安装完成之后提示如下。
此时重新将板子跟PC连接,即可在Thoony开发工具上识别如下。可以看到显示的MicroPython的版本号及硬件信息。左侧则可以看到连接的MicroPython设备及其设备上的boot.py文件
此时在shell中编辑输入:print("Hello Digi-key"),即可看到打印的Hello Digi-key
如此表明MicroPython系统正确烧录到板子上了。
双击点开左侧的boot.py文件,并编辑print("Hello Digi-key")
保存并点击下图中“运行当前脚本”按钮
即可在shell中看到打印内容。
使用Thonny开发工具,对比起esptool逐步操作确实要方便许多。
任务2:驱动扩展板上的OLED屏幕
这个任务需要使用扩展版,具体对接方式如下。
任务内容是在扩展板的OLED上显示文字内容和图形,扩展板上的OLED采用SSD1306驱动芯片。因此首先需要安装响应的包。
首先在工具菜单栏下,点击管理包按钮
在搜索栏中输入SSD1306,并点击后方按钮搜索。
搜索结果中点击ssd1306,并点击下方的安装按钮安装此包
安装过程
成功安装之后可以看到具体的安装信息。
此时在左侧的MicriPython设备中,可以在lib中看到ssd1306的包了。
接下来核对硬件,扩展板上的oled使用的是I2C驱动,正好使用如下图所示的GPIO7和GPIO6分别作为SCL和SDA引脚。
下面可以开始编程了。
首先import进来I2C以及ssd1306的包
然后指定I2C的引脚。接着指定loed的宽和长,即可显示文字内容了
调试运行当前脚本程序,扩展板上显示文字内容如下
接下去显示图形,我们可以在OLED上显示几个集合图形,分别为矩形、圆形和三角形,其中圆形单独定义了一个函数。只要输入位置和半径即可。
显示效果如下
完整代码如下
import time
from machine import Pin, SoftI2C
import ssd1306
import math
from utime import sleep_ms
import framebuf
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.show()
# 画一个简单的圆形
def draw_circle(x0, y0, r, color):
x = r
y = 0
err = 0
while x >= y:
oled.pixel(x0 + x, y0 + y, color)
oled.pixel(x0 + y, y0 + x, color)
oled.pixel(x0 - y, y0 + x, color)
oled.pixel(x0 - x, y0 + y, color)
oled.pixel(x0 - x, y0 - y, color)
oled.pixel(x0 - y, y0 - x, color)
oled.pixel(x0 + y, y0 - x, color)
oled.pixel(x0 + x, y0 - y, color)
if err <= 0:
y += 1
err += 2*y + 1
if err > 0:
x -= 1
err -= 2*x + 1
# 显示图形并切换
while True:
# 显示矩形
oled.rect(10, 10, 50, 30, 1)
oled.show()
sleep_ms(2000)
# 清空屏幕
oled.fill(0)
oled.show()
sleep_ms(200)
# 显示圆形
draw_circle(80, 40, 15, 1)
oled.show()
sleep_ms(2000)
# 清空屏幕
oled.fill(0)
oled.show()
sleep_ms(200)
# 显示三角形
oled.line(100, 10, 80, 40, 1)
oled.line(80, 40, 120, 40, 1)
oled.line(120, 40, 100, 10, 1)
oled.show()
sleep_ms(2000)
# 清空屏幕
oled.fill(0)
oled.show()
sleep_ms(200)
任务3:控制蜂鸣器播放音乐
本任务需要使用扩展版上的蜂鸣器实现播放音乐的效果。要播放音乐通常需要使用外部PWM模块,MicroPython在小型嵌入式设备上的音频处理能力相对较弱,因此通常只支持简单的音频播放。PWM引脚使用如下图中的A3。
也就是GPIO5引脚,初始化的时候需要指定PWM所使用的引脚。
通过控制PWM的频率来实现不同的音符,而通过音符的延时开实现节奏的控制。下面代码实现的是一段简化版的生日快乐歌。代码首先根据前述的硬件初始化了buzzer引脚。然后定义各个音符的频率放在notes中。然后定义播放音乐的函数,其中就根据音符以及相应的sleep延时来实现音乐的输出。接着定义好音乐的具体歌曲中的音符以及节奏延时,从而最终铜鼓查表notes来播放音乐。
这里找了一曲生日快乐歌的简谱,尝试将其调试成蜂鸣器的播放
先定义各音符频率
然后根据简谱和节奏定义歌曲内容
根据内容再将其输出到蜂鸣器的PWM控制音符以及延时控制节奏
当然也增加一点前一任务中的OLED上显示一下播放内容
整体代码
import machine
import time
from utime import sleep
from machine import Pin, SoftI2C
import ssd1306
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.show()
oled.text("Play song", 10, 15)
oled.text("Happy birthday", 10, 40)
oled.show() # 显示内容
# Buzzer settings
buzzer_pin = machine.Pin(5, machine.Pin.OUT)
# 定义音符和对应频率
notes = {'1': 523, '2': 587, '3': 659, '4': 698, '5': 784, '6': 880, '7': 988}
# 播放音乐的函数
def play_music(melody):
for note, duration in melody:
if note == 'R': # R 表示休止符(rest)
sleep(duration)
else:
buzzer_pwm.freq(notes[note])
buzzer_pwm.duty(512)
sleep(duration)
buzzer_pwm.duty(0)
sleep(0.1) # 短暂的停顿
# 初始化PWM
buzzer_pwm = machine.PWM(buzzer_pin, freq=440, duty=0) # 初始频率为440 Hz,初始占空比为0
# 播放"生日快乐"歌曲
happy_birthday_melody = [
('5', 0.5), ('5', 0.5), ('6', 1), ('5', 1), ('1', 1), ('7', 2), ('R', 0.5),
('5', 0.5), ('5', 0.5), ('6', 1), ('5', 1), ('2', 1), ('1', 2), ('R', 0.5),
('5', 0.5), ('5', 0.5), ('5', 1), ('3', 1), ('1', 1), ('7', 2), ('R', 0.5),
('4', 0.5), ('4', 0.5), ('3', 1), ('1', 1), ('2', 1), ('1', 2), ('R', 0.5),
]
play_music(happy_birthday_melody)
# 关闭PWM
buzzer_pwm.deinit()
播放效果见视频介绍
任务4:连接WiFi网络
这个任务利用了ESP32的强大网络功能了,为了测试WiFi就需要请上跟信号有关的天线,将其接到模块上的IPEX座了。
以目前ESP32的强大生态来讲,真的很轻而易举。包括官方也提供了连接指定AP的参考,如下:
其中的wifi_ssid和wifi_password需要改成对应的WiFi名称和密码,运行之后就会开始扫描WiFi网络
扫描结束之后则开始连接到前面定义的wifi_ssid所在的网络,并输出如下提示。
在路由器也可看到对应的设备
接下来我们使用NTP服务更新本地时间来测试网络联通
代码中使用 ntptime.settime() 从服务器同步本地时间,然后每一秒获取本地时间戳,再将其转换,并在打印串口以及OLED上面时间当前日期和时间。
由此也增加了前面任务中的OLED功能,在开始阶段显示任务内容,并在时间戳更新中显示当前日期和时间
执行后在打印串口可以卡到时间的更新
而在OLED上,可以看到启动任务内容提示
以及时间同步成功之后,本地时间的更新
功能完整代码如下,其中的wifi_ssid和wifi_password需要替换成自己的对应值
任务5:使用外部传感器
这次任务需要使用外接的传感器。本次搭配了两个,分别是AHT20温湿度传感器,和光照传感器。
一个是I2C接口,另一个则是ADC接口,因此需要用排线将他们连接到扩展版
先是温湿度传感器,接到I2C的接口
然后就是光照了,接到模拟扣上
接下来先准备操作外部的温湿度传感器AHT20。要使用这个传感器,必须要增加对该器件的支持包。这次我换了另一个安装方式:下载到本地再安装
然后打开包管理器
选择从本地安装
选择前面下载好的指定格式的包文件
打开之后显示正在安装
安装完成之后可以在左侧的lib文件夹中看到ahtx0的包了
然后在程序中可以使用import进来该包
使用AHT20
此后就可以使用如下操作获取温度和湿度值了
当然,I2C部分还需要跟之前的OLED一样,需要在前面先定义好
接下来准备光照传感器,本次的Grove - Light Sensor v1.2 是一个光敏传感器,常用于测量环境光强度。它可以通过连接到Grove基板或直接连接到开发板上的相应引脚来使用,上面的传感器实际使用了GL5528,一个光敏电阻(光相关电阻)来检测光的强度。光敏电阻的电阻随光强的增加而减小。板载双OpAmp芯片LM358产生对应于光强的电压(即。基于电阻值)。输出信号为模拟值,光越亮,数值越大,不过该值仅反映光强度的近似趋势,它不表示确切的明亮程度,根据手册可以初定光敏电阻的最大值可以检测到约350Lux
这样就可以使用ADC采样了。
首先设定好ADC的引脚和采样参数
然后获取ADC的值,并转换为电阻值和光照度
最后还得增加OLED 部分,在其上面更新内容
有了上述的基本操作方法,下面就可以融合一下了,即每秒采样温度和湿度,以及光敏电阻并计算照度,然后在oled上更新显示
运行效果如下
在shell输出中也会看到打印的相应内容了
完整代码如下
from machine import Pin, SoftI2C, ADC
import ssd1306
import utime
import time
from ahtx0 import AHT20
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("Task 5:Sensor", 0, 0)
oled.text("Temp:", 0, 16)
oled.text("Humi:", 0, 32)
oled.text("Light:", 0, 48)
oled.show()
# aht20
aht = AHT20(i2c)
# 光照部分
adc = ADC(Pin(2))
adc.atten(ADC.ATTN_11DB)
adc.width(ADC.WIDTH_12BIT) #4095
while True:
temp = aht.temperature
humi = aht.relative_humidity
light_adc = adc.read()
# 计算光照强度单位Lux
light_lux = light_adc * 350 * 1.0 / 4095
# 算出电阻值单位K
light_res = (4095 - light_adc) * 10.0 / light_adc
print("Temp(°):\n");
print('{:.2f}'.format(temp))
print("Humi(%):\n");
print('{:.2f}'.format(humi))
print("Light(lux)\n");
print('{:.2f}'.format(light_lux))
print("Light(K)\n");
print('{:.2f}'.format(light_res))
# 清除变化部分的内容
oled.fill_rect(64,16,64,48,0)
oled.text('{:.2f}'.format(temp), 64, 16)
oled.text('{:.2f}'.format(humi), 64, 32)
oled.text('{:.2f}'.format(light_lux), 64, 48)
oled.show()
# 延时1秒
time.sleep(1)
任务6:综合实践(分任务3:开灯提醒器)
这个任务是要求完成监测环境光强度,如果光线太暗,通过屏幕和蜂鸣器提醒用户开灯,达到保护视力的效果。而我们有了前面几个任务之后,完成这个任务相对就比较简单了。
也就是在任务5的基础上,将温湿度的部分去除,再加入蜂鸣器的部分即可
首先是添加蜂鸣器
然后在下面增加光敏获取的照度值判断,当小于一定值时,蜂鸣器响起,并在OLED屏幕上显示Turn Light On的提示,而如果照度大于该值,则蜂鸣器关闭,且OLED不提示内容。
运行效果如下
当照度大于一定值
当照度小于该值
完整代码如下
from machine import Pin, SoftI2C, ADC, PWM
import ssd1306
import utime
import time
# Buzzer settings
buzzer_pin = Pin(5, Pin.OUT)
buzzer_pwm = PWM(buzzer_pin, freq=440, duty=0) # 初始频率为440 Hz,初始占空比为0
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("Task 6-3", 0, 0)
oled.text("Light:", 0, 16)
oled.show()
# 光照部分
adc = ADC(Pin(2))
adc.atten(ADC.ATTN_11DB)
adc.width(ADC.WIDTH_12BIT) #4095
while True:
light_adc = adc.read()
# 计算光照强度单位Lux
light_lux = light_adc * 350 * 1.0 / 4095
# 算出电阻值单位K
light_res = (4095 - light_adc) * 10.0 / light_adc
print("Light(lux):");
print('{:.2f}'.format(light_lux))
print("Light(K):");
print('{:.2f}'.format(light_res))
# 清除变化部分的内容
oled.fill_rect(64,16,64,48,0)
oled.fill_rect(0,48,128,16,0)
oled.text('{:.2f}'.format(light_lux), 64, 16)
if light_lux < 66:
print("We need to turn the light on\n");
oled.text("Turn Light On", 0, 48)
buzzer_pwm.duty(512)
else:
buzzer_pwm.duty(0)
# 在此处更新显示
oled.show()
# 延时1秒
time.sleep(1)
效果见视频介绍。
总结体会
其实很荣幸能够参加这一期的的Follow Me的活动,在活动过程中,不仅有直播技术讲解,更有各位大佬们的相互热心帮助,感受到大家的技术交流氛围,也从中学到了很多,感谢得捷,感谢EEWorld。
|