-
-
Save marcelstoer/75ba30a4aec56d1b3810 to your computer and use it in GitHub Desktop.
-- inspired by: http://www.esp8266-projects.com/2015/03/buttons-pushbuttons-and-debouncing-story.html | |
local GPIO14 = 5 | |
local debounceDelay = <however-many-ms-your-sensor-requires> | |
local debounceAlarmId = <0-6> | |
gpio.mode(GPIO14, gpio.INT, gpio.PULLUP) | |
gpio.trig(GPIO14, "down", doorLocked) | |
function doorLocked() | |
-- don't react to any interupts from now on and wait 50ms until the interrupt for the up event is enabled | |
-- within that 50ms the switch may bounce to its heart's content | |
gpio.trig(GPIO14, "none") | |
tmr.alarm(debounceAlarmId, debounceDelay, tmr.ALARM_SINGLE, function() | |
gpio.trig(GPIO14, "up", doorUnlocked) | |
end) | |
-- finally react to the down event | |
end | |
function doorUnlocked() | |
-- don't react to any interupts from now on and wait 50ms until the interrupt for the down event is enabled | |
-- within that 50ms the switch may bounce to its heart's content | |
gpio.trig(GPIO14, "none") | |
tmr.alarm(debounceAlarmId, debounceDelay, tmr.ALARM_SINGLE, function() | |
gpio.trig(GPIO14, "down", doorLocked) | |
end) | |
-- finally react to the up event | |
end |
I've even tried it out... something weird is happening... i got anyway TWO execution of the "react to the XXX event" each one... i mean two for the down and two for the up if i set the delay to something like 250ms
Works perfectly for me, thanks! It's the only "debouncing" among many others which I found working - on both edges just one XXX action. From my observation it seems that all "bounced" interrupts are buffered and no matter whether there are any delays inside int routine or not. The "magic" is probably in the deactivation of triggering ( gpio.trig(GPIO14, "none")) and its activating after delay. Many other "debouncers" without it just make multiple delayed actions.
@Thyristor66, glad you like it but personally I prefer https://gist.github.com/marcelstoer/59563e791effa4acb65f because it's generically applicable.
not working anymore. PANIC: unprotected error in call to Lua API (magic.lua:6: bad argument #3 to 'trig' (invalid callback type))
This is what I was looking for. Great.
@shinji2009, just move lines
gpio.mode(GPIO14, gpio.INT, gpio.PULLUP) gpio.trig(GPIO14, "down", doorLocked)
to the end. Functions doorLocked()
and doorUnlocked()
must be defined before calling them.
@marcelstoer
I had
PANIC: unprotected error in call to Lua API (attempt to call a nil value)
with "up" and "down" events. But with "low" and "high" levels it's working great.
gpio.trig(GPIO14, "low", doorLocked)
and
gpio.trig(GPIO14, "high", doorUnlocked)
Thank you for that code. This is the only one which works as it supposed to (as I want).
Hi I am new to this site so please forgive me for a very poor looking post.
I have written several lua interrupt handlers using OO timers and they make
coding easier and future proof. Please see badly pasted example lua code below...
(It has lost all it's formating. Cut and paste into Visual Studio, save to a *.lua file and reformat)
-- Example Code using OOP Timer
-- Create Object Timers to handle deboucing hardware interrupts
-- Use the Object-oriented programming (OOP) API with tmr.create().
-- Old lua timers with numbers are going to be depreciated!!!!!!!!
local gpioGarageDoorState = 2 -- Pin 2 on nodemcu and GPIO04
local bounce = 50 -- Debounce period. 50ms time used to debounce switches
-- Interrupt vector routine for garagedoor
function GarageDoor()
-- Debounce sense switch and set door state.
-- The state is based on reading the gpio at it's settled hardware state
GaragedoorTimer:start()
end
-- Create a timer to debounce Garage door strated in by interrupt routine
-- ALARM_SEMI will only fire once. No need to execute GaragedoorTimer:stop().
-- Timer will fire again when another interrupt starts it.
GaragedoorTimer = tmr.create()
GaragedoorTimer:register(bounce, tmr.ALARM_SEMI, function()
-- Now check the switch state again as it should have settled down
if gpio.read(gpioGarageDoorState) == gpio.LOW then
-- Publish State of Garage Door Closed
mqttBroker:publish(topicQueue .. "/state", "Closed", 1, 1)-- publish and retain
else
-- Publish State of Garage Door Open
mqttBroker:publish(topicQueue .. "/state", "Open", 1, 1)-- publish and retain
end
end)
-- Set up Door Switch pin for Interrupt, (Hardware switches between open circuit and Gnd)
gpio.mode(gpioGarageDoorState, gpio.INT, gpio.PULLUP)
-- Set hardware interrupt handler for garage door.
-- (Triggered when hardware switch state changes)
gpio.trig(gpioGarageDoorState, "both", GarageDoor)
-- additional code here
Thank you marcelstoer for formatting my post.
You need to give those two meaningful values, yes. I'll make that a little more clear with the next revision.