holmes
holmes

Reputation: 578

NodeMCU gpio triggering incorrectly

I'm attempting to read IR information from a NodeMCU running Lua 5.1.4 from a master build as of 8/19/2017.

I might be misunderstanding how GPIO works and I'm having a hard time finding examples that relate to what I'm doing.

pin = 4
pulse_prev_time = 0
irCallback = nil

function trgPulse(level, now)
  gpio.trig(pin, level == gpio.HIGH and "down" or "up", trgPulse)

  duration = now - pulse_prev_time
  print(level, duration)

  pulse_prev_time = now
end

function init(callback)
  irCallback = callback
  gpio.mode(pin, gpio.INT)
  gpio.trig(pin, 'down', trgPulse)
end

-- example
print("Monitoring IR")
init(function (code)
  print("omg i got something", code)
end)

I'm triggering the initial interrupt on low, and then alternating from low to high in trgPulse. In doing so I'd expect the levels to alternate from 1 to 0 in a perfect pattern. But the output shows otherwise:

1   519855430
1   1197
0   609
0   4192
0   2994
1   589
1   2994
1   1198
1   3593
0   4201
1   23357
0   608
0   5390
1   1188
1   4191
1   1198
0   3601
0   3594
1   25147
0   608
1   4781
0   2405
1   3584
0   4799
0   1798
1   1188
1   2994

So I'm clearly doing something wrong or fundamentally don't understand how GPIO works. If this is expected, why are the interrupts being called multiple times if the low/high levels didn't change? And if this does seem wrong, any ideas how to fix it?

Upvotes: 0

Views: 1023

Answers (1)

Marcel Stör
Marcel Stör

Reputation: 23535

I'm clearly doing something wrong or fundamentally don't understand how GPIO works

I suspect it's a bit a combination of both - the latter may be the cause for the former.

My explanation may not be 100% correct from a mechanical/electronic perspective (not my world) but it should be enough as far as writing software for GPIO goes. Switches tend to bounce between 0 and 1 until they eventually settle for one. A good article to read up on this is https://www.allaboutcircuits.com/technical-articles/switch-bounce-how-to-deal-with-it/. The effect can be addressed with hardware and/or software.

Doing it with software usually involves introducing some form of delay to skip the bouncing signals as you're only interested in the "settled state". I documented the NodeMCU Lua function I use for that at https://gist.github.com/marcelstoer/59563e791effa4acb65f

-- inspired by https://github.com/hackhitchin/esp8266-co-uk/blob/master/tutorials/introduction-to-gpio-api.md
-- and http://www.esp8266.com/viewtopic.php?f=24&t=4833&start=5#p29127
local pin = 4    --> GPIO2

function debounce (func)
    local last = 0
    local delay = 50000 -- 50ms * 1000 as tmr.now() has μs resolution

    return function (...)
        local now = tmr.now()
        local delta = now - last
        if delta < 0 then delta = delta + 2147483647 end; -- proposed because of delta rolling over, https://github.com/hackhitchin/esp8266-co-uk/issues/2
        if delta < delay then return end;

        last = now
        return func(...)
    end
end

function onChange ()
    print('The pin value has changed to '..gpio.read(pin))
end

gpio.mode(pin, gpio.INT, gpio.PULLUP) -- see https://github.com/hackhitchin/esp8266-co-uk/pull/1
gpio.trig(pin, 'both', debounce(onChange))

Note: delay is an empiric value specific to the sensor/switch!

Upvotes: 0

Related Questions