Hello,
I am using Arduino Mega, 5 mpu6050 and mux.
I'm going to use these sensors to find the angular values of each sensor.
And I'm going to print these values at least 500 times per second. But now it's printed much slower than that. (100 times per second)
Is there a way to speed up the I2C sensor? (I changed my I2C clock to 400 kHz).
Thank you!
#include "I2Cdev.h"
#include "MPU6050.h"
#include "Wire.h"
#define TCAADDR 0x70 //mux address
#define MPU 0x68
MPU6050 mpu_1;
MPU6050 mpu_2;
MPU6050 mpu_3;
MPU6050 mpu_4;
MPU6050 mpu_5;
#define LED_PIN 13
bool blinkState = false;
long loopTimer, loopTimer2;
double accelPitch;
double accelRoll;
int temperature;
long acc_x, acc_y, acc_z;
double accel_x, accel_y, accel_z;
double gyroRoll, gyroPitch, gyroYaw;
int gyro_x, gyro_y, gyro_z;
long gyro_x_cal, gyro_y_cal, gyro_z_cal;
double rotation_x, rotation_y, rotation_z;
double freq, dt;
double tau = 0.98;
double roll1, pitch1 = 0;
double roll2, pitch2 = 0;
double roll3, pitch3 = 0;
double roll4, pitch4 = 0;
double roll5, pitch5 = 0;
// 250 deg/s --> 131.0, 500 deg/s --> 65.5, 1000 deg/s --> 32.8, 2000 deg/s --> 16.4
long scaleFactorGyro = 65.5;
// 2g --> 16384 , 4g --> 8192 , 8g --> 4096, 16g --> 2048
long scaleFactorAccel = 8192;
//MUX init
void tcaselect(uint8_t i)//read mux buses
{
if (i > 7) return;
Wire.beginTransmission(TCAADDR);
Wire.write(1 << i);
Wire.endTransmission();
}
//mpu init
void mpus_init(int i) {
tcaselect(i);
//Activate the MPU-6050
Wire.beginTransmission(0x68);
Wire.write(0x6B);
Wire.write(0x00);
Wire.endTransmission();
// Configure the accelerometer
// Wire.write(0x__);
// Wire.write; 2g --> 0x00, 4g --> 0x08, 8g --> 0x10, 16g --> 0x18
Wire.beginTransmission(0x68);
Wire.write(0x1C);
Wire.write(0x08);
Wire.endTransmission();
// Configure the gyro
// Wire.write(0x__);
// 250 deg/s --> 0x00, 500 deg/s --> 0x08, 1000 deg/s --> 0x10, 2000 deg/s --> 0x18
Wire.beginTransmission(0x68);
Wire.write(0x1B);
Wire.write(0x08);
Wire.endTransmission();
}
void calibrations(int i) {
tcaselect(i);
//Calibrating
Serial.println("calibration... don't move");
// 1000times for offset
for (int cal_int = 0; cal_int < 1000; cal_int ++) {
if (cal_int % 100 == 0) {
Serial.print(".");
}
// raw값 읽어오기
read_mpu_6050_data();
gyro_x_cal += gyro_x;
gyro_y_cal += gyro_y;
gyro_z_cal += gyro_z;
delay(3);
}
// Average the values
gyro_x_cal /= 1000;
gyro_y_cal /= 1000;
gyro_z_cal /= 1000;
// Display headers
Serial.print("Calibration\t");
Serial.print(gyro_x_cal);
Serial.print("\t");
Serial.print(gyro_y_cal);
Serial.print("\t");
Serial.println(gyro_z_cal);
delay(100);
// Reset the loop timer
loopTimer = micros();
loopTimer2 = micros();
}
//read raw data
void read_mpu_6050_data() {
// Subroutine for reading the raw data
Wire.beginTransmission(0x68);
Wire.write(0x3B);
Wire.endTransmission();
Wire.requestFrom(0x68, 14);
// Read data --> Temperature falls between acc and gyro registers
acc_x = Wire.read() << 8 | Wire.read();
acc_y = Wire.read() << 8 | Wire.read();
acc_z = Wire.read() << 8 | Wire.read();
temperature = Wire.read() << 8 | Wire.read();
gyro_x = Wire.read() << 8 | Wire.read();
gyro_y = Wire.read() << 8 | Wire.read();
gyro_z = Wire.read() << 8 | Wire.read();
}
//output
int count;
void output_angle() {
count++;
//mpu1
tcaselect(0);
freq = 1 / ((micros() - loopTimer2) * 1e-6);
loopTimer2 = micros();
dt = 1 / freq;
// Read the raw acc data from MPU-6050
read_mpu_6050_data();
gyro_x -= gyro_x_cal;
gyro_y -= gyro_y_cal;
gyro_z -= gyro_z_cal;
// Convert to instantaneous degrees per second
rotation_x = (double)gyro_x / (double)scaleFactorGyro;
rotation_y = (double)gyro_y / (double)scaleFactorGyro;
rotation_z = (double)gyro_z / (double)scaleFactorGyro;
// Convert to g force
accel_x = (double)acc_x / (double)scaleFactorAccel;
accel_y = (double)acc_y / (double)scaleFactorAccel;
accel_z = (double)acc_z / (double)scaleFactorAccel;
accelPitch = atan2(accel_y, accel_z) * RAD_TO_DEG;
accelRoll = atan2(accel_x, accel_z) * RAD_TO_DEG;
pitch1 = (tau) * (pitch1 + rotation_x * dt) + (1 - tau) * (accelPitch);
roll1 = (tau) * (roll1 - rotation_y * dt) + (1 - tau) * (accelRoll);
gyroPitch += rotation_x * dt;
gyroRoll -= rotation_y * dt;
gyroYaw += rotation_z * dt;
//==============================
//mpu2
tcaselect(1);
freq = 1 / ((micros() - loopTimer2) * 1e-6);
loopTimer2 = micros();
dt = 1 / freq;
// Read the raw acc data from MPU-6050
read_mpu_6050_data();
gyro_x -= gyro_x_cal;
gyro_y -= gyro_y_cal;
gyro_z -= gyro_z_cal;
// Convert to instantaneous degrees per second
rotation_x = (double)gyro_x / (double)scaleFactorGyro;
rotation_y = (double)gyro_y / (double)scaleFactorGyro;
rotation_z = (double)gyro_z / (double)scaleFactorGyro;
// Convert to g force
accel_x = (double)acc_x / (double)scaleFactorAccel;
accel_y = (double)acc_y / (double)scaleFactorAccel;
accel_z = (double)acc_z / (double)scaleFactorAccel;
accelPitch = atan2(accel_y, accel_z) * RAD_TO_DEG;
accelRoll = atan2(accel_x, accel_z) * RAD_TO_DEG;
pitch2 = (tau) * (pitch2 + rotation_x * dt) + (1 - tau) * (accelPitch);
roll2 = (tau) * (roll2 - rotation_y * dt) + (1 - tau) * (accelRoll);
gyroPitch += rotation_x * dt;
gyroRoll -= rotation_y * dt;
gyroYaw += rotation_z * dt;
//==============================
//mpu3
tcaselect(2);
freq = 1 / ((micros() - loopTimer2) * 1e-6);
loopTimer2 = micros();
dt = 1 / freq;
// Read the raw acc data from MPU-6050
read_mpu_6050_data();
gyro_x -= gyro_x_cal;
gyro_y -= gyro_y_cal;
gyro_z -= gyro_z_cal;
// Convert to instantaneous degrees per second
rotation_x = (double)gyro_x / (double)scaleFactorGyro;
rotation_y = (double)gyro_y / (double)scaleFactorGyro;
rotation_z = (double)gyro_z / (double)scaleFactorGyro;
// Convert to g force
accel_x = (double)acc_x / (double)scaleFactorAccel;
accel_y = (double)acc_y / (double)scaleFactorAccel;
accel_z = (double)acc_z / (double)scaleFactorAccel;
accelPitch = atan2(accel_y, accel_z) * RAD_TO_DEG;
accelRoll = atan2(accel_x, accel_z) * RAD_TO_DEG;
pitch3 = (tau) * (pitch3 + rotation_x * dt) + (1 - tau) * (accelPitch);
roll3 = (tau) * (roll3 - rotation_y * dt) + (1 - tau) * (accelRoll);
gyroPitch += rotation_x * dt;
gyroRoll -= rotation_y * dt;
gyroYaw += rotation_z * dt;
//==============================
//mpu4
tcaselect(3);
freq = 1 / ((micros() - loopTimer2) * 1e-6);
loopTimer2 = micros();
dt = 1 / freq;
// Read the raw acc data from MPU-6050
read_mpu_6050_data();
// 오프셋 보정 값 빼기
gyro_x -= gyro_x_cal;
gyro_y -= gyro_y_cal;
gyro_z -= gyro_z_cal;
// Convert to instantaneous degrees per second
rotation_x = (double)gyro_x / (double)scaleFactorGyro;
rotation_y = (double)gyro_y / (double)scaleFactorGyro;
rotation_z = (double)gyro_z / (double)scaleFactorGyro;
// Convert to g force
accel_x = (double)acc_x / (double)scaleFactorAccel;
accel_y = (double)acc_y / (double)scaleFactorAccel;
accel_z = (double)acc_z / (double)scaleFactorAccel;
// 상보필터 계산
accelPitch = atan2(accel_y, accel_z) * RAD_TO_DEG;
accelRoll = atan2(accel_x, accel_z) * RAD_TO_DEG;
pitch4 = (tau) * (pitch4 + rotation_x * dt) + (1 - tau) * (accelPitch);
roll4 = (tau) * (roll4 - rotation_y * dt) + (1 - tau) * (accelRoll);
gyroPitch += rotation_x * dt;
gyroRoll -= rotation_y * dt;
gyroYaw += rotation_z * dt;
//==============================
//mpu5
tcaselect(4);
freq = 1 / ((micros() - loopTimer2) * 1e-6);
loopTimer2 = micros();
dt = 1 / freq;
// Read the raw acc data from MPU-6050
read_mpu_6050_data();
gyro_x -= gyro_x_cal;
gyro_y -= gyro_y_cal;
gyro_z -= gyro_z_cal;
// Convert to instantaneous degrees per second
rotation_x = (double)gyro_x / (double)scaleFactorGyro;
rotation_y = (double)gyro_y / (double)scaleFactorGyro;
rotation_z = (double)gyro_z / (double)scaleFactorGyro;
// Convert to g force
accel_x = (double)acc_x / (double)scaleFactorAccel;
accel_y = (double)acc_y / (double)scaleFactorAccel;
accel_z = (double)acc_z / (double)scaleFactorAccel;
// comp filter
accelPitch = atan2(accel_y, accel_z) * RAD_TO_DEG;
accelRoll = atan2(accel_x, accel_z) * RAD_TO_DEG;
pitch5 = (tau) * (pitch5 + rotation_x * dt) + (1 - tau) * (accelPitch);
roll5 = (tau) * (roll5 - rotation_y * dt) + (1 - tau) * (accelRoll);
gyroPitch += rotation_x * dt;
gyroRoll -= rotation_y * dt;
gyroYaw += rotation_z * dt;
//==============================
// Data out serial monitor
Serial.print(freq, 0);
Serial.println("Hz");
// Serial.print("MPU1: ");
// Serial.print(roll1, 1);
// Serial.print("\t");
// Serial.println(pitch1, 1);
//
// Serial.print("MPU2: ");
// Serial.print(roll2, 1);
// Serial.print("\t");
// Serial.println(pitch2, 1);
//
// Serial.print("MPU3: ");
// Serial.print(roll3, 1);
// Serial.print("\t");
// Serial.println(pitch3, 1);
//
// Serial.print("MPU4: ");
// Serial.print(roll4, 1);
// Serial.print("\t");
// Serial.println(pitch4, 1);
//
// Serial.print("MPU5: ");
// Serial.print(roll5, 1);
// Serial.print("\t");
// Serial.println(pitch5, 1);
Serial.println(count);
Serial.println();
// blink LED to indicate activity
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
// Wait until the loopTimer reaches 4000us (250Hz) before next loop
while (micros() - loopTimer <= 4000);
loopTimer = micros();
}
//=====================================================================
void setup() {
Wire.begin(); //init I2C and serial port
Wire.setClock(400000); // 400kHz I2C clock
Serial.begin(115200);
while (!Serial);
//mpus init
for (int i = 0; i < 5; i++) {
mpus_init(i);
}
//error check
if (mpu_1.testConnection()) {
Serial.println("Sensor1 OK");
}
else {
Serial.println("Error sensor1");
}
if (mpu_2.testConnection()) {
Serial.println("Sensor2 OK");
}
else {
Serial.println("Error sensor2");
}
if (mpu_3.testConnection()) {
Serial.println("Sensor3 OK");
}
else {
Serial.println("Error sensor3");
}
if (mpu_4.testConnection()) {
Serial.println("Sensor4 OK");
}
else {
Serial.println("Error sensor4");
}
if (mpu_5.testConnection()) {
Serial.println("Sensor5 OK");
}
else {
Serial.println("Error sensor5");
}
//calibration
for (int i = 0; i < 5; i++) {
calibrations(i);
}
}
//=====================================================================
void loop() {
output_angle();
}