AnswerBun.com

IMU (MPU9250) and Ticker on ESP32

Arduino Asked by R. Ho on December 10, 2020

I want to read the data from an IMU (MPU9250) periodically. To do that I use a ticker as shown in the following code:

#include <Ticker.h>
#include "MPU9250.h"

constexpr int SERIAL_BAUDRATE = 115200;
constexpr float SAMPLING_FREQUENCY = 1.0;

Ticker TimerIMU;
MPU9250 IMU(Wire, 0x68);

void readIMU()
{
    // read the sensor
  IMU.readSensor();
  // display the data
  Serial.print(IMU.getAccelX_mss(),6);
  Serial.print("t");
  Serial.print(IMU.getAccelY_mss(),6);
  Serial.print("t");
  Serial.print(IMU.getAccelZ_mss(),6);
  Serial.print("t");
  Serial.print(IMU.getGyroX_rads(),6);
  Serial.print("t");
  Serial.print(IMU.getGyroY_rads(),6);
  Serial.print("t");
  Serial.println(IMU.getGyroZ_rads(),6);
}


void setup()
{
  // serial to display data
  Serial.begin(115200);
  while(!Serial) {}
  // start communication with IMU 
  int retVal = IMU.begin();
  if(retVal < 0)
    Serial.println("IMU initialization unsuccessful: check your wiring or try resetting power to the sensor.");
   // start ticker
  TimerIMU.attach(1.0 / SAMPLING_FREQUENCY, readIMU);
}

void loop()
{
}

This approach does not produce the expected results: the IMU returns always the same values. Putting the readIMU function in the main loop and commenting the Ticker works well. I use an ESP32-WROVER.

Where is my error? Any suggestion would be appreciated.

One Answer

readIMU() is called by the library from an ISR (Interrupt Service Routine). While the ISR runs, other interrupts cannot be handled. The IMU sensor works over I2C, which relies on interrupts being serviced. So, when initiating the communication inside an ISR, the transmission can never be finished correctly, since the needed ISRs are not executed. At least the library doesn't seem to block in that case, so the code runs, but the values are never updated.

You should not do interrupt dependent things inside of an ISR. Instead you can define a global flag variable, which you set inside the ISR. Then in your main code you just constantly check this flag and execute the ISR dependent code, if the flag is set. After the execution you reset the flag.

The response time is dependent on the speed, that your loop runs in. But this shouldn't be a problem here, since you don't have any other code in loop() and your frequency is just 1Hz, so a delay of a few microseconds should not be relevant.


Note, that using Serial is also interrupt dependent. So writing or printing to Serial inside an ISR is also not very good. Though you can get away with it, when you make sure, that you never send more data, than the Serial buffer can hold, and that you leave enough time between the interrupts for the actual transmission. Inside an ISR the printing and writing statements will just fill the buffer. The data will then gets send in the background via interrupts.

Answered by chrisl on December 10, 2020

Add your own answers!

Related Questions

AsyncWebServer giving wdt reset

1  Asked on September 14, 2020 by java-bee

         

serial 1 was not declared in the scope

1  Asked on July 30, 2020 by mian-yasir-shah

 

How can I set a timer?

2  Asked on July 24, 2020 by damon-swart

 

Ask a Question

Get help from others!

© 2022 AnswerBun.com. All rights reserved. Sites we Love: PCI Database, MenuIva, UKBizDB, Menu Kuliner, Sharing RPP