Loading... 本文翻译自King Tide Sailing的[博客](http://kingtidesailing.blogspot.sg/2016/02/how-to-setup-mpu-9250-on-raspberry-pi_25.html),感谢原作者。 # 硬件连接 首先,无论采用排线、跳线还是焊接的方式,都要保证MPU-9250和树莓派牢固地连接在一起。需要注意的是,下面采用了I2C接口,这就要求连接的线缆不能太长(不超过一只脚的长度)。 ![](http://blog.lxalxy.com/usr/uploads/2021/03/3458145909.jpg) 不仅如此,你还需要将MPU-9250正确地安装。我利用一些剩下的木材做了MPU-9250的外壳,这使它容易安装在家中,或者是船上。但是注意不要使用任何含铁的金属(或者是任何金属)来制作外壳,亲测,如果在MPU-9250上面挥舞一个不锈钢螺丝,航向角就会迅速改变达到30度。 # 下载并安装合适的程序 首先,在/home/pi路径下,新建文件夹kts用于存储所有用到的脚本和文件 ```bash hljs mkdir kts cd kts ``` 接下来,安装i2c工具并连接好MPU-9250(注意是3.3V供电) ```bash hljs sudo apt-get install i2c-tools ``` 安装之前需要确认树莓派已经开启I2C功能,这一步可以参考如下帖子:[树莓派入门教程——开启SPI和I2C功能](http://www.embed-net.com/thread-140-1-1.html) 安装好后,用i2cdetect命令扫描系统总线上的所有设备 ```bash hljs sudo i2cdetect -y 1 ``` 如果连接正确,会看到MPU-9250的默认地址68被打印出来 接下来,下载并安装cmake,用于编译传感器的库 ```bash hljs sudo apt-get install cmake ``` 此外,还需要安装一些python工具 ```bash hljs sudo apt-get install python-dev ``` 如果需要进行椭球拟合标定(Ellipsoid Fit Calibration,强烈推荐),还需要安装octave ```bash hljs sudo apt-get install octave ``` 接下来,获取RTIMULib库文件,[Github地址](https://github.com/RTIMULib/RTIMULib2) ```bash hljs git clone https://github.com/richards-tech/RTIMULib2.git ``` 我们真正需要的是RTIMULibCal 程序,以及其他一些脚本文件。如果你想要了解所有的demo,可以参考[项目说明](http://github.com/RTIMULib/RTIMULib2/tree/master/Linux)。否则的话,按照下列步骤进行: ```bash hljs cd RTIMULib2/Linux/RTIMULibCal make -j4 sudo make install ``` 最后,将RTEllipsoidFit 文件夹拷入上面建立的工作空间中 ```bash hljs cp -r /home/pi/kts/RTIMULib2/RTEllipsoidFit/ /home/pi/kts/ cd /home/pi/kts/RTEllipsoidFit/ ``` 接下来几步我认为是可选的,但它们被列在了github page中,因此我们简单的过一下。 首先,输入 ```bash hljs sudo nano /etc/modules ``` 确认下述两行未被注释 ```bash hljs i2c-dev i2c-bcm2708 ``` 接下来: ```bash hljs sudo nano /etc/udev/rules.d/90-i2c.rules ``` 添加: ```bash hljs KERNEL=="i2c-[0-7]",MODE="0666" ``` 最后 ```bash hljs sudo nano /boot/config.txt ``` 在文件末尾添加: ```bash hljs dtparam=i2c1_baudrate=400000 ``` 重启 ```bash hljs sudo reboot ``` # 标定 进入RTEllipsoidFit 文件夹,运行 ```bash hljs RTIMULibCal ``` 按照打印出的提示,按’m’开始标定磁力计的最大/最小值(沿所有轴旋转),按’s’保存。 按’e’进行椭球拟合标定。其可以理解为传感器位于椭球表面上,然后沿着表面移动传感器,就像海洋上航行的船一样,同时保证传感器底部正对椭球中心。这个过程会花费一段时间,当获取了足够的数据时会自动停止。 下面是一些常见错误原因: > error: ellipsoide fit returned 32512 - aborting 表明当前工作目录不是RTEllipsoidFit 文件夹 > error /bin/sh: 1: octave: not found 表明octave没有安装 > I2C read error from 104, 114 - Failed to read fifo count 表明硬件连接可能松动了 最后,按’a’标定加速度计,将传感器沿x轴放置(x指向上方),按‘e’激活该轴,轻轻的摆动,随后按‘d’禁用,并将该轴的另一端指向下方,按’e’重新激活。按‘d’和空格可以切换到下一个轴,在y轴和z轴重复上述过程,最后按‘s’保存,按‘x’退出。 现在我们得到了标定数据,将其复制到工作目录中,这里新建了一个scripts目录 ```bash hljs cp RTIMULib.ini /home/pi/kts/scripts/ ``` # MPU-9250 Python脚本 从[https://github.com/OldCC/kts](https://github.com/OldCC/kts)下载imu.py,这个脚本的输出不仅打印在了终端中,还发送给了UDP,这就可以进行一些更有趣的开发。下面会附上当前的一个版本,但并不会进行更新。 需要注意:确保之前生成的 RTIMULib.ini和imu.py在同一文件夹,例如之前提到的/home/pi/kts/scripts/ 如果初始化失败或工作过程中失败,脚本会发送一条NMEA语句,例如 ```bash hljs $IIXDR,IMU_FAIL,1.2*6F ``` 意味着1.2分钟前系统发生了错误,通常来说都是硬件连接松动导致的。 imu.py文件: ```python hljs import sys, getopt sys.path.append('.') import RTIMU import os.path import time import math import operator import socket IMU_IP = "127.0.0.2" IMU_PORT = 5005 SETTINGS_FILE = "RTIMULib" s = RTIMU.Settings(SETTINGS_FILE) imu = RTIMU.RTIMU(s) # timers t_print = time.time() t_damp = time.time() t_fail = time.time() t_fail_timer = 0.0 t_shutdown = 0 if (not imu.IMUInit()): hack = time.time() imu_sentence = "$IIXDR,IMU_FAILED_TO_INITIALIZE*7C" if (hack - t_print) > 1.0: sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.sendto(imu_sentence, (IMU_IP, IMU_PORT)) t_print = hack t_shutdown += 1 if t_shutdown > 9: sys.exit(1) imu.setSlerpPower(0.02) imu.setGyroEnable(True) imu.setAccelEnable(True) imu.setCompassEnable(True) poll_interval = imu.IMUGetPollInterval() # data variables roll = 0.0 pitch = 0.0 yaw = 0.0 heading = 0.0 rollrate = 0.0 pitchrate = 0.0 yawrate = 0.0 magnetic_deviation = -13.7 # dampening variables t_one = 0 t_three = 0 roll_total = 0.0 roll_run = [0] * 10 heading_cos_total = 0.0 heading_sin_total = 0.0 heading_cos_run = [0] * 30 heading_sin_run = [0] * 30 # sentences produces by the imu iihdt0 = "$IIHDT,,T*0C" iixdr0 = "$IIXDR,A,,D,ROLL,A,,D,PTCH,A,,D,RLLR,A,,D,PTCR,A,,D,YAWR*51" iihdt = iihdt0 iixdr = iixdr0 freq = 1 while True: hack = time.time() # if it's been longer than 5 seconds since last print if (hack - t_damp) > 5.0: if (hack - t_fail) > 1.0: t_one = 0 t_three = 0 roll_total = 0.0 roll_run = [0] * 10 heading_cos_total = 0.0 heading_sin_total = 0.0 heading_cos_run = [0] * 30 heading_sin_run = [0] * 30 t_fail_timer += 1 imu_sentence = "IIXDR,IMU_FAIL," + str(round(t_fail_timer / 60, 1)) cs = format(reduce(operator.xor,map(ord,imu_sentence),0),'X') if len(cs) == 1: cs = "0" + cs imu_sentence = "$" + imu_sentence + "*" + cs sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.sendto(imu_sentence, (IMU_IP, IMU_PORT)) t_fail = hack t_shutdown += 1 if imu.IMURead(): data = imu.getIMUData() fusionPose = data["fusionPose"] Gyro = data["gyro"] t_fail_timer = 0.0 if (hack - t_damp) > .1: roll = round(math.degrees(fusionPose[0]), 1) pitch = round(math.degrees(fusionPose[1]), 1) yaw = round(math.degrees(fusionPose[2]), 1) rollrate = round(math.degrees(Gyro[0]), 1) pitchrate = round(math.degrees(Gyro[1]), 1) yawrate = round(math.degrees(Gyro[2]), 1) if yaw < 90.1: heading = yaw + 270 - magnetic_deviation else: heading = yaw - 90 - magnetic_deviation if heading > 360.0: heading = heading - 360.0 # Dampening functions roll_total = roll_total - roll_run[t_one] roll_run[t_one] = roll roll_total = roll_total + roll_run[t_one] roll = roll_total / 10 heading_cos_total = heading_cos_total - heading_cos_run[t_three] heading_sin_total = heading_sin_total - heading_sin_run[t_three] heading_cos_run[t_three] = math.cos(math.radians(heading)) heading_sin_run[t_three] = math.sin(math.radians(heading)) heading_cos_total = heading_cos_total + heading_cos_run[t_three] heading_sin_total = heading_sin_total + heading_sin_run[t_three] heading = round(math.degrees(math.atan2(heading_sin_total/30,heading_cos_total/30)),1) if heading < 0.1: heading = heading + 360.0 t_damp = hack t_one += 1 if t_one == 10: t_one = 0 t_three += 1 if t_three == 30: t_three = 0 if (hack - t_print) > 1: hdt = "IIHDT," + str(round(heading))[:-2] + ",T" hdtcs = format(reduce(operator.xor,map(ord,hdt),0),'X') if len(hdtcs) == 1: hdtcs = "0" + hdtcs iihdt = "$" + hdt + "*" + hdtcs xdr = "IIXDR,A," + str(int(round(roll))) + ",D,ROLL,A," + str(int(round(pitch))) + ",D,PTCH,A," + str(int(round(rollrate))) + ",D,RLLR,A," + str(int(round(pitchrate))) + ",D,PTCR,A," + str(int(round(yawrate))) + ",D,YAWR" xdrcs = format(reduce(operator.xor,map(ord,xdr),0),'X') if len(xdrcs) == 1: xdrcs = "0" + xdrcs iixdr = "$" + xdr + "*" + xdrcs imu_sentence = iihdt + '\r\n' + iixdr sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.sendto(imu_sentence, (IMU_IP, IMU_PORT)) t_print = hack time.sleep(poll_interval*1.0/1000.0) ``` © 允许规范转载 赞 如果觉得我的文章对你有用,请随意赞赏