I have a project that involves using a Raspberry Pi to sense the state of a mechanical switch (actually, a relay, part of this light beam sensor). When the switch is closed, I want to sound a doorbell.
Using the Raspberry Pi is convenient because it means I can turn off the doorbell from my computer and it allows me to record the times when visitors came. It also simplifies the implementation of certain requirements, for example the doorbell solenoid will melt if it receives current for too long; with the Raspberry Pi, I can control exactly how long the solenoid should receive power.
I used this code example from Alex on RasPi.TV, which shows how to use Ben Croston's RPi.GPIO Python module to detect changes on GPIO inputs, implemented with interrupts rather than busy-waiting. The example was easy to follow and the hardware requirements are minimal. For my current project, I set the pin to 21 and configure an internal pull-up resistor. The last two pins of the GPIO header are GPIO 21 and GND. So I just connect a normally-open switch between the last two pins - the ones closest to the Ethernet jack - here is a picture of my test setup:
I discovered that correct "debouncing" of the switch signal is important. First of all, with my doorbell I sometimes get false alarms in the middle of the night - perhaps a leaf falling in the path of the light beam, or a squirrel. Secondly, sometimes just the act of sending power to the doorbell causes a glitch on the GPIO ports, so that it rings several times in succession even though the switch only closed once.
I modified the code example to use the debouncing feature of the RPi.GPIO module, but after playing around with it and reading the module code, I can see that the debouncing feature doesn't do what most users would want or expect. In RPI.GPIO, "debouncing" seems to mean that if the event you're waiting for ("falling edge") happened less than bouncetime
milliseconds ago, we ignore it. Consider the following signal, representing a noisy switch that has been closed and then opened. Imagine that we have a bouncetime
of 300 ms, and each character represents the switch's state for 100ms. The original code will detect a "debounced" falling edge at the locations indicated:
111111111111101010110010100000000000010101101111011111111
| | |
What I really want is something more like this:
111111111111101010110010100000000000010101101111011111111
|
in other words, the program waits for the signal to go to zero and stay there for bouncetime
milliseconds, before performing the action.
I would think that other Pi users would have solved this problem already, so maybe there is good code out there that I should refer to. I have solved it, at least to my satisfaction, and will post the code as an answer to this question.