基本描述: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
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代码可能冗余度还是蛮高的很多地方都还可以改进啦,大家懂这个读取方式就好啦,只是想分享而已,希望对刚接触的童鞋有些帮助! - |