- 2024-09-01
-
加入了学习《PI 电源小课堂 - 利用GaN技术应对电源适配器设计挑战》,观看 利用GaN技术应对电源适配器设计挑战
-
加入了学习《干货 PCB初学者该如何精准把握PCB封装的制作》,观看 什么是热焊盘和反焊盘
-
加入了学习《干货 PCB初学者该如何精准把握PCB封装的制作》,观看 PCB封装的组成元素有哪些
- 2023-12-25
-
发表了主题帖:
【得捷电子Follow me第3期】任务提交贴【调整版】
本帖最后由 epix 于 2023-12-26 15:03 编辑
内容一:演示视频
https://training.eeworld.com.cn/video/38617
内容二:项目总结报告
任务1:使用MicroPython系统
下图是本次活动用到的所有器件. 核心器件为Seeed Studio XIAO ESP32C3. 另外, 图中已完成的有: USB线连接, 排针焊接, PCB天线安装, 扩展板安装. 另有两个传感器, 分别是环境光传感器和温湿度传感器, 以及配套的连接线.
扩展板上, 除了按键和连接器以外, 将会重点用到OLED显示器和蜂鸣器. 两个传感器分别为模拟接口和I2C接口, 将会连接至扩展板的IIC连接器和A0连接器.
硬件组装完成后, 首先刷写MicroPython系统.
主要用到乐鑫的ESP32刷写工具esptool和MicroPython的固件.
Esptool从官网 https://github.com/espressif/esptool 下载最新的Release. 这里使用的是Windows10操作系统, 所以下载的是 esptool-v4.6.2-win64.zip, 下载后解压备用.
MicroPython固件从官网 https://micropython.org/download/ESP32_GENERIC_C3/ 下载ESP32C3对应的固件. 这里下载的是 v1.21.0 (2023-10-05) .bin, 下载后放到esptool文件夹备用.
首先需要将开发板启动至bootloader模式. 按住reset键, 然后按住boot键, 然后松开reset键, 然后松开boot键即可
此时在计算机管理中, 能看到USB串行设备. 通过确认硬件ID VID:303A, 即可判断这就是Espressif Incorporated的设备, 即这里用到的开发板.
打开cmd并更改路径为esptool文件夹, 然后执行
esptool.exe --chip esp32c3 --port COM3 --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
等待一会儿
按下reset重启设备.
打开uPyCraft, 确保Tools – Serial 选择了COM3, board选择了esp32, 在下方看到>>>字样, 说明MicroPython刷写成功. 尝试直接执行print(‘Hello World!’), 成功回显, 说明MicroPython现在可以正常使用.
由于之前有用过PyCharm编写Python程序, 后续都将使用PyCharm (Community 2023.1.4)作为开发环境. PyCharm及Python安装配置不再赘述.
在PyCharm中安装MicroPython插件后, 新建一个项目, 在 File – Settings – Languages & Frameworks – MicroPython 页面打开MicroPython支持, 其中, Device type选择 Pyboard, Device Path填写COM3. PyCharm会提示需要安装依赖, 安装即可.
编写一个main.py 文件, 内容为打印字符串, 在文件上右键 Run ‘Flash main.py’ 即可运行. 从下方REPL中可以看到运行结果.
整个流程还是非常方便的, 从得捷网站下单, 物流送上门, 硬件组装, 软件安装, 命令测试都非常顺利.
任务2:驱动扩展板上的OLED屏幕
扩展板中OLED屏幕使用SSD1306驱动, 通过IIC通讯. 根据文档, 需要使用的是GPIO6/7两个针脚.
SSD1306驱动文件使用的是 https://github.com/micropython/micropython-lib/blob/master/micropython/drivers/display/ssd1306/ssd1306.py 直接将ssd1306.py加入项目, 并刷入核心版即可.
首先显示文字和简单图形.
from machine import Pin, I2C
import ssd1306
i2c = I2C(scl=Pin(7), sda=Pin(6))
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
oled.fill(1)
oled.text('hello world', 1, 0)
oled.text('esp33c3', 0, 16)
oled.text('epix', 1, 32)
oled.rect(1, 48, 128, 16, 1)
oled.ellipse(97, 32, 16, 16, 1)
oled.show()
效果如图
显示图片
首先准备一张小于128*64的图片, 我这里使用了一张micropython的logo: https://github.com/micropython/micropython/wiki 缩放为64*64, 二值化存为256色位图
这里我们偷懒一下, 不读调色板, 直接读64*64的数据, 反正要么黑色要么白色
import struct
with open('logo.bmp', 'rb') as f:
header_type = f.read(2)
assert header_type == b'BM'
f.seek(0x0A)
offset = struct.unpack('<l', f.read(4))[0]
print(offset)
f.seek(offset)
# data = f.read(64 * 64)
for i in range(64):
for j in range(64):
index = i * 64 + j
pixel = f.read(1)
oled.pixel(j+32, 63-i, 1 if pixel == b'\xff' else 0)
oled.show()
效果如图
任务3:控制蜂鸣器播放音乐
同样通过文档可以看到, 扩展板蜂鸣器接在GPIO5, 模拟信号输出. 只要直接输出波形即可.
用PWM可以直接实现方波. 然后控制PWM频率就可以控制音高, 设置50%占空比就可以发出声音.
先进行一个声音版blink测试.
from machine import Pin, PWM
import time
buzzer = PWM(Pin(5, Pin.OUT))
buzzer.freq(1000)
while True:
buzzer.duty_u16(32767)
time.sleep(1)
buzzer.duty_u16(0)
time.sleep(1)
实际效果见分帖
https://bbs.eeworld.com.cn/thread-1266332-1-1.html
接下来尝试演奏一些真正的曲子. 这里找了一个简单的欢乐颂的简谱作为演奏目标.
欢乐颂简谱本身只有12345五个音, 先把基础频率写好.
为了把简谱录入程序, 这里设计了一种简单的格式. 每个音符之间用逗号分隔.降八度的音高, 在音符前面加一个星号表示. 默认为四分音符, 后面跟下划线就变为八分音符. 后面加点就视为浮点音符. 后面加横线就延长一个四分音符的长度. 为了区分每个音符, 每个音符末尾会暂停声音50毫秒. 而如果出现了用波浪号代表的圆划线或延音线, 就连续演奏而不暂停.
最终代码如下:
note2freq = {'1': 262, '2': 294, '3': 330, '4': 349, '5': 392, }
song = '3,3,4,5,' \
'5,4,3,2,' \
'1,1,2,3,' \
'3.,2_,2-,' \
\
'3,3,4,5,' \
'5,4,3,2,' \
'1,1,2,3,' \
'2.,1_,1-,' \
\
'2,2,3,1,' \
'2,3_~,4_,3,1,' \
'2,3_~,4_,3,2,' \
'1,2,*5,3~,' \
\
'3,3,4,5,' \
'5,4,3,2,' \
'1,1,2,3,' \
'2.,1_,1-,'
tempo = 96
base_duration = 60 * 1000 / 96
gap_duration = 50
idx = 0
rich_notes = song.strip(',').split(',')
for rich_note in rich_notes:
freq_multiplier = 1
if rich_note[0] == '*':
freq_multiplier = 0.5
rich_note = rich_note[1:]
note = rich_note[0]
freq = int(note2freq[note] * freq_multiplier)
duration_multiplier = 1
gap = True
decos = rich_note[1:]
for deco in decos:
if deco == '.':
duration_multiplier *= 1.5
if deco == '_':
duration_multiplier *= 0.5
if deco == '-':
duration_multiplier *= 2
if deco == '~':
gap = False
duration = int(base_duration * duration_multiplier)
if gap:
duration -= gap_duration
buzzer.freq(freq)
buzzer.duty_u16(32767)
time.sleep_ms(duration)
if gap:
buzzer.duty_u16(0)
time.sleep_ms(gap_duration)
buzzer.duty_u16(0)
实际效果见分帖.
https://bbs.eeworld.com.cn/thread-1266332-1-1.html
注意正常可以区分各个音符, 而出现波浪号位置会连续演奏.
任务4:连接WiFi网络
连接WiFi可以说是ESP系列的强项了, MicroPython直接提供了简单连接库: network
先简单确保能够联网, 获得路由器分配的ip, 并显示信号强度. SSID和密码单独用一个文件存储, 方便修改.
import network
import time
from settings import SSID, PASSWORD
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(SSID, PASSWORD)
max_wait_sec = 15
for wait_sec in range(max_wait_sec):
if wlan.isconnected():
break
print('Waiting for connection...')
time.sleep(1)
if not wlan.isconnected():
raise RuntimeError('Could not connect to network')
print('Connected')
status = wlan.ifconfig()
rssi = wlan.status('rssi')
print(f'ip: {status[0]}')
print(f'rssi: {rssi}')
第一次联网图没截到, reset之后联网速度就很快了
然后访问网络资源. 例如得捷首页: https://www.digikey.cn/
直接使用MicroPython内置的requests库发起请求. 使用之前任务的显示屏相关代码将结果显示在屏幕上, 首先显示请求, 获得响应后显示内容.
由于整个网页很长, 这里只读了前1500Bytes, 然后提取网页标题, 显示出来. 但由于没有汉字字库, 只好把汉字去掉, 只显示英文等字符.
import requests
url = 'https://www.digikey.cn/'
oled.text(f'HTTP/1.0 GET', 0, 0)
oled.text(f'{url}', 0, 10)
oled.show()
resp = requests.get(url)
status_code = resp.status_code
content = resp.raw.read(1500)
text = content.decode('utf-8')
start = text.find('<title>')
end = text.find('</title>')
title = text[start + 7:end].strip()
print(title)
en_title = ''.join([char for char in title if char <= '\u4e00'])
print(en_title)
resp.close()
oled.text(str(status_code), 0, 30)
oled.text(en_title, 0, 40)
oled.show()
实际效果参考分帖 https://bbs.eeworld.com.cn/thread-1266333-1-1.html (为了演示效果, 在最前面清空显示器并等待了几秒)
可以看到请求还是花费了一点时间的.
REPL窗口里可以看到获取到的网页完整标题. 以及能显示的文字.
任务5:使用外部传感器
环境光传感器:
这是一颗模拟传感器. 通过Grove连接到核心板的GPIO2接口, 利用内置的ADC进行电压读取
ADC读取时可以以u16格式读数, 也可以直接拿到具体电压值. 直接调用方法即可.
这颗环境光传感器使用的是SENBA的LS06-S传感器, 串联一颗68k电阻, 中间输出至LM358. 由于输出与光照强度不太不线性, 这里不计算具体照度值, 只做定性分析.
旁边放一个手机作为亮度参考.
读取的数据通过显示屏显示.
代码如下
adc = ADC(Pin(2), atten=ADC.ATTN_11DB)
while True:
light_adc = adc.read_u16()
light_uv = adc.read_uv()
oled.fill(0)
oled.text(f'light_adc: {light_adc}', 0, 0)
oled.text(f'light_mv: {light_uv / 1000}', 0, 10)
oled.show()
sleep(1)
运行效果参考分帖https://bbs.eeworld.com.cn/thread-1266335-1-1.html.
可以看到, 一开始亮度较高, 手机和显示屏显示的数字都较大, 用手遮住光线, 手机和显示屏显示的数字都变得很小. 移开手后恢复较大数值. 下面绿色电路板仅为固定作用
温湿度传感器:
这颗是数字传感器, 通过I2C协议传输数据. 使用的芯片是AHT20, 可以直接按照规格书的说明通过I2C协议通信. 由于使用广泛, 已经有写好的库了, 这里直接调用ahtx0.py 即可. 首先需要确保此文件已写入核心板.
旁边放一个温湿度表作为参考.
同样, 读取的数据通过显示屏显示. 这里限制了读取速度为2秒一次, 以防止读取本身的发热
代码如下
import ahtx0
aht20 = ahtx0.AHT20(i2c)
while True:
t = aht20.temperature
h = aht20.relative_humidity
oled.fill(0)
oled.text(f'T: {t}', 0, 0)
oled.text(f'H: {h}', 0, 10)
oled.show()
sleep(2)
运行效果参考分帖 https://bbs.eeworld.com.cn/thread-1266335-1-1.html.
可以看到, 一开始温度与湿度与温湿度表相近, 读取较为准确. 用手指堵住sensor后, 由于人体的温度和汗液, 导致湿度和温度都有明显的快速上升.
任务6:远程控制滚轮
任务动机
看漫画/视频时, 翻页/快进快退总需要手动控制, 但有时是躺在床上椅子上的奇葩姿势, 按鼠标键盘并不方便, 如果使用蓝牙鼠标键盘, 则会有个头过大按键过小等问题. 这里翻页/快进快退需求很简单, 就是两个键. 所以就直接做一个吧.
方案选择
要做滚轮显然需要能检测滚动的东西, 一般是旋转编码器, 常用的有光栅/机械/磁, 这几种鼠标上都有用. 光栅需要做对管, 机械一般是通过触点接通切换来实现相对位置编码器, 磁编码器是用霍尔元件. 现在有部分鼠标/手柄使用了磁编码器, 有一些明显的好处, 结构简单, 无机械接触. 这里我也是用磁编码器实现. 旋转轴是竖直的, 与一般鼠标滚轮不同. 这样做的好处是不必松开手指就可以旋转无限圈.
控制方式上, 可以通过核心板上的各种连接实现, USB/WiFi/BLE. 这里由于本核心板USB只支持串口, 所以放弃USB方式. WiFi控制的话, 还需要服务端. BLE就是普通蓝牙鼠标的方式. 这里选择WiFi方式控制, 直接HTTP发送滚动请求. 好处是无视蓝牙范围限制, 扩展WiFi比扩展蓝牙简单多了. 缺点是只有有服务端的电脑才能被控制, 以及经过HTTP会增加许多延迟.
服务端不打算手写, 直接用Unified Remote Server(以下简称UR), 虽然UR没有直接开放api, 不过有个简单的网页前端. 只要模拟网页前端即可.
硬件实现
磁编码器型号选择上, AS5600似乎更流行一点, 最后使用的是MT6701, 精度稍微高一点.
磁铁使用圆磁铁, 注意要使用直径充磁的方向, 才能正常被磁编码器检测.
MT6701支持多种通信方式, 这里选择与任务2中相同的I2C接口通信. 封装选择SOP-8, 手动焊接容易一点. 首先参考MT6701文档的I2C参考电路设计:
画一个简单的PCB.
编码器部分体积越小越好, 选择较薄的PCB打板, 人肉SMT. 接口使用MX 51146, 容易插拔也够小.
另做一条MX51146连接线.
为了旋转顺滑, 使用了一颗滚珠轴承.
整个编码器部分的机械结构
外形
剖面
爆炸图
外壳使用尼龙3D打印
组装好的编码器部分
编码器部分与核心版的电源和I2C接口连接即可.
考虑到本身就是无线控制, 连上一颗 14500锂电池.
所有硬件就安装完了.
软件实现
首先是MT6701的数据读取.
先从REPL扫一下I2C设备:
60是之前用过的显示屏驱动, 81是RTC. 糟糕, 好像没有发现MT6701.
还是得看文档, 文档里提到I2C的地址是0x06, 而MicroPython的I2C.scan只会扫描地址大于0x08的设备.
按照文档, 直接按照地址读是有信息的.
按照计算公式, 一圈是16384
拿出Serial Studio读一下试试
while True:
high_bit = i2c.readfrom_mem(0x06, 0x03, 1)
low_bit = i2c.readfrom_mem(0x06, 0x04, 1)
value = int.from_bytes(high_bit + low_bit, 'big') >> 2
print(f'/*{value}*/')
time.sleep_ms(1)
serialstudio效果参考分帖视频 https://bbs.eeworld.com.cn/thread-1266941-1-1.html
可以观测到正反转时读取到角度绝对值的变化, 过零点时的突变.
这样只要连续读取角度值, 然后计算与之前记录值的变化, 大于阈值就算转了一下就可以了. 过零点的情况需要特判一下.
UR控制方面, 参考一篇home-assistant论坛的文章, 然后抓包一下网页端
不难发现用这个就可以模拟左右箭头.
这样就都连起来了, 只要旋转超过阈值, 就根据旋转方向, 发送左键或右键指令
简单把代码整理一下. 就可以运行了. 快进快退视频.
参考分帖视频 https://bbs.eeworld.com.cn/thread-1266941-1-1.html
翻漫画之类图片当然也可以.
参考分帖视频 https://bbs.eeworld.com.cn/thread-1266941-1-1.html
未来计划
做个更好的外壳, 把电池等都装好.
扩展板不是必须的, 可以去掉, 大幅减小设备体积.
逆向UR的socket接口, 实现更低的控制延迟.
Wireshark抓包其实能看到类似的控制内容, 但是还需要更多逆向.
做个BLE版, 方便给安卓设备使用.
分帖汇总
必做任务1:使用MicroPython系统
[作品提交] 【得捷Follow me第3期】任务1:使用MicroPython系统
必做任务2:驱动扩展板上的OLED屏幕
[作品提交] 【得捷Follow me第3期】任务2:驱动扩展板上的OLED屏幕
必做任务3:控制蜂鸣器播放音乐
[作品提交] 【得捷Follow me第3期】任务3:控制蜂鸣器播放音乐
必做任务4:连接WiFi网络
[作品提交] 【得捷Follow me第3期】任务4:连接WiFi网络
必做任务5:使用外部传感器
[作品提交] 【得捷Follow me第3期】任务5:使用外部传感器
可选任务6:
[作品提交] 【得捷Follow me第3期】任务6:远程控制滚轮
总结(心得体会)
很幸运有机会参加这次活动. Seeed Studio XIAO ESP32C3 开发板本身还是很好玩的, 尺寸超小, 接口够全, USB-C接口. 板载4M存储啥都放得下. 扩展板把屏幕和各种接口都集成好了, 各种传感器/电池都方便连接, RESET键用着很顺手. MicroPython非常简单, 就和在电脑上跑Python脚本一样, 直接有一个REPL对调试有很大帮助. 无线功能很强大, 连接WiFi很容易, 上网以后有无限可能. 之后将继续使用XIAO和MicroPython进行更多开发.
内容三:可编译下载的代码
https://download.eeworld.com.cn/detail/epix/630280
-
加入了学习《【得捷电子Follow me第3期】任务汇总视频》,观看 【得捷电子Follow me第3期】任务汇总视频
- 2023-12-15
-
加入了学习《直播回放: FollowMe 3 与得捷一起解锁开发板的超能力》,观看 FollowMe 3 与得捷一起解锁开发板的超能力
-
发表了主题帖:
【得捷电子Follow me第3期】任务汇总
第一部分
必须提交任务一:3—5分钟短视频
https://training.eeworld.com.cn/video/38617
第二部分
必须提交任务二:任务/项目总结报告
必做任务1:使用MicroPython系统
[作品提交] 【得捷Follow me第3期】任务1:使用MicroPython系统
必做任务2:驱动扩展板上的OLED屏幕
[作品提交] 【得捷Follow me第3期】任务2:驱动扩展板上的OLED屏幕
必做任务3:控制蜂鸣器播放音乐
[作品提交] 【得捷Follow me第3期】任务3:控制蜂鸣器播放音乐
必做任务4:连接WiFi网络
[作品提交] 【得捷Follow me第3期】任务4:连接WiFi网络
必做任务5:使用外部传感器
[作品提交] 【得捷Follow me第3期】任务5:使用外部传感器
可选任务6:
[作品提交] 【得捷Follow me第3期】任务6:远程控制滚轮
第三部分
必须提交任务三:可编译下载的代码
https://download.eeworld.com.cn/detail/epix/630280
很幸运有机会参加这次活动. Seeed Studio XIAO ESP32C3 开发板本身还是很好玩的, 尺寸超小, 接口够全, USB-C接口. 板载4M存储啥都放得下. 扩展板把屏幕和各种接口都集成好了, 各种传感器/电池都方便连接, RESET键用着很顺手. MicroPython非常简单, 就和在电脑上跑Python脚本一样, 直接有一个REPL对调试有很大帮助. 无线功能很强大, 连接WiFi很容易, 上网以后有无限可能. 之后将继续使用XIAO和MicroPython进行更多开发.
-
上传了资料:
【得捷电子Follow me第3期】任务汇总
-
发表了主题帖:
【得捷Follow me第3期】任务6:远程控制滚轮
本帖最后由 epix 于 2023-12-15 01:46 编辑
看漫画/视频时, 翻页/快进快退总需要手动控制, 但有时是躺在床上椅子上的奇葩姿势, 按鼠标键盘并不方便, 如果使用蓝牙鼠标键盘, 则会有个头过大按键过小等问题. 这里翻页/快进快退需求很简单, 就是两个键. 所以就直接做一个吧.
方案选择:
要做滚轮显然需要能检测滚动的东西, 一般是旋转编码器, 常用的有光栅/机械/磁, 这几种鼠标上都有用. 光栅需要做对管, 机械一般是通过触点接通切换来实现相对位置编码器, 磁编码器是用霍尔元件. 现在有部分鼠标/手柄使用了磁编码器, 有一些明显的好处, 结构简单, 无机械接触. 这里我也是用磁编码器实现. 旋转轴是竖直的, 与一般鼠标滚轮不同. 这样做的好处是不必松开手指就可以旋转无限圈.
控制方式上, 可以通过核心板上的各种连接实现, USB/WiFi/BLE. 这里由于本核心板USB只支持串口, 所以放弃USB方式. WiFi控制的话, 还需要服务端. BLE就是普通蓝牙鼠标的方式. 这里选择WiFi方式控制, 直接HTTP发送滚动请求. 好处是无视蓝牙范围限制, 扩展WiFi比扩展蓝牙简单多了. 缺点是只有有服务端的电脑才能被控制, 以及经过HTTP会增加许多延迟.
服务端不打算手写, 直接用Unified Remote Server(以下简称UR), 虽然UR没有直接开放api, 不过有个简单的网页前端. 只要模拟网页前端即可.
硬件实现:
磁编码器型号选择上, AS5600似乎更流行一点, 最后使用的是MT6701, 精度稍微高一点.
磁铁使用圆磁铁, 注意要使用直径充磁的方向, 才能正常被磁编码器检测.
MT6701支持多种通信方式, 这里选择与任务2中相同的I2C接口通信. 封装选择SOP-8, 手动焊接容易一点. 首先参考MT6701文档的I2C参考电路设计:
画一个简单的PCB.
编码器部分体积越小越好, 选择较薄的PCB打板, 人肉SMT. 接口使用MX 51146, 容易插拔也够小.
另做一条MX51146连接线.
为了旋转顺滑, 使用了一颗滚珠轴承.
整个编码器部分的机械结构
外形
剖面
爆炸图
外壳使用尼龙3D打印
组装好的编码器部分
编码器部分与核心版的电源和I2C接口连接即可.
考虑到本身就是无线控制, 连上一颗 14500锂电池.
所有硬件就安装完了.
软件实现:
首先是MT6701的数据读取.
先从REPL扫一下I2C设备:
60是之前用过的显示屏驱动, 81是RTC. 糟糕, 好像没有发现MT6701.
还是得看文档, 文档里提到I2C的地址是0x06, 而MicroPython的I2C.scan只会扫描地址大于0x08的设备.
按照文档, 直接按照地址读是有信息的.
按照计算公式, 一圈是16384
拿出Serial Studio读一下试试
while True:
high_bit = i2c.readfrom_mem(0x06, 0x03, 1)
low_bit = i2c.readfrom_mem(0x06, 0x04, 1)
value = int.from_bytes(high_bit + low_bit, 'big') >> 2
print(f'/*{value}*/')
time.sleep_ms(1)
[localvideo]4e6550ea89857167362273a924cfd054[/localvideo]
可以观测到正反转时读取到角度绝对值的变化, 过零点时的突变.
这样只要连续读取角度值, 然后计算与之前记录值的变化, 大于阈值就算转了一下就可以了. 过零点的情况需要特判一下.
UR控制方面, 参考一篇home-assistant论坛的文章, 然后抓包一下网页端
不难发现用这个就可以模拟左右箭头.
这样就都连起来了, 只要旋转超过阈值, 就根据旋转方向, 发送左键或右键指令
简单把代码整理一下. 就可以运行了. 快进快退视频.
[localvideo]5cdb1adac44e01eb77ab9a38d06a3b8d[/localvideo]
翻漫画之类图片当然也可以
[localvideo]f1341f8f5dc74a16af8b6919e6d7ce4c[/localvideo]
未来计划:
做个更好的外壳, 把电池等都装好.
扩展板不是必须的, 可以去掉, 大幅减小设备体积.
逆向UR的socket接口, 实现更低的控制延迟.
Wireshark抓包其实能看到类似的控制内容, 但是还需要更多逆向.
做个BLE版, 方便给安卓设备使用.
- 2023-12-10
-
发表了主题帖:
【得捷Follow me第3期】任务5:使用外部传感器
本帖最后由 epix 于 2023-12-10 23:21 编辑
环境光传感器:
这是一颗模拟传感器. 通过Grove连接到核心板的GPIO2接口, 利用内置的ADC进行电压读取
ADC读取时可以以u16格式读数, 也可以直接拿到具体电压值. 直接调用方法即可.
这颗环境光传感器使用的是SENBA的LS06-S传感器, 串联一颗68k电阻, 中间输出至LM358. 由于输出与光照强度不太不线性, 这里不计算具体照度值, 只做定性分析.
旁边放一个手机作为亮度参考.
读取的数据通过显示屏显示.
代码如下
adc = ADC(Pin(2), atten=ADC.ATTN_11DB)
while True:
light_adc = adc.read_u16()
light_uv = adc.read_uv()
oled.fill(0)
oled.text(f'light_adc: {light_adc}', 0, 0)
oled.text(f'light_mv: {light_uv / 1000}', 0, 10)
oled.show()
sleep(1)
运行效果如下. 可以看到, 一开始亮度较高, 手机和显示屏显示的数字都较大, 用手遮住光线, 手机和显示屏显示的数字都变得很小. 移开手后恢复较大数值. 下面绿色电路板仅为固定作用
[localvideo]28f63d8ab83baf65ddab7fa0228ec46f[/localvideo]
温湿度传感器:
这颗是数字传感器, 通过I2C协议传输数据. 使用的芯片是AHT20, 可以直接按照规格书的说明通过I2C协议通信. 由于使用广泛, 已经有写好的库了, 这里直接调用ahtx0.py 即可. 首先需要确保此文件已写入核心板.
旁边放一个温湿度表作为参考.
同样, 读取的数据通过显示屏显示. 这里限制了读取速度为2秒一次, 以防止读取本身的发热
代码如下
import ahtx0
aht20 = ahtx0.AHT20(i2c)
while True:
t = aht20.temperature
h = aht20.relative_humidity
oled.fill(0)
oled.text(f'T: {t}', 0, 0)
oled.text(f'H: {h}', 0, 10)
oled.show()
sleep(2)
运行效果如下. 可以看到, 一开始温度与湿度与温湿度表相近, 读取较为准确. 用手指堵住sensor后, 由于人体的温度和汗液, 导致湿度和温度都有明显的快速上升.
[localvideo]3138c0f58f7a50c05bc1eb0f860ca7a7[/localvideo]
-
发表了主题帖:
【得捷Follow me第3期】任务4:连接WiFi网络
连接WiFi可以说是ESP系列的强项了, MicroPython直接提供了简单连接库: network
先简单确保能够联网, 获得路由器分配的ip, 并显示信号强度. SSID和密码单独用一个文件存储, 方便修改.
import network
import time
from settings import SSID, PASSWORD
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(SSID, PASSWORD)
max_wait_sec = 15
for wait_sec in range(max_wait_sec):
if wlan.isconnected():
break
print('Waiting for connection...')
time.sleep(1)
if not wlan.isconnected():
raise RuntimeError('Could not connect to network')
print('Connected')
status = wlan.ifconfig()
rssi = wlan.status('rssi')
print(f'ip: {status[0]}')
print(f'rssi: {rssi}')
第一次联网图没截到, reset之后联网速度就很快了
然后访问网络资源. 例如得捷首页: https://www.digikey.cn/
直接使用MicroPython内置的requests库发起请求. 使用之前任务的显示屏相关代码将结果显示在屏幕上, 首先显示请求, 获得响应后显示内容.
由于整个网页很长, 这里只读了前1500Bytes, 然后提取网页标题, 显示出来. 但由于没有汉字字库, 只好把汉字去掉, 只显示英文等字符.
import requests
url = 'https://www.digikey.cn/'
oled.text(f'HTTP/1.0 GET', 0, 0)
oled.text(f'{url}', 0, 10)
oled.show()
resp = requests.get(url)
status_code = resp.status_code
content = resp.raw.read(1500)
text = content.decode('utf-8')
start = text.find('<title>')
end = text.find('</title>')
title = text[start + 7:end].strip()
print(title)
en_title = ''.join([char for char in title if char <= '\u4e00'])
print(en_title)
resp.close()
oled.text(str(status_code), 0, 30)
oled.text(en_title, 0, 40)
oled.show()
实际效果: (为了演示效果, 在最前面清空显示器并等待了几秒)
[localvideo]d816e21244eea600509e1de18f1b6912[/localvideo]
可以看到请求还是花费了一点时间的.
REPL窗口里可以看到获取到的网页完整标题. 以及能显示的文字.
-
发表了主题帖:
【得捷Follow me第3期】任务3:控制蜂鸣器播放音乐
任务3:控制蜂鸣器播放音乐
同样通过文档可以看到, 扩展板蜂鸣器接在GPIO5, 模拟信号输出. 只要直接输出波形即可.
用PWM可以直接实现方波. 然后控制PWM频率就可以控制音高, 设置50%占空比就可以发出声音.
先进行一个声音版blink测试.
from machine import Pin, PWM
import time
buzzer = PWM(Pin(5, Pin.OUT))
buzzer.freq(1000)
while True:
buzzer.duty_u16(32767)
time.sleep(1)
buzzer.duty_u16(0)
time.sleep(1)
实际效果如下
[localvideo]5325fbb64cc5a992ec0def56d2df4f43[/localvideo]
接下来尝试演奏一些真正的曲子. 这里找了一个简单的欢乐颂的简谱作为演奏目标.
欢乐颂简谱本身只有12345五个音, 先把基础频率写好.
为了把简谱录入程序, 这里设计了一种简单的格式. 每个音符之间用逗号分隔.降八度的音高, 在音符前面加一个星号表示. 默认为四分音符, 后面跟下划线就变为八分音符. 后面加点就视为浮点音符. 后面加横线就延长一个四分音符的长度. 为了区分每个音符, 每个音符末尾会暂停声音50毫秒. 而如果出现了用波浪号代表的圆划线或延音线, 就连续演奏而不暂停.
最终代码如下:
note2freq = {'1': 262, '2': 294, '3': 330, '4': 349, '5': 392, }
song = '3,3,4,5,' \
'5,4,3,2,' \
'1,1,2,3,' \
'3.,2_,2-,' \
\
'3,3,4,5,' \
'5,4,3,2,' \
'1,1,2,3,' \
'2.,1_,1-,' \
\
'2,2,3,1,' \
'2,3_~,4_,3,1,' \
'2,3_~,4_,3,2,' \
'1,2,*5,3~,' \
\
'3,3,4,5,' \
'5,4,3,2,' \
'1,1,2,3,' \
'2.,1_,1-,'
tempo = 96
base_duration = 60 * 1000 / 96
gap_duration = 50
idx = 0
rich_notes = song.strip(',').split(',')
for rich_note in rich_notes:
freq_multiplier = 1
if rich_note[0] == '*':
freq_multiplier = 0.5
rich_note = rich_note[1:]
note = rich_note[0]
freq = int(note2freq[note] * freq_multiplier)
duration_multiplier = 1
gap = True
decos = rich_note[1:]
for deco in decos:
if deco == '.':
duration_multiplier *= 1.5
if deco == '_':
duration_multiplier *= 0.5
if deco == '-':
duration_multiplier *= 2
if deco == '~':
gap = False
duration = int(base_duration * duration_multiplier)
if gap:
duration -= gap_duration
buzzer.freq(freq)
buzzer.duty_u16(32767)
time.sleep_ms(duration)
if gap:
buzzer.duty_u16(0)
time.sleep_ms(gap_duration)
buzzer.duty_u16(0)
[localvideo]65c5e96a84d561b427ca3a3d67939eb5[/localvideo]
实际效果如下. 注意正常可以区分各个音符, 而出现波浪号位置会连续演奏.
-
发表了主题帖:
【得捷Follow me第3期】任务2:驱动扩展板上的OLED屏幕
扩展板中OLED屏幕使用SSD1306驱动, 通过IIC通讯. 根据文档, 需要使用的是GPIO6/7两个针脚.
SSD1306驱动文件使用的是 https://github.com/micropython/micropython-lib/blob/master/micropython/drivers/display/ssd1306/ssd1306.py 直接将ssd1306.py加入项目, 并刷入核心版即可.
首先显示文字和简单图形.
from machine import Pin, I2C
import ssd1306
i2c = I2C(scl=Pin(7), sda=Pin(6))
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
oled.fill(1)
oled.text('hello world', 1, 0)
oled.text('esp33c3', 0, 16)
oled.text('epix', 1, 32)
oled.rect(1, 48, 128, 16, 1)
oled.ellipse(97, 32, 16, 16, 1)
oled.show()
效果如图
显示图片
首先准备一张小于128*64的图片, 我这里使用了一张micropython的logo: https://github.com/micropython/micropython/wiki 缩放为64*64, 二值化存为256色位图
这里我们偷懒一下, 不读调色板, 直接读64*64的数据, 反正要么黑色要么白色
import struct
with open('logo.bmp', 'rb') as f:
header_type = f.read(2)
assert header_type == b'BM'
f.seek(0x0A)
offset = struct.unpack('<l', f.read(4))[0]
print(offset)
f.seek(offset)
# data = f.read(64 * 64)
for i in range(64):
for j in range(64):
index = i * 64 + j
pixel = f.read(1)
oled.pixel(j+32, 63-i, 1 if pixel == b'\xff' else 0)
oled.show()
效果如图
- 2023-12-09
-
发表了主题帖:
【得捷Follow me第3期】任务1:使用MicroPython系统
下图是本次活动用到的所有器件. 核心器件为Seeed Studio XIAO ESP32C3. 另外, 图中已完成的有: USB线连接, 排针焊接, PCB天线安装, 扩展板安装. 另有两个传感器, 分别是环境光传感器和温湿度传感器, 以及配套的连接线.
扩展板上, 除了按键和连接器以外, 将会重点用到OLED显示器和蜂鸣器. 两个传感器分别为模拟接口和I2C接口, 将会连接至扩展板的IIC连接器和A0连接器.
硬件组装完成后, 首先刷写MicroPython系统.
主要用到乐鑫的ESP32刷写工具esptool和MicroPython的固件.
Esptool从官网 https://github.com/espressif/esptool 下载最新的Release. 这里使用的是Windows10操作系统, 所以下载的是 esptool-v4.6.2-win64.zip, 下载后解压备用.
MicroPython固件从官网 https://micropython.org/download/ESP32_GENERIC_C3/ 下载ESP32C3对应的固件. 这里下载的是 v1.21.0 (2023-10-05) .bin, 下载后放到esptool文件夹备用.
首先需要将开发板启动至bootloader模式. 按住reset键, 然后按住boot键, 然后松开reset键, 然后松开boot键即可
此时在计算机管理中, 能看到USB串行设备. 通过确认硬件ID VID:303A, 即可判断这就是Espressif Incorporated的设备, 即这里用到的开发板.
打开cmd并更改路径为esptool文件夹, 然后执行
esptool.exe --chip esp32c3 --port COM3 --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
等待一会儿
按下reset重启设备.
打开uPyCraft, 确保Tools – Serial 选择了COM3, board选择了esp32, 在下方看到>>>字样, 说明MicroPython刷写成功. 尝试直接执行print(‘Hello World!’), 成功回显, 说明MicroPython现在可以正常使用.
由于之前有用过PyCharm编写Python程序, 后续都将使用PyCharm (Community 2023.1.4)作为开发环境. PyCharm及Python安装配置不再赘述.
在PyCharm中安装MicroPython插件后, 新建一个项目, 在 File – Settings – Languages & Frameworks – MicroPython 页面打开MicroPython支持, 其中, Device type选择 Pyboard, Device Path填写COM3. PyCharm会提示需要安装依赖, 安装即可.
编写一个main.py 文件, 内容为打印字符串, 在文件上右键 Run ‘Flash main.py’ 即可运行. 从下方REPL中可以看到运行结果.
整个流程还是非常方便的, 从得捷网站下单, 物流送上门, 硬件组装, 软件安装, 命令测试都非常顺利.