Use GPIO interrupts instead of sensor sampling to simplify code

Naively, I’ve been using sensor sampling as the only way to detect changes in sensor readings. Shaking my head over here. Just sad.

Sampling means periodically reading sensor value to detect changes. My period was typically around 10Hz, or 10 times every second. Not only it is wasteful in many cases, it also has a problem of potentially missing changes if they happen and revert between samplings.

Using GPIO interrupts is akin to event-based programming where you subscribe to an event and sit back waiting to be notified about the change. Much more sensible, clean and you won’t miss anything.

The Problem

I have a Hall effect sensor with an ESP8266 running NodeMCU/Lua that detects open/closed status of my garage door. The status doesn’t change often so checking it 10 times/second is a waste. The status is communicated over MQTT. Let’s compare solutions.

Solution 1: Sampling

local hall_pin = 2

gpio.mode(hall_pin, gpio.INPUT) -- simple input pin mode

local function check_open_closed()
  local val = gpio.read(hall_pin)

  if val == gpio.LOW then
    print("CLOSED")
  else
    print("OPEN")
  end
end

local open_close_sensor_timer = tmr.create()

local function loop_open_close_check()
  check_open_closed()
  open_close_sensor_timer:start() -- restart timer
end

open_close_sensor_timer:register(100, tmr.ALARM_SEMI, loop_open_close_check)
open_close_sensor_timer:start()

Solution 2: Listening for interrupts

There’s no need to make another reading as the callback function receives the current sensor reading as the first argument.

The code is simpler. It won’t miss events. Solid.

local hall_pin = 2

gpio.mode(hall_pin, gpio.INT) -- interrupt mode

local function check_open_closed(val, when, event_count)
  if val == gpio.LOW then
    print("CLOSED")
  else
    print("OPEN")
  end
end

-- listening to "both" means detecting changes from HIGH to LOW and from LOW to HIGH 
gpio.trig(hall_pin, "both", check_open_closed)

-- call check_open_closed here to report the initial status at startup
local intial_value = gpio.read(hall_pin)
check_open_closed(initial_value)


Posted

in

by

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *