Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: main.cpp
- Revision:
- 1:8459e28d77a1
- Parent:
- 0:efb1550773f1
--- a/main.cpp Fri Mar 19 21:59:25 2021 +0000 +++ b/main.cpp Mon Mar 29 21:16:25 2021 +0000 @@ -1,6 +1,7 @@ /* ICM20948 Basic Example Code by: Kris Winer - date: April 1, 2014 + modified by Eric Nativel MBEB_OS6 port + date: 29, MArch 2021 license: Beerware - Use this code however you'd like. If you find it useful you can buy me a beer some time. Modified by Brent Wilkins July 19, 2016 @@ -8,179 +9,168 @@ addresses, initializing the sensor, getting properly scaled accelerometer, gyroscope, and magnetometer data out. Added display functions to allow display to on breadboard monitor. Addition of 9 DoF sensor fusion using open source - Madgwick and Mahony filter algorithms. Sketch runs on the 3.3 V 8 MHz Pro Mini - and the Teensy 3.1. - SDA and SCL should have external pull-up resistors (to 3.3V). - 10k resistors are on the EMSENSR-9250 breakout board. - Hardware setup: - ICM20948 Breakout --------- Arduino - VDD ---------------------- 3.3V - VDDI --------------------- 3.3V - SDA ----------------------- A4 - SCL ----------------------- A5 - GND ---------------------- GND + Madgwick and Mahony filter algorithms. Pimoroni icm20948 and stm32L432kc nucleo board */ -#include "AHRSAlgorithms.h" -#include "ICM20948.h" +#include "mbed.h" +#include "ahrs.h" +#include "icm20948.h" +#include <cstdio> +#include <stdint.h> -#define AHRS false // Set to false for basic data read -#define SerialDebug true // Set to true to get Serial output for debugging +using namespace std::chrono; +Timer t1; +typedef unsigned char byte; +float selft[6]; +static BufferedSerial pc(USBTX, USBRX); -ICM20948 myIMU; +char msg[255]; void setup() { - Wire.begin(); - // TWBR = 12; // 400 kbit/sec I2C speed - Serial.begin(115200); - while(!Serial) delay(10); + //Set up I2C - pinMode(myLed, OUTPUT); - digitalWrite(myLed, HIGH); - + pc.set_baud(9600); + pc.set_format( + /* bits */ 8, + /* parity */ BufferedSerial::None, + /* stop bit */ 1 + ); // Reset ICM20948 - myIMU.writeByte(ICM20948_ADDRESS, PWR_MGMT_1, READ_FLAG); - delay(100); - myIMU.writeByte(ICM20948_ADDRESS, PWR_MGMT_1, 0x01); - delay(100); + begin(); + + writeByte(ICM20948_ADDRESS, PWR_MGMT_1, READ_FLAGS); + thread_sleep_for(100); + writeByte(ICM20948_ADDRESS, PWR_MGMT_1, 0x01); + thread_sleep_for(100); // Read the WHO_AM_I register, this is a good test of communication - byte c = myIMU.readByte(ICM20948_ADDRESS, WHO_AM_I_ICM20948); - Serial.print(F("ICM20948 I AM 0x")); - Serial.print(c, HEX); - Serial.print(F(" I should be 0x")); - Serial.println(0xEA, HEX); - + byte c = readByte(ICM20948_ADDRESS, WHO_AM_I_ICM20948); + sprintf(msg,"ICM20948 I AM 0x %x I should be 0x %x",c,0xEA); + pc.write(msg, strlen(msg)); if (c == 0xEA) // WHO_AM_I should always be 0x71 { - Serial.println(F("ICM20948 is online...")); - + sprintf(msg,"ICM20948 is online...\n"); + pc.write(msg, strlen(msg)); + // writeByte(ICM20948_ADDRESS, REG_BANK_SEL, 0x10); // Start by performing self test and reporting values - myIMU.ICM20948SelfTest(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"); + ICM20948SelfTest(selft); + sprintf(msg,"x-axis self test: acceleration trim within : %f of factory value\n",selft[0]); + pc.write(msg, strlen(msg)); + sprintf(msg,"y-axis self test: acceleration trim within : %f of factory value\n",selft[1]); + pc.write(msg, strlen(msg)); + sprintf(msg,"z-axis self test: acceleration trim within : %f of factory value\n",selft[2]); + pc.write(msg, strlen(msg)); + sprintf(msg,"x-axis self test: gyration trim within : %f of factory value\n",selft[3]); + pc.write(msg, strlen(msg)); + sprintf(msg,"y-axis self test: gyration trim within : %f of factory value\n",selft[4]); + pc.write(msg, strlen(msg)); + sprintf(msg,"z-axis self test: gyration trim within : %f of factory value\n",selft[5]); + pc.write(msg, strlen(msg)); + // Calibrate gyro and accelerometers, load biases in bias registers + calibrateICM20948(gyroBias, accelBias); - // Calibrate gyro and accelerometers, load biases in bias registers - myIMU.calibrateICM20948(myIMU.gyroBias, myIMU.accelBias); - - myIMU.initICM20948(); + initICM20948(); // Initialize device for active mode read of acclerometer, gyroscope, and // temperature - Serial.println("ICM20948 initialized for active data mode...."); - - // Read the WHO_AM_I register of the magnetometer, this is a good test of + sprintf(msg,"ICM20948 initialized for active data mode....\n"); + pc.write(msg, strlen(msg)); + // Read the WHO_AM_I register of the magnetometer, this is a good test of // communication - byte d = myIMU.readByte(AK09916_ADDRESS, WHO_AM_I_AK09916); - Serial.print("AK8963 "); - Serial.print("I AM 0x"); - Serial.print(d, HEX); - Serial.print(" I should be 0x"); - Serial.println(0x09, HEX); + tempCount =readTempData(); // Read the adc values + // Temperature in degrees Centigrade + temperature = ((float) tempCount) / 333.87 + 21.0; + // Print temperature in degrees Centigrade + sprintf(msg,"Temperature is %f degrees C\n",temperature); + pc.write(msg, strlen(msg)); + byte d = readByte(AK09916_ADDRESS<<1, WHO_AM_I_AK09916); + sprintf(msg,"AK8963 I AM 0x %x I should be 0x %d\n",d,0x09); + pc.write(msg, strlen(msg)); if (d != 0x09) { // Communication failed, stop here - Serial.println(F("Communication with magnetometer failed, abort!")); - Serial.flush(); - abort(); + sprintf(msg,"Communication with magnetometer failed, abort!\n"); + pc.write(msg, strlen(msg)); + exit(0); } // Get magnetometer calibration from AK8963 ROM - myIMU.initAK09916(); + initAK09916(); // Initialize device for active mode read of magnetometer - Serial.println("AK09916 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); - } - */ + sprintf(msg,"AK09916 initialized for active data mode....\n"); + pc.write(msg, strlen(msg)); + + // Get sensor resolutions, only need to do this once - myIMU.getAres(); - myIMU.getGres(); - myIMU.getMres(); - + getAres(); + getGres(); + getMres(); // The next call delays for 4 seconds, and then records about 15 seconds of // data to calculate bias and scale. - myIMU.magCalICM20948(myIMU.magBias, myIMU.magScale); - Serial.println("AK09916 mag biases (mG)"); - Serial.println(myIMU.magBias[0]); - Serial.println(myIMU.magBias[1]); - Serial.println(myIMU.magBias[2]); - - Serial.println("AK09916 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 + magCalICM20948(magBias, magScale); + sprintf(msg,"AK09916 mag biases (mG)\n %f\n%f\n%f\n",magBias[0],magBias[1],magBias[2]); + pc.write(msg, strlen(msg)); + sprintf(msg,"AK09916 mag scale (mG)\n %f\n%f\n%f\n",magScale[0],magScale[1],magScale[2]); + pc.write(msg, strlen(msg)); + thread_sleep_for(2000); // Add delay to see results before pc spew of data } // if (c == 0x71) else { - Serial.print("Could not connect to ICM20948: 0x"); - Serial.println(c, HEX); - + sprintf(msg,"Could not connect to ICM20948: 0x%x",c); + pc.write(msg, strlen(msg)); // Communication failed, stop here - Serial.println(F("Communication failed, abort!")); - Serial.flush(); - abort(); + sprintf(msg," Communication failed, abort!\n"); + pc.write(msg, strlen(msg)); + exit(0); } } - -void loop() +int main(void) +{int i=0; + setup(); +while(i<100) { // If intPin goes high, all data registers have new data // On interrupt, check if data ready interrupt - if (myIMU.readByte(ICM20948_ADDRESS, INT_STATUS_1) & 0x01) - { - myIMU.readAccelData(myIMU.accelCount); // Read the x/y/z adc values + if (readByte(ICM20948_ADDRESS, INT_STATUS_1) & 0x01) +{ + readAccelData(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 + ax = (float)accelCount[0] * aRes; // - accelBias[0]; + ay = (float)accelCount[1] * aRes; // - accelBias[1]; + az = (float)accelCount[2] * aRes; // - accelBias[2]; + sprintf(msg,"X-acceleration: %f mg\n",1000*ax); + pc.write(msg, strlen(msg)); + sprintf(msg,"Y-acceleration: %f mg\n",1000*ay); + pc.write(msg, strlen(msg)); + sprintf(msg,"Z-acceleration: %f mg\n",1000*az); + pc.write(msg, strlen(msg)); + readGyroData(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 + gx = (float)gyroCount[0] * gRes; + gy = (float)gyroCount[1] * gRes; + gz = (float)gyroCount[2] * gRes; +sprintf(msg,"x -gyroscope: %f and bias %f deg/s\n",gx,gyroBias[0]); + pc.write(msg, strlen(msg)); + readMagData(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.magBias[0]; - myIMU.my = (float)myIMU.magCount[1] * myIMU.mRes - myIMU.magBias[1]; - myIMU.mz = (float)myIMU.magCount[2] * myIMU.mRes - myIMU.magBias[2]; - } // if (readByte(ICM20948_ADDRESS, INT_STATUS) & 0x01) + mx = (float)magCount[0] * mRes - magBias[0]; + my = (float)magCount[1] * mRes - magBias[1]; + mz = (float)magCount[2] * mRes - magBias[2]; + // if (readByte(ICM20948_ADDRESS, INT_STATUS) & 0x01) // Must be called before updating quaternions! - myIMU.updateTime(); + 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 @@ -190,83 +180,9 @@ // 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)); - } + MahonyQuaternionUpdate(ax, ay, az, gx * DEG_TO_RAD, + gy * DEG_TO_RAD, gz * DEG_TO_RAD, my, + mx, mz, deltat); // Define output variables from updated quaternion---these are Tait-Bryan // angles, commonly used in aircraft orientation. In this coordinate system, @@ -284,42 +200,34 @@ // 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() + 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() + pitch = -asin(2.0f * (*(getQ()+1) * *(getQ()+3) - *getQ() * *(getQ()+2))); - myIMU.roll = atan2(2.0f * (*getQ() * *(getQ()+1) + *(getQ()+2) + 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; + pitch *= RAD_TO_DEG; + 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 + // 1° 46' E 2021-03-27 // - http://www.ngdc.noaa.gov/geomag-web/#declination - myIMU.yaw -= 8.5; - myIMU.roll *= RAD_TO_DEG; + yaw -= 1.7666; + 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) + + sprintf(msg,"Yaw %f, Pitch %f, Roll %f\n ",yaw,pitch,roll); + pc.write(msg, strlen(msg)); + sumCount = 0; + sum = 0; +} + i++; + //thread_sleep_for(200); + } + return 0; } \ No newline at end of file