Skip to content

Instantly share code, notes, and snippets.

@SpotlightKid
Last active January 23, 2023 17:51
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save SpotlightKid/0a0aac56606286a80f860b116423c94f to your computer and use it in GitHub Desktop.
Save SpotlightKid/0a0aac56606286a80f860b116423c94f to your computer and use it in GitHub Desktop.
Debounced switch using pin and timer IRQs on MicroPython
#
# 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)
@adamoell
Copy link

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

@SpotlightKid
Copy link
Author

Yes, sure, go ahead. I hereby declare this code to be licensed under the MIT License, Copyright 2017, Christopher Arndt.

@adamoell
Copy link

adamoell commented Oct 2, 2021

Ah, that's fantastic Christopher. I'll copy & paste that into the header :-)

@edwinm
Copy link

edwinm commented Aug 8, 2022

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