Датчики серии MQ-* и библиотека TroykaMQ

Тема в разделе "Схемотехника, компоненты, модули", создана пользователем Андрей Новичок, 20 сен 2018.

Метки:
  1. Реализация для MQ-4 с учётом модели влажности и температуры.
    Это для таких извращенцев как я :)
    Код (C++):
    //For users MQ-4 sensors
    //This example using model "value dependence on temperature and humidity"
    //Data sheet - https://www.winsen-sensor.com/d/files/PDF/Semiconductor%20Gas%20Sensor/MQ-4%20(Ver1.4)%20-%20Manual.pdf
    //mq4_schematic - http://wiki.amperka.ru/_media/%D0%BF%D1%80%D0%BE%D0%B4%D1%83%D0%BA%D1%82%D1%8B:mq4:troyka-mq4_schematic.png
    //Pre-heating MQ-4 sensor done early (at 168 hours)
    //The stand contains one MQ-4 sensor and one DHT-11 sensor for simpe example using MQ-4.

    //Value dependence on temperature and humidity
    // 1. Bounds.
    //Humidity 0.0 ... 1.0 (0% ... 100% relative humidity)
    //Temperature -10 deg. Cel. to 50 deg. Cel. But, when we using DHT-11, bounds shifting from 0 deg. Celcius to 50 deg. Celcius.
    //ppm 200 ... 10000 ppm
    // 2. Digitalized model from Data sheet, "Fig4. Typical temperature/humidity characteristics"
    //k_hum = 0.00672096284322792*Hum + (-0.0159038179354688);
    //b_hum = -0.741244323718154*Hum + 1.77535862501753;
    // Model "dependence on temperature and humidity" RsR0 = RsR0_getting*(k_hum*temp + b_hum);
    // 3. Constants.
    //U0 in the clean air previously obtained concrete instance of the sensor MQ-4. Its value U0=92 from 1024 on analog pin.
    //When Rs/R0 = ((1024/Us)-1)/((1024/U0)-1), then Rs/R0 = ((1024/Us)-1)*U0_const_clean_air.
    //U0_const_clean_air = 1/((1024/U0)-1) = 0,0987124463519313
    //For concrete instance of the sensor MQ-4 in the middle temperature and middle humidity was obtained shifting value Rs/R0 in clean air was getting from "U0_const_clean_air" with using model "value dependence on temperature and humidity"
    //RsR0_clean_air = 1,31848506314236

    #include <DHT.h> //For get actual temperature and humidity.
    #define DHT_PIN 2
    #define PIN_MQ4  A1

    //Constants for MQ-4
    #define Tconfidential_interval 3600000 //3600000 = One hour pre-heating needs for get stable value; your may using 40 minites or more every time after turn on the controller
    #define U0_const_clean_air 0.09871245 // 1/((1024/U0)-1) = 0,0987124463519313, then ADC value = 92.
    #define RsR0_clean_air_model_coefficient 1.318485 // Error of model then was getting Rs/R0 in clean air: Rs/R0 on data sheet = 1, then we using model Rs/R0 = 1.318485 (~32%): http://forum.amperka.ru/attachments/%D0%9C%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C-%D1%87%D0%B8%D1%81%D1%82%D0%BE%D0%B3%D0%BE-%D0%B2%D0%BE%D0%B7%D0%B4%D1%83%D1%85%D0%B0-%D1%82%D0%B5%D0%BC%D0%BF%D0%B5%D1%80%D0%B0%D1%82%D1%83%D1%80%D0%B0-%D0%B8-%D0%B2%D0%BB%D0%B0%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D1%8C-png.16701/
    #define Refresh_H_n_T_period 20000 //300000 = 5 minutes. In millis, its for your choice, min - about 20000 ms. But better - minimum time reaction as a minimum time reaction of all components: DHT reaction - 2-5 minutes.
    #define Output_period 20000 //60000 - One minute

    //Humidity and temperature variables
    float Hum=0.0;
    float temp=0.0;

    DHT dht; //dht init.
    void setup() {
      Serial.begin(9600); Serial.println("------------ Starting ------------");
      dht.setup(DHT_PIN);
    }


    void loop() {
      String DataMessage;
      int Uadc;

      Refresh_Hum_n_Temp_values();

      if (millis()<Tconfidential_interval){
        delay(2000);
        Uadc = analogRead(PIN_MQ4);
        DataMessage+="Current value ADC = "; DataMessage+=String(Uadc); Serial.print(DataMessage);
        DataMessage ="; Heating is performed on "; DataMessage+=String((millis()/float(Tconfidential_interval))*100); DataMessage +="%; Minutes left: "; DataMessage+=String((float(Tconfidential_interval)-millis())/60000);Serial.println(DataMessage);Serial.println("--------------------------------------------------------------------------------");
      }
      else{
        Uadc = analogRead(PIN_MQ4);
        delay(Output_period);
        Serial.println("-------------------------");
        ppm_model(Uadc);
        ppm_model_hum_n_tepm(Uadc);
      }
    }

    void Refresh_Hum_n_Temp_values(){
      //This is not real-time timer, only for this example
      static unsigned long previousMillis;
      if (millis() - previousMillis > Refresh_H_n_T_period){
        previousMillis=millis();
        //Get humidity and temperature variables from DHT-11
        delay(dht.getMinimumSamplingPeriod());
        temp = dht.getTemperature();
        Hum = (dht.getHumidity())/100;
      }
    }

    void ppm_model(int ADC_value){
      //Get ppm by model free from humidity and tempereature
      unsigned int MyPPM=(23.99428*pow(((1024/(float(ADC_value)-1)*U0_const_clean_air)/RsR0_clean_air_model_coefficient),-1.659292));//http://forum.amperka.ru/attachments/formula5-png.16324/
      Serial.print("PPM_MODEL free hum and temp = ");Serial.println(MyPPM);
    }

    void ppm_model_hum_n_tepm(int ADC_value){
      float RsR0=((1024/(float(ADC_value)-1)*U0_const_clean_air)); Serial.print("--- RsR0, not corrected =  ");Serial.println(RsR0,6);
      float Correction_hum_n_temp; Serial.print("--- Hum = "); Serial.print(Hum*100,0);Serial.print(", temp = ");Serial.print(temp,0);Serial.print(", ");

      if(Hum <= 0 or Hum >= 0.95 or temp <=0 or temp >=60 ){
        Correction_hum_n_temp = 1.0;
        Serial.println("Out of limit, using typical values: Correction_hum_n_temp = 1");
      }else{
        float k_hum = 0.00672096284322792*Hum + (-0.0159038179354688);
        float b_hum = -0.741244323718154*Hum + 1.77535862501753;
        //Serial.print("k_hum = ");Serial.print(k_hum);Serial.print(", b_hum =");Serial.println(b_hum);
        Correction_hum_n_temp = (k_hum*temp + b_hum)/RsR0_clean_air_model_coefficient;
        Serial.print("Correction_hum_n_temp =");Serial.println(Correction_hum_n_temp,6);
      }

      RsR0 = RsR0*Correction_hum_n_temp; Serial.print("--- RsR0 corrected =  ");Serial.println(RsR0,6);
      float MyPPM=(23.99428*pow(RsR0,-1.659292)); Serial.print("PPM_MODEL hum and temp correction = ");Serial.println(MyPPM);
    }
    Теперь давайте посмотрим, что эта модель нам даёт. Измерения проводились по-быстрому, вместе с подготовкой измерения заняли где-то час. Правильно, конечно, измерять в течении длительного времения, так, чтобы захватить несколько периодов длиной в сутки с их периодичность тепмературы и влажности. Но и того что было сделано для демонстрации должно быть достаточно.
    Пример применения модели влажности и температуры по-быстрому.png
    Чисто теоретически нормированные графики должны были почти совпасть, и это "почти", т.е. небольшая разница и должна была стать результатом сравнения моделей с учётом температуры и влажности, а также без их учёта. Но поскольку, я делал всё по-быстрому, вылезли дополнительные погрешности в виде несовершенных датчиков DHT-11 с их инертностью, которая составляет 2-5 минут + конденсат.
    Модель то, конечно, работает, но посмотрим какой у нас результат? Ха-ха-ха, - всего 1% разницы. С учётом других погрешностей в районе 30% не бог весть что.
    Это не означает, что следует пренебрегать компенсацией температуры и влажности. На длинных дистанциях, таких, как "сезон" (зима, весна, лето, осень) очень может пригодиться. Для кратковременных измерений - точно нет. Если говорим о сезонах, то с учётом того, что датчик MQ-XX служит максимум 5 лет, получаем кол-во сезонов в количестве 20 штук. Надо заморачиваться с температурой и влажностью или нет здесь решает каждый сам.
    Потом, датчик работает в комнатных условиях, во всяком случае под крышей/навесом, в сарае, котельной и т.п. Если, скажем, в комнате 8 кв. метров (Data sheet) находятся 2 человека с температурой 36,6, то каждый из них выдыхает СО2, пукает, потеет, осуществляет какую-то деятельность. Не знаю, какая поверхность кожи у человека, но по-любому она больше, чем у вашего маслянного нагревателя, используемого в межсезонье. Если прилетят инопланетяне, посмотрят на нас в нашей среде обитания, то сразу испугаются и улетят обратно в свою далёкую галактику :). Это я к тому, что деятельность Человека на объекте измерения не поддаётся анализу и мы можем получить вообще странные показания, даже если они правдивые. Поэтому я, лично, вижу возможность использования датчиков MQ-XX с учётом температуры и влажности на удалённых объектах без Человека.
    В общем, я поделился своим мнением, а как поступать каждый решает сам.

    ------------------------------------------------------------------------------------------------------------------------
    ДОБАВЛЕНО 12.05.2019. Ошибки в модели.
    Была допущена ошибка в определении ppm:
    ppm_model()
    БЫЛО не правильно:
    СТАЛО правильно:
    ppm_model_hum_n_tepm()
    БЫЛО не правильно:
    СТАЛО правильно:
    Ошибка уже исправлена в коде выше, можно пользоваться. Приношу извинения :(.
     

    Вложения:

    Последнее редактирование: 13 май 2019
  2. В принципе, я получил, что хотел. Остался пока один вопрос: что такое "Power of Sensitivity body"?
    Выдержка из Data sheet Power of Sensitivity body (Ps): Ps=Vc^2×Rs/(Rs+RL)^2
    Где Vc - измеряемое нами напряжение, Rs - измеренное нами сопротивление, а RL - сопротивление установленное на датчик.
    Размерность этой Ps есть Вольт квадрат на Ом. Чем ниже RL, тем выше "сила чувствительности". Это и дураку понятно, смысл какой в этом?
    Со значениями RL я разобрался - проще простого. Может так задаются потенциально возможные значения АЦП (диапазон)? Может мне кто грамотно объяснить?
     
  3. Так задаются потенциально возможные значения АЦП.
     
  4. Здравствуйте, товарищи.
    Итоги.
    Данный пост был сформирован в результате политики газовых компаний, которые по указанию государства действительно снизили цену на подключение газа, но монетизировали свой недополученный доход в виде дополнительных услуг, от которых, как оказалось, не возможно отказаться :). Я был злой и решил рассмотреть альтернативные варианты. Выбор пал на проекты ARDUINO, и на самую, как мне кажется, лучшую компанию в своём сегменте - Амперку.
    В процессе изучения библиотеки для датчиков MQ-XX выявилось много косяков, с чего, собственно пост и начинается.
    К сожалению, изысканиями пришлось заниматься совершенно самостоятельно, т.к. на формуе я техподдержки не получил (ну может быть несколько лайков от приятных собеседников).
    Результаты все могут увидеть выше. Они не очень презентабельные, скажем так. Но зато совершенно бесплатные. Даже если я где-то накосясил, то всё равно, общий подход считаю верным.
    Использованные материалы:

    До того, как я ещё не стал злым от реакции на суровую действительность об ARDUINO не знал вообще ничего, кроме каких-то упоминаний в некоторых статьях. Мои проблемы давно решены, дело было в вентиляции, что кстати, не только по наитию, но и по результатам измерений удалось зафиксировать, и, в дальнейшем, решить. Так что закупленные компоненты для мини-проекта себя финансово точно "отбили". И самое главное, - я получил удовольствие от такой работы. Всех агитирую заниматься проектами ARDUINO!

    В общем всё, я кончил! :)
     
    parovoZZ нравится это.
  5. Здравствуйте, товарищи!
    Наткнулся случайно на этот пост:
    http://meteolab.ru/ru/edu/arduino/sensor/gas/
    Мат. модель мне нравится, но определение значения на чистом воздухе взято от балды. Не уверен ни разу в работоспособности приведённого примера.
    Тем не менее, работа была проведена, и с ней имеет смысл ознакомиться. Самое интересное - ссылки на источники в посте.
    Всем удачи!
     
  6. asam

    asam Гик

    Спасибо. Интересно. Только вот с этим утвердением не согласен "Наиболее важным является мониторинг содержания пяти загрязняющих газов: NO, NO2, CO, SO2, O3"
    Какой же NO2 загрязняющий газ? Это очень даже веселящий газ!
     
  7. Боюсь Вас разочаровать. NO2 вреден в указанных концентрациях, и он как проба манту - индикатор текущего состояния.
    Веселятся от него, пожалуй, разве только что менеджеры вредных производств, сумевшие обмануть органы технадзора.
     
  8. Вася

    Вася Нерд

    Ардуино - маразм и библиотека TroykaMQ-master - маразм. По памяти. В ардуино: применяется правое выравнивание в АЦП, т.е. старшие 6 разрядов равны нулю. После переводит результат в float,проверяет старший разряд и куча кода, если число отрицательно (дополнительный код, проверка переполнения ...), но 6 старших разрядов нулевые!!! положительные. В библиотеке: зачем вообще переводить числа в float? Пять делить на 1024, после умножать на значение АЦП. Можно просто оперировать 10-битными числами, любое измерение хоть чистого, хоть грязного воздуха по сути есть 10-битное число. Нужно только перевести, насколько помню, 27 Ом - табличное число в 10 бит.
     
    Андрей Новичок, b707 и parovoZZ нравится это.
  9. Как интересно. Кто же инициировал дискуссию? Пойду шапочку из фольги надену.
    1. Критику я высказал ранее, да, не комильфо. Замечания здесь: http://forum.amperka.ru/threads/Датчики-серии-mq-и-библиотека-troykamq.16377/page-5#post-214779
    2. Библиотека обучающая, та, которая обучает основную аудиторию Амперки. Для этого и сделана. Вы против?
    3. Очень важно: похоже, вы мыслите не в том ключе. Да, Вы правы, но! Правы в конкретном случае. Процесс то аналоговый. Значения возможны все.
     
  10. b707

    b707 Гуру

    Вася, это не ардуино - маразм, а расчеты автора и его "модель"

    Андрей Новичок - вот это что за бред
    Код (C++):
     float k_hum = 0.00672096284322792*Hum + (-0.0159038179354688);
        float b_hum = -0.741244323718154*Hum + 1.77535862501753;
    Вы в курсе, что точность ардуиновского флоат - не более 5-6 значащих цифр?
    Все остальные цифры после запятой - в ваших формулах абсолютно бесполезны. И если вы внимательно почитаете чужие ответы в ветке - вы увидите, что вам уже несколько человек об этом говорили.

    Единственное, что можно сказать по этой формуле - что вы ничего не понимаете в математике.
    Люди без математического, а чаще просто без образования - очень любят формулы с огромными бессмысленными коэффициентами.
     
    Последнее редактирование: 29 сен 2021
    Вася и Андрей Новичок нравится это.
  11. Разумеется. Хоть и опыт не большой.
    Автор не стремился сделать красиво. Автору было интересно как ведёт себя физический процесс. И решение его конкретных задач.
    Вы снова уходите в сторону от реальности. Обсуждаете только программирование. Решение задач всегда комплексное.
    Вы хотите упрекнуть меня в незнании контроллеров? Я не знаю. Мне до лампочки. Я беру инструмент и пользую его.
    Вот, скажем, недавно купил Гоноровского, Цепи и сигналы, изучаю по новой теорему о вычетах.
    Вы, простите, ограничиваетесь, только дискретной математикой.
    Шапочки из фольги привет.

    ДОБАВЛЕНО: так быстро прочесть всю ветку и вынести решение о том, что говорилось об использованных числовых переменных за пару минут не реально. Подумайте, что пишите.
     
  12. Не очень по теме, из прошлого.
    ДОБАВЛЕНО: это было понятно изначально. Начал забывать уже.
     
  13. b707

    b707 Гуру

    я и не читал всех ваших рассуждений. Мне вполне достаточно тех двух формул из вашей "модели", что я процитировал в #130
    Я рассуждаю с точки зрения математики и программирования. Вы поместили свою "модель" в скетч, исполняемый на конкретном языке программирования с конкретными ограничениями. Так вот, эти ограничения не позволяют вам работать с коэффициентами точнее чем 5-6 знаков после запятой. ВСЕ. После этого вся ваша заумная теория не имеет ровно никакого значения, раз результат ее невозможно отразить в коде.

    Это реализация. Теперь рассмотрим саму модель. Если не ошибаюсь, она описывает 4 точки на графике из даташита, которые вы переводили в значения вручную? Вы пробовали хотя бы приблизительно прикинуть точность этих данных? Думаете, она даст хотя бы 4 знака после запятой? А если нет - какого ж фига вы рассчитываете модель до 17 цифры?
    Судя по всему, в ВУЗе вы статистику не проходили. Или прогуляли. Иначе знали бы главное правило - точность результата никогда не может быть лучше точности исходных данных. Если ваши данные - 4 знака после запятой, значит в результате не может быть 18.
    Если вы даете формулу с 18 знаками - вы расписываетесь в своем полном невежестве в математической статистике и просто в здравом смысле.

    А что касается ваших длинных рассуждений - Вы заметили, как мало народу обсуждало ваши пассажи? Это бывает в двух случаях - когда они настолько сложные, что никому не понятны. и когда автор несет такой бред. что даже связываться противно. Вы думаете, ваш случай к какому ближе?
     
    Последнее редактирование: 29 сен 2021
    Вася и Андрей Новичок нравится это.
  14. b707

    b707 Гуру

    не тешьте себя мыслью, что ваша формула имеет какой-то физический смысл. 17 цифр после запятой бессмысленны и с точки зрения математики, а уж с точки зрения физики реального процесса - это просто чушь в квадрате.
    Вы потратили 1.5 года на рассчет зубодробительной формулы, которую можно было вывести в Экселе за один вечер.
    Надеюсь, что вы сами хоть чему-то научились за это время, иначе оно просто потрачено впустую.
     
    Андрей Новичок и DetSimen нравится это.
  15. Я с вами полностью согласен, и подтверждаю все что написали. Перестаньте сыпать бомбами с высоты ваших познаний.
    "Длинные" числа это копи-паста из вычислений в электронной таблице для наглядности тем, кто хочет разобраться. Компилятор их прекрасно прожуёт, как и многие другие огрехи.
     
  16. Уважаемый Вася, нас прервали.
    1. Библиотеку не используйте никакую. Если посмотрите начало этого поста то он, собственно, и начинается с вежливого вопроса, который кратко звучит "А что это за фигня?"
    2. Касательно разрядности. При использовании электрохимических датчиков в быту потенциальные границы измерений определяются жизненными обстоятельствами. Скажем, при ppm=1000, жизнедеятельность организма мягко говоря под угрозой. А эта тысяча, кстати, точка отсчёта для характеристики датчика (см. Data Sheet). И очевидно, что диапазон интересующих нас измерений лежит в определённых границах.
    3. Ограничение значений, которые преобразуются АЦП также связаны с обвязкой датчика.
    Я использовал 2 датчика от производителя и 2 левых из Али. Там стоит подтягивающий резистор в 20к (пишу по памяти). Но на рынке присутствуют также с резисторами на 10 и 5к. Потенциально динамический диапазон разный.

    Если вы всё-таки решили как-то использовать этот датчик-убожество, то в бытовых условиях нет никакого другого решения, кроме как определять R0 рекомендуемыми выше методами.
     
  17. b707

    b707 Гуру

    В чем тут "наглядность"? чем эти цифры помогут "тем, кто хочет разобраться"?
    Код (C++):
    float k_hum = 0.00672096284322792*Hum + (-0.0159038179354688);
    Напишите вот так и не позорьтесь. это будет в миллион раз правильнее:
    Код (C++):
    float k_hum = 0.00672*Hum -0.01590;
    В саму суть вашей формулы, повторяю - я не вникаю, хочется вам верить, что вы открыли "сокровенное знание" про MQ4 - верьте на здоровье. Но чушь с точки зрения математики в своих расчетвах уберите
     
    Последнее редактирование: 30 сен 2021
    Вася нравится это.
  18. b707

    b707 Гуру

    вы не поняли того, о чем писал Вася. Он писал о разрядности АЦП на ардуине, которая ВСЕГДА 10 бит и не определяется ни "жизненными обстоятельствами". ни "политической целесообразностью"
     
    Вася нравится это.
  19. parovoZZ

    parovoZZ Гуру

    Разрядность АЦП для медленно изменяющихся сигналов можно повысить не хитрым способом.
     
  20. Вася

    Вася Нерд

    Процесс аналоговый, но как может быть отрицательным сопротивление датчика? В этом маразм!