树莓派2上基于Flask与MPR121的触摸状态读取线程创建问题
解决MPR121触摸传感器读取线程+Flask GET接口的问题
我来帮你搞定这个问题!核心思路是把MPR121的持续读取逻辑放到后台线程里,这样既不会阻塞Flask的Web服务,又能实时更新触摸状态,然后Flask的GET接口只需要读取这个预存的状态就行。
完整实现代码
import time import threading from flask import Flask, jsonify import Adafruit_MPR121.MPR121 as MPR121 # 初始化Flask应用 app = Flask(__name__) # 线程安全的触摸状态存储:用锁保护,避免多线程冲突 touch_states = [False] * 12 # 12个电极的状态,初始全为False state_lock = threading.Lock() # 初始化MPR121传感器 mpr = MPR121.MPR121() if not mpr.begin(): raise RuntimeError("MPR121传感器初始化失败!请检查接线和I2C设置") def read_mpr121_thread(): """后台线程:持续读取MPR121触摸状态并更新到全局变量""" global touch_states while True: # 获取当前触摸状态(返回整数,每一位对应一个电极的触摸状态) touched = mpr.touched() # 更新状态列表 with state_lock: for i in range(12): touch_states[i] = bool(touched & (1 << i)) # 控制轮询频率,这里设为50ms(可根据需求调整) time.sleep(0.05) # 启动后台读取线程(设置daemon=True,Flask退出时线程自动终止) threading.Thread(target=read_mpr121_thread, daemon=True).start() @app.route('/touch-status', methods=['GET']) def get_touch_status(): """GET接口:返回当前所有电极的触摸状态""" with state_lock: # 复制一份状态,避免在返回过程中被线程修改 current_states = touch_states.copy() # 把状态整理成更易读的格式返回 status = {f"electrode_{i+1}": state for i, state in enumerate(current_states)} return jsonify(status) if __name__ == '__main__': # 运行Flask服务,允许外部访问(树莓派的IP) app.run(host='0.0.0.0', port=5000, debug=False)
关键细节说明
- 线程安全处理:用
threading.Lock()来保护touch_states变量,因为Flask会用多个线程处理请求,后台读取线程也会修改这个变量,加锁能避免数据不一致的问题。 - 后台线程设置:把线程设为
daemon=True,这样当Flask主进程退出时,后台线程会自动终止,不用手动管理。 - 轮询频率:
time.sleep(0.05)控制每50ms读取一次状态,你可以根据需求调整——频率太高会占用更多CPU,太低会导致状态更新不及时。 - 触摸状态解析:
mpr.touched()返回的是一个整数,比如第3个电极被触摸时,返回值的第3位(从0开始数)是1,所以用(1 << i)来判断每个电极的状态。
使用方法
- 确保树莓派已经开启I2C:通过
raspi-config的Interface Options里启用I2C。 - 安装依赖库:
pip install flask adafruit-mpr121 - 运行代码后,在浏览器或者用curl访问
http://<树莓派IP>:5000/touch-status,就能看到所有电极的触摸状态了。
内容的提问来源于stack exchange,提问作者mkiss
相关产品推荐
相关产品推荐

