一、系统设计需求
应项目要求,对于某项目利用“4*4”的MPU6050形成阵列,同时采集到这么多个MPU6050的数据进行一种新的姿态解算的算法。本人利用简单的MCU和TCA9548便完成了IIC拓展,可在串口上读取这些数据,可惜没有一拓16路的IIC模块,要不然只需一块就可完成。
二、设计思路
对于MPU6050芯片的信号处理,由于MPU6050是由IIC和上位机进行通讯,但又因为一个MPU6050的IIC通讯地址只有0x68和0x69(由MPU6050上的9号引脚AD0控制的,接GND即为0x68,VCC为0x69,注意这里的VCC为3.3V)。当有多个相同的IIC从机器件且从机的器件地址相同要和IIC主机器件进行通信,若也挂在IIC两根总线上进行通信将会变得紊乱,所以我们使用了TCA9845A芯片扩展IIC接口,TCA9845A能有效的解决这种情况的出现,可以使八个IIC从机地址相同的器件和IIC主机进行有效的通信。我们扩展八路IIC接口来解决16个MPU6050的通信问题。
上面只是理想情况,先实现MPU6050的AD0全接地的情况下,实现一拓八路的情况吧。
三、硬件设计
3.1 MCU
采用市面上常用的arduino板子。由于是姿态解算有新的算法,我们只需要取到四元数就可,交由其他人进行姿态解算即可。
3.2 TCA9548a
就是一个i2c的多路多路开关,可以把最多8个地址相同的i2c设备分别接在TCA9548APWR芯片上,通过i2c命令对TCA9548APWR芯片进行设置,即选择接通一个chanel,这样也就是选择了8个i2c设备中的一个设备。
既然TCA9548APWR芯片是一个i2c设备,那么一定有i2c设备地址,如下图所示,7位地址的低3位取决于外接电平状态。
当然,对于不同的地址,不用外接A0,A1,A2,用程序控制软件控制切换即可。
3.3 MPU6050
我们这里使用的MPU6050,肯定不是市面上的模块,仅仅利用MPU6050芯片,我这边还需要对其设计外围电路,参考芯片手册如下。
AD0默认是接地的,如有需求,可接3.3V拉高改变其通信地址,这里我们引出每个芯片的SDA和SCL即可,别忘了他们有4.7kΩ的上拉电阻,设计的AD原理接线图如下:
没办法,没有现成的1拓16路的芯片,所以只能两块TCA9548a来实现对16路MPU6050的数据读取了。对于TCA9548a,我们只需要把SDA和SCL接上arduino板子上的A4,A5即可,接线很简单的。
四、软件设计
在使用如下程序之前,要先安装这样的库。
代码如下:
#include "MPU6050_6Axis_MotionApps20.h"
MPU6050 Mpu6050;
#define TCAADDR 0x70
#define MPU6050_NUMS 7 //传感器数量
#define DELAY_TIME 200 //延迟时间
int16_t ax, ay, az, gx, gy, gz;
void tcaselect(uint8_t i) {
if (i > 7) return;
Wire.begin();
Wire.beginTransmission(TCAADDR);
Wire.write(1 << i);
Wire.endTransmission();
}
void setup()
{
Serial.begin(9600);
for (int i = 0; i < MPU6050_NUMS; i++) {
tcaselect(i);
delay(400);
Mpu6050.initialize(); //初始化MPU6050
delay(100);
Serial.println(i);
}
}
void loop()
{
for (int i = 0; i < MPU6050_NUMS; i++) {
tcaselect(i);
Mpu6050.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
Serial.print("#");
Serial.print(i);
Serial.print(" AX:");
Serial.print(ax);
Serial.print("|");
Serial.print("AY:");
Serial.print(ay);
Serial.print("|");
Serial.print("AZ:");
Serial.print(az);
Serial.print("|");
Serial.print("GX:");
Serial.print(gx);
Serial.print("|");
Serial.print("GY:");
Serial.print(gy);
Serial.print("|");
Serial.print("GZ:");
Serial.print(gz);
Serial.print("|");
Serial.println();
}
delay(DELAY_TIME);
}
只需要修改上面的传感器数量,接上相应的SDA和SCL就可以在串口中读出,我这里测试了七个,因为SDA8断开了,手动调节了传感器的数量为7,接线无误情况下测试效果如下:
由于我的接口没有进行焊接,所以测试的时候,前三路完全一样的原因可能是接触不好或者是那个位置的MPU6050芯片有问题,因为我试过了如果后面的MPU6050没有接或者检测到,就会打印前一个的数据,可以肯定的是,没一个MPU6050数据会完全一样,但也足以验证程序的正确性,在传感器正常和接线正常的情况下肯定能够读出数据。
五、改进计划
1、需要姿态解算的小伙伴自行开发。
2、鄙人能力有限,不能利用MPU6050的AD0引脚的拉高拉低来完成仅用一个TCA9548a完成16路MPU6050的读取,有能力者做出可告我一声。