• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

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

SSS_Viva

Member
попробуйте так :
-----------------------------
local function mh19Begin(level, timestamp)
print("mh19Begin", level, timestamp)
if (level == gpio.HIGH ) then highDuration =timestamp
else highDuration =timestamp-highDuration
print("T=", highDuration)
--local co2 = calculateCo2Ppm(highDuration, lowDuration)
---print("co2", co2)
end
end
---------------------------
upload_2018-12-19_23-35-22.png

Вот такой ответ.

Через некоторое время вот так, но это я так понимаю надо датчику некоторое время чтоб показания устаканились.
upload_2018-12-19_23-37-16.png

Пока поправил скрипт вот так :
Код:
   local pin, highDuration, lowDuration, co2, TRIGGER_ON, lastTimestamp, calculateCo2Ppm = 3, 0, 0, 0, "both", 0, 0
   local function calculateCo2Ppm(highDuration, lowDuration)
        return 5000 * (highDuration - 2) / (highDuration + lowDuration - 4);

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

end

   lastTimestamp = timestamp

end
 
   gpio.mode(pin,gpio.INT)
   gpio.trig(pin, TRIGGER_ON, mh19Begin)
В начале вроде как правдивые показатели, потом происходит вот так :
upload_2018-12-20_0-5-28.png
 
Последнее редактирование:

SSS_Viva

Member
по-моему Вы не правильно поправили.
алгоритм такой
мы измеряем положительный импульс
начало его когда придет положительный фронт т е уровень станет высоким.
это после else
при этом мы должны запомнить время и ВСЕ
т е после else должно быть присваивание
например так: highDuration = timestamp
-------------------------
по отрицательному фронту мы должны закончить измерение при этом уровень станет низким
и рассчитать длительность импульса
это после
if (level == gpio.LOW) then
расчет длительности импульса делаем так
highDuration = timestamp - highDuration
длительность получается в микросекундах а нам надо в миллисекундах т е надо делить на 1000
----------------------
в результате получим так
---------------------------------
local co2; --делаем глобальной чтобы можно было работать в других колбеках
----
local function mh19Begin(level, timestamp)
-- print("mh19Begin", level, timestamp)
if (level == gpio.LOW) then
highDuration = timestamp - highDuration
print("Th=", highDuration)
co2 = calculateCo2Ppm(highDuration, lowDuration)
print("co2", co2)
else
highDuration = timestamp
end
end
Так без lowDuration CO2 не посчитается.
 

SSS_Viva

Member
---------------------------------------------
local co2,T1,TH;
----
local function mh19Begin(level, timestamp)
-- print("mh19Begin", level, timestamp)
if (level == gpio.LOW) then
TH = timestamp - T1
print("Th=", TH)
else
local THL=timestamp-T1;
co2 = 2*(TH-2000)/(THL-4000)
print("co2", co2)
T1=timestamp;
end
end
-----------------------
Код:
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)
Так вот собственно, раньше так и было, только подсчет CO2 по другому был.
 

SSS_Viva

Member
почти так.
сравните результат.
Поправил вот так :
Код:
   local pin, highDuration, lowDuration, co2, TRIGGER_ON, lastTimestamp, calculateCo2Ppm = 1, 0, 0, 0, "both", 0, 0
--   local function calculateCo2Ppm(highDuration, lowDuration)
--   return 5000 * (highDuration - 2) / (highDuration + lowDuration - 4);

--   end
   local function mh19Begin(level, timestamp)
       -- print("mh19Begin", level, timestamp)
         if (level == gpio.LOW) then
            highDuration = timestamp - lastTimestamp
            print("Th=", highDuration)
         else
            lowDuration = timestamp - lastTimestamp
            print("Tl=", lowDuration)
            co2 = 5000 * (highDuration-2000) / (lowDuration - 4000)
--            co2 = calculateCo2Ppm(highDuration, lowDuration)
            print("co2", co2)
       
            lastTimestamp = timestamp
           
end
end
 
   gpio.mode(pin,gpio.INT)
   gpio.trig(pin, TRIGGER_ON, mh19Begin)
результат вот такой
upload_2018-12-20_13-43-40.png
 

SSS_Viva

Member
поставьте для контроля вывод на печать
highDuration ,timestamp , lastTimestamp, lowDuration
и поделите их на 1000 при выводе
Посмотреть вложение 6953
Код:
    local pin, highDuration, lowDuration, co2, TRIGGER_ON, lastTimestamp, calculateCo2Ppm = 1, 0, 0, 0, "both", 0, 0
--   local function calculateCo2Ppm(highDuration, lowDuration)
--   return 5000 * (highDuration - 2) / (highDuration + lowDuration - 4);
--   end
   local function mh19Begin(level, timestamp)
       -- print("mh19Begin", level, timestamp)
         if (level == gpio.LOW) then
            highDuration = timestamp - lastTimestamp
            print("Th=", highDuration)
         else
            lowDuration = timestamp - lastTimestamp
            print("Tl=", lowDuration)
            co2 = 5000 * (highDuration-2000) / (lowDuration - 4000)
--            co2 = calculateCo2Ppm(highDuration, lowDuration)
            print("co2", co2)
      
            lastTimestamp = timestamp
            print("highDuration", highDuration / 1000)
            print("lowDuration", lowDuration / 1000)
            print("timestamp", timestamp / 1000)
            print("lastTimestamp", lastTimestamp / 1000)
          
end
end
   gpio.mode(pin,gpio.INT)
   gpio.trig(pin, TRIGGER_ON, mh19Begin)
upload_2018-12-20_15-21-41.png
 

nikolz

Well-known member
Посмотреть вложение 6953
Код:
    local pin, highDuration, lowDuration, co2, TRIGGER_ON, lastTimestamp, calculateCo2Ppm = 1, 0, 0, 0, "both", 0, 0
--   local function calculateCo2Ppm(highDuration, lowDuration)
--   return 5000 * (highDuration - 2) / (highDuration + lowDuration - 4);
--   end
   local function mh19Begin(level, timestamp)
       -- print("mh19Begin", level, timestamp)
         if (level == gpio.LOW) then
            highDuration = timestamp - lastTimestamp
            print("Th=", highDuration)
         else
            lowDuration = timestamp - lastTimestamp
            print("Tl=", lowDuration)
            co2 = 5000 * (highDuration-2000) / (lowDuration - 4000)
--            co2 = calculateCo2Ppm(highDuration, lowDuration)
            print("co2", co2)
    
            lastTimestamp = timestamp
            print("highDuration", highDuration / 1000)
            print("lowDuration", lowDuration / 1000)
            print("timestamp", timestamp / 1000)
            print("lastTimestamp", lastTimestamp / 1000)
        
end
end
   gpio.mode(pin,gpio.INT)
   gpio.trig(pin, TRIGGER_ON, mh19Begin)
Посмотреть вложение 6954
у вас co2 отрицательное.
предположу что это результат расчетов с фиксированной точкой
я вам выше написал - соберите прошивку без integer
================
еще у вас формула для расчета не верная
интервал вы измеряете в мкс а в док речь идет о мс
см формулу в моем варианте или в документации
 

SSS_Viva

Member
у вас co2 отрицательное.
предположу что это результат расчетов с фиксированной точкой
я вам выше написал - соберите прошивку без integer
================
еще у вас формула для расчета не верная
интервал вы измеряете в мкс а в док речь идет о мс
см формулу в моем варианте или в документации
Попробую перепрошить с FLOAT.
Но вот тут явно с INTEGER, и вроде все работает.
popstas/nodemcu-co2-temp-hum-grafana

Вот вы выше писали :
co2 = 2000.*(TH-2000)/(THL-4000)
Вот в моем варианте:
co2 = 5000 * (highDuration-2000) / (lowDuration - 4000)
я вижу разницу только в том что в моем нет точки, после 5000, а в вашем есть, и китайцы в датащите берут 2000, хотя реально датчик есть как на 2000, 5000, и 10 000, у меня 5000.
 

nikolz

Well-known member
Попробую перепрошить с FLOAT.
Но вот тут явно с INTEGER, и вроде все работает.
popstas/nodemcu-co2-temp-hum-grafana

Вот вы выше писали :
co2 = 2000.*(TH-2000)/(THL-4000)
Вот в моем варианте:
co2 = 5000 * (highDuration-2000) / (lowDuration - 4000)
я вижу разницу только в том что в моем нет точки, после 5000, а в вашем есть, и китайцы в датащите берут 2000, хотя реально датчик есть как на 2000, 5000, и 10 000, у меня 5000.
да вижу, что у вас исправлено.
обратите внимание что CO2 не может быть отрицательным в форме с полученными значениями
т е формула считается у вас не верно.
в ссылке время измеряется в мс и нет переполнения
поделите перед вычислением интервалы на 1000 должно быть правильно без переполнения
но целое дает вам меньшую точность
надо использовать блочно-плавающую точку (если вы знаете что это)
какой смысл использовать целочисленную арифметику если удобнее считать с плав точкой
 

SSS_Viva

Member
да вижу, что у вас исправлено.
обратите внимание что CO2 не может быть отрицательным в форме с полученными значениями
т е формула считается у вас не верно.
в ссылке время измеряется в мс и нет переполнения
поделите перед вычислением интервалы на 1000 должно быть правильно без переполнения
но целое дает вам меньшую точность
надо использовать блочно-плавающую точку (если вы знаете что это)
какой смысл использовать целочисленную арифметику если удобнее считать с плав точкой
Вот так получилось вроде получить стабильные значения и без минусов, только вот показания не радуют, если они соответствуют действительности.
Код:
local pin, h, l, co2, TRIGGER_ON, th, tl, calculateCo2Ppm = 1, 0, 0, 0, "both", 0, 0, 0
local function calculateCo2Ppm(th, tl)
return 5000 * (th - 2) / (th + tl - 4);
local function mh19Begin(level)
    
  local tt = tmr.now()/1000;
if level == 1 then

      h = tt;
      tl = h - l;
      else
      l = tt;
      th = l - h;
      co2 = calculateCo2Ppm(th, tl)
      print("co2", co2)
                  
end
end
   gpio.mode(pin,gpio.INT)
   gpio.trig(pin, TRIGGER_ON, mh19Begin)
upload_2018-12-20_18-46-14.png
 

SSS_Viva

Member
а что у Вас датчик до 5000 ppm?
дайте ссылку на документацию.
---------------
попробуйте подышать на него.
потом открыть окно.
Как изменятся показания?
---------------------
выведите на печать длительность импульса длительность паузы и длительность всего интервала для проверки на вшивость
-------
Вы неправильно считаете
нельзя привязываться к началу паузы
надо считать от начала импульса
т е расчет надо делать в момент начала импульса
----------------
сумма импульса и пазу не должна сильно отличаться от 1004 мс
Датчик вот такой : Это тот же MH-Z19B только с диапазоном от 0 до 5000. Из названия лота видно что они бывают 2000, 5000, 10 000. На моем наклеено 0-5000. Документация думаю вряд ли отличается от этой, кроме того что надо поменять 2000 на 5000, .
Открыл окно прошло минут 15:
upload_2018-12-20_19-18-40.png

Вот для проверки на вшивость.

upload_2018-12-20_19-27-31.png
 

SSS_Viva

Member
вроде нормально почти
попробуйте исправить измерение от начала импульса и перейти на плавающую точку
-------------------------
НОРМЫ УГЛЕКИСЛОГО ГАЗА В ЖИЛЫХ ПОМЕЩЕНИЯХ
Проектировщики многоквартирных и частных домов берут за основу ГОСТ 30494-2011 под названием «Здания жилые и общественные. Параметры микроклимата в помещениях».
Этот документ оптимальным для здоровья человека уровнем CO2 считает 800 — 1 000 ppm.
Отметка на уровне 1 400 ppm – предел допустимого содержания углекислого газа в помещении. Если его больше, то качество воздуха считается низким.
Однако уже 1 000 ppm не признается вариантом нормы целым рядом исследований, посвященных зависимости состояния организма от уровня CO2.
Их данные свидетельствует о том, что на отметке 1 000 ppm больше половины испытуемых ощущают последствия ухудшения микроклимата:
учащение пульса, головную боль, усталость и, конечно,
пресловутое «нечем дышать».
Физиологи нормальным уровнем CO2 считают 600 – 800 ppm.
Перешел на Float.
upload_2018-12-20_21-11-1.png

Как перейти н расчет от начала импульса пока не придумал.
 

SSS_Viva

Member
исправил
----------------
local function mh19Begin(level)
local tt = tmr.now()/1000;
if level == 1 then
co2 = 5000 * (tt-l- 2) / (tt-h - 4); h=tt;
print("co2", co2)
else
l = tt;
end
end
local function mh19Begin(level)
local tt = tmr.now()/1000;
if level == 1 then
co2 = 5000 * (tt-l- 2) / (tt-h - 4); h=tt;
print("co2", co2)
else
l = tt;
end
end

да вроде ничего не изменилось, это если сравнивать предыдущий пост и последний)
 

SSS_Viva

Member
исправьте
co2 = 5000 * (l-h- 2) / (tt-h - 4); h=tt;
Код:
local pin, h, l, co2, TRIGGER_ON, calculateCo2Ppm, tt = 1, 0, 0, 0, "both", 0, 0
local function calculateCo2Ppm(h, l)
return 5000 * (l - h - 2) / (tt - h - 4);
end
local function mh19Begin(level,tt)
if level == 1 then
      co2 = calculateCo2Ppm(h, l)
      print("co2", co2)
      h = tt;
      else
      l = tt;
      print("tt", tt)
      print("h", h)
      print("l", l)
      print("h+l", h+l)  
end
end
   gpio.mode(pin,gpio.INT)
   gpio.trig(pin, TRIGGER_ON, mh19Begin)
upload_2018-12-21_13-5-2.png
 

SSS_Viva

Member
По моей логике, и смотря в дата шит, надо все таки мониторить когда level ==0 и тогда в этот момент время будт равно Th, а else время перехода в 1 минус Th и будет равно Tl.
 

nikolz

Well-known member
По моей логике, и смотря в дата шит, надо все таки мониторить когда level ==0 и тогда в этот момент время будт равно Th, а else время перехода в 1 минус Th и будет равно Tl.
поставьте функцию ровно так как я ее написал
и уберите функцию расчета CO2
------------------
функции нужны для экономии памяти , если код используете повторно
а у вас один раз - только зря тратите время на вызов и ничего не экономите
------------------
в вашем варианте переменная tt это мкс а в формуле мс
-----------------
полный бардак получился
 

nikolz

Well-known member
вот так напишите
------------------------
local function mh19Begin(level)
local tt = tmr.now()/1000;
if level == 1 then
co2 = 5000 * (l-h- 2) / (tt-h - 4); h=tt;
print("co2", co2)
else
l = tt;
end
end
 
Последнее редактирование:

SSS_Viva

Member
вот так напишите
------------------------
local function mh19Begin(level)
local tt = tmr.now()/1000;
if level == 1 then
co2 = 5000 * (l-h- 2) / (tt-h - 4); h=tt;
print("co2", co2)
else
l = tt;
end
end
Код:
local pin, h, l, co2, TRIGGER_ON = 1, 0, 0, 0, "both"
local function mh19Begin(level)
local tt = tmr.now()/1000;
if level == 1 then
      co2 = 5000 * (l-h- 2) / (tt-h - 4); h=tt;
      print("co2", co2)
else
      l = tt;
      print("tt", tt)
      print("h", h)
      print("l", l)
      print("h+l", h+l) 
end
end
   gpio.mode(pin,gpio.INT)
   gpio.trig(pin, TRIGGER_ON, mh19Begin)
upload_2018-12-21_13-39-10.png
 
Последнее редактирование:
Сверху Снизу