Психометрический гигрометр

Тема в разделе "Arduino & Shields", создана пользователем Ar4ik, 8 июл 2019.

  1. Ar4ik

    Ar4ik Нерд

    Прошу вашей помощи, не могу разобраться, как правильно записать условие для выполнения данной задачи.
    В наличии два датчика DS18B20, хочу на базе двух датчиков сделать психометрический гигрометр. Таблицу со значениями приложу ниже, а также ниже будет скетч с моими набросками.
    Немного расскажу о принципе работы психометрического гигрометра.
    Измерение относительной влажности воздуха основано на разнице показаний "сухого" и "увлажненного" термометров. После снятия показаний термометров по психрометрической таблице определяют относительную влажность воздуха.

    Например Тсухого = 25,00 , Твлажного=24,00 ∆Т=Тс-Тв=1
    Из таблицы видно что при Тс=25 и разности показаний ∆Т=1 влажность составляет 87%

    Заранее прошу прощения возможно если оформил, написал не в том разделе или такая тема уже обговаривалась. Всем откликнувшимся заранее огромное спасибо.

    Код (C++):
    #include <Wire.h>                          
    #include <LiquidCrystal_PCF8574.h>        
    #include <DallasTemperature.h>            
    #include <OneWire.h>

    #define ONE_WIRE_BUS 2                          // Указываем, к какому выводу подключена DQ
    byte simvol[8]   = {B11100,B10100,B11100,B00000,B00000,B00000,B00000,B00000,}; // Символ градуса
    LiquidCrystal_PCF8574 lcd(0x27);          
    OneWire oneWire(ONE_WIRE_BUS);              
    DallasTemperature ds(&oneWire);

    float tempSensor[1]; // массив куда читается температура

    DeviceAddress sensor1 = {0x28, 0x2E, 0x8D, 0x79, 0x97, 0x10, 0x03, 0xFB};
    DeviceAddress sensor2 = {0x28, 0x80, 0x11, 0x79, 0x97, 0x09, 0x03, 0x7C};
    void getTemp()
    {
       ds.requestTemperatures();  
       tempSensor[0] = ds.getTempC(sensor1);
       tempSensor[1] = ds.getTempC(sensor2);
    }
    void setup()
    {
        lcd.begin(16, 2);
        lcd.setBacklight(255);
        ds.begin();  
        lcd.setCursor(0,0);                      
        lcd.print("Ts= ");                    
        lcd.setCursor(0,1);                        
        lcd.print("Tv= ");
    }
    void loop()
    {
        float Tsuxoy=tempSensor[0];
        float Tvlagniy=tempSensor[1];
        float dT=(Tsuxoy-Tvlagniy);
        //int H ;

        lcd.setCursor(11,1);
        lcd.print("T=");
        dT=round(dT/0.5)*0.5;
        lcd.print(dT);
     
    if(Tsuxoy == 25 && dT == 0.5){H == 91;}
    if(Tsuxoy == 25, dT == 1.0){H == 87;}
    if(Tsuxoy == 25, dT == 1.5){H == 83;}
    if(Tsuxoy == 25, dT == 2.0){H == 79;}
    if(Tsuxoy == 25, dT == 2.5){H == 75;}
    if(Tsuxoy == 25, dT == 3.0){H == 71;}
    if(Tsuxoy == 25, dT == 3.5){H == 67;}
    if(Tsuxoy == 25, dT == 4.0){H == 63;}
    if(Tsuxoy == 25, dT == 4.5){H == 60;}
    if(Tsuxoy == 25, dT == 5.0){H == 56;}
    if(Tsuxoy == 25, dT == 5.5){H == 52;}
    if(Tsuxoy == 25, dT == 6.0){H == 49;}
    if(Tsuxoy == 25, dT == 6.5){H == 45;}
    if(Tsuxoy == 25, dT == 7.0){H == 42;}
    if(Tsuxoy == 25, dT == 7.5){H == 38;}
    if(Tsuxoy == 26, dT == 0.5){H == 92;}
    if(Tsuxoy == 26, dT == 1.0){H == 88;}
    if(Tsuxoy == 26, dT == 1.5){H == 84;}
    if(Tsuxoy == 26, dT == 2.0){H == 80;}
    if(Tsuxoy == 26, dT == 2.5){H == 76;}
    if(Tsuxoy == 26, dT == 3.0){H == 72;}
    if(Tsuxoy == 26, dT == 3.5){H == 69;}
    if(Tsuxoy == 26, dT == 4.0){H == 65;}
    if(Tsuxoy == 26, dT == 4.5){H == 61;}
    if(Tsuxoy == 26, dT == 5.0){H == 58;}
    if(Tsuxoy == 26, dT == 5.5){H == 54;}
    if(Tsuxoy == 26, dT == 6.0){H == 51;}
    if(Tsuxoy == 26, dT == 6.5){H == 49;}
    if(Tsuxoy == 26, dT == 7.0){H == 44;}
    if(Tsuxoy == 26, dT == 7.5){H == 42;}
    if(Tsuxoy == 26, dT == 8.0){H == 39;}
    if(Tsuxoy == 26, dT == 8.5){H == 35;}
    if(Tsuxoy == 26, dT == 9.0){H == 32;}
    if(Tsuxoy == 26, dT == 9.5){H == 29;}
    if(Tsuxoy == 26, dT == 10.0){H == 26;}
    if(Tsuxoy == 26, dT == 10.5){H == 23;}
    if(Tsuxoy == 26, dT == 11.0){H == 20;}

    if(Tsuxoy == 27, dT == 0.5){H == 92;}
    if(Tsuxoy == 27, dT == 1.0){H == 88;}
    if(Tsuxoy == 27, dT == 1.5){H == 84;}
    if(Tsuxoy == 27, dT == 2.0){H == 80;}
    if(Tsuxoy == 27, dT == 2.5){H == 77;}
    if(Tsuxoy == 27, dT == 3.0){H == 73;}
    if(Tsuxoy == 27, dT == 3.5){H == 69;}
    if(Tsuxoy == 27, dT == 4.0){H == 66;}
    if(Tsuxoy == 27, dT == 4.5){H == 62;}
    if(Tsuxoy == 27, dT == 5.0){H == 59;}
    if(Tsuxoy == 27, dT == 5.5){H == 55;}
    if(Tsuxoy == 27, dT == 6.0){H == 52;}
    if(Tsuxoy == 27, dT == 6.5){H == 50;}
    if(Tsuxoy == 27, dT == 7.0){H == 46;}
    if(Tsuxoy == 27, dT == 7.5){H == 43;}
    if(Tsuxoy == 27, dT == 8.0){H == 41;}
    if(Tsuxoy == 27, dT == 8.5){H == 36;}
    if(Tsuxoy == 27, dT == 9.0){H == 33;}
    if(Tsuxoy == 27, dT == 9.5){H == 30;}
    if(Tsuxoy == 27, dT == 10.0){H == 28;}
    if(Tsuxoy == 27, dT == 10.5){H == 25;}
    if(Tsuxoy == 27, dT == 11.0){H == 22;}

     //lcd.setCursor(11,0);                        
     //lcd.print("H= %");
     //lcd.print(H);
     
      getTemp(); // читаем температуру с датчиков

      lcd.createChar(1, simvol);                  // Создаем символ под номером 1
      lcd.setCursor(3,0);                         // Устанавливаем курсор на 1 строку, ячейка 7
      lcd.print(tempSensor[0]);
      lcd.setCursor(8,0);                        // Устанавливаем курсор на 1 строку, ячейка 12
      lcd.print("\1");                            // Выводим символ градуса
      lcd.setCursor(9,0);                        // Устанавливаем курсор на 1 строку, ячейка 13
      lcd.print("C");                             // Выводим текст
      lcd.setCursor(3,1);
      lcd.print(tempSensor[1]);
      lcd.setCursor(8,1);                        // Устанавливаем курсор на 1 строку, ячейка 12
      lcd.print("\1");                            // Выводим символ градуса
      lcd.setCursor(9,1);                        // Устанавливаем курсор на 1 строку, ячейка 13
      lcd.print("C");                             // Выводим текст
      }
     

    Вложения:

    • Psipho2.png
      Psipho2.png
      Размер файла:
      109,8 КБ
      Просмотров:
      26
  2. BAR__MEN

    BAR__MEN Вселенский Няш Команда форума

    А что, разве так можно было? :eek:

    @Ar4ik, а в чем проблема текущего кода?
     
  3. Ar4ik

    Ar4ik Нерд

    Я если честно не силен, но всячески пытаюсь в этом разобраться. Я бы хотел что бы контроллер по формуле сам считал дТ , что он и делает и на основании этой дельты мне на экран выводил значение относительной влажности. Я пробовал датчик влажности и температуры DHT22, но он через чур чувствителен к резким изменениям, да и показывает чушь, если сравнивать DHT22 с эталонным психометрическим гигрометром который прошел поверку
     
  4. Ar4ik

    Ar4ik Нерд

    Так скорее всего нельзя, бо оно так не работает ((
     
  5. Не, ну и в чем проблема ? Задайте двумерный массив и занесите в него из таблицы. Около 400 значений. Влезет. Или вы хотите по таблице вывести формулу и воткнуть ее в расчет ? Тогда придется выполнить математическую работу по решению полинома с 400 неизвестными. Или 20 отдельных полиномов с 20 неизвестными. Весьма непростая затея. Хотя может в Гугле найдется сервис такого рода.
    ПС. Может в Экселе есть готовый макрос для этого ?!
     
    Последнее редактирование: 8 июл 2019
  6. Ar4ik

    Ar4ik Нерд

    Если бы я знал как это сделать я бы не обращался за помощью. Не проблема занести 400 символов, проблема как правильно написать это условие.
     
  7. Условие чего ? Как вывести формулу ? Университетский курс. Полином Лагранжа (вроде так).
    Влажность = Массив(T, dT)
    Справочник Ардуины че там про массивы (arrays) говорит ? Кстати щас сам гляну...
    ПС. Если двумерный массив не проглотит, сделайте 20 одномерных и выбирайте по
    Код (C++):
        switch (Т) {
        case T1:
        W = МассивТ1(dT);
        break;
        case T2:
        W = МассивТ2(dT);
        ...
        }
     
     
    Последнее редактирование: 8 июл 2019
  8. Ar4ik

    Ar4ik Нерд

    Спасибо за помощь, завтра попробую
    Спасибо за помощь, завтра попробую
     
  9. Daniil

    Daniil Гуру

    Есть двумерный массив W.
    Строка вычисляется по сухому термометру:
    i=round(Tc)-minTc;
    Разность температур столбца умноженная на 10 вычисляется по разности термометров:
    dТj=round(abs(Tc-Tv)*10);
    строки состоят из температур умноженных на 10:
    dt={5, 10, 15....};
    цикл n по столбцам:
    если (abs(dt(n)-dТj)<=5)
    {
    влажность равна = W(i,n);
    break; // нужно, чтобы цикл не по всем столбцам пробегал
    }
    меньше или равно, т.к. точное равенство во флоатах получить сложно, а округлять до 5-ти десятых неприятно.
    Кажется, я привел решение в интах.

    Главное, учесть выход за пределы массива
     
    Последнее редактирование: 8 июл 2019
  10. Daniil

    Daniil Гуру

    почему так сложно?:eek: Неизвестных 2 - Тс и dT, всё остальное, лишь константы для аппроксимации, которые можно занести/аппроксимировать заранее (tableCurve 2D/3D / excel / scilab / octave / др. мат. пакет в помощь)
     
  11. Как раз Tc и dT - известные, те аргументы. А табличные значения - реперные точки для построения полинома. Короче читайте Гугл - Полином Лагранжа. Но как сделать полином для двух аргументов я не в курсах честно говоря.
     
  12. Daniil

    Daniil Гуру

    Понял. Я обычно скармливаю tableCurve (платная, но удивительно простой комбайн. Скармливаете ей точки и она аппроксимирует огромным кол-вом ф-ий, выбирайте что хотите - линейные, логарифмические, полиномы, отношение полиномов, пользовательские... к каждому варианту вычисляется СКО) или scilab/octave'y (тут нужно написать кодик) и получаю поверхность или набор ф-ий.
     
  13. Сначала берутся две крайние точки. Построится линейная функция. Проверяются на допустимые отклонения. Если слишком - берут точку из середины. Получается ф-я второго порядка. Проверяется на отклонения. Останавливаются на том порядке, когда отклонения влезут в нужный предел. Но это для одного аргумента. Для двух - не в курсах.
     
  14. Ar4ik

    Ar4ik Нерд

    К сожалению не могу проверить скетч так как на работе, если сделать так, оно будет работать??

    Код (C++):
      int myarray[3][22] = {
                    {90,85,81,79,71,67,63,58,54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                    {90,85,81,77,72,68,64,59,55,51,47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                    {91,85,82,77,73,69,64,61,56,52,48,44,41, 0, 0, 0, 0, 0, 0, 0, 0, 0}
                            };
      int H;
      if(Tsuxoy==20 && dT==0.5){H=myarray[0][0];} //90%
      if(Tsuxoy==20 && dT==1.0){H=myarray[0][1];} //85%
      if(Tsuxoy==20 && dT==1.5){H=myarray[0][2];} //81%
      //.............

    lcd.setCursor(11,0);                      
    lcd.print("H= %");
    lcd.print(H);
     
  15. Daniil

    Daniil Гуру

    Знак "==" на флоатах очень плохо работать будет, а если dT=0.499(9)?
    Смысл расписывать каждый элемент массива через if? Можно, но будете писать долго.
    Мне кажется проще перевести Ts и dT в номера столбца и строки массива.
    Я выше писал, номер строки можно получить вычитанием из Тс числа 20 (минимальная Тс) и взять нужно целую часть.
    Пример:
    Тс=22.56.
    Тс-minTc=2.56
    индекс не может быть дробным, поэтому нужно округлять:
    round(Tc-minTc)=3 - 4ая строка (т.к счёт начинается от нуля).
    Аналогично по столбцам, только там шаг кратен 5, можно всё поделить на 5...
     
  16. Ar4ik

    Ar4ik Нерд

    Я как та собака, вроде понимаю как это сделать, но отобразить не могу, если Вам не трудно Даниил привидете пример для одного полинома, дальше я попробую сам
     
  17. Daniil

    Daniil Гуру

    Никаких полиномов - всё дискретно как ваша таблица.
    Код (C++):
    int myarray[3][22] = {
                    {90,85,81,79,71,67,63,58,54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                    {90,85,81,77,72,68,64,59,55,51,47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                    {91,85,82,77,73,69,64,61,56,52,48,44,41, 0, 0, 0, 0, 0, 0, 0, 0, 0}
                            };
                       
    #define minTsuxoy 20
    int Col, Row; //Номер колонки, номер столбца

    float Tsuxoy=getTsuxoy();//я не знаю как вы получаете Tsuxoy

    Row = round(Tsuxoy-minTsuxoy);//пример работы я уже расписывал

    float dT=getdT();//я не знаю как вы получаете dT

    Col = round(dt/5*10)-1;//примеры в спойлере ниже

      int H=myarray[Row][Col];
    Код (C++):
    //Пример dT=0.59; (мы должны получить нулевой столбей)
    //dT/5=0.118
    //dT/5*10=1.18
    //round(dt/5*10)=1
    //round(dt/5*10)-1 = 0 - что мы и хотели
    //Пример dT=1.59; (мы должны получить второй столбей)
    //dT/5=0.318
    //dT/5*10=3.18
    //round(dt/5*10)=3
    //round(dt/5*10)-1 = 2 - что мы и хотели
    На компилируемость не поверял, на правильность заполнения массивов не проверял. Я всегда путаюсь с массивами в программировании, где там указывается строка или столбец.
    Проверял только формулы получения Row и Col.
     
    Max_dk нравится это.
  18. Ar4ik

    Ar4ik Нерд

    Я так понял что дТ будет щитать только целые числа, а как же значение 0.5 , 1.5, ...... ведь там тоже есть значение относительной влажности.
     
  19. Ar4ik

    Ar4ik Нерд

    Ага я понял )) 0.5 это индекс 0, 1.0 это 1, 1.5 это 2, и тд ...
     
    Daniil нравится это.
  20. Ar4ik

    Ar4ik Нерд

    Код (C++):
      float Tsuxoy=tempSensor[0];
        float Tvlagniy=tempSensor[1];
        float dT=(Tsuxoy-Tvlagniy);
    Код (C++):
    DeviceAddress sensor1 = {0x28, 0x2E, 0x8D, 0x79, 0x97, 0x10, 0x03, 0xFB};
    DeviceAddress sensor2 = {0x28, 0x80, 0x11, 0x79, 0x97, 0x09, 0x03, 0x7C};
    void getTemp()
    {
       ds.requestTemperatures();  
       tempSensor[0] = ds.getTempC(sensor1);
       tempSensor[1] = ds.getTempC(sensor2);
    }[/code

    Вот так я получаю значение переменных Тс, Тв, дТ