0

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;
}
vvv444
  • 2,764
  • 1
  • 14
  • 25
Aldarme
  • 23
  • 4
  • I find an information: "The main thing here is that while you are in an interrupt routine "the clock isn't ticking". millis() and micros() won't change (well, micros() will initially, but once it goes past that magic millisecond point where a millisecond tick is required it all falls apart.)". So I can not used millis in y ISR, but I need it in my function to get value from my sensor... – Aldarme Dec 05 '17 at 22:57

2 Answers2

1

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?

Delta_G
  • 2,927
  • 2
  • 9
  • 15
  • Hi ! Thank you for your answer. My sensor use SPI to communicate. As I had understood the usage of ISR, it allow me to get value from my sensor with a given frequency. So i wanted to used ISR to get the value from my gyroscope and after in the main prog. use this value to calculate my PID. Could you give me more information to develop a better usage of the ISR ? – Aldarme Dec 06 '17 at 00:10
  • You don't need an interrupt to do something at regular intervals. Use millis to keep track of the time and keep your loop tight and non-blocking. See the Blink Without Delay example that comes with the IDE. It blinks an LED at 1 second intervals, but you could easily change the interval and put whatever code in to run at the timed intervals. – Delta_G Dec 06 '17 at 00:35
  • Thanks you. I will start heading back this way. – Aldarme Dec 06 '17 at 00:50
0

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.