• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Нужна помощь ESP8266 CH340 NodeMcu V3 Lua+MH-Z19B подключение по PWM.

SSS_Viva

Member
Доброго дня.
Может есть у кого опыт подключения MH-Z19B с использованием PWM и реализации получения данных на LUA?
Два дня борюсь, и толку 0.
Датчик подключен в выводу D3.
Нашёл два подобных проекта, пробовал из них почерпнуть информацию, тоже не помогло, буду благодарен за любую помощь.
P.S. По UART не подключить, занят.
 

SSS_Viva

Member
Пока вот что получилось, но результат не очень.
Код:
 gpio.mode(3, gpio.INPUT)
  
    local h = 0
    local l = 0
    local th = 0
    local tl = 0

    local function pin3cb(level)
    local tt = tmr.now()/1000;

if level == 1 then

      h = tt;
      tl = h - l;
      ppm = 5000 * (th - 2) / (th + tl - 4)
     print("pp0",ppm)
   
else
      l = tt;
      th = l - h;
      ppm = 5000 * (th - 2) / (th + tl - 4)
     print("pp2",ppm)
end
 

nikolz

Well-known member
Доброго дня.
Может есть у кого опыт подключения MH-Z19B с использованием PWM и реализации получения данных на LUA?
Два дня борюсь, и толку 0.
Датчик подключен в выводу D3.
Нашёл два подобных проекта, пробовал из них почерпнуть информацию, тоже не помогло, буду благодарен за любую помощь.
P.S. По UART не подключить, занят.
есть такая штука в столе.
для информации
Тёмная сторона MH-Z19
bertrik/mhz19
-----------------------------------
popstas/nodemcu-co2-temp-hum-grafana
------------------------------
используйте PWM output
согласно документации длительность импульса пропорциональна концентрации
начинает от 2 мs и до 1004 мс для диапазона 0-2000 ppm
---------------------------
таким образом в этом режиме вешаете на любой пин и измеряете длительность импульса либо прямым счетом либо через прерывание
-----------------------------
 
Последнее редактирование:

nikolz

Well-known member
Пока вот что получилось, но результат не очень.
Код:
 gpio.mode(3, gpio.INPUT)
 
    local h = 0
    local l = 0
    local th = 0
    local tl = 0

    local function pin3cb(level)
    local tt = tmr.now()/1000;

if level == 1 then

      h = tt;
      tl = h - l;
      ppm = 5000 * (th - 2) / (th + tl - 4)
     print("pp0",ppm)
 
else
      l = tt;
      th = l - h;
      ppm = 5000 * (th - 2) / (th + tl - 4)
     print("pp2",ppm)
end
это явно не то
если прямым счетом
то делаете цикл который запускается когда на пине 1 и останавливается когда на пине ноль
если был ноль а стала 1 то запоминаем время
если была 1 а стал 0 - измеряем интервал вычитает из текущего времени запомненное
 

SSS_Viva

Member
это явно не то
если прямым счетом
то делаете цикл который запускается когда на пине 1 и останавливается когда на пине ноль
если был ноль а стала 1 то запоминаем время
если была 1 а стал 0 - измеряем интервал вычитает из текущего времени запомненное
Спасибо за ответ, но я бы начал с более раннего.
Прошивку для модуля генерировал вот на этом сайте NodeMCU custom builds .
Включил в нее вот такие модули (часть из них на всякий случай): bit, bme280, cron, dht, file, gpio, http, i2c, net, node, pwm, spi, sqlite3, tmr, uart, ucg, wif, в модуль прошил с окончанием integer.
Сначала хотелось бы понять как прописать правильно PIN на котором висит PWM, если брать обозначение с платы это D3, и соответственно везде ссылаемся на 3 (по мне это праввильно), хотя GPIO это ноль, потом нужно настроить этот пин, он может быть как выходом, так и входом, а так же interrupt mode, это и есть то прерывание, ок котором вы говорите, правильно использовать INT, но я пока с ним не разобрался, по сему для теста ставим INPUT, gpio.mode(3, gpio.INPUT), что собственно и сделано. Далее хотелось бы убедиться что на этом входе есть сигнал с датчика, единственно что придумал, это вот так gpio.read(3), в консоле видел сначала 0 потом 1, то есть вроде как есть изменение уровней, вопрос то ли это.....
Понимаю, что для вас наверное это глупые вопросы, но все же хочется понимать что делаешь, а не бездумно копипастить чужие куски кода.
 

nikolz

Well-known member
Спасибо за ответ, но я бы начал с более раннего.
Прошивку для модуля генерировал вот на этом сайте NodeMCU custom builds .
Включил в нее вот такие модули (часть из них на всякий случай): bit, bme280, cron, dht, file, gpio, http, i2c, net, node, pwm, spi, sqlite3, tmr, uart, ucg, wif, в модуль прошил с окончанием integer.
Сначала хотелось бы понять как прописать правильно PIN на котором висит PWM, если брать обозначение с платы это D3, и соответственно везде ссылаемся на 3 (по мне это праввильно), хотя GPIO это ноль, потом нужно настроить этот пин, он может быть как выходом, так и входом, а так же interrupt mode, это и есть то прерывание, ок котором вы говорите, правильно использовать INT, но я пока с ним не разобрался, по сему для теста ставим INPUT, gpio.mode(3, gpio.INPUT), что собственно и сделано. Далее хотелось бы убедиться что на этом входе есть сигнал с датчика, единственно что придумал, это вот так gpio.read(3), в консоле видел сначала 0 потом 1, то есть вроде как есть изменение уровней, вопрос то ли это.....
Понимаю, что для вас наверное это глупые вопросы, но все же хочется понимать что делаешь, а не бездумно копипастить чужие куски кода.
Можно в цикле печать пина поставить его на ввод , пин подтянуть через 10-20к 3.3 на пин кнопку к земле Нажали - ноль отпустили 1 .
проще использовать GPIO4(D2) и GPIO5(D1)
------------------------------
Overview - NodeMCU Documentation
NodeMCU v3 — Zerynth Docs documentation
https://handsontec.com/pdf_learn/esp8266-V10.pdf
nodemcu/nodemcu-firmware
Начало работы с платой NodeMcu ESP8266 v3 Lua
-----------------------------
 

SSS_Viva

Member
Можно в цикле печать пина поставить его на ввод , пин подтянуть через 10-20к 3.3 на пин кнопку к земле Нажали - ноль отпустили 1 .
проще использовать GPIO4(D2) и GPIO5(D1)
------------------------------
Overview - NodeMCU Documentation
NodeMCU v3 — Zerynth Docs documentation
https://handsontec.com/pdf_learn/esp8266-V10.pdf
nodemcu/nodemcu-firmware
Начало работы с платой NodeMcu ESP8266 v3 Lua
-----------------------------
Выход с датчика проверил тестером пульсации есть. Состояние на gpio тоже меняется то 0 то 1, проверил принтом gpio.read(3).
Теперь надо мониторить данный пин, я так понимаю это делается при помощи функции pin3cb на интересует уровень на 3 пине это (level) итого получаем function pin3cb(level) теперь вызывая level у нас буде либо 0 либо 1. Так я понимаю ? 3 пин поменяю на 1, не проблема, только почему проще ?
 

SSS_Viva

Member
Можно в цикле печать пина поставить его на ввод , пин подтянуть через 10-20к 3.3 на пин кнопку к земле Нажали - ноль отпустили 1 .
проще использовать GPIO4(D2) и GPIO5(D1)
------------------------------
Overview - NodeMCU Documentation
NodeMCU v3 — Zerynth Docs documentation
https://handsontec.com/pdf_learn/esp8266-V10.pdf
nodemcu/nodemcu-firmware
Начало работы с платой NodeMcu ESP8266 v3 Lua
-----------------------------
И спасибо за ссылки, часть читал, но некоторые двольно полезные, и я их не находил.
 

enjoynering

Well-known member
вот как я считал длительность импульса для HC-SR04 с помощью pulseIn()

Код:
uint16_t HCSR04::getEchoPulseLength(void)
{
  int16_t length = 0;

  #ifdef HCSR04_DISABLE_INTERRUPTS
  noInterrupts();                                                      //disable all interrupts
  #endif

  /* start measurement */
  digitalWrite(_triggerPin, HIGH);
  delayMicroseconds(10);                                               //length of triger pulse, 100μs maximum
  digitalWrite(_triggerPin, LOW);                                      //300..500μs after trigger low, module during next 200μs sends 8 pulses at 40 kHz & measures echo

  length = pulseIn(_echoPin, HIGH, _timeOutMax);                       //must be called at least a few dozen μs before expected pulse, avarage tHOLLDOFF=700μs

  #ifdef HCSR04_DISABLE_INTERRUPTS
  interrupts();                                                        //re-enable all interrupts
  #endif

  #ifdef HCSR04_ECHO_CANCELLATION
  delay(50);                                                           //wait until echo from previous measurement disappears
  #endif

  if (length == 0 || length < _timeOutMin) return HCSR04_OUT_OF_RANGE;
                                           return length;
}
весь код тут - enjoyneering/HCSR04
 

nikolz

Well-known member
вот как я считал длительность импульса для HC-SR04 с помощью pulseIn()

Код:
uint16_t HCSR04::getEchoPulseLength(void)
{
  int16_t length = 0;

  #ifdef HCSR04_DISABLE_INTERRUPTS
  noInterrupts();                                                      //disable all interrupts
  #endif

  /* start measurement */
  digitalWrite(_triggerPin, HIGH);
  delayMicroseconds(10);                                               //length of triger pulse, 100μs maximum
  digitalWrite(_triggerPin, LOW);                                      //300..500μs after trigger low, module during next 200μs sends 8 pulses at 40 kHz & measures echo

  length = pulseIn(_echoPin, HIGH, _timeOutMax);                       //must be called at least a few dozen μs before expected pulse, avarage tHOLLDOFF=700μs

  #ifdef HCSR04_DISABLE_INTERRUPTS
  interrupts();                                                        //re-enable all interrupts
  #endif

  #ifdef HCSR04_ECHO_CANCELLATION
  delay(50);                                                           //wait until echo from previous measurement disappears
  #endif

  if (length == 0 || length < _timeOutMin) return HCSR04_OUT_OF_RANGE;
                                           return length;
}
весь код тут - enjoyneering/HCSR04
что-то на луа не похоже?
Я тоже могу на СИ написать будет вообще просто, но просят же на луа?
 

SSS_Viva

Member
вот как я считал длительность импульса для HC-SR04 с помощью pulseIn()

Код:
uint16_t HCSR04::getEchoPulseLength(void)
{
  int16_t length = 0;

  #ifdef HCSR04_DISABLE_INTERRUPTS
  noInterrupts();                                                      //disable all interrupts
  #endif

  /* start measurement */
  digitalWrite(_triggerPin, HIGH);
  delayMicroseconds(10);                                               //length of triger pulse, 100μs maximum
  digitalWrite(_triggerPin, LOW);                                      //300..500μs after trigger low, module during next 200μs sends 8 pulses at 40 kHz & measures echo

  length = pulseIn(_echoPin, HIGH, _timeOutMax);                       //must be called at least a few dozen μs before expected pulse, avarage tHOLLDOFF=700μs

  #ifdef HCSR04_DISABLE_INTERRUPTS
  interrupts();                                                        //re-enable all interrupts
  #endif

  #ifdef HCSR04_ECHO_CANCELLATION
  delay(50);                                                           //wait until echo from previous measurement disappears
  #endif

  if (length == 0 || length < _timeOutMin) return HCSR04_OUT_OF_RANGE;
                                           return length;
}
весь код тут - enjoyneering/HCSR04
Больщое спасибо за пример. Тут как ситуация такая что теорию я вроде усвоил, а вот как грамотно описать это на LUA, пока не получается.
Давайте допустим что у меня ESP прошита выше описанной прошивкой. Чтение будем реализовывать при помощи одного init.lua.
На данном этапе я пришел к вот этому:
Код:
   local pin, highDuration, lowDuration, co2, TRIGGER_ON, lastTimestamp, calculateCo2Ppm = 3, 0, 0, 0, "both", 0, 0

   local function calculateCo2Ppm(highDuration, lowDuration)
        return 5000 * (1002 * highDuration - 2 * lowDuration) / 1000 / (highDuration + lowDuration);

end
   local function mh19Begin(level, timestamp)
        print("mh19Begin", level, timestamp)
        if (level == gpio.LOW) then
            highDuration = timestamp - lastTimestamp
        else
            lowDuration = timestamp - lastTimestamp
            local co2 = calculateCo2Ppm(highDuration, lowDuration)
            print("co2", co2)
   end

   lastTimestamp = timestamp

end
 
   gpio.mode(pin,gpio.INT)
   gpio.trig(pin, TRIGGER_ON, mh19Begin)
 

nikolz

Well-known member
Больщое спасибо за пример. Тут как ситуация такая что теорию я вроде усвоил, а вот как грамотно описать это на LUA, пока не получается.
Давайте допустим что у меня ESP прошита выше описанной прошивкой. Чтение будем реализовывать при помощи одного init.lua.
На данном этапе я пришел к вот этому:
Код:
   local pin, highDuration, lowDuration, co2, TRIGGER_ON, lastTimestamp, calculateCo2Ppm = 3, 0, 0, 0, "both", 0, 0

   local function calculateCo2Ppm(highDuration, lowDuration)
        return 5000 * (1002 * highDuration - 2 * lowDuration) / 1000 / (highDuration + lowDuration);

end
   local function mh19Begin(level, timestamp)
        print("mh19Begin", level, timestamp)
        if (level == gpio.LOW) then
            highDuration = timestamp - lastTimestamp
        else
            lowDuration = timestamp - lastTimestamp
            local co2 = calculateCo2Ppm(highDuration, lowDuration)
            print("co2", co2)
   end

   lastTimestamp = timestamp

end
 
   gpio.mode(pin,gpio.INT)
   gpio.trig(pin, TRIGGER_ON, mh19Begin)
посмотрите это
Особенности создания программ в NODEMCU ESP8266 для «интернета вещей»
и попробуйте написать правильно на луа
 

SSS_Viva

Member
Если вы про структуру init start и так далее, то я про это в курсе и весь проект сейчас состоит из вот такого колличества файлов
upload_2018-12-19_10-13-9.png
Если про структуру того что я выложил выше, то я по ка не очень понимаю.
 

nikolz

Well-known member
Если вы про структуру init start и так далее, то я про это в курсе и весь проект сейчас состоит из вот такого колличества файлов
Посмотреть вложение 6946
Если про структуру того что я выложил выше, то я по ка не очень понимаю.
обычно в проекте на луа
ставят таймер и колбек
все действия которые надо делать периодически помещаем в колбек таймера
например туда можно поместить измерение импульса шим от сенсора
все что вне колбека будет исполняться один раз
 

SSS_Viva

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

nikolz

Well-known member
Спасибо за советы, попробую разобраться с колбеком и таймером. Вот только надо еще со скриптом смотреть иногда не понятные значения возвращает, а иногда и минусовые, хотя вроде длительности высокого и низкого уровня считает ровно.
покажите скрипт в части проверки пина.
 
Сверху Снизу