0

I´m currently developing basic routines in order to communicate with an IMU or Inertial Measurement Unit, the ICM20948 from TDK - InvenSense using the I2C protocol through a PCB I have develop myself, I currently have functions to communicate with it like:

int writeRegister(uint8 slaveAdress, uint8 registerAdress, uint8 data);

uint8 readRegisters(uint8 slaveAdress, uint8_t subAddress, uint8 count, uint8 dest);

int selectAutoClockSource(uint8 slaveAdress)

And some more which are working properly (I have read registers who tell me this is working) the point is that the ICM20948 datasheet device doesn´t specifies me the order to configurate it in order to read the acceleration data, I have found a code on a GitHub, more concretely https://github.com/dtornqvist/icm-20948-arduino-library which is written in Arduino, I tried to port it to c, the language I'm currently using on it, getting the current configuration function

int begin(uint8 slaveAdress){
   if (changeUserBank_force(slaveAdress, USER_BANK_0) < 0) {
      return -1;
   }

   if (selectAutoClockSource(slaveAdress) < 0) {
      return -2;
   }

  // enable I2C master mode
   if(enableI2cMaster(slaveAdress) < 0){
      return -3;
   }

   if (powerDownMag(slaveAdress) < 0) {
      return -4;
   }

   reset(slaveAdress);
   CyDelay(10);

   if (selectAutoClockSource(slaveAdress) < 0) {
      return -6;
   }

   whoAreU(slaveAdress);
   if(enableAccelGyro(slaveAdress, UB0_PWR_MGMNT_2, UB0_PWR_MGMNT_2_SEN_ENABLE) == 1){
   } else {
        UART_DEBUG_PutString("\r\n Error al habilitar el giroscopio y acelerometro");
        return -7;
   }
   if(configAccel(slaveAdress, ACCEL_RANGE_2G, ACCEL_DLPF_BANDWIDTH_246HZ) != 1){
      return -8;
   }
   if (setAccelSrd(slaveAdress,0) < 0) { 
      return -12;
   }
   return 1;
}

After that I call my:

int16_t getAccelX_mss(uint8 slaveAdress){
   uint8 _axcountsH, _axcountsL;
   int16_t _axcounts;

   if (changeUserBank_force(slaveAdress, USER_BANK_0) < 0) {
      return -1;
   }
   _axcountsH = readRegisters(slaveAdress, 0x45u, 1, _axcountsH);

   _axcountsL = readRegisters(slaveAdress, 0x46u, 1, _axcountsL);

   _axcounts = (((int16_t)_axcountsH) << 8) | _axcountsL;

   sprintf(Rx_aux, " 0x%d ", _axcounts);
   UART_DEBUG_PutString("\r\n Acce Read: ");
   UART_DEBUG_PutString(Rx_aux);

   return 1;
}

Function, which is supposed to return me trough UART the mix of 45u and 46u (acceleration) registers info, but I'm receiving the next output (I'm using Hterm 0.8.3 to capture the uart output)

UART ok...<\r><\n>
Begin.<\r><\n>
Begin with no errors.<\r><\n>
Acce Read: 0x0

I have no real clue about, even when I move my pcb, generating an acceleration the result keeps as 0x0. Have anyone worked with this class of software and can give me some advice about how to keep working? Or I have any important error on my code that I haven't seen?

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Sosa
  • 35
  • 6
  • Are you trying to use your imu by the help of imu's driver package ? Why dont you try to read directly by ```read``` and ```write``` function of c by the help of ```ioctl```? The 0x00 value is the default value because you didnt power on accelerometer yet. – Yunus Temurlenk Feb 21 '20 at 17:54
  • Hi Yunus, thanks for your comment, im using the psoc creator default functions to interactuate as an I2C master with my IMU (the slave one), because of this i didn´t noticed the existence of ioctl. The psoc´s api provides me functions to write and read directly from the registers of the IMU with the adress and static buffers. I could read parameters like who_am_i and others. I would swear im enabling and configurating the accelerometer wich i thought would power it but i´m obviusly wrong, Any more steps that I'm skipping? – Sosa Feb 21 '20 at 20:38
  • *"I´m currently developing an api ... have functions to communicate with it like: .."* -- Those do not seem like functions of an API but rather basic routines in a device driver IMO. For an API I would expect more high-level functions that performed tasks that did not require the caller to provide register addresses and/or device-specific operation codes. IOW a well-designed API will abstract the underlying hardware as much as possible so that you could replace the existing hardware and its driver with something different next year without too much disruption. – sawdust Feb 22 '20 at 01:48
  • Already edited, sry for the missunderstood, any help about the question of the itself? – Sosa Feb 22 '20 at 09:29
  • Have you read the article sparkfun has on the device? They give an example of use, albeit using the Arduino library for the device. I suppose you'd just turn the C++ code into C, using structs to hold the data instead of a class. Here's the article I'm thinking of: https://learn.sparkfun.com/tutorials/sparkfun-9dof-imu-icm-20948-breakout-hookup-guide – enhzflep Feb 22 '20 at 09:53
  • @Sosa -- A google search using `ICM20948 driver` leads to [this code](https://github.com/CoryCline/ICM20948/blob/master/ICM20948.c) that has an initialization routine. – sawdust Feb 22 '20 at 20:25

0 Answers0