上接 ESP32、MicroPython、MPU6050,ESP32、MicroPython、MPU6050-优快云博客,主要是从硬件方面解决MPU6050的温漂问题,简单起见,直接更换了一款比较高级的IMU——JY901S。
一、JY901S
JY901S是维特智能公司生产的一款基于MEMS技术的高性能三维运动姿态测量系统。包含三轴陀螺仪、三轴加速度计,三轴电子罗盘等运动传感器。该传感器集成高性能传感器和自主研发的姿态动力学核心算法引擎以及高动态卡尔曼滤波融合算法,提供了高精度、高动态、实时补偿的三轴姿态角度,通过对各类数据的灵活选择配置,满足不同的应用场景。
模块内部自带电压稳定电路,工作电压3.3~5V,引脚电平兼容3.3V/5V的嵌入式系统,连接方便。支持串口和IIC两种数字接口。方便用户选择最佳的连接方式。串口速率4800bps~230400bps可调,IIC接口支持全速400K速率。保留4路扩展端口,可以分别配置为模拟输入,数字输入,数字输出等功能。
引脚序号 | 引脚名称 | 引脚功能 |
1 | D0 | 模拟输入、数字输入输出,拉高唤醒 |
2 | Vcc | 电源3.3~5V |
3 | RX | 串行数据输入 |
4 | TX | 串行数据输出 |
5 | GND | 接地 |
6 | D1 | 模拟输入、数字输入输出、设置角度参考 |
7 | D3 | 模拟输入、数字输入输出、角度报警输出、X-角度报警输出 |
8 | GND | 接地 |
9 | SDA | I2C数据线、Y-角度报警输出 |
10 | SCL | I2C时钟线、Y+角度报警输出 |
11 | Vcc | 电源3.3~5V |
12 | D2 | 模拟输入、数字输入输出、硬件复位、X+角度报警输出 |
资料来源:JY901S产品资料 · 深圳维特智能科技有限公司
二、硬件连接
JY901S | ESP32-S3 |
Vcc(2) | 3V3 |
RX(3) | TX(17) |
TX(4) | RX(18) |
GND(5) | GND |
三、主要程序
参考链接:树莓派4B-用串口读取JY901S陀螺仪数据-优快云博客
from machine import UART
import time
acceleration_data = [0] * 8
gyroscope_data = [0] * 8
angle_data = [0] * 8
frame_state = 0
byte_count = 0
checksum = 0
acceleration = [0.0] * 3
gyroscope = [0.0] * 3
angle = [0.0] * 3
# 加速度数据
def parse_acceleration(data):
ax_low, ax_high = data[0], data[1]
ay_low, ay_high = data[2], data[3]
az_low, az_high = data[4], data[5]
scale_acceleration = 16.0
acc_x = (ax_high << 8 | ax_low) / 32768.0 * scale_acceleration
acc_y = (ay_high << 8 | ay_low) / 32768.0 * scale_acceleration
acc_z = (az_high << 8 | az_low) / 32768.0 * scale_acceleration
if acc_x >= scale_acceleration:
acc_x -= 2 * scale_acceleration
if acc_y >= scale_acceleration:
acc_y -= 2 * scale_acceleration
if acc_z >= scale_acceleration:
acc_z -= 2 * scale_acceleration
return acc_x, acc_y, acc_z
# 陀螺仪数据
def parse_gyroscope(data):
gx_low, gx_high = data[0], data[1]
gy_low, gy_high = data[2], data[3]
gz_low, gz_high = data[4], data[5]
scale_gyroscope = 2000.0
gyro_x = (gx_high << 8 | gx_low) / 32768.0 * scale_gyroscope
gyro_y = (gy_high << 8 | gy_low) / 32768.0 * scale_gyroscope
gyro_z = (gz_high << 8 | gz_low) / 32768.0 * scale_gyroscope
if gyro_x >= scale_gyroscope:
gyro_x -= 2 * scale_gyroscope
if gyro_y >= scale_gyroscope:
gyro_y -= 2 * scale_gyroscope
if gyro_z >= scale_gyroscope:
gyro_z -= 2 * scale_gyroscope
return gyro_x, gyro_y, gyro_z
# 角度数据
def parse_angle(data):
roll_low, roll_high = data[0], data[1]
pitch_low, pitch_high = data[2], data[3]
yaw_low, yaw_high = data[4], data[5]
scale_angle = 180.0
angle_x = (roll_high << 8 | roll_low) / 32768.0 * scale_angle
angle_y = (pitch_high << 8 | pitch_low) / 32768.0 * scale_angle
angle_z = (yaw_high << 8 | yaw_low) / 32768.0 * scale_angle
if angle_x >= scale_angle:
angle_x -= 2 * scale_angle
if angle_y >= scale_angle:
angle_y -= 2 * scale_angle
if angle_z >= scale_angle:
angle_z -= 2 * scale_angle
return angle_x, angle_y, angle_z
# 数据处理
def process_data(input_data):
global frame_state, byte_count, checksum, acceleration, gyroscope, angle
global acceleration_data, gyroscope_data, angle_data
for byte in input_data:
if frame_state == 0:
if byte == 0x55 and byte_count == 0:
checksum = byte
byte_count = 1
elif byte in (0x51, 0x52, 0x53) and byte_count == 1:
checksum += byte
frame_state = byte - 0x50
byte_count = 2
elif frame_state in (1, 2, 3):
if byte_count < 10:
if frame_state == 1:
acceleration_data[byte_count - 2] = byte
elif frame_state == 2:
gyroscope_data[byte_count - 2] = byte
elif frame_state == 3:
angle_data[byte_count - 2] = byte
checksum += byte
byte_count += 1
else:
if byte == (checksum & 0xFF):
if frame_state == 1:
acceleration = parse_acceleration(acceleration_data)
elif frame_state == 2:
gyroscope = parse_gyroscope(gyroscope_data)
elif frame_state == 3:
angle = parse_angle(angle_data)
checksum = 0
byte_count = 0
frame_state = 0
if __name__ == '__main__':
uart = UART(1, baudrate=9600, tx=17, rx=18)
print('开始读取JY901s数据...')
while True:
data_buffer = uart.read(33)
if data_buffer:
process_data(data_buffer)
print("角度 (度): X=%10.3f Y=%10.3f Z=%10.3f" % (angle[0], angle[1], angle[2]))