My previous posts on using Eclipse M2M with Raspberry Pi:
- HelloWorld in Lua on Raspberry Pi running Mihini on ArchLinux with Koneki as IDE (link)
- LED Blinky in Lua on Raspberry Pi running Mihini on ArchLinux (link)
- Autostart Lua script on RasPi+Archlinux+Mihini at power up (link)
After having accomplished the above, I moved on to reading switches and controlling LEDs
My schematic looks like below:
This is how I connected 4 switches and 4 LEDs to the GPIO pins of my Raspberry Pi. Black wire is Gnd. |
I wanted to toggle an LED for each press of the corresponding switch. I paired up each switch to an LED:
Switch at GPIO 4 would control the LED at GPIO 22
Switch at GPIO 17 would control the LED at GPIO 23
Switch at GPIO 18 would control the LED at GPIO 24
Switch at GPIO 21 would control the LED at GPIO 25
I registered a hook function which would be called whenever the state changed of any of the four GPIOs to which the switches were connected. From within the hook functions, LED corresponding to that switch is toggled. A message is printed from inside the hook function with timestamp retrieved using the gettime() function of the 'socket' module. gettime() provides higher resolution (returns time in milliseconds) than the time() function of the 'os' module (returns time in seconds). We create an idle task using main() with an infinite loop in it. This keeps the script running albeit doing nothing while the hook listens for switch presses.
sw2leds.lua:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | -- Switches to LEDs package.path = '/opt/mihini/lua/?.lua;/opt/mihini/lua/?/init.lua;' .. package.path package.cpath = '/opt/mihini/lua/?.so;' .. package.cpath local sched = require "sched" local gpio = require "gpio" local socket = require "socket" --------------------------------------------------------------- local function toggle_led(n) local stat = gpio.read(n) if stat == 1 then gpio.write(n,0) elseif stat == 0 then gpio.write(n,1) end end local function main() while true do sched.wait(1) end end local function myhook(id, value) print(string.format("Time %15s | GPIO %2d changed | New value %s",socket.gettime(), id, value)) if id == 4 then toggle_led(22) elseif id == 17 then toggle_led(23) elseif id == 18 then toggle_led(24) elseif id == 21 then toggle_led(25) end end --------------------------------------------------------------- gpio.configure(22, {direction="out", edge="both", activelow="0"}) gpio.configure(23, {direction="out", edge="both", activelow="0"}) gpio.configure(24, {direction="out", edge="both", activelow="0"}) gpio.configure(25, {direction="out", edge="both", activelow="0"}) gpio.configure(4, {direction="in", edge="falling", activelow="1"}) gpio.configure(17, {direction="in", edge="falling", activelow="1"}) gpio.configure(18, {direction="in", edge="falling", activelow="1"}) gpio.configure(21, {direction="in", edge="falling", activelow="1"}) gpio.register(4, myhook) gpio.register(17, myhook) gpio.register(18, myhook) gpio.register(21, myhook) sched.run(main) sched.loop() |
As you will note, this script doesn't debounce the switches and on each press, you end up with flickering LEDs which end up in a random state post bouncing. You also get a lot of messages printed for each press:
Time 1376043551.5499 | GPIO 4 changed | New value 0
Time 1376043551.5523 | GPIO 17 changed | New value 0
Time 1376043551.554 | GPIO 18 changed | New value 0
Time 1376043551.556 | GPIO 21 changed | New value 0
Time 1376043552.9756 | GPIO 4 changed | New value 0
Time 1376043552.9786 | GPIO 4 changed | New value 1
Time 1376043552.9816 | GPIO 4 changed | New value 1
Time 1376043552.9844 | GPIO 4 changed | New value 1
Time 1376043552.9874 | GPIO 4 changed | New value 1
Time 1376043552.9901 | GPIO 4 changed | New value 1
Time 1376043552.993 | GPIO 4 changed | New value 1
Time 1376043552.9956 | GPIO 4 changed | New value 1
Time 1376043552.9989 | GPIO 4 changed | New value 1
Time 1376043553.0015 | GPIO 4 changed | New value 1
Time 1376043553.0044 | GPIO 4 changed | New value 1
Time 1376043553.007 | GPIO 4 changed | New value 1
Time 1376043553.0098 | GPIO 4 changed | New value 1
Time 1376043553.0124 | GPIO 4 changed | New value 1
Time 1376043553.161 | GPIO 4 changed | New value 0
Time 1376043554.0234 | GPIO 4 changed | New value 0
Time 1376043554.0333 | GPIO 4 changed | New value 1
Time 1376043554.0359 | GPIO 4 changed | New value 1
Time 1376043554.0387 | GPIO 4 changed | New value 1
Time 1376043554.1286 | GPIO 4 changed | New value 1
Time 1376043554.1311 | GPIO 4 changed | New value 1
Time 1376043570.8616 | GPIO 17 changed | New value 1
Time 1376043570.8643 | GPIO 17 changed | New value 1
Time 1376043570.8674 | GPIO 17 changed | New value 1
Time 1376043570.8704 | GPIO 17 changed | New value 1
Time 1376043570.8732 | GPIO 17 changed | New value 1
Time 1376043570.9058 | GPIO 17 changed | New value 0
Time 1376043571.5563 | GPIO 17 changed | New value 0
Time 1376043571.5589 | GPIO 17 changed | New value 1
Time 1376043571.681 | GPIO 17 changed | New value 0
Time 1376043571.7638 | GPIO 17 changed | New value 0
Time 1376043551.5499 | GPIO 4 changed | New value 0
Time 1376043551.5523 | GPIO 17 changed | New value 0
Time 1376043551.554 | GPIO 18 changed | New value 0
Time 1376043551.556 | GPIO 21 changed | New value 0
Time 1376043552.9756 | GPIO 4 changed | New value 0
Time 1376043552.9786 | GPIO 4 changed | New value 1
Time 1376043552.9816 | GPIO 4 changed | New value 1
Time 1376043552.9844 | GPIO 4 changed | New value 1
Time 1376043552.9874 | GPIO 4 changed | New value 1
Time 1376043552.9901 | GPIO 4 changed | New value 1
Time 1376043552.993 | GPIO 4 changed | New value 1
Time 1376043552.9956 | GPIO 4 changed | New value 1
Time 1376043552.9989 | GPIO 4 changed | New value 1
Time 1376043553.0015 | GPIO 4 changed | New value 1
Time 1376043553.0044 | GPIO 4 changed | New value 1
Time 1376043553.007 | GPIO 4 changed | New value 1
Time 1376043553.0098 | GPIO 4 changed | New value 1
Time 1376043553.0124 | GPIO 4 changed | New value 1
Time 1376043553.161 | GPIO 4 changed | New value 0
Time 1376043554.0234 | GPIO 4 changed | New value 0
Time 1376043554.0333 | GPIO 4 changed | New value 1
Time 1376043554.0359 | GPIO 4 changed | New value 1
Time 1376043554.0387 | GPIO 4 changed | New value 1
Time 1376043554.1286 | GPIO 4 changed | New value 1
Time 1376043554.1311 | GPIO 4 changed | New value 1
Time 1376043570.8616 | GPIO 17 changed | New value 1
Time 1376043570.8643 | GPIO 17 changed | New value 1
Time 1376043570.8674 | GPIO 17 changed | New value 1
Time 1376043570.8704 | GPIO 17 changed | New value 1
Time 1376043570.8732 | GPIO 17 changed | New value 1
Time 1376043570.9058 | GPIO 17 changed | New value 0
Time 1376043571.5563 | GPIO 17 changed | New value 0
Time 1376043571.5589 | GPIO 17 changed | New value 1
Time 1376043571.681 | GPIO 17 changed | New value 0
Time 1376043571.7638 | GPIO 17 changed | New value 0
And so, I added some debouncing to each of the switches. We do this by ignoring the latter of two consecutive calls to the hook function for a particular switch if the time difference between them is less than quarter of a second. All message prints have been removed from this code.
sw2leds_debounce.lua:
sw2leds_debounce.lua:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | -- Switches to LEDs (with debouncing) package.path = '/opt/mihini/lua/?.lua;/opt/mihini/lua/?/init.lua;' .. package.path package.cpath = '/opt/mihini/lua/?.so;' .. package.cpath local sched = require "sched" local gpio = require "gpio" local socket = require "socket" --------------------------------------------------------------- local function toggle_led(n) -- Function to toggle the led local stat = gpio.read(n) if stat == 1 then gpio.write(n,0) elseif stat == 0 then gpio.write(n,1) end end do -- Hook function to debounce the switches -- First up are the variables to store the time when the switch was last pressed local gpio4time = socket.gettime() local gpio17time = socket.gettime() local gpio18time = socket.gettime() local gpio21time = socket.gettime() -- Second we have the variable to hold the debounce time in seconds -- If two consecutive pulses arrive within this interval, second pulse is ignored local bounce_interval_secs = 0.25 -- Finally we have the function function hook_switch_debounce(id, value) if id == 4 then if socket.gettime() - gpio4time > bounce_interval_secs then toggle_led(22) end gpio4time = socket.gettime() elseif id == 17 then if socket.gettime() - gpio17time > bounce_interval_secs then toggle_led(23) end gpio17time = socket.gettime() elseif id == 18 then if socket.gettime() - gpio18time > bounce_interval_secs then toggle_led(24) end gpio18time = socket.gettime() elseif id == 21 then if socket.gettime() - gpio21time > bounce_interval_secs then toggle_led(25) end gpio21time = socket.gettime() end end end local function main() -- Idle task while true do sched.wait(1) end end --------------------------------------------------------------- -- Main Logic Begins -- -- Configure the GPIOS for the 4 LEDs gpio.configure(22, {direction="out", edge="both", activelow="0"}) gpio.configure(23, {direction="out", edge="both", activelow="0"}) gpio.configure(24, {direction="out", edge="both", activelow="0"}) gpio.configure(25, {direction="out", edge="both", activelow="0"}) -- -- Configure the GPIOS for the 4 Switches gpio.configure(4, {direction="in", edge="falling", activelow="1"}) gpio.configure(17, {direction="in", edge="falling", activelow="1"}) gpio.configure(18, {direction="in", edge="falling", activelow="1"}) gpio.configure(21, {direction="in", edge="falling", activelow="1"}) -- -- Register the hooks for the 4 Switches gpio.register(4, hook_switch_debounce) gpio.register(17, hook_switch_debounce) gpio.register(18, hook_switch_debounce) gpio.register(21, hook_switch_debounce) -- -- Schedule the idle thread sched.run(main) -- -- Start Scheduler sched.loop() |
Comments
Post a Comment