Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Debounce #51

Closed
thisboyiscrazy opened this issue Jul 19, 2016 · 13 comments
Closed

Debounce #51

thisboyiscrazy opened this issue Jul 19, 2016 · 13 comments

Comments

@thisboyiscrazy
Copy link

thisboyiscrazy commented Jul 19, 2016

I am having an issue with a nosy input.

The interrupts are firing very fast but reading the same value (I think because of the noise).

For example I have an input the is low but the watch listeners are firing always reading 0.

I have tried setting debounceTimeout but this only delays the interrupt and cause them to occur less often.

Can the code be changed to add a readSync after the timeout and fire the watch listeners if the value changed.

Also don't know if the help but it is on a bealge bone black.

@fivdi
Copy link
Owner

fivdi commented Jul 19, 2016

Are you using onoff for buttons or switches? If so, please try gpio-button instead. It provides better support for such use-cases.

@thisboyiscrazy
Copy link
Author

It's a signal from a light stack that goes though a optocopler.

@fivdi
Copy link
Owner

fivdi commented Jul 19, 2016

Note that debounceTimeout isn't documented as it's not really that good.

Can the code be changed to add a readSync after the timeout and fire the watch listeners if the value changed.

If this can be used to resolve the issue then it should be possible to achieve this without modifying onoff. onoff could be used without making used of the debounceTimeout option. The watch callback in your program can start a timeout and the timeout handler can call readSync and fire an event or call a callback if the value changed.

@thisboyiscrazy
Copy link
Author

Correct I can add the check to my code.

It just seemed the watch callback was intended to be a "on change" (rising or falling edge) callback and when it gets called with no change in value, it seems to not work as expected.

@fivdi
Copy link
Owner

fivdi commented Jul 19, 2016

The problem here is the bounce on the interrupt input. onoff is notified about the interrupt, but by the time onoff gets around to reading the corresponding input, it may have changed state. The watch callback is called irrespective of the state of the input.

@fivdi
Copy link
Owner

fivdi commented Jul 19, 2016

The onoff debounce code really isn't the best and should be either improved or removed. I'll try to improve it but it may take a while.

@GottZ
Copy link

GottZ commented Jul 29, 2016

yo. i just made a debouncer based on watch: https://gist.github.com/GottZ/e4be78c928817c6701155f6ae910d841

@fivdi if you'd want me to, i could clean it up and create a pull request. just let me know 👍

video of it in action: https://usercontent.irccloud-cdn.com/file/c8pO8syE/VID-20160729-WA0001.mp4

i'm not using any resistor at all. this button goes directly to ground and gpio 3

any idea how i should name this function?
i'd also need to add a dequeue function like unwatch if this should go in.
or maybe, it would be a good idea to just add this to watcher itself.
let me know about your thoughts.

i'm thinking about something like .watch(func, delay) where delay is 0 ms by default wich means no debouncing.

@raffaelecassia
Copy link

Hi guys,
I had the same noisy input problem but I solved with lodash.
You can use https://lodash.com/docs#throttle or https://lodash.com/docs#debounce

var last = 0;
sensor.watch(_.throttle(function (err, value) {
    if (err) {
        // ...
    }
    if (value != last) {
        last = value;
        // ...
    }
}, 100));  // throttle value

@dkebler
Copy link

dkebler commented Dec 28, 2016

In my use case I chose debounce over throttle and it worked great. @fivdi I'd say there is no reason to keep your debounce code if an alternate solution works fine. So I'd close this issue but with a mention of these lodash options in the readme though.

debounce = require('lodash/debounce')

switchPortIntr.watch(
	debounce(function(err, value) {
		if (err) {
			throw err;
		}
// whatever you need to do when interrupt happens, but only do it once without "bouncing"
	}, 200, {
		'leading': false,
		'trailing': true
	})
)

leading false and trailing true will do it at the end of the 200ms. If you need a faster response try leading true and tailing false. If your interrupting device is really sloppy you might need more that 200ms. I could have used was less 200ms but that is plenty fast enough for a human actuated switch even with trailing true.

@fivdi
Copy link
Owner

fivdi commented Dec 28, 2016

Although debounceTimeout isn't actually documented, I did suggest that people use it in issues like this. This makes removing the code a little difficult. However, documenting a solution based on lodash or replacing the existing solution with a lodash based solution would be a good idea.

@dkebler
Copy link

dkebler commented Dec 29, 2016

besides lodash there is this one off package by Sindre Sorhus. He has a throttle as well
https://github.com/sindresorhus/p-debounce

@rafaelquines
Copy link

I did a package with a node module adding watchFilter usage with onoff package.

I believe it can help others developers with the same problems

https://www.npmjs.com/package/inputmonitor

https://github.com/rafaelquines/inputmonitor

;)

@fivdi
Copy link
Owner

fivdi commented Mar 31, 2018

It took a while but this issue has been resolved and onoff v3.0.0 has an effective implementation for debouncing based lodash.debounce.

For more details see here.

An example showing how to debounce buttons can be seen at Debouncing Buttons

Sorry for taking so long to fix this.

@fivdi fivdi closed this as completed Mar 31, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants