上一个帖子提到ESP32版的cpy无法实现BLE,这两天又特意去adafruit的github仓库上找了一圈,找到了BLE库,但按照例程实现后还是报错,因此放弃走BLE远程控制的路径,改为WIFI控制。
剩余实现效果
舵机控制逻辑
pwm = pwmio.PWMOut(board.A2, duty_cycle=2 ** 15, frequency=50) my_servo = servo.Servo(pwm) # Servo def stepPress(): my_servo.angle = 180 time.sleep(0.10) my_servo.angle = 0 time.sleep(0.10) my_servo.angle = 90
实现思路很简单,既然无法控制转动角度,只能控方向,而任务需求是要实现按键功能,那就改成朝一个方向以固定速度走固定时长,再反方向走相同的时长,这样就模拟了一次按键按下事件。
由于板卡只有一个地,为了同时接舵机和光线传感器,使用了I2C hub板卡把地,vbus,3.3V,以及舵机控制信号(A2脚)引出,以便调试。
WIFI AP远程控制
这个我想到了使用类似于路由器后台的思路,不过实现更加局域网,采用AP模式(要改成非AP模式也简单,将start_ap函数注释掉,增加等待wifi.radio.connectedbwifi.radio.connected变为True的操作,并在settings.toml中添加要连接的wifi网络信息便可),电脑主动链接ESP32后,通过访问后台网页操作的方式实现读取亮度值和按下拍照功能。
python部分代码
#wifi wifi.radio.start_ap(ssid = 'ESP32_S3', password = '') pool = socketpool.SocketPool(wifi.radio) server = Server(pool, "/static", debug=True) websocket: Websocket = None next_message_time = time.monotonic() @server.route("/client", GET) def client(request: Request): return Response(request, HTML_TEMPLATE, content_type="text/html") @server.route("/connect-websocket", GET) def connect_client(request: Request): global websocket if websocket is not None: print("websocket.close") websocket.close() websocket = Websocket(request) return websocket server.start(str(wifi.radio.ipv4_address_ap), port = 5000) time.sleep(2) def wifiHdl(): global server global websocket global next_message_time server.poll() if websocket is not None: if (data := websocket.receive(True)) is not None: stepPress() if websocket is not None and next_message_time < time.monotonic(): time.sleep(0.2) if websocket is not None: websocket.send_message(str(sensor.lux)) next_message_time = time.monotonic() + 1
通过socket的方法上报和获取网页设置下来的信息,由于只和浏览器相关,因此理论上手机pc都能操作,实际验证也是如此,只要在浏览器中输入192.168.4.1:5000便可以打开网页操作了。
index.html源码
<html> <head> <!--Warning:use utf-8 coding--> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> <title>Web Control center</title> </head> <body> <p>Lux: <strong>-</strong></p> <p>Photo: <input type="color"></p> <script> const Lux = document.querySelector('strong'); const Photo = document.querySelector('input[type="color"]'); let ws = new WebSocket('ws://' + location.host + '/connect-websocket'); ws.onopen = () => console.log('WebSocket connection opened'); ws.onclose = () => console.log('WebSocket connection closed'); ws.onmessage = event => Lux.textContent = event.data; ws.onerror = error => Lux.textContent = error; Photo.oninput = debounce(() => ws.send(Photo.value), 200); <!--warning: Create a delay function,Debounce RGB--> function debounce(callback, delay = 1000) { let timeout return (...args) => { clearTimeout(timeout) timeout = setTimeout(() => { callback(...args) }, delay) } } </script> </body> </html>
这段代码是在网上找到的其他人写的html测试脚本改的,本来想把color控件改成button控件,奈何自己完全不懂javascript,能用HTML把按键画出来,但无法实现按键事件,只能沿用原先实现做成亮度发生改变就认为按下了,这是一个败笔。
最终效果
网页上亮度以1s为周期刷新,对应的是光线传感器读到的亮度值,同时,对photo项目进行亮度操作,舵机会触发转动事件。
最终视频
https://www.bilibili.com/video/BV1jhUTY1EDW/
最终代码
物料清单
元件名 | 功能 |
M5STACK HAT AMBIENT LIGHT SEN | 光线传感器 |
ESP32-S3 REVERSE TFTTEATHER | ESP32主板 |
SERVOMOTOR RC 4.8-6V | 360度舵机 |
GRAVITY:I2C HUB | I2C扩展版 |