Debounced switch using pin and timer IRQs on MicroPython
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# inspired by: https://forum.micropython.org/viewtopic.php?t=1938#p10931 | |
# | |
import micropython | |
try: | |
from machine import Timer | |
timer_init = lambda t, p, cb: t.init(period=p, callback=cb) | |
except ImportError: | |
from pyb import Timer | |
timer_init = lambda t, p, cb: t.init(freq=1000 // p, callback=cb) | |
# uncomment when debugging callback problems | |
#micropython.alloc_emergency_exception_buf(100) | |
class DebouncedSwitch: | |
def __init__(self, sw, cb, arg=None, delay=50, tid=4): | |
self.sw = sw | |
# Create references to bound methods beforehand | |
# http://docs.micropython.org/en/latest/pyboard/library/micropython.html#micropython.schedule | |
self._sw_cb = self.sw_cb | |
self._tim_cb = self.tim_cb | |
self._set_cb = getattr(self.sw, 'callback', None) or self.sw.irq | |
self.delay = delay | |
self.tim = Timer(tid) | |
self.callback(cb, arg) | |
def sw_cb(self, pin=None): | |
self._set_cb(None) | |
timer_init(self.tim, self.delay, self._tim_cb) | |
def tim_cb(self, tim): | |
tim.deinit() | |
if self.sw(): | |
micropython.schedule(self.cb, self.arg) | |
self._set_cb(self._sw_cb if self.cb else None) | |
def callback(self, cb, arg=None): | |
self.tim.deinit() | |
self.cb = cb | |
self.arg = arg | |
self._set_cb(self._sw_cb if cb else None) | |
def test_pyb(ledno=1): | |
import pyb | |
sw = pyb.Switch() | |
led = pyb.LED(ledno) | |
return DebouncedSwitch(sw, lambda l: l.toggle(), led) | |
def test_machine(swpin=2, ledpin=16): | |
from machine import Pin | |
sw = Pin(swpin, Pin.IN) | |
led = Pin(ledpin, Pin.OUT) | |
return DebouncedSwitch(sw, lambda l: l.value(not l.value()), led) |
Yes, sure, go ahead. I hereby declare this code to be licensed under the MIT License, Copyright 2017, Christopher Arndt.
Ah, that's fantastic Christopher. I'll copy & paste that into the header :-)
This is the best Micropython debounce code I could find. Others are using delays inside IRQ’s (wrong) or calling the callbacks directly, without using schedule (wrong). Thank for sharing! Maybe, one day, it will have its own repo with documentation and demo code 😉
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi Christopher,
I would like to use this code pretty much as-is in a small GPLv3 licensed project I'm working on (a free Laser Tag system). There doesn't seem to be a copyright notice; could you confirm that you're OK with me using your code in this way?
Thanks so much!
Adam