Прошу вашей помощи, не могу разобраться, как правильно записать условие для выполнения данной задачи. В наличии два датчика 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"); // Выводим текст }
Я если честно не силен, но всячески пытаюсь в этом разобраться. Я бы хотел что бы контроллер по формуле сам считал дТ , что он и делает и на основании этой дельты мне на экран выводил значение относительной влажности. Я пробовал датчик влажности и температуры DHT22, но он через чур чувствителен к резким изменениям, да и показывает чушь, если сравнивать DHT22 с эталонным психометрическим гигрометром который прошел поверку
Не, ну и в чем проблема ? Задайте двумерный массив и занесите в него из таблицы. Около 400 значений. Влезет. Или вы хотите по таблице вывести формулу и воткнуть ее в расчет ? Тогда придется выполнить математическую работу по решению полинома с 400 неизвестными. Или 20 отдельных полиномов с 20 неизвестными. Весьма непростая затея. Хотя может в Гугле найдется сервис такого рода. ПС. Может в Экселе есть готовый макрос для этого ?!
Если бы я знал как это сделать я бы не обращался за помощью. Не проблема занести 400 символов, проблема как правильно написать это условие.
Условие чего ? Как вывести формулу ? Университетский курс. Полином Лагранжа (вроде так). Влажность = Массив(T, dT) Справочник Ардуины че там про массивы (arrays) говорит ? Кстати щас сам гляну... ПС. Если двумерный массив не проглотит, сделайте 20 одномерных и выбирайте по Код (C++): switch (Т) { case T1: W = МассивТ1(dT); break; case T2: W = МассивТ2(dT); ... }
Есть двумерный массив 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-ти десятых неприятно. Кажется, я привел решение в интах. Главное, учесть выход за пределы массива
почему так сложно? Неизвестных 2 - Тс и dT, всё остальное, лишь константы для аппроксимации, которые можно занести/аппроксимировать заранее (tableCurve 2D/3D / excel / scilab / octave / др. мат. пакет в помощь)
Как раз Tc и dT - известные, те аргументы. А табличные значения - реперные точки для построения полинома. Короче читайте Гугл - Полином Лагранжа. Но как сделать полином для двух аргументов я не в курсах честно говоря.
Понял. Я обычно скармливаю tableCurve (платная, но удивительно простой комбайн. Скармливаете ей точки и она аппроксимирует огромным кол-вом ф-ий, выбирайте что хотите - линейные, логарифмические, полиномы, отношение полиномов, пользовательские... к каждому варианту вычисляется СКО) или scilab/octave'y (тут нужно написать кодик) и получаю поверхность или набор ф-ий.
Сначала берутся две крайние точки. Построится линейная функция. Проверяются на допустимые отклонения. Если слишком - берут точку из середины. Получается ф-я второго порядка. Проверяется на отклонения. Останавливаются на том порядке, когда отклонения влезут в нужный предел. Но это для одного аргумента. Для двух - не в курсах.
К сожалению не могу проверить скетч так как на работе, если сделать так, оно будет работать?? Код (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);
Знак "==" на флоатах очень плохо работать будет, а если dT=0.499(9)? Смысл расписывать каждый элемент массива через if? Можно, но будете писать долго. Мне кажется проще перевести Ts и dT в номера столбца и строки массива. Я выше писал, номер строки можно получить вычитанием из Тс числа 20 (минимальная Тс) и взять нужно целую часть. Пример: Тс=22.56. Тс-minTc=2.56 индекс не может быть дробным, поэтому нужно округлять: round(Tc-minTc)=3 - 4ая строка (т.к счёт начинается от нуля). Аналогично по столбцам, только там шаг кратен 5, можно всё поделить на 5...
Я как та собака, вроде понимаю как это сделать, но отобразить не могу, если Вам не трудно Даниил привидете пример для одного полинома, дальше я попробую сам
Никаких полиномов - всё дискретно как ваша таблица. Код (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.
Я так понял что дТ будет щитать только целые числа, а как же значение 0.5 , 1.5, ...... ведь там тоже есть значение относительной влажности.
Код (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 Вот так я получаю значение переменных Тс, Тв, дТ