【得捷Follow me第3期】基于 XIAO ESP32 C3 和MicroPthon 的实验报告
[复制链接]
本帖最后由 nemon 于 2023-12-16 09:33 编辑
感谢主办方,我又一次参加了Follow Me的活动。
拿到板子之后自己做了一些功课,也跟着公开课(https://training.eeworld.com.cn/video/38591)进行了学习。现在按要求,把作业发一下。
一:视频介绍:
楼主语言能力比脚差,啰嗦了13分钟,视频一个多G,所以只好传到外站了:
二、任务/项目总结报告
1.项目介绍
我把3个选做题目放到2个小项目里完成了:
1.1 WiFi信号提示器
日常生活中,有时会发现wifi信号不好的情况,那么那些地方需要调整,增强信号呢?我们并没有一个明确的概念。
基于 Seeed Studio XIAO ESP32C3、Seeed Studio Expansion Board Base for XIAO的OLED屏,可以做一个WIFI信号测量器。你只要拿着它在房间里转一转就知道哪里信号强、适合放张床了。实际上只用到了XIAO ESP32C3和ssd1306 oled屏:
运行的效果可以看前面的视频,在OLED屏上显示热点名、信号强度的横向条形图、信号强度。直接用线来连接器件,组合起来是这样的:
1.2 生活环境助手
这个设计的目标是,能够在OLED上显示亮度、温度、湿度这3个数值,便于用户了解环境状况。另外,如果环境照度低于6勒克斯,说明实在是太黑了,蜂鸣器就会一直响,提醒用户开灯。
这个制作用到的器件比较多,包括光传感器、温湿度传感器、蜂鸣器和OLED屏。
运行的效果可以看前面的视频,在OLED屏上显示亮度、温度、湿度,并在光线昏暗的时候,用蜂鸣器警告用户。直接用线来连接器件,组合起来是这样的:
3. 各任务功能完成过程,对应的主要代码片段及说明
任务1 使用MicroPython系统
在XIAO官网wiki(https://wiki.seeedstudio.com/XIAO_ESP32C3_MicroPython/),可以学到,刷microPython古剑的步骤是:
首先 从 克隆获取烧写工具;
然后到 https://micropython.org/download/ESP32_GENERIC_C3/ 下载最新固件,我找到的是 v1.21.0 (2023-10-05) .bin ,并放在esptool-master\esptool 里;
之后 执行
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 ESP32_GENERIC_C3-20231005-v1.21.0.bin
注意 “COM10”要换成自己的串口。
然后就可以支持microPython了。我用的工具是Thonny,代码是
print( ("%s {who}!"%"hello").format(**{"who":"world"}) )
用两种不同的格式化方式组合,输出了“hello world!”,效果请看前面的视频。
任务2:驱动扩展板上的OLED屏幕
仍然是参考官网wiki,并且在学习了老师的视频(https://training.eeworld.com.cn/video/38591)。
使用I2C接口来控制OLED,并且使用gfx库来实现绘图。gfx的绘图方法看上去有点笨,是调用初始化时硬件的绘制一个像素点的方法。但是配合硬件库show()的刷新机制,对性能也没有什么大的影响。
# task 2
# show graph and word by OLED
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)
import gfx
grf=gfx.GFX(oled_width, oled_height, oled.pixel)
oled.fill(0)
oled.text("hello world!",16,8)
grf.rect(0,0,127,64,1)
grf.rect(4,4,119,56,1)
grf.fill_circle(64-6*2,20+6,6,1)
grf.line( 64+6+12,20+6 , 64+6,20+6,6 )
grf.rect( 64+6,20+0 , 12,12 ,1)
grf.triangle( 64-6*2,20+6*5 , 64,20+6*2 , 64+6*2,20+6*5 , 1)
oled.show()
这段代码效果是在OLED边沿画双层的矩形框输出“hello world!”和实心圆形、正方形(中间有一横线)、三角形,效果请看前面的视频。
任务3:控制蜂鸣器播放音乐
蜂鸣器是用GPIO输出PWM直接驱动的,我首先定义了音阶,然后定义了曲子,遍历曲子的每一个字符输出即可:
# task 3
# play music
import machine
import time
# Buzzer settings
buzzer_pin = machine.Pin(5, machine.Pin.OUT)
buzzer = machine.PWM(buzzer_pin)
buzzer.freq(1047)
##### ( C4, D4, E4, F4, G4, A4 , B4, C5, D5, E5, F5, G5, A5, B5)
sim = (262,294,330,349,392,440 ,494,523,587,659,698,784,880,988)
# little strars
notes = (
1,1,5,5,6,6,5,0, 4,4,3,3,2,2,1,0,
5,5,4,4,3,3,2,0, 5,5,4,4,3,3,2,0,
1,1,5,5,6,6,5,0, 4,4,3,3,2,2,1,0,
)
# 2 tigers
#notes = (
# 1,2,3,1,0, 3,4,5,0, 3,4,5,0,
# 5,6,5,4,3,1,0, 5,6,5,4,3,1,0,
# 1,5,1,0, 1,5,1,0,
#)
dur = 250
def play_a_song(music):
l = len(music)
for i in range(l):
c = music[i]
wait = dur
if c != 0:
buzzer.duty(512)
buzzer.freq(sim[ c - 1 ])
else:
buzzer.duty(0) # Turn off
time.sleep_ms(wait)
buzzer.duty(0) # Turn off
time.sleep_ms(50)
while True:
play_a_song(notes)
time.sleep(1)
这段代码效果是播放歌曲“小星星”,效果请看前面的视频。
任务4:连接WiFi网络
Seeed Studio XIAO ESP32C3 自带WiFi功能,我的无线AP虽然信号不是太好,但因为离得进所以没有XIAO接天线一样能用。但是由于没有接外网,所以自己做了个简单的http服务:
from http.server import BaseHTTPRequestHandler, HTTPServer
import time
class SvrHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.end_headers()
self.wfile.write(b'OK')
print("ok")
def run_server():
server_address = ('', 80)
httpd = HTTPServer(server_address, SvrHandler)
print('Server running on port 80...')
httpd.serve_forever()
run_server()
这段代码的作用是当收到对根的访问时,返回字符“OK”。而XIAO上的代码是这样的:
# task 4
# connect to wifi
from machine import Pin, SoftI2C
from time import sleep
import time
import network
import urequests
station = network.WLAN(network.STA_IF)
station.active(True)
# Network settings
wifi_ssid = "FAST_538C80"
wifi_password = "12345678"
#url = "http://api.vvhan.com/api/color"
url = "http://172.16.3.41/"
station.scan()
while not station.isconnected():
print("Connecting...")
station.connect(wifi_ssid, wifi_password)
time.sleep(10)
print("Connected!")
print("My IP Address:", station.ifconfig()[0])
#print("station:", station.ifconfig() )
response = urequests.get(url)
if response.status_code == 200:
print("response:",response.text)
else:
print("Failed",response.status_code)
这段代码作用是联网后访问服务器并打印返回的信息,效果请看前面的视频。
任务5:使用外部传感器
这个必做任务的要求是连接环境光传感器或温湿度传感器,获取传感器的数值,并转换成真实的物理量。考虑选做任务有这两项:
分任务2:温湿度数据记录仪(定时记录温湿度传感器的值,并展示出来。可记录到开发板内置存储中,也可以通过物联网服务发送数据到云端。)
分任务3:开灯提醒器(监测环境光强度,如果光线太暗,通过屏幕和蜂鸣器提醒用户开灯,达到保护视力的效果。)
于是在做任务5的时候一并做了:
# task 5
# light sensor,
from machine import Pin,ADC,PWM,SoftI2C
import time
adc = ADC(Pin(2))
adc.atten(ADC.ATTN_11DB)
adc.width(ADC.WIDTH_12BIT) #0~4095
def get_lux():
light_adc = adc.read()
lux = light_adc * 350 * 1.0 / 4095
return lux
import ahtx0
i2c = SoftI2C(scl=Pin(7), sda=Pin(6))
aht = ahtx0.AHT20(i2c)
def get_temp_humi():
temp = aht.temperature
humi = aht.relative_humidity
return (temp,humi)
import ssd1306,gfx
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
grf=gfx.GFX(128, 64, oled.pixel)
bz_pin = Pin(5, Pin.OUT)
bzer = PWM(bz_pin)
bzer.freq(1047)
def show_val(lux,temp,humi):
oled.fill(0)
oled.text("lux:%.4f"%lux,2,2)
oled.text("tmp:%.4f"%temp,2,12)
oled.text("hum:%.4f"%humi,2,22)
oled.show()
while True:
lux = get_lux()
temp,humi = get_temp_humi()
print("lux",lux,"temp:%f,humi:%f"%(temp,humi) )
show_val(lux,temp,humi)
if lux<6:
bzer.duty(512)
bzer.freq(330)
else:
bzer.duty(0)
time.sleep(1)
这段代码执行后效果是在OLED屏上显示亮度、温度、湿度,并在光线昏暗的时候,用蜂鸣器警告用户。效果请看前面的视频。
任务6:综合实践
这题虽然是选做题目,但是既然在任务5里做了2个选做题了,那剩下的那个选做题也休想逃出我的魔爪。
分任务1“寻找WiFi发射源的位置”的要求是实时测量WiFi信号强度,同时移动开发板位置,找到WiFi发射源(例如路由器)的位置。
这个移动开发板实在是没思路,靠人力吧。但是这“实时测量WiFi信号强度”还是不成问题的,前面在连接Wifi的时候就发现,用热点名和密码连接之前,必须要做一次scan。这个scan,就可以返回搜索到的热点的信号强度。为了不把隔壁老王家的wifi也搜出来显示,我在显示前筛选了一下,代码如下:
# task 6
#
import network
import urequests
import utime as time
from machine import Pin, SoftI2C
import ssd1306
import gfx
i2c = SoftI2C(scl=Pin(7), sda=Pin(6))
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
grf=gfx.GFX(128, 64, oled.pixel)
def scan_and_show(ap_list=['FAST_538C80']):
rtn={}
station = network.WLAN(network.STA_IF)
station.active(True)
for ssid, bssid, channel, RSSI, authmode, hidden in station.scan():
if "{:s}".format(ssid) in ap_list:
rtn[ssid]=int(RSSI)
return rtn
while True:
oled.fill(0)
v=scan_and_show(['FAST_538C80'])
i=0
for k in v:
w=-v[k]
if w>100:
w=100
grf.fill_rect(0,(1+i)*16+1,20+w,14,1)
oled.text(k,2,i*16+1+3)
oled.text("%d"%v[k],2,i*16+1+3+32)
i=i+1
if i>2:
break
oled.show()
time.sleep(0.1)
这段代码执行后效果是在OLED屏上显示热点名、信号强度的横向条形图、信号强度。效果请看前面的视频。
4. 心得体会
感谢主办方组织了这次活动,让我感觉对micropython的应用前景有了更直观的认识。在解决问题的过程中得到了微信群里很多热心朋友的帮助,谢谢你们!
三:代码
在这里免积分下载:https://download.eeworld.com.cn/detail/nemon/630290
|