☰
JY901姿态传感器上手实测:从开箱到读出第一帧角度数据
2026/10/15 7:20:35 网站建设 项目流程

简介:这份JY901官方使用说明文档面向嵌入式开发者、无人机与机器人爱好者及需要姿态测量方案的学生工程师,用于解决高精度惯性导航模块的选型、接线与调试问题。资源包共1个PDF文件,大小约1.35MB,内容为官方说明书,涵盖产品概述、性能参数、引脚与轴向说明、串口与IIC硬件连接方法、上位机软件操作、恢复出厂设置及陀螺加计与磁场校准等完整章节。文档详细列出加速度0.01g、角速度0.05°/s、姿态稳定度0.01°等指标,并说明3V至6V供电、兼容3.3V/5V电平、最高200Hz输出、4路扩展端口及GPS-IMU组合导航能力,可帮助读者快速完成模块与Arduino、51、STM32的对接和校准。目前已有3516人学习下载,适合作为调试与二次开发的案头参考。

1. 姿态传感器 JY901 上手实测:从开箱到读出第一帧角度数据

手里拿到一块邮票孔封装的姿态传感器 JY901,第一反应往往是「这么小一块,真能输出 0.01° 稳定度的姿态角?」我最初也这么想。它集成三轴陀螺仪、加速度计和地磁传感器,内部跑动力学解算加卡尔曼动态滤波,直接吐欧拉角、四元数、加速度、角速度、磁场,JY901B 还带气压和高度,接上 GPS 能组 IMU 组合导航。串口和 IIC 双接口,3V~6V 供电,引脚兼容 3.3V/5V 系统,最高 200Hz 输出。适合做无人机、平衡车、云台、机器人导航的团队,也适合拿它当高精度倾角仪用的嵌入式开发者。这篇笔记按「硬件怎么接、上位机怎么调、协议怎么解、坑在哪」的顺序拆一遍,读完能直接复现。

2. 硬件连接与上位机联调:串口、IIC 两条路怎么选

2.1 串口连接:USB-TTL 模块的交叉接线

和电脑通信最省事的方式是 USB 转 TTL 串口模块。接线核心就一句:模块的 TX 接 USB 模块的 RX,模块的 RX 接 USB 模块的 TX,VCC 和 GND 对应接上。很多人第一次翻车就翻在这里——TXD 和 RXD 没交叉,打开上位机一片空白,还以为模块坏了。

具体接法:

JY901 引脚USB-TTL 模块引脚说明
VCC+5V3V~6V 均可,模块内部有 LDO
RXTXD注意交叉
TXRXD注意交叉
GNDGND共地必须接

接好之后装 USB-TTL 驱动,在设备管理器里查到串口号。打开上位机,先点波特率菜单选 9600(出厂默认),再点串口设置选对应 COM 口,正常就能看到数据曲线在跳。

如果打开串口没数据,按这个顺序排查:先确认 TX/RX 有没有交叉,再确认波特率。忘了模块波特率是多少,点「波特率 → Auto」让软件自动搜。自动搜索有个前提——模块输出速率要大于 5Hz,速率太低搜不到。实在不行就恢复出厂设置,回到 9600 再连。

连单片机也是同样的逻辑,只是把 USB-TTL 换成 MCU 的串口外设。注意模块是 TTL 电平,不是 RS232 电平,错接到 RS232 可能直接烧模块,这点在协议章节里也专门强调了。

2.2 IIC 连接:上拉电阻不能省

IIC 接法的关键细节是模块的 IIC 总线是开漏输出,MCU 连接时必须通过一个 4.7K 电阻把 SCL 和 SDA 上拉到 VCC。省掉这两个电阻,通信大概率不稳定或者直接不通。IIC 最大支持 400K 全速速率,默认地址 0x50,可以通过上位机改,但改完要重新上电才生效。

选串口还是 IIC,我的经验是:调试阶段一律用串口,因为上位机直接能看数据、能校准、能改配置;量产嵌入 PCB 后再切 IIC,省引脚。串口速率 2400bps~921600bps 可调,IIC 400K,两者数据输出速率上限都是 200Hz。

2.3 上位机基本操作:记录、清图、三维显示

上位机几个按钮值得单独说。点「记录」可以把采集数据存到文本文件,但注意——必须点「停止」之后文件才会写入硬盘,路径在上位机根目录下,以记录起始时间命名。直接关软件,这次记录就没了,这是血泪经验。

「清图」按钮在两次采集间隔较长时特别有用,图表更新会变慢,点一下清图能加快刷新。「三维」按钮调出三维姿态显示,默认全屏,按 F 键切回窗口模式。如果按 F 没反应,先按 Ctrl+空格关掉中文输入法再按,这个玄学问题卡过不少人。

3. 校准与配置:不校准,数据就是废的

3.1 陀螺/加计校准:去除零偏

模块出厂时陀螺仪和加速度计都有不同程度的零偏误差,不校准测量就不准。校准步骤:

  1. 把模块保持水平放置
  2. 点「设置」选项卡,进入设置页面
  3. 点「陀螺、加计校准」按钮
  4. 等 AxOffset、AyOffset、AzOffset、GxOffset、GyOffset、GzOffset 这几个值稳定
  5. 点「正常模式」按钮完成校准
  6. 点「保存配置」按钮写入模块内部 FLASH

第 6 步是重点。不点保存,掉电以后校准值全丢,下次上电又回到未校准状态。校准完成后,静止状态下陀螺仪输出应该回到 0°/s 附近。这几个零偏值也可以手动填,点对应的 GxOffset 等按钮就能设置。

3.2 磁场校准:航向角准不准全看这一步

磁场传感器制造时的零点误差通常比较大,不校准航向角基本没法用。校准方法:

  1. 模块和电脑连好,放到远离干扰磁场的地方
  2. 点「设置」选项卡 → 「磁场校准」按钮
  3. 绕模块 X 轴转 360°,可以来回转几圈
  4. 绕 Y 轴转 360°
  5. 绕 Z 轴转 360°
  6. 再随意转动几圈
  7. 等 HxOffset、HyOffset、HzOffset 不再变化
  8. 点「正常模式」完成,再点「保存配置」

只有磁场校准做完,模块才能输出准确的航向角。同样,不保存就掉电丢失。

3.3 高度置零与回传内容定制

高度置零只对带气压传感器的 JY901B 有用。模块高度是根据气压算的,置零就是把当前气压当作零高度。点「设置」→「高度校准」即可。注意高度校准值模块不做保存,所以不用点保存配置。

回传内容可以按需勾选,时间、加速度、角速度、角度、磁场、端口状态、气压、高度、经纬度、地速都能单独开关。设置完必须点「保存配置」,否则掉电丢失。几个容易忽略的点:

  • 时间默认以上电时刻为 2015 年 1 月 1 日 0:0:0.0,接 GPS 后用 GPS 时间,注意 GPS 时间比北京时间晚 8 小时
  • 气压数据仅 JY901B 有效
  • 经纬度和地速仅在连接 GPS 后有效,且要把 D1 扩展端口设为 GPSRX,GPS 连接波特率设成 GPS 模块的输出波特率

3.4 回传速率、通信波特率与 IIC 地址

回传速率在设置选项卡里选,点后面的「更改」立即生效,要掉电保存再点「保存配置」。默认 10Hz,最高 200Hz。这里有个自动降频机制:如果回传内容多、通信波特率又低,传不了这么多数据,模块会自动降频到允许的最大速率。所以别一味拉高回传速率,先算一下带宽够不够。

通信波特率默认 9600,改完不会立即生效,必须重新上电。IIC 地址默认 0x50,改完同样要重新上电。GPS 连接波特率默认 9600,改完也是重新上电生效。这三个「重新上电才生效」是新手最容易懵的地方——改完发现没变化,以为没改成功,其实是没断电重启。

4. 串口协议解析:从字节流到物理量

4.1 数据帧结构与校验和

模块向上位机发的数据是 16 进制,不是 ASCII。每帧以 0x55 开头,第二个字节是包类型标识,后面跟数据,最后是校验和。校验和的计算规则是:从帧头 0x55 开始,把所有字节累加,取低 8 位。

以加速度包为例:

0x55 0x51 AxL AxH AyL AyH AzL AzH TL TH SUM

校验和 Sum = 0x55 + 0x51 + AxH + AxL + AyH + AyL + AzH + AzL + TH + TL。

解析时最容易踩的坑是负数处理。数据分低字节和高字节依次传送,组合成一个有符号 short。转换时必须先把高字节强制转成有符号 short 再移位,否则负数会解析错。用 Python 写解析大概是这个逻辑:

import struct def parse_accel(frame): # frame 是从 0x55 0x51 开始的完整帧 AxL, AxH = frame[2], frame[3] AyL, AyH = frame[4], frame[5] AzL, AzH = frame[6], frame[7] TL, TH = frame[8], frame[9] # 关键:先转有符号 short 再移位 ax_raw = struct.unpack('<h', bytes([AxL, AxH]))[0] ay_raw = struct.unpack('<h', bytes([AyL, AyH]))[0] az_raw = struct.unpack('<h', bytes([AzL, AzH]))[0] ax = ax_raw / 32768 * 16 * 9.8 # 单位 m/s^2 ay = ay_raw / 32768 * 16 * 9.8 az = az_raw / 32768 * 16 * 9.8 temp = struct.unpack('<h', bytes([TL, TH]))[0] / 100.0 return ax, ay, az, temp

struct.unpack('<h', ...)里的<h表示小端有符号 short,这一步替代了手动移位,避免符号位出错。量程系数 16g 对应加速度,32768 是 16 位有符号数的满量程。

4.2 各数据包的计算公式

角度包 0x53 的计算:

def parse_angle(frame): RollL, RollH = frame[2], frame[3] PitchL, PitchH = frame[4], frame[5] YawL, YawH = frame[6], frame[7] roll = struct.unpack('<h', bytes([RollL, RollH]))[0] / 32768 * 180 pitch = struct.unpack('<h', bytes([PitchL, PitchH]))[0] / 32768 * 180 yaw = struct.unpack('<h', bytes([YawL, YawH]))[0] / 32768 * 180 return roll, pitch, yaw

角速度包 0x52 系数是 2000°/s,磁场包 0x54 直接是原始值不做缩放,四元数包 0x59 除以 32768。

气压高度包 0x56 是 32 位无符号数:

def parse_pressure_height(frame): P = frame[2] | (frame[3] << 8) | (frame[4] << 16) | (frame[5] << 24) H = frame[6] | (frame[7] << 8) | (frame[8] << 16) | (frame[9] << 24) return P, H # 气压 Pa,高度 cm

经纬度包 0x57 也是 32 位,但要注意 NMEA-0183 格式的换算。经度输出时去掉了小数点,度数 dd = Lon / 100000000,分数 mm.mmmmm = (Lon % 10000000) / 100000。纬度同理,除数换成 10000000。

4.3 姿态角的坐标系与欧拉角特性

姿态角结算用的是东北天坐标系,正方向放置模块时向左为 X 轴、向前为 Y 轴、向上为 Z 轴。欧拉角旋转顺序是 Z-Y-X,先绕 Z 转,再绕 Y,再绕 X。

这里有两个必须知道的特性:一是俯仰角范围只有 ±90°,超过 90° 会变换到小于 90°,同时让 X 轴角度大于 180°;二是三轴耦合,只有小角度时才表现出独立变化,大角度时姿态角会耦合。比如 X 轴接近 90° 时,即使只绕 X 轴转,Y 轴角度也会跟着大幅变化。这是欧拉角表示姿态的固有特性,不是模块的问题。要避免这个问题,直接用四元数包 0x59 做后续运算。

5. 避坑与排查:那些让我重来一遍的坑

5.1 打开串口没数据

现象:上位机连上后曲线不动,一片空白。 原因:最常见是 TX/RX 没交叉,其次是波特率不匹配。 解决:先检查接线是否交叉,再用「波特率 → Auto」自动搜索。搜不到就恢复出厂设置回 9600。恢复出厂设置用短路法:D2 引脚和 VCC 短接,上电,LED 长亮约 2 秒后熄灭,完成。

5.2 校准后掉电数据又不对

现象:校准完当时准,断电再上电又偏了。 原因:没点「保存配置」,校准值没写入 FLASH。 解决:陀螺/加计校准和磁场校准完成后,必须点「保存配置」。高度校准不用保存。

5.3 改了波特率/IIC 地址没反应

现象:在上位机改了波特率或 IIC 地址,发现没变化。 原因:这两个设置不是立即生效的。 解决:改完必须重新上电。回传速率是立即生效的,但掉电保存仍需点保存配置。

5.4 高回传速率下数据丢包

现象:设了 200Hz,但收到的数据不完整或频率对不上。 原因:回传内容多、波特率低,带宽不够,模块自动降频了。 解决:要么减少回传内容,要么提高通信波特率。算一下:假设回传角度包 11 字节,200Hz 就是 2200 字节/秒,9600bps 约 960 字节/秒,根本不够。至少要把波特率提到 115200 以上。

5.5 航向角漂移严重

现象:Yaw 角慢慢漂,或者指的方向不对。 原因:磁场没校准,或者校准环境有干扰磁场。 解决:把模块拿到远离电机、磁铁、大电流走线的地方重新做磁场校准,绕三轴各转 360° 再随意转几圈,等零偏值稳定后保存。

6. 进阶技巧:用寄存器指令做自动化配置

上位机点按钮适合调试,但量产或者集成到自动化测试流程里,就得直接发指令。模块的配置指令格式统一是:

0xFF 0xAA Address DataL DataH

比如设置回传速率为 100Hz,查寄存器表 RATE 地址是 0x03,100Hz 对应值 0x09:

import serial def send_config(ser, addr, data): frame = bytes([0xFF, 0xAA, addr, data & 0xFF, (data >> 8) & 0xFF]) ser.write(frame) ser = serial.Serial('COM3', 9600, timeout=1) # 设置回传速率 100Hz send_config(ser, 0x03, 0x09) # 保存配置 send_config(ser, 0x00, 0x00)

几个常用寄存器地址:0x00 保存配置,0x01 校准(1 陀螺加计、2 磁场、3 高度置零),0x02 回传内容,0x03 回传速率,0x04 串口波特率,0x1a IIC 地址,0x1b 关闭 LED。

回传内容 RSW 寄存器 0x02 是位定义,每一位对应一个包:bit0 是 0x50 时间包,bit1 是 0x51 加速度包,bit2 是 0x52 角速度包,bit3 是 0x53 角度包,bit4 是 0x54 磁场包,bit5 是 0x55 端口状态包,bit6 是 0x56 气压高度包,bit7 是 0x57 经纬度包。默认值是 0x1E,也就是只输出加速度、角速度、角度、磁场四个包。

扩展端口配置也走寄存器。D0~D3 模式地址分别是 0x0e~0x11,值 0x00 模拟输入、0x01 数字输入、0x02 输出高、0x03 输出低、0x04 输出 PWM。D1 还多一个 0x05 连接 GPS 的 TX。PWM 高电平宽度地址 0x12~0x15,周期地址 0x16~0x19,单位都是 us。比如舵机控制信号高电平 1500us、周期 20000us,就把对应端口的 PWMH 设为 1500、PWMT 设为 20000。

模拟输入的电压换算公式要记牢:U = DxStatus / 1024 * Uvcc。Uvcc 的判断分两种情况——供电大于 3.5V 时 Uvcc 为 3.3V(片上有 LDO),供电小于 3.5V 时 Uvcc = 电源电压 - 0.2V。这个细节在直接读端口状态做电压采集时很关键,搞错了读数就偏。

从那以后我每次拿到新模块,都强制走一遍「恢复出厂 → 校准 → 保存 → 重新上电验证」的流程,确认静止时角速度归零、航向角稳定,再开始写业务代码。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询