Search code examples
iotgpioraspberry-pi3windows-10-iot-core

Windows 10 IoT GPIO interrupt frequency


I have a raspberry pi 3 with Windows 10 IoT. I would like to get the data from a sensor that sends pulses. Namely the Swiss Flow SF800 link. This sensor will send out an amount of pulses equal to the amount of flow through the sensor. The datasheet says that I will send up to 2kHz.

My question is will the GPIO on the raspberry pi handle an interrupt frequency this high? I have looked into the lightning provider https://developer.microsoft.com/en-us/windows/iot/docs/lightningproviders which is supposed to be a huge performance gain but cannot find any documentation about what kind of performance I should expect.


Solution

  • Initially I suspected that I would need to use the lightning driver in order to achieve the interrupt frequency that I needed. It turns out that the standard Inbox Driver is adequate for what I need.

    Here are the steps to reproduce my situation:

    I created a simple Arduino sketch that would send out pulses at the rate of 10,000 Hz.

    int dataPin = 12;
    
    void setup() {
        pinMode(dataPin, OUTPUT);
    }
    
    void loop() {
        int count = 0;
        while (count < 400)
        {
            //pulse
            digitalWrite(dataPin, HIGH);
            digitalWrite(dataPin, LOW);
            //This delay presumably makes the pulse be 10000 Hz
            delayMicroseconds(100);
            count++;
        }
        delay(5000);
    }
    

    Created a UWP app with a simple UI that had a TextBlock in the center of the page.

     public sealed partial class MainPage : Page
        {
            private GpioController gpio;
    
            private const int inputPinNumber = 17;
    
            private GpioPin inputPin;
    
            private int count;
    
            private I2cController i2cController;
    
            private SpiController spiController;
    
            public MainPage()
            {
                this.InitializeComponent();
                this.Setup();
            }
    
            private void Setup()
            {
                if (LightningProvider.IsLightningEnabled)
                {
                    LowLevelDevicesController.DefaultProvider = LightningProvider.GetAggregateProvider();
                }
    
                this.gpio = GpioController.GetDefault();
    
    
                this.inputPin = this.gpio.OpenPin(inputPinNumber);
                if (this.inputPin.IsDriveModeSupported(GpioPinDriveMode.InputPullUp))
                {
                    this.inputPin.SetDriveMode(GpioPinDriveMode.InputPullUp);
                }
                else
                {
                    this.inputPin.SetDriveMode(GpioPinDriveMode.Input);
                }
    
                this.inputPin.ValueChanged += InputPinOnValueChanged;
            }
    
            private void InputPinOnValueChanged(GpioPin sender, GpioPinValueChangedEventArgs args)
            {
    
                var task = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
                    if (args.Edge == GpioPinEdge.FallingEdge)
                    {
                        this.count++;
                        this.CountBlock.Text = this.count.ToString();
                    }
                    else
                    {
                        }
                });
            }
        }
    }
    

    Set Windows IoT to use the Direct Memory Mapped Driver.

    The next step was to connect the pin on the Arduino with the pin on the Pi through a transistor. I did this so that I could take advantage of the built in Pull-Up resistor on the GPIO pins on the Pi.

    When both applications were run at the same time I was only collecting about 30 pulses per cycle.

    Went back into the Windows IoT setup and reset the driver back to the Inbox Driver and reran both applications. This time I did not miss a pulse.

    In conclusion the Inbox Driver should be sufficient to give me up to 10khz without any issue.