• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе 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
Спасибо за советы, попробую разобраться с колбеком и таймером. Вот только надо еще со скриптом смотреть иногда не понятные значения возвращает, а иногда и минусовые, хотя вроде длительности высокого и низкого уровня считает ровно.
покажите скрипт в части проверки пина.
 
Сверху Снизу