相关知识介绍
陀螺仪是一种用来感测与维持方向的装置,基于角动量的理论设计出来的。陀螺仪主要是由一个位于轴心可以旋转的轮子构成,陀螺仪一旦开始旋转,由于轮子的「角动量」,陀螺仪有抗拒方向改变的趋向。陀螺仪多用于导航、定位等系统
JY901S是9轴姿态角度传感器,支持串口和 IIC 两种数字接口。串口速率2400bps~921600bps 可调, IIC 接口支持全速 400K 速率,本文均是使用串口。
9轴分别为加速度传感器(即加速计)、角速度传感器(即陀螺仪)、磁感应传感器(即电子罗盘)。
连接说明
我是用的USB转TTL电平串口模块与树莓派连接,用的型号是CH340。
在windows电脑上的端口号都是ComX,在Liunx系统下的端口号如果是直接插在树莓派USB接口上的话就是写
'/dev/ttyAMA0'否则就是'/dev/ttyAMA0',具体如下。
port = '/dev/ttyUSB0' # use '/dev/ttyAMA0' for USB or '/dev/ttyAMA0' for GPIO
注意:RX和TX是需要反着接的,无论是直接连在GPIO上还是用USB转TTL,否则会出现问题。
轴向说明
如上图所示,模块的轴向在上图的右上方,向右为 X 轴,向上 Y 轴,垂直模块向外为 Z 轴。旋转的方向按右手法则定义,即右手大拇指指向轴向,四指弯曲的方向即为绕该轴 旋转的方向。X 轴角度即为绕 X 轴旋转方向的角度,Y 轴角度即为绕 Y 轴旋转方向的角度, Z 轴角度即为绕 Z
测试结果
完整代码
#coding:UTF-8
import serial
ACCData=[0.0]*8
GYROData=[0.0]*8
AngleData=[0.0]*8
FrameState = 0 #通过0x后面的值判断属于哪一种情况
Bytenum = 0 #读取到这一段的第几位
CheckSum = 0 #求和校验位
a = [0.0]*3
w = [0.0]*3
Angle = [0.0]*3
def DueData(inputdata): #新增的核心程序,对读取的数据进行划分,各自读到对应的数组里
global FrameState
global Bytenum
global CheckSum
global a
global w
global Angle
for data in inputdata: #在输入的数据进行遍历
# print(inputdata)
# print(data, type(data))
if FrameState==0: #当未确定状态的时候,进入以下判断
if data ==0x55 and Bytenum==0: #0x55位于第一位时候,开始读取数据,增大bytenum
CheckSum=data
Bytenum=1
continue
elif data==0x51 and Bytenum==1:#在byte不为0 且 识别到 0x51 的时候,改变frame
CheckSum+=data
FrameState=1
Bytenum=2
elif data==0x52 and Bytenum==1: #同理
CheckSum+=data
FrameState=2
Bytenum=2
elif data==0x53 and Bytenum==1:
CheckSum+=data
FrameState=3
Bytenum=2
elif FrameState==1: # acc #已确定数据代表加速度
if Bytenum<10: # 读取8个数据
ACCData[Bytenum-2]=data # 从0开始
CheckSum+=data
Bytenum+=1
else:
if data == (CheckSum&0xff): #假如校验位正确
a = get_acc(ACCData)
CheckSum=0 #各数据归零,进行新的循环判断
Bytenum=0
FrameState=0
elif FrameState==2: # gyro
if Bytenum<10:
GYROData[Bytenum-2]=data
CheckSum+=data
Bytenum+=1
else:
if data == (CheckSum&0xff):
w = get_gyro(GYROData)
CheckSum=0
Bytenum=0
FrameState=0
elif FrameState==3: # angle
if Bytenum<10:
AngleData[Bytenum-2]=data
CheckSum+=data
Bytenum+=1
else:
if data == (CheckSum&0xff):
Angle = get_angle(AngleData)
d = a+w+Angle
print("a(g):%10.3f %10.3f %10.3f w(deg/s):%10.3f %10.3f %10.3f Angle(deg):%10.3f %10.3f %10.3f"%d)
CheckSum=0
Bytenum=0
FrameState=0
def get_acc(datahex):
axl = datahex[0]
axh = datahex[1]
ayl = datahex[2]
ayh = datahex[3]
azl = datahex[4]
azh = datahex[5]
k_acc = 16.0
acc_x = (axh << 8 | axl) / 32768.0 * k_acc
acc_y = (ayh << 8 | ayl) / 32768.0 * k_acc
acc_z = (azh << 8 | azl) / 32768.0 * k_acc
if acc_x >= k_acc:
acc_x -= 2 * k_acc
if acc_y >= k_acc:
acc_y -= 2 * k_acc
if acc_z >= k_acc:
acc_z-= 2 * k_acc
return acc_x,acc_y,acc_z
def get_gyro(datahex):
wxl = datahex[0]
wxh = datahex[1]
wyl = datahex[2]
wyh = datahex[3]
wzl = datahex[4]
wzh = datahex[5]
k_gyro = 2000.0
gyro_x = (wxh << 8 | wxl) / 32768.0 * k_gyro
gyro_y = (wyh << 8 | wyl) / 32768.0 * k_gyro
gyro_z = (wzh << 8 | wzl) / 32768.0 * k_gyro
if gyro_x >= k_gyro:
gyro_x -= 2 * k_gyro
if gyro_y >= k_gyro:
gyro_y -= 2 * k_gyro
if gyro_z >=k_gyro:
gyro_z-= 2 * k_gyro
return gyro_x,gyro_y,gyro_z
def get_angle(datahex):
rxl = datahex[0]
rxh = datahex[1]
ryl = datahex[2]
ryh = datahex[3]
rzl = datahex[4]
rzh = datahex[5]
k_angle = 180.0
angle_x = (rxh << 8 | rxl) / 32768.0 * k_angle
angle_y = (ryh << 8 | ryl) / 32768.0 * k_angle
angle_z = (rzh << 8 | rzl) / 32768.0 * k_angle
if angle_x >= k_angle:
angle_x -= 2 * k_angle
if angle_y >= k_angle:
angle_y -= 2 * k_angle
if angle_z >=k_angle:
angle_z-= 2 * k_angle
return angle_x,angle_y,angle_z
if __name__=='__main__':
port = '/dev/ttyUSB0' # use '/dev/ttyAMA0' for USB or '/dev/ttyAMA0' for GPIO
baud = 9600 # baudrate
ser = serial.Serial(port, baud, timeout=0.5) # ser = serial.Serial('com7',115200, timeout=0.5)
if ser.is_open:
print('The serial port was opened successfully!')
while True:
datahex = ser.read(33) # How many bytes are read from the port
DueData(datahex)
else:
print('Failed to open the serial!')
标签:acc,树莓,angle,gyro,datahex,Bytenum,JY901S,串口,data
From: https://www.cnblogs.com/kevenduan/p/18292231