nodemcu / nodemcu-firmware

Lua based interactive firmware for ESP8266, ESP8285 and ESP32
https://nodemcu.readthedocs.io
MIT License
7.66k stars 3.12k forks source link

Interrupt-driven programming #122

Closed dvv closed 8 years ago

dvv commented 9 years ago

Hello!

From what I see in lua_modules, sensor read procedures are all based on synchronous waiting. Is it ever possible to write non-blocking interrupt-driven logic with set of tools exposed by nodemcu-firmware (or at all by underlying sdk)?

E.g. DHT11/22 query is about bitbanging a start of measurement condition and then just measuring the intervals between pin values.

TIA, --Vladimir

dvv commented 9 years ago

The following does not collect waveform from DHT11

r = { }
function p()
  for i = 1, #r do print(r[i]) end
end
pin = 4
gpio.mode(pin, gpio.OUTPUT)
gpio.write(pin, gpio.HIGH)
tmr.delay(100)
gpio.write(pin, gpio.LOW)
tmr.delay(20000)
gpio.write(pin, gpio.HIGH)
gpio.mode(pin, gpio.INPUT, gpio.PULLUP) 
gpio.trig(pin, "both", function(level)
  r[#r + 1] = level
end)
gpio.mode(pin, gpio.INT, gpio.PULLUP)
tmr.delay(1000000)
print(p()) -- WTF: shows 2 to 3 values, they do not interchange as expected, eg. 001 can be seen

Wonder why? Starting impulse is copied from example dht22, interrupt handler attached, sufficient time waited. TIA

dvv commented 9 years ago

It seems no precise timing is possible with current tmr. Running the following

...
mode(pin, OUTPUT)
write(pin, LOW)
tmr.alarm(0, X, 0, function()
  mode(pin, INPUT, PULLUP)
  ...

and measuring the low pulse duration with logic analyser, I see X+7 ms instead of X... I start to believe gpio.trig just is not as fast as needed for microsecond pulses...

zerog2k commented 9 years ago

@dvv I agree. I have been trying to implement an interrupt driven decode of of pulse width detection from a 433 MHz ASK RX module, which has pulse widths of 600, 400, and 200 uS.

I even did some very simple code with interrupt to follow one gpio interrupt and copy that state to antoher pin to see if the interrupts are keeping up with logic analyzer too.

gpio.mode(6, gpio.INPUT)  -- gpio12
gpio.mode(6, gpio.INT)  -- gpio12
gpio.mode(5, gpio.OUTPUT) --gpio14

function myISR(level)
  if level == 1 then
     -- rising edge
     gpio.write(5, 1)
  else
     gpio.write(5, 0)
  end
end

gpio.write(5, gpio.LOW)
gpio.trig(6, "both", myISR)

Sometimes it seems like it can keep up with pulses of about 100 uS or longer, but there are times where it just stops triggering the interrupt for 50-80 ms which is bad. I can do this on arduino with no problems.

Maybe there another internal routine hogging the interrupts.

I wish ESP8266 SDK setup wasnt so tricky to get working, because this would probably work better in C.

TerryE commented 8 years ago

We have to work within the SDK constraints = no interrupt pure programming, except where the developer wishes to implement their own interrupt handler within the SDK.