NodeMCU gpio запускается некорректно

Я пытаюсь прочитать информацию IR из NodeMCU, на котором запущен Lua 5.1.4, из основной сборки по состоянию на 19.08.2017.

Возможно, я неправильно понимаю, как работает GPIO, и мне трудно найти примеры, относящиеся к тому, что я делаю.

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)

Я инициирую начальное прерывание на низком уровне, а затем чередую от низкого к высокому в trgPulse. При этом я ожидаю, что уровни будут чередоваться от 1 до 0 в идеальном порядке. Но вывод показывает иное:

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

Так что я явно что-то делаю не так или принципиально не понимаю, как работает GPIO. Если это ожидается, почему прерывания вызываются несколько раз, если низкий / высокий уровни не изменились? И если это кажется неправильным, есть идеи, как это исправить?


person holmes    schedule 20.08.2017    source источник
comment
Я не знаком с этой платформой, но уверены ли вы, что на ИК-входе нет шума? Первое, что я сделал бы, это отключил его, подключил вход к земле и посмотрел, что произойдет. Также не уверен для этой платформы, но на некоторых микроконтроллерах изменение фронта прерывания не работает в процедуре прерывания, если у вас есть запасные входы, возможно, подключите оба к ИК-приемнику и установите по одному для каждого фронта.   -  person PeterJ    schedule 20.08.2017
comment
что вы имеете в виду под прочитанной информацией IR? что вы подключили к пину 4?   -  person Piglet    schedule 20.08.2017
comment
Я сомневаюсь, что слышу шум, я вижу изменения прерывания данных только сразу после нажатия кнопки на пульте дистанционного управления. Он длится все время, пока я нажимаю кнопку, поэтому кажется довольно стабильным. У меня ИК-приемник подключен к контакту 4.   -  person holmes    schedule 21.08.2017


Ответы (1)


Я явно что-то делаю не так или принципиально не понимаю, как работает GPIO

Я подозреваю, что это комбинация того и другого - последнее может быть причиной первого.

Мое объяснение может быть не на 100% правильным с механической / электронной точки зрения (не в моем мире), но этого должно быть достаточно для написания программного обеспечения для GPIO. Переключатели имеют тенденцию колебаться между 0 и 1, пока в конечном итоге не доведутся до единицы. Хорошая статья, чтобы прочитать об этом: https://www.allaboutcircuits.com/technical-articles/switch-bounce-how-to-deal-with-it/. Эффект может быть устранен с помощью оборудования и / или программного обеспечения.

Выполнение этого с помощью программного обеспечения обычно включает в себя введение некоторой формы задержки, чтобы пропустить отскакивающие сигналы, поскольку вас интересует только «установившееся состояние». Я задокументировал функцию NodeMCU Lua, которую использую для этого, на 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))

Примечание: delay - это эмпирическое значение, специфичное для датчика / переключателя!

person Marcel Stör    schedule 21.08.2017
comment
Похоже, очень вероятно. Я попробую! - person holmes; 21.08.2017