Modified Arduino library for ICM_20948 IMU for Nucleo boards
ICM_20948.h@0:894b603d32ee, 2022-01-31 (annotated)
- Committer:
- saloutos
- Date:
- Mon Jan 31 03:25:31 2022 +0000
- Revision:
- 0:894b603d32ee
modified ICM_20948 Arduino library for Nucleo boards
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
saloutos | 0:894b603d32ee | 1 | /* |
saloutos | 0:894b603d32ee | 2 | |
saloutos | 0:894b603d32ee | 3 | A C++ interface to the ICM-20948 |
saloutos | 0:894b603d32ee | 4 | |
saloutos | 0:894b603d32ee | 5 | */ |
saloutos | 0:894b603d32ee | 6 | |
saloutos | 0:894b603d32ee | 7 | |
saloutos | 0:894b603d32ee | 8 | // Modified from Arduino library at https://github.com/sparkfun/SparkFun_ICM-20948_ArduinoLibrary |
saloutos | 0:894b603d32ee | 9 | |
saloutos | 0:894b603d32ee | 10 | #ifndef _ICM_20948_H_ |
saloutos | 0:894b603d32ee | 11 | #define _ICM_20948_H_ |
saloutos | 0:894b603d32ee | 12 | |
saloutos | 0:894b603d32ee | 13 | #include "util/ICM_20948_C.h" // The C backbone. ICM_20948_USE_DMP is defined in here. |
saloutos | 0:894b603d32ee | 14 | #include "util/AK09916_REGISTERS.h" |
saloutos | 0:894b603d32ee | 15 | |
saloutos | 0:894b603d32ee | 16 | #include "mbed.h" |
saloutos | 0:894b603d32ee | 17 | |
saloutos | 0:894b603d32ee | 18 | #define ICM_20948_ARD_UNUSED_PIN 0xFF |
saloutos | 0:894b603d32ee | 19 | |
saloutos | 0:894b603d32ee | 20 | // Base |
saloutos | 0:894b603d32ee | 21 | class ICM_20948 |
saloutos | 0:894b603d32ee | 22 | { |
saloutos | 0:894b603d32ee | 23 | private: |
saloutos | 0:894b603d32ee | 24 | |
saloutos | 0:894b603d32ee | 25 | |
saloutos | 0:894b603d32ee | 26 | const uint8_t MAX_MAGNETOMETER_STARTS = 10; // This replaces maxTries |
saloutos | 0:894b603d32ee | 27 | |
saloutos | 0:894b603d32ee | 28 | protected: |
saloutos | 0:894b603d32ee | 29 | ICM_20948_Device_t _device; |
saloutos | 0:894b603d32ee | 30 | |
saloutos | 0:894b603d32ee | 31 | float getTempC(int16_t val); |
saloutos | 0:894b603d32ee | 32 | float getGyrDPS(int16_t axis_val); |
saloutos | 0:894b603d32ee | 33 | float getAccMG(int16_t axis_val); |
saloutos | 0:894b603d32ee | 34 | float getMagUT(int16_t axis_val); |
saloutos | 0:894b603d32ee | 35 | |
saloutos | 0:894b603d32ee | 36 | public: |
saloutos | 0:894b603d32ee | 37 | ICM_20948(); // Constructor |
saloutos | 0:894b603d32ee | 38 | |
saloutos | 0:894b603d32ee | 39 | Serial *_debugSerial; // change to serial port |
saloutos | 0:894b603d32ee | 40 | bool _printDebug = false; //Flag to print the serial commands we are sending to the Serial port for debug |
saloutos | 0:894b603d32ee | 41 | |
saloutos | 0:894b603d32ee | 42 | void enableDebugging(Serial &debugPort); // TODO: check this syntax |
saloutos | 0:894b603d32ee | 43 | |
saloutos | 0:894b603d32ee | 44 | void disableDebugging(void); //Turn off debug statements |
saloutos | 0:894b603d32ee | 45 | |
saloutos | 0:894b603d32ee | 46 | void debugPrintStatus(ICM_20948_Status_e stat); |
saloutos | 0:894b603d32ee | 47 | |
saloutos | 0:894b603d32ee | 48 | ICM_20948_AGMT_t agmt; // Acceleometer, Gyroscope, Magenetometer, and Temperature data |
saloutos | 0:894b603d32ee | 49 | ICM_20948_AGMT_t getAGMT(void); // Updates the agmt field in the object and also returns a copy directly |
saloutos | 0:894b603d32ee | 50 | |
saloutos | 0:894b603d32ee | 51 | float magX(void); // micro teslas |
saloutos | 0:894b603d32ee | 52 | float magY(void); // micro teslas |
saloutos | 0:894b603d32ee | 53 | float magZ(void); // micro teslas |
saloutos | 0:894b603d32ee | 54 | |
saloutos | 0:894b603d32ee | 55 | float accX(void); // milli g's |
saloutos | 0:894b603d32ee | 56 | float accY(void); // milli g's |
saloutos | 0:894b603d32ee | 57 | float accZ(void); // milli g's |
saloutos | 0:894b603d32ee | 58 | |
saloutos | 0:894b603d32ee | 59 | float gyrX(void); // degrees per second |
saloutos | 0:894b603d32ee | 60 | float gyrY(void); // degrees per second |
saloutos | 0:894b603d32ee | 61 | float gyrZ(void); // degrees per second |
saloutos | 0:894b603d32ee | 62 | |
saloutos | 0:894b603d32ee | 63 | float temp(void); // degrees celsius |
saloutos | 0:894b603d32ee | 64 | |
saloutos | 0:894b603d32ee | 65 | ICM_20948_Status_e status; // Status from latest operation |
saloutos | 0:894b603d32ee | 66 | |
saloutos | 0:894b603d32ee | 67 | // Device Level |
saloutos | 0:894b603d32ee | 68 | ICM_20948_Status_e setBank(uint8_t bank); // Sets the bank |
saloutos | 0:894b603d32ee | 69 | ICM_20948_Status_e swReset(void); // Performs a SW reset |
saloutos | 0:894b603d32ee | 70 | ICM_20948_Status_e sleep(bool on = false); // Set sleep mode for the chip |
saloutos | 0:894b603d32ee | 71 | ICM_20948_Status_e lowPower(bool on = true); // Set low power mode for the chip |
saloutos | 0:894b603d32ee | 72 | ICM_20948_Status_e setClockSource(ICM_20948_PWR_MGMT_1_CLKSEL_e source); // Choose clock source |
saloutos | 0:894b603d32ee | 73 | ICM_20948_Status_e checkID(void); // Return 'ICM_20948_Stat_Ok' if whoami matches ICM_20948_WHOAMI |
saloutos | 0:894b603d32ee | 74 | |
saloutos | 0:894b603d32ee | 75 | bool dataReady(void); // Returns 'true' if data is ready |
saloutos | 0:894b603d32ee | 76 | uint8_t getWhoAmI(void); // Return whoami in out prarmeter |
saloutos | 0:894b603d32ee | 77 | bool isConnected(void); // Returns true if communications with the device are sucessful |
saloutos | 0:894b603d32ee | 78 | |
saloutos | 0:894b603d32ee | 79 | // Internal Sensor Options |
saloutos | 0:894b603d32ee | 80 | ICM_20948_Status_e setSampleMode(uint8_t sensor_id_bm, uint8_t lp_config_cycle_mode); // Use to set accel, gyro, and I2C master into cycled or continuous modes |
saloutos | 0:894b603d32ee | 81 | ICM_20948_Status_e setFullScale(uint8_t sensor_id_bm, ICM_20948_fss_t fss); |
saloutos | 0:894b603d32ee | 82 | ICM_20948_Status_e setDLPFcfg(uint8_t sensor_id_bm, ICM_20948_dlpcfg_t cfg); |
saloutos | 0:894b603d32ee | 83 | ICM_20948_Status_e enableDLPF(uint8_t sensor_id_bm, bool enable); |
saloutos | 0:894b603d32ee | 84 | ICM_20948_Status_e setSampleRate(uint8_t sensor_id_bm, ICM_20948_smplrt_t smplrt); |
saloutos | 0:894b603d32ee | 85 | |
saloutos | 0:894b603d32ee | 86 | // Interrupts on INT and FSYNC Pins |
saloutos | 0:894b603d32ee | 87 | ICM_20948_Status_e clearInterrupts(void); |
saloutos | 0:894b603d32ee | 88 | |
saloutos | 0:894b603d32ee | 89 | ICM_20948_Status_e cfgIntActiveLow(bool active_low); |
saloutos | 0:894b603d32ee | 90 | ICM_20948_Status_e cfgIntOpenDrain(bool open_drain); |
saloutos | 0:894b603d32ee | 91 | ICM_20948_Status_e cfgIntLatch(bool latching); // If not latching then the interrupt is a 50 us pulse |
saloutos | 0:894b603d32ee | 92 | ICM_20948_Status_e cfgIntAnyReadToClear(bool enabled); // If enabled, *ANY* read will clear the INT_STATUS register. So if you have multiple interrupt sources enabled be sure to read INT_STATUS first |
saloutos | 0:894b603d32ee | 93 | ICM_20948_Status_e cfgFsyncActiveLow(bool active_low); |
saloutos | 0:894b603d32ee | 94 | ICM_20948_Status_e cfgFsyncIntMode(bool interrupt_mode); // Can use FSYNC as an interrupt input that sets the I2C Master Status register's PASS_THROUGH bit |
saloutos | 0:894b603d32ee | 95 | |
saloutos | 0:894b603d32ee | 96 | ICM_20948_Status_e intEnableI2C(bool enable); |
saloutos | 0:894b603d32ee | 97 | ICM_20948_Status_e intEnableDMP(bool enable); |
saloutos | 0:894b603d32ee | 98 | ICM_20948_Status_e intEnablePLL(bool enable); |
saloutos | 0:894b603d32ee | 99 | ICM_20948_Status_e intEnableWOM(bool enable); |
saloutos | 0:894b603d32ee | 100 | ICM_20948_Status_e intEnableWOF(bool enable); |
saloutos | 0:894b603d32ee | 101 | ICM_20948_Status_e intEnableRawDataReady(bool enable); |
saloutos | 0:894b603d32ee | 102 | ICM_20948_Status_e intEnableOverflowFIFO(uint8_t bm_enable); |
saloutos | 0:894b603d32ee | 103 | ICM_20948_Status_e intEnableWatermarkFIFO(uint8_t bm_enable); |
saloutos | 0:894b603d32ee | 104 | |
saloutos | 0:894b603d32ee | 105 | ICM_20948_Status_e WOMThreshold(uint8_t threshold); |
saloutos | 0:894b603d32ee | 106 | |
saloutos | 0:894b603d32ee | 107 | // Interface Options |
saloutos | 0:894b603d32ee | 108 | ICM_20948_Status_e i2cMasterPassthrough(bool passthrough = true); |
saloutos | 0:894b603d32ee | 109 | ICM_20948_Status_e i2cMasterEnable(bool enable = true); |
saloutos | 0:894b603d32ee | 110 | ICM_20948_Status_e i2cMasterReset(); |
saloutos | 0:894b603d32ee | 111 | |
saloutos | 0:894b603d32ee | 112 | //Used for configuring peripherals 0-3 |
saloutos | 0:894b603d32ee | 113 | ICM_20948_Status_e i2cControllerConfigurePeripheral(uint8_t peripheral, uint8_t addr, uint8_t reg, uint8_t len, bool Rw = true, bool enable = true, bool data_only = false, bool grp = false, bool swap = false, uint8_t dataOut = 0); |
saloutos | 0:894b603d32ee | 114 | ICM_20948_Status_e i2cControllerPeriph4Transaction(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len, bool Rw, bool send_reg_addr = true); |
saloutos | 0:894b603d32ee | 115 | |
saloutos | 0:894b603d32ee | 116 | //Used for configuring the Magnetometer |
saloutos | 0:894b603d32ee | 117 | ICM_20948_Status_e i2cMasterSingleW(uint8_t addr, uint8_t reg, uint8_t data); |
saloutos | 0:894b603d32ee | 118 | uint8_t i2cMasterSingleR(uint8_t addr, uint8_t reg); |
saloutos | 0:894b603d32ee | 119 | |
saloutos | 0:894b603d32ee | 120 | // Default Setup |
saloutos | 0:894b603d32ee | 121 | ICM_20948_Status_e startupDefault(bool minimal = false); // If minimal is true, several startup steps are skipped. If ICM_20948_USE_DMP is defined, .begin will call startupDefault with minimal set to true. |
saloutos | 0:894b603d32ee | 122 | |
saloutos | 0:894b603d32ee | 123 | // direct read/write |
saloutos | 0:894b603d32ee | 124 | ICM_20948_Status_e read(uint8_t reg, uint8_t *pdata, uint32_t len); |
saloutos | 0:894b603d32ee | 125 | ICM_20948_Status_e write(uint8_t reg, uint8_t *pdata, uint32_t len); |
saloutos | 0:894b603d32ee | 126 | |
saloutos | 0:894b603d32ee | 127 | //Mag specific |
saloutos | 0:894b603d32ee | 128 | ICM_20948_Status_e startupMagnetometer(bool minimal = false); // If minimal is true, several startup steps are skipped. The mag then needs to be set up manually for the DMP. |
saloutos | 0:894b603d32ee | 129 | ICM_20948_Status_e magWhoIAm(void); |
saloutos | 0:894b603d32ee | 130 | uint8_t readMag(AK09916_Reg_Addr_e reg); |
saloutos | 0:894b603d32ee | 131 | ICM_20948_Status_e writeMag(AK09916_Reg_Addr_e reg, uint8_t *pdata); |
saloutos | 0:894b603d32ee | 132 | ICM_20948_Status_e resetMag(); |
saloutos | 0:894b603d32ee | 133 | |
saloutos | 0:894b603d32ee | 134 | //FIFO |
saloutos | 0:894b603d32ee | 135 | ICM_20948_Status_e enableFIFO(bool enable = true); |
saloutos | 0:894b603d32ee | 136 | ICM_20948_Status_e resetFIFO(void); |
saloutos | 0:894b603d32ee | 137 | ICM_20948_Status_e setFIFOmode(bool snapshot = false); // Default to Stream (non-Snapshot) mode |
saloutos | 0:894b603d32ee | 138 | ICM_20948_Status_e getFIFOcount(uint16_t *count); |
saloutos | 0:894b603d32ee | 139 | ICM_20948_Status_e readFIFO(uint8_t *data, uint8_t len = 1); |
saloutos | 0:894b603d32ee | 140 | |
saloutos | 0:894b603d32ee | 141 | //DMP |
saloutos | 0:894b603d32ee | 142 | |
saloutos | 0:894b603d32ee | 143 | // Done: |
saloutos | 0:894b603d32ee | 144 | // Configure DMP start address through PRGM_STRT_ADDRH/PRGM_STRT_ADDRL |
saloutos | 0:894b603d32ee | 145 | // Load Firmware |
saloutos | 0:894b603d32ee | 146 | // Configure Accel scaling to DMP |
saloutos | 0:894b603d32ee | 147 | // Configure Compass mount matrix and scale to DMP |
saloutos | 0:894b603d32ee | 148 | // Reset FIFO |
saloutos | 0:894b603d32ee | 149 | // Reset DMP |
saloutos | 0:894b603d32ee | 150 | // Enable DMP interrupt |
saloutos | 0:894b603d32ee | 151 | // Configuring DMP to output data to FIFO: set DATA_OUT_CTL1, DATA_OUT_CTL2, DATA_INTR_CTL and MOTION_EVENT_CTL |
saloutos | 0:894b603d32ee | 152 | // Configuring DMP to output data at multiple ODRs |
saloutos | 0:894b603d32ee | 153 | // Configure DATA_RDY_STATUS |
saloutos | 0:894b603d32ee | 154 | // Configuring Accel calibration |
saloutos | 0:894b603d32ee | 155 | // Configuring Compass calibration |
saloutos | 0:894b603d32ee | 156 | // Configuring Gyro gain |
saloutos | 0:894b603d32ee | 157 | // Configuring Accel gain |
saloutos | 0:894b603d32ee | 158 | // Configure I2C_SLV0 and I2C_SLV1 to: request mag data from the hidden reserved AK09916 registers; trigger Single Measurements |
saloutos | 0:894b603d32ee | 159 | // Configure I2C Master ODR (default to 68.75Hz) |
saloutos | 0:894b603d32ee | 160 | |
saloutos | 0:894b603d32ee | 161 | // To Do: |
saloutos | 0:894b603d32ee | 162 | // Additional FIFO output control: FIFO_WATERMARK, BM_BATCH_MASK, BM_BATCH_CNTR, BM_BATCH_THLD |
saloutos | 0:894b603d32ee | 163 | // Configuring DMP features: PED_STD_STEPCTR, PED_STD_TIMECTR |
saloutos | 0:894b603d32ee | 164 | // Enabling Activity Recognition (BAC) feature |
saloutos | 0:894b603d32ee | 165 | // Enabling Significant Motion Detect (SMD) feature |
saloutos | 0:894b603d32ee | 166 | // Enabling Tilt Detector feature |
saloutos | 0:894b603d32ee | 167 | // Enabling Pick Up Gesture feature |
saloutos | 0:894b603d32ee | 168 | // Enabling Fsync detection feature |
saloutos | 0:894b603d32ee | 169 | // Biases: add save and load methods |
saloutos | 0:894b603d32ee | 170 | |
saloutos | 0:894b603d32ee | 171 | ICM_20948_Status_e enableDMP(bool enable = true); |
saloutos | 0:894b603d32ee | 172 | ICM_20948_Status_e resetDMP(void); |
saloutos | 0:894b603d32ee | 173 | ICM_20948_Status_e loadDMPFirmware(void); |
saloutos | 0:894b603d32ee | 174 | ICM_20948_Status_e setDMPstartAddress(unsigned short address = DMP_START_ADDRESS); |
saloutos | 0:894b603d32ee | 175 | ICM_20948_Status_e enableDMPSensor(enum inv_icm20948_sensor sensor, bool enable = true); |
saloutos | 0:894b603d32ee | 176 | ICM_20948_Status_e enableDMPSensorInt(enum inv_icm20948_sensor sensor, bool enable = true); |
saloutos | 0:894b603d32ee | 177 | ICM_20948_Status_e writeDMPmems(unsigned short reg, unsigned int length, const unsigned char *data); |
saloutos | 0:894b603d32ee | 178 | ICM_20948_Status_e readDMPmems(unsigned short reg, unsigned int length, unsigned char *data); |
saloutos | 0:894b603d32ee | 179 | ICM_20948_Status_e setDMPODRrate(enum DMP_ODR_Registers odr_reg, int interval); |
saloutos | 0:894b603d32ee | 180 | ICM_20948_Status_e readDMPdataFromFIFO(icm_20948_DMP_data_t *data); |
saloutos | 0:894b603d32ee | 181 | ICM_20948_Status_e setGyroSF(unsigned char div, int gyro_level); |
saloutos | 0:894b603d32ee | 182 | ICM_20948_Status_e initializeDMP(void) __attribute__((weak)); // Combine all of the DMP start-up code in one place. Can be overwritten if required |
saloutos | 0:894b603d32ee | 183 | }; |
saloutos | 0:894b603d32ee | 184 | |
saloutos | 0:894b603d32ee | 185 | // SPI |
saloutos | 0:894b603d32ee | 186 | #define ICM_20948_SPI_DEFAULT_FREQ 4000000 |
saloutos | 0:894b603d32ee | 187 | #define ICM_20948_SPI_DEFAULT_ORDER MSBFIRST |
saloutos | 0:894b603d32ee | 188 | #define ICM_20948_SPI_DEFAULT_MODE SPI_MODE0 |
saloutos | 0:894b603d32ee | 189 | |
saloutos | 0:894b603d32ee | 190 | class ICM_20948_SPI : public ICM_20948 |
saloutos | 0:894b603d32ee | 191 | { |
saloutos | 0:894b603d32ee | 192 | private: |
saloutos | 0:894b603d32ee | 193 | protected: |
saloutos | 0:894b603d32ee | 194 | public: |
saloutos | 0:894b603d32ee | 195 | |
saloutos | 0:894b603d32ee | 196 | SPI *_spi; |
saloutos | 0:894b603d32ee | 197 | DigitalOut *_cs; |
saloutos | 0:894b603d32ee | 198 | ICM_20948_Serif_t _serif; |
saloutos | 0:894b603d32ee | 199 | |
saloutos | 0:894b603d32ee | 200 | ICM_20948_SPI(); // Constructor |
saloutos | 0:894b603d32ee | 201 | |
saloutos | 0:894b603d32ee | 202 | // ICM_20948_Status_e begin(uint8_t csPin, SPIClass &spiPort = SPI, uint32_t SPIFreq = ICM_20948_SPI_DEFAULT_FREQ); |
saloutos | 0:894b603d32ee | 203 | ICM_20948_Status_e begin(DigitalOut &cspin, SPI &spiPort, uint32_t SPIFreq = ICM_20948_SPI_DEFAULT_FREQ); // TODO: check this! |
saloutos | 0:894b603d32ee | 204 | }; |
saloutos | 0:894b603d32ee | 205 | |
saloutos | 0:894b603d32ee | 206 | #endif /* _ICM_20948_H_ */ |