dotnet / iot

This repo includes .NET Core implementations for various IoT boards, chips, displays and PCBs.
MIT License
2.16k stars 580 forks source link

Jitter on PIN Rising and Falling on GPIO Pin callback #2260

Closed codeputer closed 9 months ago

codeputer commented 9 months ago

After I open a pin:

    var pinMode = PinMode.Input;
    Log($"Requesting GPIO Controller pin:{applicationConfiguration.ValveMonitoredOnGpioPin} to open in PinMode of:{pinMode}");
    gpioController!.OpenPin(applicationConfiguration.ValveMonitoredOnGpioPin, pinMode);
    pinOpened = true;
    Log($"GPIO Controller pin:{applicationConfiguration.ValveMonitoredOnGpioPin} has opened with PinMode:{pinMode}");

and register a callback on a GPIO PIN 21 (using Raspberry PI 2w, on Linux X64).

   gpioController.RegisterCallbackForPinValueChangedEvent(
       applicationConfiguration.ValveMonitoredOnGpioPin,
       PinEventTypes.Falling | PinEventTypes.Rising,
       OnPinEvent);

I get this response when circuit closes (Rising = Dispersed is the circuit closed, and Falling = Charged for when the circuit is open) image

For what I know, when the circuit closes, the power is a constant 3.3V until the circuit opens and falls to zero.

My expected behaviour is a rising event when the circuit closes and a falling event when the circuit opens, and not having to de-bounce the messages between rising and falling when power is on (which is very difficult to ensure the order is maintained). Is this expected behaviour or not when the circuit is closed for a GPIO Pin?

I have a step-down device that drops the voltage from 9V (battery supplied) down to 3.3V. When there is no power, there are no events generated. This is my first IOT project, and I apologize if I'm missing something fundamental here.

raffaeler commented 9 months ago

Hi, welcome and happy new year. The dotnet/iot library read and writes the I/O through one of the underlying Linux drivers (sysfs or libgpiod). The duty of these driver is to provide fidelity of the signal that appears on the physical pin.

The jitter you are experiencing can be see as "bad" in your specific application, but it can be a "high frequency signal" in other cases, therefore there is no way for the driver to understand whether this rapid oscillation should be propagated to the events or not.

In order to avoid the jittering, you have two possible solutions: hardware or software. Dealing with debouncing in software can be tricky but it should work. If you instead want a neat signal, you can use an RC circuit to filter the high frequencies that are typical of the jittering. A more sophisticated technique is to use a Schmitt Trigger 74HC14 chip (very cheap) that can give you the "perfect" de-bounced signal.

In both cases, I link here a very good guide to de-bouncing (both hw and sw): https://my.eng.utah.edu/~cs5780/debouncing.pdf

HTH

codeputer commented 9 months ago

Thanks! I wish I had known this earlier! I recommend an update in the documentation on the callback. I never expected a falling when the circuit was closed. As batteries are direct current, can you help me understand why the falling occurs? Why this could not be a feature flag in the driver to set the fidelity of the callbacks? Reading that PDF now, as the hardware is not an option at the moment, as I have devices deployed.

raffaeler commented 9 months ago

You are welcome! Do you have an oscilloscope to monitor the gpio line after the step down? What are you using to power off the line after the step down? The bouncing always occurs in any type of physical switch.

Also be careful when using step down converters because they use an internal oscillator to "generate" the required voltage. Some cheap circuits may lead to propagate the oscillations to the power line, causing "noise" to the line.

To make a test, you can try putting two 1.5 AA batteries in series to reach the 3V. But even in this case, depending on which device is switching, you can still see jittering.

The simplest test is to "short" an output GPIO to your input GPIO. In this case there will be no bouncing and you should see the exact line changes.

codeputer commented 9 months ago

The simplest test is to "short" an output GPIO to your input GPIO. In this case there will be no bouncing and you should see the exact line changes.

Sorry - "short an output GPIO to your input GPIO" an output? I'm not following. Do you mean close the circuit on the board directly, and see if it jitters?

The circuit here can close on two events: 1) a button is pressed, and 2) glass vial that breaks due to heat, and the circuit come on. I don't have an oscilloscope, but I understand that either could create a "noisy" circuit in terms of power supply.

raffaeler commented 9 months ago

Sorry - "short an output GPIO to your input GPIO" an output? I'm not following. Do you mean close the circuit on the board directly, and see if it jitters?

Yes, you can short the GPIO output to another GPIO input safely because they have the same voltage and you can control the output via software instead of a mechanical switch. This is the easiest way to verify that your issues is not software related.

The circuit here can close on two events: 1) a button is pressed, and 2) glass vial that breaks due to heat, and the circuit come on. I don't have an oscilloscope, but I understand that either could create a "noisy" circuit in terms of power supply.

In case of the button, this is guaranteed to cause bouncing because all mechanical switches behave like that. You will often find at least an RC circuit (see the PDF for their configuration) that is used to de-bounce the buttons. The reason for the RC is because is a simple way to create a low-pass filter. This means that it "cuts away" the high frequencies, whatever nature they may have. In an audio file, high frequencies are a soprano singer. In your case the high frequencies comes from the jitter of the button. The values for the R and C components determine the cut-off frequency of the filter. Since the button is pressed by a human, you don´t expect high frequency from multiple consecutive manual clicks.

In case of the breaking glass, I am not sure what sensor you are using. It may bounce or not depending whether it's mechanical or made with an accelerometer (which is subject to other kind of noise).

raffaeler commented 9 months ago

@codeputer if you need other info, please let me know. Otherwise consider closing the issue. Thanks

codeputer commented 9 months ago

Thanks, I 'll close it. I still would like the debounce to occur within the features of the GPIOController. I'm sure I'm not the first one who had to rewrite code due to my lack of electrical concepts. In my case, I ended up with three observables, 1 which would publish one event pin type (rising), 2, which would publish pin type 2 (falling), and one more that had a throttle of 30 seconds. That way I would listen to rising or lowering, and then wait on the throttle to settle the jitter before again paying attention to the events again.

raffaeler commented 9 months ago

I still would like the debounce to occur within the features of the GPIOController.

I opened this issue https://github.com/dotnet/iot/issues/2261 to suggest the creation of a documentation with the essential knowledge/links. I am afraid the amount of topics can quickly become quite large.

I'm sure I'm not the first one who had to rewrite code due to my lack of electrical concepts.

Absolutely, and the opposite happens in hardware communities with software knowledge. The gap is quite inevitable.