[Arduino] MPU9250+ArduinoGenuino101读取传感器数据

    xiaoxiao2022-07-07  211

    MPU9250+Arduino/Genuino101读取传感器数据

    下文的内容来自于sparkfun网站中的MPU9250教程。教程中软硬件讲的很清晰,同时还包括许多扩展阅读,受益良多。这篇笔记会写一下如何使用MPU9250传感器,通过Arduino/Genuino101获取传感器数据,并分析该教程中提供的代码文件提供的接口。本人菜鸟新手,这篇文章只是学习记录一些新的知识,以供以后参考。

    一、接线与库文件配置

    MPU9250传感器和Arduino的连线方式如下:VCC->3.3V;GND->GND;SDA->A4;SCL->A5。 在Arduino IDE中的配置:在正确选择Arduino硬件型号和连接端口之后,选择项目->加载库->管理库打开库管理器,在搜索栏中输入“SparkFun MPU-9250”安装该库。 然后新建一个空白脚本,将下一节中的代码粘贴在脚本中,编译并上传到Arduino中就可以正常运行代码了。在工具->串口监视器中看到输出的数字就是从MPU9250传感器中读取的信息。

    二、代码

    原始代码包含了在LCD显示屏中的控制功能,下面的代码不包括这一功能。另外我保留了部分原始注释。如果只是读取传感器数据需要保证第三行的#define AHRS为false,如果需要输出传感器位姿,则需要修改为true。

    #include "quaternionFilters.h" #include "MPU9250.h" #define AHRS false #define SerialDebug true // Pin definitions int intPin = 12; // These can be changed, 2 and 3 are the Arduinos ext int pins int myLed = 13; // Set up pin 13 led for toggling #define I2Cclock 400000 #define I2Cport Wire #define MPU9250_ADDRESS MPU9250_ADDRESS_AD0 // Use either this line or the next to select which I2C address your device is using //#define MPU9250_ADDRESS MPU9250_ADDRESS_AD1 MPU9250 myIMU(MPU9250_ADDRESS, I2Cport, I2Cclock); void setup() { Wire.begin(); // TWBR = 12; // 400 kbit/sec I2C speed Serial.begin(9600); while(!Serial){}; // Set up the interrupt pin, its set as active high, push-pull pinMode(intPin, INPUT); digitalWrite(intPin, LOW); pinMode(myLed, OUTPUT); digitalWrite(myLed, HIGH); // Read the WHO_AM_I register, this is a good test of communication byte c = myIMU.readByte(MPU9250_ADDRESS, WHO_AM_I_MPU9250); Serial.print(F("MPU9250 I AM 0x")); Serial.print(c, HEX); Serial.print(F(" I should be 0x")); Serial.println(0x71, HEX); if (c == 0x71) // WHO_AM_I should always be 0x71 { Serial.println(F("MPU9250 is online...")); // Start by performing self test and reporting values myIMU.MPU9250SelfTest(myIMU.selfTest); Serial.print(F("x-axis self test: acceleration trim within : ")); Serial.print(myIMU.selfTest[0],1); Serial.println("% of factory value"); Serial.print(F("y-axis self test: acceleration trim within : ")); Serial.print(myIMU.selfTest[1],1); Serial.println("% of factory value"); Serial.print(F("z-axis self test: acceleration trim within : ")); Serial.print(myIMU.selfTest[2],1); Serial.println("% of factory value"); Serial.print(F("x-axis self test: gyration trim within : ")); Serial.print(myIMU.selfTest[3],1); Serial.println("% of factory value"); Serial.print(F("y-axis self test: gyration trim within : ")); Serial.print(myIMU.selfTest[4],1); Serial.println("% of factory value"); Serial.print(F("z-axis self test: gyration trim within : ")); Serial.print(myIMU.selfTest[5],1); Serial.println("% of factory value"); // Calibrate gyro and accelerometers, load biases in bias registers myIMU.calibrateMPU9250(myIMU.gyroBias, myIMU.accelBias); myIMU.initMPU9250(); // Initialize device for active mode read of acclerometer, gyroscope, and // temperature Serial.println("MPU9250 initialized for active data mode...."); // Read the WHO_AM_I register of the magnetometer, this is a good test of // communication byte d = myIMU.readByte(AK8963_ADDRESS, WHO_AM_I_AK8963); Serial.print("AK8963 "); Serial.print("I AM 0x"); Serial.print(d, HEX); Serial.print(" I should be 0x"); Serial.println(0x48, HEX); if (d != 0x48) { // Communication failed, stop here Serial.println(F("Communication failed, abort!")); Serial.flush(); abort(); } // Get magnetometer calibration from AK8963 ROM myIMU.initAK8963(myIMU.factoryMagCalibration); // Initialize device for active mode read of magnetometer Serial.println("AK8963 initialized for active data mode...."); if (SerialDebug) { // Serial.println("Calibration values: "); Serial.print("X-Axis factory sensitivity adjustment value "); Serial.println(myIMU.factoryMagCalibration[0], 2); Serial.print("Y-Axis factory sensitivity adjustment value "); Serial.println(myIMU.factoryMagCalibration[1], 2); Serial.print("Z-Axis factory sensitivity adjustment value "); Serial.println(myIMU.factoryMagCalibration[2], 2); } // Get sensor resolutions, only need to do this once myIMU.getAres(); myIMU.getGres(); myIMU.getMres(); // The next call delays for 4 seconds, and then records about 15 seconds of // data to calculate bias and scale. // myIMU.magCalMPU9250(myIMU.magBias, myIMU.magScale); Serial.println("AK8963 mag biases (mG)"); Serial.println(myIMU.magBias[0]); Serial.println(myIMU.magBias[1]); Serial.println(myIMU.magBias[2]); Serial.println("AK8963 mag scale (mG)"); Serial.println(myIMU.magScale[0]); Serial.println(myIMU.magScale[1]); Serial.println(myIMU.magScale[2]); // delay(2000); // Add delay to see results before serial spew of data if(SerialDebug) { Serial.println("Magnetometer:"); Serial.print("X-Axis sensitivity adjustment value "); Serial.println(myIMU.factoryMagCalibration[0], 2); Serial.print("Y-Axis sensitivity adjustment value "); Serial.println(myIMU.factoryMagCalibration[1], 2); Serial.print("Z-Axis sensitivity adjustment value "); Serial.println(myIMU.factoryMagCalibration[2], 2); } } // if (c == 0x71) else { Serial.print("Could not connect to MPU9250: 0x"); Serial.println(c, HEX); // Communication failed, stop here Serial.println(F("Communication failed, abort!")); Serial.flush(); abort(); } } void loop() { // If intPin goes high, all data registers have new data // On interrupt, check if data ready interrupt if (myIMU.readByte(MPU9250_ADDRESS, INT_STATUS) & 0x01) { myIMU.readAccelData(myIMU.accelCount); // Read the x/y/z adc values // Now we'll calculate the accleration value into actual g's // This depends on scale being set myIMU.ax = (float)myIMU.accelCount[0] * myIMU.aRes; // - myIMU.accelBias[0]; myIMU.ay = (float)myIMU.accelCount[1] * myIMU.aRes; // - myIMU.accelBias[1]; myIMU.az = (float)myIMU.accelCount[2] * myIMU.aRes; // - myIMU.accelBias[2]; myIMU.readGyroData(myIMU.gyroCount); // Read the x/y/z adc values // Calculate the gyro value into actual degrees per second // This depends on scale being set myIMU.gx = (float)myIMU.gyroCount[0] * myIMU.gRes; myIMU.gy = (float)myIMU.gyroCount[1] * myIMU.gRes; myIMU.gz = (float)myIMU.gyroCount[2] * myIMU.gRes; myIMU.readMagData(myIMU.magCount); // Read the x/y/z adc values // Calculate the magnetometer values in milliGauss // Include factory calibration per data sheet and user environmental // corrections // Get actual magnetometer value, this depends on scale being set myIMU.mx = (float)myIMU.magCount[0] * myIMU.mRes * myIMU.factoryMagCalibration[0] - myIMU.magBias[0]; myIMU.my = (float)myIMU.magCount[1] * myIMU.mRes * myIMU.factoryMagCalibration[1] - myIMU.magBias[1]; myIMU.mz = (float)myIMU.magCount[2] * myIMU.mRes * myIMU.factoryMagCalibration[2] - myIMU.magBias[2]; } // if (readByte(MPU9250_ADDRESS, INT_STATUS) & 0x01) // Must be called before updating quaternions! myIMU.updateTime(); // Sensors x (y)-axis of the accelerometer is aligned with the y (x)-axis of // the magnetometer; the magnetometer z-axis (+ down) is opposite to z-axis // (+ up) of accelerometer and gyro! We have to make some allowance for this // orientationmismatch in feeding the output to the quaternion filter. For the // MPU-9250, we have chosen a magnetic rotation that keeps the sensor forward // along the x-axis just like in the LSM9DS0 sensor. This rotation can be // modified to allow any convenient orientation convention. This is ok by // aircraft orientation standards! Pass gyro rate as rad/s MahonyQuaternionUpdate(myIMU.ax, myIMU.ay, myIMU.az, myIMU.gx * DEG_TO_RAD, myIMU.gy * DEG_TO_RAD, myIMU.gz * DEG_TO_RAD, myIMU.my, myIMU.mx, myIMU.mz, myIMU.deltat); if (!AHRS) { myIMU.delt_t = millis() - myIMU.count; if (myIMU.delt_t > 500) { if(SerialDebug) { // Print acceleration values in milligs! Serial.print("X-acceleration: "); Serial.print(1000 * myIMU.ax); Serial.print(" mg "); Serial.print("Y-acceleration: "); Serial.print(1000 * myIMU.ay); Serial.print(" mg "); Serial.print("Z-acceleration: "); Serial.print(1000 * myIMU.az); Serial.println(" mg "); // Print gyro values in degree/sec Serial.print("X-gyro rate: "); Serial.print(myIMU.gx, 3); Serial.print(" degrees/sec "); Serial.print("Y-gyro rate: "); Serial.print(myIMU.gy, 3); Serial.print(" degrees/sec "); Serial.print("Z-gyro rate: "); Serial.print(myIMU.gz, 3); Serial.println(" degrees/sec"); // Print mag values in degree/sec Serial.print("X-mag field: "); Serial.print(myIMU.mx); Serial.print(" mG "); Serial.print("Y-mag field: "); Serial.print(myIMU.my); Serial.print(" mG "); Serial.print("Z-mag field: "); Serial.print(myIMU.mz); Serial.println(" mG"); myIMU.tempCount = myIMU.readTempData(); // Read the adc values // Temperature in degrees Centigrade myIMU.temperature = ((float) myIMU.tempCount) / 333.87 + 21.0; // Print temperature in degrees Centigrade Serial.print("Temperature is "); Serial.print(myIMU.temperature, 1); Serial.println(" degrees C"); } myIMU.count = millis(); digitalWrite(myLed, !digitalRead(myLed)); // toggle led } // if (myIMU.delt_t > 500) } // if (!AHRS) else { // Serial print and/or display at 0.5 s rate independent of data rates myIMU.delt_t = millis() - myIMU.count; // update LCD once per half-second independent of read rate if (myIMU.delt_t > 500) { if(SerialDebug) { Serial.print("ax = "); Serial.print((int)1000 * myIMU.ax); Serial.print(" ay = "); Serial.print((int)1000 * myIMU.ay); Serial.print(" az = "); Serial.print((int)1000 * myIMU.az); Serial.println(" mg"); Serial.print("gx = "); Serial.print(myIMU.gx, 2); Serial.print(" gy = "); Serial.print(myIMU.gy, 2); Serial.print(" gz = "); Serial.print(myIMU.gz, 2); Serial.println(" deg/s"); Serial.print("mx = "); Serial.print((int)myIMU.mx); Serial.print(" my = "); Serial.print((int)myIMU.my); Serial.print(" mz = "); Serial.print((int)myIMU.mz); Serial.println(" mG"); Serial.print("q0 = "); Serial.print(*getQ()); Serial.print(" qx = "); Serial.print(*(getQ() + 1)); Serial.print(" qy = "); Serial.print(*(getQ() + 2)); Serial.print(" qz = "); Serial.println(*(getQ() + 3)); } // Define output variables from updated quaternion---these are Tait-Bryan // angles, commonly used in aircraft orientation. In this coordinate system, // the positive z-axis is down toward Earth. Yaw is the angle between Sensor // x-axis and Earth magnetic North (or true North if corrected for local // declination, looking down on the sensor positive yaw is counterclockwise. // Pitch is angle between sensor x-axis and Earth ground plane, toward the // Earth is positive, up toward the sky is negative. Roll is angle between // sensor y-axis and Earth ground plane, y-axis up is positive roll. These // arise from the definition of the homogeneous rotation matrix constructed // from quaternions. Tait-Bryan angles as well as Euler angles are // non-commutative; that is, the get the correct orientation the rotations // must be applied in the correct order which for this configuration is yaw, // pitch, and then roll. // For more see // http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles // which has additional links. myIMU.yaw = atan2(2.0f * (*(getQ()+1) * *(getQ()+2) + *getQ() * *(getQ()+3)), *getQ() * *getQ() + *(getQ()+1) * *(getQ()+1) - *(getQ()+2) * *(getQ()+2) - *(getQ()+3) * *(getQ()+3)); myIMU.pitch = -asin(2.0f * (*(getQ()+1) * *(getQ()+3) - *getQ() * *(getQ()+2))); myIMU.roll = atan2(2.0f * (*getQ() * *(getQ()+1) + *(getQ()+2) * *(getQ()+3)), *getQ() * *getQ() - *(getQ()+1) * *(getQ()+1) - *(getQ()+2) * *(getQ()+2) + *(getQ()+3) * *(getQ()+3)); myIMU.pitch *= RAD_TO_DEG; myIMU.yaw *= RAD_TO_DEG; // Declination of SparkFun Electronics (40°05'26.6"N 105°11'05.9"W) is // 8° 30' E ± 0° 21' (or 8.5°) on 2016-07-19 // - http://www.ngdc.noaa.gov/geomag-web/#declination myIMU.yaw -= 8.5; myIMU.roll *= RAD_TO_DEG; if(SerialDebug) { Serial.print("Yaw, Pitch, Roll: "); Serial.print(myIMU.yaw, 2); Serial.print(", "); Serial.print(myIMU.pitch, 2); Serial.print(", "); Serial.println(myIMU.roll, 2); Serial.print("rate = "); Serial.print((float)myIMU.sumCount / myIMU.sum, 2); Serial.println(" Hz"); } myIMU.count = millis(); myIMU.sumCount = 0; myIMU.sum = 0; } // if (myIMU.delt_t > 500) } // if (AHRS) }
    最新回复(0)