• Система автоматизации с открытым исходным кодом на базе 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
 
Последнее редактирование:
Сверху Снизу