Arduino - Gyro sensor - ISR - TimeStamp

291 Views Asked by At

I currently working to recreate a quad-copter controller.

I am working on getting data from my gyro sensor, and to do that, I'm using an ISR with an interuption.

My problem is, when I call my function "gyro.getX" on the main program, it work. But, when I call this function from my ISR, it doesn't work. I think that I found the reson of the bug, the function I'm using is provided by the "Adafruit_LSM9DS0" library (from ST), and it used a "timestamp". I think that the current time from my ISR is different that the current time from my Main program, but i don't know how to fix it.

Here a shortcut of my program:

void loop(){
/*main prog*/
}

/*
*Reserve interrupt routine service (ISR) by Arduino
*/
ISR(TIMER2_OVF_vect)
{
    TCNT2 = 256 - 250; // 250 x 16 µS = 4 ms
    if (varCompteur++ > 25)// 25 * 4 ms = 100 ms (half-period)
    {
        varCompteur = 0;
        
        SensorGet(pX, pY);//Feed gyro circular buffers
    }
}

void SensorGet(float * pRollX, float * pPitchY)
{   
    lsm.getEvent(&accel, &mag, &gyro, &temp);
    
    GiroX_Feed(pX, gyro.gyro.x);
    GiroY_Feed(pPitchY, gyro.gyro.y);
}
    


bool Adafruit_LSM9DS0::getEvent(sensors_event_t *accelEvent,
                                sensors_event_t *magEvent,
                                sensors_event_t *gyroEvent,
                                sensors_event_t *tempEvent)
{
  /* Grab new sensor reading and timestamp. */
  read();
  uint32_t timestamp = millis();

  /* Update appropriate sensor events. */
  if (accelEvent) getAccelEvent(accelEvent, timestamp);
  if (magEvent)   getMagEvent(magEvent, timestamp);
  if (gyroEvent)  getGyroEvent(gyroEvent, timestamp);
  if (tempEvent)  getTempEvent(tempEvent, timestamp);

  return true;
}
2

There are 2 best solutions below

3
On BEST ANSWER

The problem isn't the time. The problem is likely that your sensor uses the I2C and it is disabled during an interrupt routine, or it's some other communication protocol that relies on interrupts to function and is therefore disabled during your ISR.

You are really abusing the interrupt. This is not the kind of thing interrupts are for. Interrupt should be super fast, no time for communications there. So the real question is why do you think you need an interrupt for this?

0
On

Personally I'm not a huge fan of tinkering around with complicated, sometimes even nested millis()-elapsed-statements. I usually prefer to use a combination of a statemachine-like loop and some timer-interrupts to set states as i find them to be more versatile.

  1. the timer (which can be a timer-interrupt as well) sets a State-variable STATE = READ
  2. inside the loop() the associated STATE with the read_sensor()-function inside is called and STATE is reset to IDLE.
// NOTE: Is use ESP32, so maybe timer implementation might be a little different on other platforms
void IRAM_ATTR ISR_timer() {
  STATE = READ;
}

// in global definitions
hw_timer_t* timer = NULL;

// inside setup()
timer = timerBegin(0, 80, countUp);                     // countUp [true/false]
timerAttachInterrupt(timer, ISR_timer, edge);           // edge [true: rising/false: falling]
timerAlarmWrite(timer, interval_ms * 1e3, autoreload);  // autoreload [true/false]
timerAlarmEnable(timer);        // starts timer
// timerAlarmDisable(timer);    // stops timer


// inside loop()
switch(STATE) 
{ 
  case IDLE: break;
  ... 
  case READ: 
    read_sensor(...);
    STATE = IDLE;
    break;
  ...
}

Hope this helps. Feel free to add comments, if you have any thoughts towards that.