Search code examples
embeddedinterruptsensorspolling

Embedded System - Polling


I have about 6 sensors (GPS, IMU, etc.) that I need to constantly collect data from. For my purposes, I need a reading from each (within a small time frame) to have a complete data packet. Right now I am using interrupts, but this results in more data from certain sensors than others, and, as mentioned, I need to have the data matched up.

Would it be better to move to a polling-based system in which I could poll each sensor in a set order? This way I could have data from each sensor every 'cycle'.

I am, however, worried about the speed of polling because this system needs to operate close to real time.


Solution

  • Polling combined with a "master timer interrupt" could be your friend here. Let's say that your "slowest" sensor can provide data on 20ms intervals, and that the others can be read faster. That's 50 updates per second. If that's close enough to real-time (probably is close for an IMU), perhaps you proceed like this:

    1. Set up a 20ms timer.
    2. When the timer goes off, set a flag inside an interrupt service routine:

      volatile uint8_t timerFlag = 0;
      
      ISR(TIMER_ISR_whatever)
      {
          timerFlag = 1;  // nothing but a semaphore for later...
      }
      
    3. Then, in your main loop act when timerFlag says it's time:

      while(1)
      {
          if(timerFlag == 1)
          {
              <read first device>
              <read second device>
              <you get the idea ;) >
              timerflag = 0;
          }
      }
      

    In this way you can read each device and keep their readings synched up. This is a typical way to solve this problem in the embedded space. Now, if you need data faster than 20ms, then you shorten the timer, etc. The big question, as it always is in situations like this, is "how fast can you poll" vs. "how fast do you need to poll." Only experimentation and knowing the characteristics and timing of your various devices can tell you that. But what I propose is a general solution when all the timings "fit."

    EDIT, A DIFFERENT APPROACH

    A more interrupt-based example:

    volatile uint8_t device1Read = 0;
    volatile uint8_t device2Read = 0;
    etc...
    
    ISR(device 1)
    {
        <read device>
        device1Read = 1;
    }
    ISR(device 2)
    {
        <read device>
        device2Read = 1;
    }
    etc...
    
    
    // main loop
    while(1)
    {
        if(device1Read == 1 && device2Read == 1 && etc...)
        {
            //< do something with your "packet" of data>
            device1Read = 0;
            device2Read = 0;
            etc...
        }
    }
    

    In this example, all your devices can be interrupt-driven but the main-loop processing is still governed, paced, by the cadence of the slowest interrupt. The latest complete reading from each device, regardless of speed or latency, can be used. Is this pattern closer to what you had in mind?