基本描述:9轴姿态角度传感器广泛用于物联网开发,其中JY901陀螺仪由于自带卡尔曼动态滤波算法便作为了我硬件开发的选择。JY901陀螺仪基本可以在各个平台上进行数据的读取(如arduino、stm32、树莓派、上位机等),但由于JY901的官方只提供了树莓派串口通信的读取方式,而未提供树莓派IIC通信的读取方式。为了实现树莓派上多个JY901陀螺仪的同时运作,本方案决定采用使用IIC通信方式,用Python3进行数据的读取。
第一步:硬件连接
将JY901陀螺仪对应的VCC、SDA、SCL、GND与树莓派进行连接
第二步:
使用i2cdetect命令侦测是否成功接入I2C的设备:
sudo i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- 51 -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
查看该地址下的设备寄存器信息
i2cdump -y 1 0x51
No size specified (using byte-data access)
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 00 00 1e 06 02 00 00 00 f8 1b fe 00 00 00 00 00 ..???...???.....
10: 00 00 00 00 00 00 00 00 00 00 51 00 b0 b1 a6 04 ..........Q.????
20: 03 03 00 00 00 1e 01 ff 2c 00 00 00 e8 01 c0 00 ??...??.,...???.
30: 00 00 15 d4 70 a1 3b 00 00 00 e6 6d d1 f2 81 a3 ..??p?;...?m????
40: 89 16 45 22 48 00 00 00 00 00 00 00 00 00 00 00 ??E"H...........
50: 00 93 80 18 aa 00 00 00 00 00 00 00 00 00 00 00 .????...........
60: 00 00 00 00 00 00 00 00 00 00 03 00 00 00 00 00 ..........?.....
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
80: 00 00 1e 06 02 00 00 00 f8 1b fe 00 00 00 00 00 ..???...???.....
90: 00 00 00 00 00 00 00 00 00 00 51 00 b0 b1 a6 04 ..........Q.????
a0: 03 03 00 00 00 1e 01 ff 2c 00 00 00 e8 01 c0 00 ??...??.,...???.
b0: 00 00 15 4b 70 a3 39 00 00 00 e5 6d d3 f2 81 a3 ..?Kp?9...?m????
c0: 89 37 1d 5a 1c 00 00 00 00 00 00 00 00 00 00 00 ?7?Z?...........
d0: 00 93 80 18 aa 00 00 00 00 00 00 00 00 00 00 00 .????...........
e0: 00 00 00 00 00 00 00 00 00 00 03 00 00 00 00 00 ..........?.....
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
查看JY901使用说明书V4.0:
我们可知加速度、角速度、角度所在的寄存器地址,接下来可以通过Python3进行编码读取了
第三步:
import smbus
import time
class Gyro(object):
def __init__(self, addr):
self.addr = addr
self.i2c = smbus.SMBus(1)
def get_acc(self):
try:
self.raw_acc_x = self.i2c.read_i2c_block_data(self.addr, 0x34, 2)
self.raw_acc_y = self.i2c.read_i2c_block_data(self.addr, 0x35, 2)
self.raw_acc_z = self.i2c.read_i2c_block_data(self.addr, 0x36, 2)
except IOError:
print("ReadError: gyro_acc")
return (0, 0, 0)
else:
self.k_acc = 16 * 9.8
self.acc_x = (self.raw_acc_x[1] << 8 | self.raw_acc_x[0]) / 32768 * self.k_acc
self.acc_y = (self.raw_acc_y[1] << 8 | self.raw_acc_y[0]) / 32768 * self.k_acc
self.acc_z = (self.raw_acc_z[1] << 8 | self.raw_acc_z[0]) / 32768 * self.k_acc
if self.acc_x >= self.k_acc:
self.acc_x -= 2 * self.k_acc
if self.acc_y >= self.k_acc:
self.acc_y -= 2 * self.k_acc
if self.acc_z >= self.k_acc:
self.acc_z -= 2 * self.k_acc
return (self.acc_x, self.acc_y, self.acc_z)
def get_gyro(self):
try:
self.raw_gyro_x = self.i2c.read_i2c_block_data(self.addr, 0x37, 2)
self.raw_gyro_y = self.i2c.read_i2c_block_data(self.addr, 0x38, 2)
self.raw_gyro_z = self.i2c.read_i2c_block_data(self.addr, 0x39, 2)
except IOError:
print("ReadError: gyro_gyro")
return (0, 0, 0)
else:
self.k_gyro = 2000
self.gyro_x = (self.raw_gyro_x[1] << 8 | self.raw_gyro_x[0]) / 32768 * self.k_gyro
self.gyro_y = (self.raw_gyro_y[1] << 8 | self.raw_gyro_y[0]) / 32768 * self.k_gyro
self.gyro_z = (self.raw_gyro_z[1] << 8 | self.raw_gyro_z[0]) / 32768 * self.k_gyro
if self.gyro_x >= self.k_gyro:
self.gyro_x -= 2 * self.k_gyro
if self.gyro_y >= self.k_gyro:
self.gyro_y -= 2 * self.k_gyro
if self.gyro_z >= self.k_gyro:
self.gyro_z -= 2 * self.k_gyro
return (self.gyro_x, self.gyro_y, self.gyro_z)
def get_angle(self):
try:
self.raw_angle_x = self.i2c.read_i2c_block_data(self.addr, 0x3d, 2)
self.raw_angle_y = self.i2c.read_i2c_block_data(self.addr, 0x3e, 2)
self.raw_angle_z = self.i2c.read_i2c_block_data(self.addr, 0x3f, 2)
except IOError:
print("ReadError: gyro_angle")
return (0, 0, 0)
else:
self.k_angle = 180
self.angle_x = (self.raw_angle_x[1] << 8 | self.raw_angle_x[0]) / 32768 * self.k_angle
self.angle_y = (self.raw_angle_y[1] << 8 | self.raw_angle_y[0]) / 32768 * self.k_angle
self.angle_z = (self.raw_angle_z[1] << 8 | self.raw_angle_z[0]) / 32768 * self.k_angle
if self.angle_x >= self.k_angle:
self.angle_x -= 2 * self.k_angle
if self.angle_y >= self.k_angle:
self.angle_y -= 2 * self.k_angle
if self.angle_z >= self.k_angle:
self.angle_z -= 2 * self.k_angle
return (self.angle_x, self.angle_y, self.angle_z)
def main():
head_gyro = Gyro(0x51)
while(True):
print(" Acc: " + repr(head_gyro.get_acc()) + "\n", "Gyro: " + repr(head_gyro.get_gyro()) + "\n", "Angle:" + repr(head_gyro.get_angle()) + "\n")
time.sleep(0.2)
main()
然后运行:
对于异常情况的处理:
总结:树莓派通过IIC的通信方式对JY901陀螺仪进行数据读取可以解决一个树莓派读取多个JY901陀螺仪(或设备)的问题,由于JY901卖家未提供相关的代码加之网上很多资料都采用的串口读取方式,所以并有对此问题有很好的解决。由于初学Python代码可能冗余度还是蛮高的很多地方都还可以改进啦,大家懂这个读取方式就好啦,只是想分享而已,希望对刚接触的童鞋有些帮助!