拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Zephyr 传感器绑定模块 zsensor 完整指南:在 MicroPython Zephyr 端口中读取与配置传感器

嵌入式语言运行时编程语言解释器编译器物联网系统编程【免费下载链接】micropythonMicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems项目地址https://gitcode.com/gh_mirrors/mi/micropython点击查看免费下载导读本文围绕 MicroPython 官方 Zephyr 移植版ports/zephyr中内置的zsensor模块系统讲解如何通过 Zephyr devicetree 中定义的传感器设备在 MicroPython 层面完成测量采样、数值读取整数/毫/微秒级、通道属性查询与设置。读完本文你将掌握Sensor类的完整 API、全部传感器通道与通道属性常量以及如何从源码层面理解zsensor与 Zephyr sensor 驱动 API 的映射关系可直接在支持 Zephyr 的开发板上写出可运行的传感器数据采集程序。一、zsensor模块是什么zsensor是 MicroPython 为 Zephyr RTOS 移植版提供的传感器绑定模块。Zephyr 自身拥有一套完整的 sensor 驱动抽象层sensor driver API支持加速度计、陀螺仪、磁力计、温湿度、气压、光照等各类传感器zsensor模块将这一套 C 语言驱动接口封装为 Python 类使开发者可以在 MicroPython REPL 或脚本中直接访问板上传感器的数据。在 ports/zephyr/README.md 的功能列表中明确列出 zsensormodule for reading sensors说明该模块是 Zephyr 移植版默认支持的能力之一。其编译开关定义在 ports/zephyr/mpconfigport.h#define MICROPY_PY_ZSENSOR (1)即默认构建时zsensor模块会被编译进固件。在 ports/zephyr/CMakeLists.txt 中也能看到modzsensor.c被纳入构建。zsensor模块的对外形态非常简单它导出一个Sensor类以及一组描述传感器通道channels和通道属性channel attributes的常量。模块源码位于 ports/zephyr/modzsensor.c由 Linaro 于 2018 年贡献。二、核心概念传感器、通道与通道属性在使用zsensor之前需要理解三个基本概念这也是理解后续 API 的前提传感器Sensor每个板上传感器在 Zephyr devicetree设备树中都有一个节点并被分配一个设备名device name。例如 FRDM-K64F 开发板上的加速度计其设备名就是FXOS8700。Sensor(device_name)构造函数正是用这个设备名去查找对应的 Zephyr 设备。通道Channel一个传感器可以测量的物理量类别称为通道。一个传感器往往有多个通道——既可以是同一个物理量的多个轴如 X/Y/Z 三个方向的加速度也可以是该传感器能够测量的多个不同属性如同时测温度与湿度。例如zsensor.ACCEL_X表示 X 轴加速度zsensor.DIE_TEMP表示芯片结温。通道属性Channel Attribute每个通道可能有一个或多个可查询、可修改的属性例如采样频率ATTR_SAMPLING_FREQUENCY、触发阈值ATTR_LOWER_THRESH/ATTR_UPPER_THRESH等。属性通常由传感器驱动按通道实现具体支持哪些属性取决于所用传感器驱动。这一概念模型完全对应 Zephyr 官方 sensor 子系统的设计sensor driver API 中sensor_channel_get、sensor_attr_set、sensor_attr_get等接口详见 Zephyr 官方文档的 Sensors 参考页。数值表示整数部分 百万分之一小数部分Zephyr sensor API 使用struct sensor_value表示测量值它由两个整数字段组成val1数值的整数部分val2数值的小数部分单位是百万分之一1/1,000,000。例如温度读数1.5会被存储为(val11, val2500000)。zsensor模块在 Python 层完整保留了这一表示measure()得到的内部缓冲即整数部分百万分之一小数部分的有用数值对随后由get_*系列方法按需转换成你想要的形态。这一结构在源码中有直接体现。看 ports/zephyr/modzsensor.c 中读取通道的内部函数static void sensor_get_internal(mp_obj_t self_in, mp_obj_t channel_in, struct sensor_value *res) { mp_obj_sensor_t *self MP_OBJ_TO_PTR(self_in); int st sensor_channel_get(self-dev, mp_obj_get_int(channel_in), res); if (st ! 0) { mp_raise_OSError(-st); } }它直接调用 Zephyr 的sensor_channel_get()把 Python 传入的通道常量实际就是SENSOR_CHAN_*枚举的整数值原样传给驱动。三、Sensor 类构造函数与设备名构造函数from zsensor import Sensor sensor Sensor(FXOS8700) # 设备名来自开发板 devicetree构造函数接受一个字符串参数device_name即 Zephyr devicetree 中为传感器节点定义的设备名。文档以 FRDM-K64F 板的加速度计为例其设备名为FXOS8700。设备名的解析过程在 ports/zephyr/zephyr_device.c 中实现首先通过device_get_binding(dev_name)按设备名查找绑定如果失败且固件开启了CONFIG_DEVICE_DT_METADATA还会尝试按 devicetree 的 node label 查找device_get_by_dt_nodelabel两者都找不到时抛出ValueError详细模式下会附带 device %s not found 信息。从源码结构可以推断如果你在 devicetree 中为传感器节点添加了 node label也可以用该 label 作为设备名。但最稳妥、最常用的方式仍是使用文档所述的 devicetree 设备名。对象的打印表示Sensor对象支持repr风格的打印。在 ports/zephyr/modzsensor.c 中sensor_print会输出Sensor 设备名的形式 from zsensor import Sensor s Sensor(FXOS8700) s Sensor FXOS8700使用限制需要注意Sensor类仅在 Zephyr 移植版固件中可用MICROPY_PY_ZSENSOR编译开关且只能操作 Zephyr devicetree 中已声明、且固件已使能其驱动的传感器。未在 devicetree 中配置的传感器无法被Sensor构造出来。四、测量与取值measure() 与 get_* 系列方法传感器使用的基本流程是先调用measure()触发一次采样再通过get_*系列方法从内部缓冲中取出结果。measure() —— 触发采样sensor.measure()功能调用 Zephyr 的sensor_sample_fetch()从传感器获取一个测量样本并以整数部分百万分之一小数部分的有用值对形式存入驱动内部缓冲区。返回值成功时返回None失败时抛出OSError。源码中 ports/zephyr/modzsensor.c 的实现非常直白static mp_obj_t sensor_measure(mp_obj_t self_in) { mp_obj_sensor_t *self MP_OBJ_TO_PTR(self_in); int st sensor_sample_fetch(self-dev); if (st ! 0) { mp_raise_OSError(-st); } return mp_const_none; }Zephyr 返回的负错误码会被转换为OSError抛出mp_raise_OSError(-st)这与 MicroPython 一贯的错误处理风格一致。注意measure()只是把数据取到驱动内部缓冲区并不会返回数值。读取数值必须配合下一节的get_*方法。get_float() / get_micros() / get_millis() / get_int() —— 读取通道值value sensor.get_float(channel) # 返回 float如 1.5 value sensor.get_micros(channel) # 返回百万分之一整数如 1500000 value sensor.get_millis(channel) # 返回千分之一整数如 1500 value sensor.get_int(channel) # 仅返回整数部分如 1四个方法都接受一个通道常量作为参数区别仅在返回值形式方法返回类型说明示例内部值为 (1, 500000)get_float(channel)float直接换算为浮点数1.5get_micros(channel)int数值 × 1,000,000百万分之一1500000get_millis(channel)int数值 × 1,000千分之一1500get_int(channel)int仅取整数部分1它们在源码中的换算关系ports/zephyr/modzsensor.c// get_float: val1 val2 / 1000000 return mp_obj_new_float(val.val1 (mp_float_t)val.val2 / 1000000); // get_micros: val1 * 1000000 val2 return MP_OBJ_NEW_SMALL_INT(val.val1 * 1000000 val.val2); // get_millis: val1 * 1000 val2 / 1000 return MP_OBJ_NEW_SMALL_INT(val.val1 * 1000 val.val2 / 1000); // get_int: val1 return MP_OBJ_NEW_SMALL_INT(val.val1);选型建议需要浮点精度用get_float需要整数且关心小数部分时get_micros与get_millis可避免浮点误差并保留小数信息只关心整数位时用get_int最省事。完整示例读取加速度计三轴from zsensor import Sensor s Sensor(FXOS8700) # FRDM-K64F 板载加速度计 while True: s.measure() x s.get_float(zsensor.ACCEL_X) # 注意channel 常量来自 zsensor 模块 y s.get_float(zsensor.ACCEL_Y) z s.get_float(zsensor.ACCEL_Z) print(accel: x%.3f y%.3f z%.3f (m/s^2) % (x, y, z)) time.sleep_ms(100)五、通道属性attr_set 与 attr_get_* 系列方法除了读取测量值zsensor还允许查询和修改通道属性例如改变采样频率、设置触发阈值、调整量程等。attr_set() —— 设置通道属性sensor.attr_set(sensor_channel, channel_attribute, val1, [val2])参数说明sensor_channel目标通道常量也可以使用伪通道如ACCEL_XYZ见下文channel_attribute要设置的属性常量见第六节val1属性值。可以是浮点数此时不传val2也可以作为属性值的整数部分val2可选属性值的小数部分单位为百万分之一。返回值成功返回None失败抛出OSError。源码中mp_sensor_attr_set对两种传参方式做了分支处理ports/zephyr/modzsensor.cif (n_args 4) { // One float argument float v mp_obj_get_float(args[3]); val.val1 (int32_t)v; val.val2 (int32_t)((v - val.val1) * 1000000); } else { // Two integer arguments val.val1 mp_obj_get_int(args[3]); val.val2 mp_obj_get_int(args[4]); }也就是说attr_set(ch, attr, 100.5)与attr_set(ch, attr, 100, 500000)等价。这与文档中val1可为浮点此时不给val2或val1作整数部分、val2作百万分之一小数部分的描述完全一致。示例——设置采样频率为 100 Hzs.attr_set(zsensor.ACCEL_XYZ, zsensor.ATTR_SAMPLING_FREQUENCY, 100) # 等价写法 s.attr_set(zsensor.ACCEL_XYZ, zsensor.ATTR_SAMPLING_FREQUENCY, 100, 0)示例——设置触发阈值浮点写法 vs 整数对写法s.attr_set(zsensor.ACCEL_XYZ, zsensor.ATTR_LOWER_THRESH, -1.5) s.attr_set(zsensor.ACCEL_XYZ, zsensor.ATTR_UPPER_THRESH, -1, 500000) # 即 1.5attr_get_*() —— 查询通道属性v sensor.attr_get_float(channel, attribute) # float v sensor.attr_get_micros(channel, attribute) # 百万分之一整数 v sensor.attr_get_millis(channel, attribute) # 千分之一整数 v sensor.attr_get_int(channel, attribute) # 仅整数部分四个方法分别对应get_*的四种返回形式换算规则完全相同例内部值为(1, 500000)时四个方法分别返回1.5、1500000、1500、1。文档特别提醒许多传感器并不支持attr_get系列方法也不支持attr_set中的某些属性。这是因为属性支持情况完全取决于具体传感器驱动——驱动未实现某属性时Zephyr 的sensor_attr_get()/sensor_attr_set()会返回负错误码zsensor随之抛出OSError。因此生产代码中建议对属性读写做异常捕获try: freq s.attr_get_float(zsensor.ACCEL_XYZ, zsensor.ATTR_SAMPLING_FREQUENCY) except OSError: print(该驱动不支持查询采样频率)伪通道Pseudo-channelACCEL_XYZ与GYRO_XYZ是两个特殊通道ACCEL_XYZ代表加速度计三个轴的伪通道GYRO_XYZ代表陀螺仪三个轴的伪通道。它们不能用于measure()之后的get_*取值而是专门用于attr_set和attr_get_*系列方法——即对三个轴统一设置/查询某个属性如一次设置 X/Y/Z 三轴的采样频率或阈值避免逐个轴操作。这在 Zephyr sensor API 中对应SENSOR_CHAN_ACCEL_XYZ/SENSOR_CHAN_GYRO_XYZ通道驱动通过它支持批量属性配置。六、通道常量Channels速查表zsensor模块把 Zephyr 的SENSOR_CHAN_*枚举逐一映射为同名 Python 常量源码映射见 ports/zephyr/modzsensor.c。下表汇总文档定义的通道及其单位常量含义单位ACCEL_XX 轴加速度m/s²ACCEL_YY 轴加速度m/s²ACCEL_ZZ 轴加速度m/s²ACCEL_XYZ三轴加速度伪通道用于属性设置/查询—GYRO_XX 轴角速度rad/sGYRO_YY 轴角速度rad/sGYRO_ZZ 轴角速度rad/sGYRO_XYZ三轴角速度伪通道用于属性设置/查询—MAGN_XX 轴磁场强度Gauss高斯MAGN_YY 轴磁场强度GaussMAGN_ZZ 轴磁场强度GaussDIE_TEMP芯片结温°CPRESS气压kPa千帕PROX接近度无量纲值为 1 表示物体靠近—HUMIDITY湿度%LIGHT可见光亮度lux勒克斯ALTITUDE海拔高度m源码中额外暴露的通道阅读源码可见modzsensor.c实际暴露的通道比文档更多MP_REGISTER_MODULE前的全局表ports/zephyr/modzsensor.c包括MAGN_XYZ三轴磁场伪通道AMBIENT_TEMP环境温度IR、RED、GREEN、BLUE红外与 RGB 颜色分量常见于颜色传感器PM_1_0、PM_2_5、PM_10颗粒物浓度DISTANCE距离CO2、VOC、GAS_RES气体相关VOLTAGE、VSHUNT、CURRENT、POWER、RESISTANCE电流/电压/功率/电阻类传感器如电流检测芯片这些常量的整数值直接来自 Zephyr 的SENSOR_CHAN_*枚举源码用宏C(ACCEL_X)展开为SENSOR_CHAN_ACCEL_X所以它们与 Zephyr 驱动层一一对应。具体某块板上能用哪些通道取决于 devicetree 中挂载的传感器类型及其驱动能力。七、通道属性常量Channel Attributes速查表zsensor同样把 Zephyr 的SENSOR_ATTR_*枚举映射为同名常量ports/zephyr/modzsensor.c常量含义ATTR_SAMPLING_FREQUENCY采样频率即传感器每秒测量的次数HzATTR_LOWER_THRESH触发器的下阈值ATTR_UPPER_THRESH触发器的上阈值ATTR_SLOPE_TH任意运动斜率触发阈值ATTR_SLOPE_DUR斜率值需在阈值之外持续的时间触发器才会触发ATTR_HYSTERESIS迟滞值文档未给出进一步说明通常用于避免阈值附近抖动ATTR_OVERSAMPLING过采样因子ATTR_FULL_SCALE传感器量程单位与 SI 单位一致ATTR_OFFSET偏移量最终读数会被该值修正final_value sensor_value offsetATTR_CALIB_TARGET校准目标供芯片内部算法在某个轴或全部轴上做自校准ATTR_CONFIGURATION配置传感器的工作模式ATTR_CALIBRATION设置传感器所需的校准值ATTR_FEATURE_MASK启用/禁用传感器功能ATTR_ALERT告警阈值或告警的启用/禁用ATTR_FF_DUR自由落体持续时间单位毫秒。若运行期间改变了采样频率应重新设置该属性使其与新的采样频率匹配ATTR_BATCH_DURATION硬件批处理持续时间单位为 tickATTR_GAIN增益文档未给出进一步说明通常用于放大/衰减系数ATTR_RESOLUTION分辨率文档未给出进一步说明通常指 ADC/转换分辨率属性使用要点属性是按通道含伪通道生效的attr_set/attr_get_*的第一个参数都是通道并非所有传感器都实现全部属性使用前应先确认驱动支持否则会得到OSError文档对ATTR_FF_DUR有专门提示ATTR_FF_DUR以毫秒为单位若采样频率在运行期被修改必须同步调整该属性否则自由落体检测的时长判定会失真——这是因为 Zephyr 驱动内部常以采样周期数来计量该时长。八、从源码理解 zsensor 的完整调用链为了让读者对zsensor的底层原理有完整认识这里梳理一条典型的调用链涉及文件均在 ports/zephyr 下MicroPython 脚本 │ s Sensor(FXOS8700) ▼ sensor_make_new() (modzsensor.c:42) 构造对象 │ zephyr_device_find() (zephyr_device.c:30) 按设备名/NodeLabel 查找 struct device ▼ s.measure() │ sensor_sample_fetch(dev) (modzsensor.c:57) 触发 Zephyr 驱动采样 ▼ s.get_float(zsensor.ACCEL_X) │ sensor_channel_get(dev, SENSOR_CHAN_ACCEL_X, val) (modzsensor.c:68) │ val.val1 val.val2 / 1000000 (modzsensor.c:77) ▼ 返回 floatsensor_attr_set/sensor_attr_get的链路与之类似直接透传 Zephyr 的sensor_attr_set()/sensor_attr_get()驱动 API。整个模块本质上是Zephyr sensor 驱动 API 的一个极薄封装不做任何数值加工数值换算只在 get 阶段按需进行不维护任何状态也不做缓存所有错误码一律转成OSError抛给 Python 层。这种薄封装设计的好处是行为透明、与 Zephyr 驱动行为完全一致代价是 Python 层无法绕过驱动的限制——驱动不支持的功能在 Python 层也必然报错。九、环境要求与构建说明要实际运行zsensor需要MicroPython Zephyr 移植版固件zsensor仅存在于 Zephyr 移植版ports/zephyr其他移植版如 unix、esp32、stm32没有该模块Zephyr 开发环境按 Zephyr 官方入门指南安装 Zephyr SDK 并获取 Zephyr 源码MicroPython 的 Zephyr 移植版当前支持 Zephyr v3.7 (LTS)、v4.4 及开发分支详见 ports/zephyr/README.md目标板与传感器板上需有 devicetree 中声明、且固件已使能驱动的传感器节点。典型构建命令来自 ports/zephyr/README.md假设 MicroPython 仓库克隆在主目录下# 构建 FRDM-K64F 板固件 west build -b frdm_k64f ~/micropython/ports/zephyr # 构建 QEMU 目标 west build -b qemu_x86 ~/micropython/ports/zephyr # 烧录 west flash烧录后通过 Zephyr UART 控制台进入 MicroPython REPL即可开始import zsensor实验。注意QEMU 目标通常没有真实传感器实践时应使用带传感器的真实开发板如 FRDM-K64F 这类板载加速度计/磁力计/光照传感器的板子。十、实践建议与注意事项最后汇总zsensor使用中的关键注意事项先 measure 再取值get_*读取的是最近一次measure()存入的缓冲数据跳过measure()直接读取不会得到新数据设备名要正确设备名来自目标板 devicetree写错会得到ValueErrordevice not found可以先用s打印对象确认设备句柄是否解析成功通道常量来自 zsensor 模块ACCEL_X、DIE_TEMP等都是zsensor模块级常量需要from zsensor import Sensor, ACCEL_X或import zsensor后以zsensor.ACCEL_X引用伪通道专用于属性操作ACCEL_XYZ/GYRO_XYZ用于attr_set/attr_get_*批量操作不要用于get_*取值属性支持因驱动而异attr_set/attr_get_*失败会抛OSError多传感器通用代码务必捕获异常数值精度get_micros/get_millis返回整数避免了浮点表示误差get_float适合直观显示采样频率变更后重设自由落体时长如果修改了ATTR_SAMPLING_FREQUENCY记得同步用新的频率重设ATTR_FF_DUR。掌握以上 API 与概念后你就可以在任意支持 Zephyr sensor 驱动且 devicetree 已声明的传感器上用寥寥几行 MicroPython 代码完成采样、读取与配置让 MicroPython 与 Zephyr 生态的传感器驱动无缝协作。赞分享嵌入式语言运行时编程语言解释器编译器物联网系统编程【免费下载链接】micropythonMicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems项目地址https://gitcode.com/gh_mirrors/mi/micropython点击查看免费下载相关推荐MicroPython Zephyr 移植版专用模块 zephyr线程分析、Shell 交互、磁盘/Flash/显示与传感器绑定全面指南MicroPython Zephyr 移植版专用模块 zephyr 线程分析、Shell 交互、磁盘/Flash/显示与传感器绑定全面指南 导读 zephyr嵌入式语言运行时编程语言解释器编译器物联网系统编程Zephyr RTOS的I2C设备驱动传感器数据读取Zephyr RTOS的I2C设备驱动传感器数据读取 在嵌入式开发中I2CInter Integrated Circuit集成电路间总线因简单的双线设操作系统嵌入式RTOS物联网Zephyr RTOS外设驱动温湿度传感器接口Zephyr RTOS外设驱动温湿度传感器接口 在物联网设备开发中温湿度监测是最常见的需求之一。Zephyr RTOS实时操作系统提供了统一的传感器驱动操作系统嵌入式RTOS物联网创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门