ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

树莓派倾斜传感器实战:从滚珠开关到MPU6050倾角模块

树莓派倾斜传感器实战:从滚珠开关到MPU6050倾角模块 1. 倾斜传感器到底是个什么东西第一次接触倾斜传感器是在一个云台项目里当时需要让摄像头跟着臂架的俯仰角度自动调整姿态一开始想用编码器算角度但臂架本身有形变编码器只能测电机转了多少圈测不了真实的空间姿态。后来换用倾斜传感器问题一下就简单了。从那时候起我陆续在树莓派、STM32、Arduino几个平台上都折腾过倾斜传感器踩了不少坑也积累了一些实际经验这里一并整理出来。倾斜传感器英文叫 Tilt Sensor 或者 Inclinometer本质上是一种测量物体相对于水平面或重力方向倾斜角度的器件。它输出的可以是开关量比如滚珠式倾斜开关倾斜到一定角度就导通或断开也可以是模拟量或数字量比如基于加速度计原理的倾角模块能读出具体的角度值。前者便宜、简单适合做倾倒报警、姿态检测这种“有或没有”的判断后者精度高、能读数值适合做云台调平、平台姿态监测、太阳能板追光这类需要连续角度反馈的场景。这篇文章适合谁看如果你正在做传感器课程设计、物联系统设计或者单纯想在树莓派上接一个倾斜传感器玩玩那这篇内容基本能覆盖你从选型、接线、写代码到调试排错的全部流程。我默认你手上有树莓派 4B 或者树莓派 5系统是 Ubuntu 22.04 或者 Raspberry Pi OS会基本的 Python 和 Linux 命令行操作。不会也没关系关键步骤我都会写清楚。先说一下我自己的硬件配置方便你对照树莓派 4B4GB 版本系统是 Ubuntu 22.04 LTS倾斜传感器用的是常见的滚珠式倾斜开关模块SW-520D和基于加速度计的模拟倾角模块两种后面会分别讲。滚珠式那个几块钱模拟倾角模块二十来块都很便宜适合入门。2. 倾斜传感器的核心原理与选型思路2.1 滚珠式倾斜开关最便宜的倾斜检测方案滚珠式倾斜开关的结构特别简单一个金属滚珠放在一个金属管内管子一端或两端有触点。当传感器水平放置时滚珠停在管子中间不接触触点电路断开当传感器倾斜到一定角度滚珠滚到一端碰到触点电路导通。就这么简单。这种传感器的优点是便宜、皮实、不需要任何驱动电路直接接树莓派的 GPIO 就能读。缺点是只能判断“倾斜超过某个角度”和“没超过”读不出具体角度值而且那个触发角度跟安装方向、滚珠大小都有关系一致性一般。我实测过一批 SW-520D标称触发角度是 10 度到 45 度之间但实际每个的触发点都有差异有的 15 度就触发有的要 30 度。所以如果你要做精确角度测量这个方案不合适但如果只是做“倒了没倒”的判断比如设备倾倒报警、箱子被翻动检测那它完全够用而且成本极低。选型的时候注意一点滚珠式倾斜开关有常开和常闭两种。常开的意思是平时断开、倾斜时导通常闭反过来。买的时候看清楚不然代码逻辑要反过来写。我一般用常开的因为接树莓派 GPIO 的时候平时是高电平通过上拉电阻倾斜时被拉到低电平逻辑比较直观。2.2 基于加速度计的倾角模块能读具体角度如果你需要读出具体的倾斜角度那就得用加速度计原理的倾角模块。常见的有基于 MPU6050、ADXL345、MMA7361 这些芯片的模块。它们内部是三轴加速度计通过测量重力加速度在三个轴上的分量反算出物体相对于水平面的倾斜角度。原理其实不难理解。想象你手里拿一个球放在一个平面上平面水平时球受到的重力全部垂直于平面水平方向没有分量平面倾斜时重力在水平方向就有了分量倾斜角度越大水平分量越大。加速度计就是测这个分量的。具体计算的时候如果是单轴倾斜角度 θ arcsin(ax / g)其中 ax 是加速度计在倾斜方向上的读数g 是重力加速度约 9.8 m/s²。如果是双轴倾斜可以用 θ arctan(ax / sqrt(ay² az²)) 这样的公式来算。这里有个细节要注意加速度计测倾角在静态或低速运动时很准但如果物体本身在加速运动加速度计会把运动加速度和重力加速度混在一起算出来的角度就不准了。所以如果你的应用场景里物体本身有较大的加速度比如车载、机械臂快速运动要么用陀螺仪做融合这就是 MPU6050 这类六轴传感器的价值要么就得接受一定的误差。我那个云台项目里臂架运动比较慢所以直接用加速度计算倾角就够了没上融合算法。2.3 树莓派上怎么选GPIO 直读还是 I2C 读取在树莓派上接倾斜传感器有两条路。一条是滚珠式开关直接接 GPIO用 Python 的 RPi.GPIO 或者 gpiozero 库读引脚电平简单直接。另一条是加速度计模块通过 I2C 或 SPI 接树莓派用 Python 的 smbus 或者专门库比如 mpu6050-raspberrypi读原始数据再换算角度。我建议新手先从滚珠式开关入手因为接线简单、代码短、不需要装额外库十分钟就能跑通。等把 GPIO 读写、中断、去抖动这些基本操作搞明白了再上加速度计模块。这样学习曲线比较平缓不容易一上来就被 I2C 地址、寄存器配置这些东西劝退。树莓派 4B 和树莓派 5 的 GPIO 引脚定义基本兼容40 针的排针布局一样。但树莓派 5 的 GPIO 底层驱动换了新的芯片如果你用 gpiozero 库大部分情况下代码不用改如果用 RPi.GPIO树莓派 5 上可能要用 rpi-lgpio 这个兼容层。我实测下来gpiozero 在树莓派 4B 和 5 上都能正常工作推荐优先用它。3. 硬件接线与实操步骤3.1 滚珠式倾斜开关接树莓派 GPIO先说滚珠式开关的接线。SW-520D 模块一般有三个引脚VCC、GND、DO数字输出。有的模块还有 AO模拟输出但滚珠式开关本身是开关量AO 其实也是通过分压得到的意义不大。接线很简单模块 VCC 接树莓派 3.3V物理引脚 1 或 17模块 GND 接树莓派 GND物理引脚 6、9、14、20、25、30、34、39 任意一个模块 DO 接树莓派任意一个 GPIO比如 GPIO17物理引脚 11这里有个坑要注意树莓派的 GPIO 是 3.3V 电平绝对不能接 5V否则可能烧掉 GPIO 甚至整块板子。有些倾斜开关模块标称工作电压 3.3V 到 5V接 3.3V 完全没问题。但如果你买的是裸的滚珠开关不是模块那就需要自己加一个上拉或下拉电阻。我一般用 10kΩ 上拉电阻接 3.3V开关另一端接 GND这样平时 GPIO 读到高电平倾斜时读到低电平。接线的时候树莓派一定要断电。我见过有人带电插拔杜邦线结果不小心碰到旁边引脚直接把 GPIO 烧了。虽然树莓派 GPIO 有一定的保护但别赌这个概率。断电接线、检查无误再上电这是基本习惯。3.2 加速度计倾角模块接树莓派 I2C加速度计模块以 MPU6050 为例接线稍微多一点但也不复杂。MPU6050 模块一般有 8 个引脚VCC、GND、SCL、SDA、XDA、XCL、AD0、INT。我们只需要用前四个VCC 接树莓派 3.3VGND 接树莓派 GNDSCL 接树莓派 GPIO3物理引脚 5I2C1 SCLSDA 接树莓派 GPIO2物理引脚 3I2C1 SDAAD0 引脚决定 I2C 地址接 GND 时地址是 0x68接 VCC 时是 0x69。如果你只接一个 MPU6050AD0 接 GND 就行。INT 引脚是中断输出一般不用接除非你要做中断触发读取。接好线之后需要在树莓派上启用 I2C。在 Raspberry Pi OS 里用 raspi-config 命令进 Interface Options把 I2C 打开。在 Ubuntu 22.04 里I2C 默认可能是关的需要手动改配置。具体操作是编辑 /boot/firmware/config.txt树莓派 4B 的 Ubuntu 22.04 是这个路径老版本可能是 /boot/config.txt加上一行 dtparami2c_armon然后重启。重启后用 ls /dev/i2c* 看看有没有 i2c-1 设备再用 i2cdetect -y 1 扫描一下如果看到 0x68 就说明模块被识别了。这里有个常见问题i2cdetect 扫不到设备。原因通常是接线松了、SDA 和 SCL 接反了、或者模块供电不对。我遇到过好几次都是杜邦线接触不良尤其是那种便宜的杜邦线插上去看着挺紧其实里面没接触上。换一根线或者用万用表量一下通断基本能解决。3.3 树莓派系统准备与依赖安装不管你用哪种传感器树莓派上的软件环境都要先准备好。我习惯用 Ubuntu 22.04因为跟服务器环境一致后面部署方便。树莓派 4B 装 Ubuntu 22.04 的流程这里不展开网上教程很多注意选对镜像raspi 版本不是 desktop 版本除非你要图形界面。系统装好后先更新一下源。Ubuntu 22.04 在树莓派上的默认源速度一般可以换成国内源这个网上也有现成脚本。更新命令sudo apt update sudo apt upgrade -y然后装 Python 相关的依赖。如果你用 gpiozerosudo apt install python3-gpiozero python3-pigpio -y如果你用 smbus 读 I2Csudo apt install python3-smbus i2c-tools -y如果你用 MPU6050 的专用库可以用 pip 装pip3 install mpu6050-raspberrypi注意Ubuntu 22.04 默认的 Python 是 3.10pip 装包的时候如果提示 externally-managed-environment需要加 --break-system-packages 参数或者用 apt 装对应的 python3-xxx 包。我一般优先用 apt实在没有再 pip。4. 代码实现与调试4.1 滚珠式倾斜开关的 Python 读取代码先上滚珠式开关的代码用 gpiozero 库简洁明了from gpiozero import Button from time import sleep # 倾斜开关接在 GPIO17上拉电阻启用 tilt_sensor Button(17, pull_upTrue, bounce_time0.1) def tilted(): print(检测到倾斜) def level(): print(恢复水平) tilt_sensor.when_pressed tilted tilt_sensor.when_released level print(倾斜传感器监测中按 CtrlC 退出) try: while True: sleep(1) except KeyboardInterrupt: print(退出)这段代码里Button 类默认是上拉所以开关一端接 GPIO17另一端接 GND。bounce_time0.1 是去抖动时间因为滚珠开关在临界角度时可能会快速通断产生抖动。0.1 秒的去抖在实际测试中效果不错既能滤掉抖动又不会太迟钝。如果你不用中断也可以用轮询的方式from gpiozero import Button from time import sleep tilt_sensor Button(17, pull_upTrue, bounce_time0.1) while True: if tilt_sensor.is_pressed: print(倾斜) else: print(水平) sleep(0.5)轮询方式简单但会占用 CPU 时间而且响应没那么及时。中断方式更优雅推荐用中断。4.2 加速度计倾角模块的角度计算代码MPU6050 的代码稍微复杂一点。如果你用 mpu6050-raspberrypi 库读取原始数据很简单from mpu6050 import mpu6050 import math import time sensor mpu6050(0x68) def read_angle(): accel sensor.get_accel_data() ax accel[x] ay accel[y] az accel[z] # 计算绕 Y 轴和 X 轴的倾角 angle_x math.atan2(ay, math.sqrt(ax**2 az**2)) * 180 / math.pi angle_y math.atan2(ax, math.sqrt(ay**2 az**2)) * 180 / math.pi return angle_x, angle_y while True: ax_angle, ay_angle read_angle() print(fX轴倾角: {ax_angle:.2f} 度, Y轴倾角: {ay_angle:.2f} 度) time.sleep(0.5)这里用的是 atan2 加 sqrt 的公式比单纯的 arcsin 更稳定因为当某个轴接近 ±90 度时arcsin 会出现数值问题。atan2 的好处是能处理所有象限输出范围是 -180 到 180 度。实际测试的时候模块平放读出来的角度应该在 0 度附近可能有 ±1 到 ±2 度的偏差这是正常的因为模块本身有零偏而且手工焊接的模块不一定完全水平。如果要更准可以做零偏校准平放时读一组数据取平均作为零点偏移后面读数都减去这个偏移。4.3 数据滤波让角度读数更稳定加速度计原始数据会有噪声读出来的角度会跳。我实测 MPU6050 静止时角度波动大概在 ±0.5 度左右如果对稳定性要求高需要做滤波。最简单的是一阶低通滤波alpha 0.8 filtered_angle alpha * filtered_angle (1 - alpha) * new_anglealpha 越大滤波效果越强但响应越慢。我一般取 0.8 到 0.95 之间根据实际需求调。如果要做更平滑的效果可以用滑动平均取最近 N 次读数的平均值。N 取 10 到 20 比较合适再多就太迟钝了。还有一个办法是用 MPU6050 内置的 DMP数字运动处理器它内部做了传感器融合直接输出姿态角比我们自己算的准。但 DMP 的配置比较麻烦需要加载固件、配置寄存器代码量大很多。如果你的项目对角度精度要求很高比如云台稳定那值得上 DMP如果只是做课程设计或者简单监测自己算就够了。5. 常见问题与排查技巧5.1 倾斜开关一直触发或不触发这是最常见的问题。先检查接线VCC 和 GND 有没有接反DO 有没有接对 GPIO。然后用万用表量一下开关两端的通断倾斜时应该导通水平时断开。如果开关本身没问题那就是代码里的上拉/下拉设置不对。gpiozero 的 Button 默认是上拉如果你的模块是常闭型那逻辑就反了需要把 pull_up 改成 False或者用 Button(17, pull_upFalse)。还有一种情况是触发角度不对。滚珠开关的触发角度跟安装方向有关如果你把开关横着装可能永远触发不了。我建议先把开关拿在手里慢慢倾斜看什么时候导通找到触发方向后再固定安装。5.2 I2C 设备扫描不到前面提过先查接线。SDA 和 SCL 接反是最常见的错误很多人看引脚图的时候看串行了。树莓派 4B 的物理引脚 3 是 SDA5 是 SCL别搞混。然后确认 I2C 有没有启用用 lsmod | grep i2c 看看 i2c_bcm2835 模块有没有加载。如果没有说明配置没生效检查 config.txt 里的 dtparami2c_armon 有没有写对写完要重启。如果接线和配置都没问题还是扫不到那可能是模块坏了。我买到过一批便宜的 MPU6050 模块有一半是坏的I2C 完全没反应。换一个模块试试如果换了就好那就是模块问题。5.3 角度读数跳动大或不准先做零偏校准平放取平均。如果校准后还是跳检查电源是否稳定。树莓派的 3.3V 输出在带多个传感器时可能会有波动尤其是用 USB 供电且电流不足的时候。可以试试给树莓派单独供电或者用外部 3.3V 稳压模块给传感器供电。另外MPU6050 对振动很敏感如果传感器装在振动的平台上读数会乱跳。这种情况下要么加机械减震比如用橡胶垫要么用软件滤波把高频振动滤掉。我那个云台项目里臂架运动时振动不大所以软件滤波就够了。5.4 树莓派 GPIO 被占用或权限不足用 gpiozero 的时候如果提示 GPIO 被占用可能是之前运行的脚本没退出干净。用 ps aux | grep python 看看有没有残留进程有就 kill 掉。权限方面gpiozero 默认用 pigpio 后端需要 root 权限或者把用户加到 gpio 组。Ubuntu 22.04 上默认用户一般在 gpio 组里如果没有用 sudo usermod -aG gpio $USER 加一下然后重新登录。还有一个坑是树莓派 5 的 GPIO 兼容性。树莓派 5 换了新的 GPIO 芯片RPi.GPIO 库在树莓派 5 上不能直接用需要装 rpi-lgpio 兼容层或者直接用 gpiozero。我实测 gpiozero 在树莓派 5 上工作正常所以如果你用树莓派 5建议直接用 gpiozero省得折腾。6. 实际项目中的应用与扩展6.1 云台自动调平倾斜传感器加舵机回到开头提到的云台项目。需求是让摄像头跟着臂架俯仰自动调整角度保持摄像头始终水平。方案是倾斜传感器MPU6050装在摄像头上实时读俯仰角树莓派根据角度偏差控制舵机反向转动抵消倾斜。控制逻辑用简单的比例控制就行target_angle 0 # 目标水平 kp 2.0 # 比例系数 while True: current_angle, _ read_angle() error target_angle - current_angle servo_angle kp * error # 限制舵机角度范围 servo_angle max(-90, min(90, servo_angle)) set_servo(servo_angle) time.sleep(0.05)kp 的取值需要实际调试太大容易震荡太小响应慢。我一般从 1.0 开始试慢慢加。舵机用树莓派的 PWM 控制gpiozero 里有 Servo 类很方便。树莓派 Pico 控制舵机也很常见Pico 的 PWM 更稳定适合做实时控制。6.2 倾倒报警倾斜开关加蜂鸣器另一个简单项目是倾倒报警。设备上装一个滚珠式倾斜开关一旦倾斜超过阈值树莓派触发蜂鸣器报警同时通过 MQTT 发消息到服务器。这个方案成本极低一个倾斜开关几块钱一个蜂鸣器几块钱树莓派用 Zero 或者 4B 都行。代码逻辑就是前面滚珠开关的代码加一个蜂鸣器控制from gpiozero import Button, Buzzer tilt Button(17, pull_upTrue, bounce_time0.1) buzzer Buzzer(18) def alarm(): buzzer.on() print(倾倒报警) def normal(): buzzer.off() tilt.when_pressed alarm tilt.when_released normal这个项目适合做物联系统设计的课程作业涉及传感器读取、GPIO 控制、网络通信知识点比较全。6.3 太阳能板追光倾角加光敏太阳能板追光系统里倾角传感器用来监测板的俯仰角光敏传感器或者辐照度传感器用来判断哪个方向光强最大。两者结合树莓派控制两个舵机一个水平旋转一个俯仰让太阳能板始终对准光源。这个项目里倾角传感器的作用是提供俯仰角的闭环反馈确保舵机转到目标角度后板子确实到了那个角度而不是因为机械间隙或负载导致偏差。光敏传感器可以用光电传感器模块也可以用 TDS 传感器那种模拟输出的接树莓派的 ADC树莓派本身没有 ADC需要外接 MCP3008 这类芯片。这个项目复杂度高一些但做出来很有成就感适合作为毕业设计或者课程设计的大作业。6.4 与编码器配合更精确的姿态控制如果对角度精度要求极高比如医疗设备或者精密仪器单靠倾斜传感器可能不够。这时候可以倾斜传感器加编码器融合。编码器测电机的转动角度精度高、响应快但会有累积误差倾斜传感器测绝对姿态没有累积误差但噪声大、响应慢。两者融合用互补滤波或者卡尔曼滤波能得到又准又稳的角度。互补滤波的公式很简单angle 0.98 * (angle gyro_rate * dt) 0.02 * accel_angle这里 gyro_rate 是陀螺仪角速度accel_angle 是加速度计算的倾角。0.98 和 0.02 是权重根据实际调试调整。这个方案在云台、平衡车、无人机里都很常见树莓派算力足够跑。7. 几个我踩过的坑和实操心得第一个坑是杜邦线的质量。我一开始图便宜买了一大包杜邦线结果接 I2C 的时候死活扫不到设备换了三根线才好。后来我学乖了关键连接都用万用表量一下通断或者直接焊死。尤其是 I2C 这种对信号质量敏感的接口线材和接触电阻影响很大。第二个坑是电源。树莓派用 USB 供电的时候如果同时带多个传感器和舵机3.3V 和 5V 的电压可能会被拉低导致传感器工作不稳定。我后来给舵机单独供电树莓派只负责信号问题就解决了。舵机的电流冲击很大尤其是堵转的时候直接从树莓派取电很容易导致树莓派重启。第三个坑是安装方向。倾斜传感器的安装方向决定了读数的正负和轴对应关系。我一开始没注意装上去之后发现角度是反的调了半天代码才发现是安装方向的问题。后来我养成习惯装之前先在手里转一圈确认哪个方向对应哪个轴再固定。第四个坑是温度漂移。MPU6050 这类 MEMS 传感器对温度比较敏感长时间工作后零偏会漂。如果项目要求高要么做温度补偿要么定期重新校准。我那个云台项目连续跑几个小时角度会慢慢偏个一两度后来加了定期校准每半小时平放一次重新取零偏才稳定下来。第五个坑是树莓派 5 的 GPIO 库兼容性。我一开始在树莓派 5 上用 RPi.GPIO代码跑不起来报错说找不到模块。后来查了才知道树莓派 5 换了 GPIO 芯片RPi.GPIO 不兼容要装 rpi-lgpio 或者用 gpiozero。这个坑花了我一个下午希望你别再踩。最后分享一个小技巧调试倾斜传感器的时候用 Python 的 matplotlib 实时画角度曲线比看打印数字直观得多。树莓派上装 matplotlib 稍微麻烦点但跑起来之后角度变化一目了然调滤波参数的时候特别有用。如果树莓派性能不够可以把数据通过串口或者网络发到电脑上画效果一样。
返回列表