вещь называется интерполяция, самый простой вариант - линейная. находишь первое число в массиве значений i которого больше чем температура термометра (и соответствующее ему значение крепости) и берешь предыдущую пару i-1 потом по формуле %i - %i-1 / Ti-1 - Ti считаешь прирост крепости на градус цельсия в диапазоне от i-1 до i и добавляешь к первому значению крепости дельту температуры умноженой на прирост крепости: %текущее = %i-1 + (Tтекущее - Тi-1)*прирост крепости (только по знакам смотри, могу нахомутать че и с минусом значения будут)
_k0t_
Бакалавр
Санкт-Петербург
56 22
Отв.981 07 Окт. 14, 00:07 (через 24 мин)
2Брагин Спасибо. Я правильно понял, мне нужен только этот кусок кода?
int Term []={782,962,961,785,942,932,790,918,892,795,901,854,800,877,787,805,863,733,810,850,677,815,838,619,820,828,569,825,818,516,830,810,481,835,802,440,840,793,403,845,784,374,850,772,340,855,761,312,860,750,290,865,736,265,870,724,245,875,714,229,880,695,206,885,684,194,890,677,185,895,658,166,900,646,156,905,637,148,910,612,131,915,594,120,920,575,110,925,558,101,930,537,93,935,516,85,940,492,77,945,466,69,950,438,62,955,415,54,960,383,47,965,342,40,970,300,33,975,255,27,980,207,21,985,158,15,990,112,10,995,47,3,100,0,0,50,100,100};
float spirt (float TempIn, int mode) { //TempIn -входная температура, mode - 0 -пар, 1-жидкость int temp=TempIn*10; if (temp<=781) {TempOut=100.0;} else { int p=0; do { if (mode==0) {TempOut=((float)Term[p+1])/10;} else {TempOut=((float)Term[p+2])/10;} p=p+3 ; } while (temp>=Term[p]); } return TempOut; }
lcd.print(spirt);
Кстати, в этом скетче удобно спрятано меню инициализации датчиков DS18B20 а то как проедешь мимо, так и сбились все датчики, а тут отдельно.
PS: не понял, как потом выводить символ градус Цельсия?
svarnoy
Профессор
Жуковский.
9.3K 4.6K
Отв.982 07 Окт. 14, 11:39
_k0t_, На лабспирте тему глянь http://labspirt.com/forum/index.php/topic,2403.0.html Вот формула оттуда без интерполяции: "Короче вот формула, она конечно тоже не самая простая, но легко встраивается в программирование.
К%мас - удалено,т.к. было сделано по "не очень правильным" таблицам)))
К%об = 16,75 - 19,05 * Ti + 12,64 * Ti ^ 2 - 3,69 * Ti ^ 3 - 0.38 * Ti ^ 4
Где Ti = ( t[град] - 89,03 ) / 6,54
Где t[град] - температура где угодно (где кипит спиртосодержащая жидкость) в градусах Цельсия.
Пользуйтесь. И для гурманов - восьмая степень . К%об = 17,26 - 18,32 * Ti + 7,81 * Ti ^ 2 - 1,77 * Ti ^ 3 +4,81 * Ti ^ 4 - 2,95 * Ti ^ 5 - 1,43 * Ti ^ 6 + 0,8 * Ti ^ 7 + 0,05 * Ti ^ 8 Где Ti = ( t[град] - 89 ) / 6,49" Автор наш форумчанин mekkaod Я давно сравнивал реальные показания термометра при разной спиртуозности,эту формулу,и калькулятор "руди",Формула кривовато считала,потом за темой не следил.
_k0t_
Бакалавр
Санкт-Петербург
56 22
Отв.983 07 Окт. 14, 14:34
Вроде разобрался, забыл: 1. переменную еще нужно определить - float TempOut ; 2. lcd.print(spirt(T[1],0)); так вроде нужно выводить спирт в струе? 3. lcd.createChar(0,degc); - записать символ С° Пошел пробовать. Спасибо за помощь.
makМодератор
Екатеринбург
6.3K 1.8K
Отв.984 07 Окт. 14, 14:38 (через 5 мин)
формула местами не точно считает, да и тяжелые там вычисления поэтому гораздо проще с табличными значениями работать делал такой термометр на атмега8 - если что есть алгоритм, но писал там в CV не для ардуинки хотя адаптировать несложно, если что - в личку
сообщение удалено
Брагин
Магистр
Краснодар
278 76
Отв.985 07 Окт. 14, 19:48
_k0t_, все верно градус цельсия объявлен первым символом в наборе. проверь по куркуляторам, вроде правду показывает. lcd.print(spirt(T[1],0)) 0 -пар, 1 -куб. если есть желание можно добавить таблицу с точностью до 0.25 градуса, если не лень. полином с восьмой степенью считать не советую, памяти еще много - проще таблицу увеличить чем загрузить МК. ему подсчета средневыпрямленного итак хватает... это ж не 8 ядер интела. формат наверное понял (градус, температура 1, температура 2.Г.Т1.Т2...) снизу вверх. значения умножены на 10 - что б использовать таблицу с целыми числами - я так думаю и места в памяти меньше занимают и быстрее считать. а на 10 умножить\поделить уже в программе
_k0t_
Бакалавр
Санкт-Петербург
56 22
Отв.986 07 Окт. 14, 19:58 (через 11 мин)
Да, вроде понял с данными в массиве. Сегодня погонял, потестил: в среднем получается врет на 5% в бОльшую сторону. Чтобы поправить, нужно переделывать весь массив, как я понимаю? Да, и наверно было бы не плохо, еслиб: spirt >= 96, то отображать на экране, например: n/a. 100 как-то глаза режет )
makМодератор
Екатеринбург
6.3K 1.8K
Отв.987 07 Окт. 14, 21:23
Я когда оптимизировал размещение в памяти, целую часть в один массив байтовый, дробную в другой )) Так каждое число всего 2 байта занимает
_k0t_
Бакалавр
Санкт-Петербург
56 22
Отв.988 08 Окт. 14, 20:27
Опять прошу помощи, не могу разобраться, в чем проблема? Вот в в аттаче скетч, который я использую, будет время, посмотрите, пожалуйста. Проблема вот в чем: Все работает, но при запуске программы фракционной дистилляции происходит следующее: 1. Не срабатывает сигнал и не программа переходит на следующий шаг после отбора голов. 2. То же самое с хвостами. Срабатывает только сигнал при переполнении емкости, когда поднят поплавок, и при окончании дистилляции. Самое интересное: если заново запустить программу, когда датчики показывают температуру больше 88 - программа моментально проходит все шаги, с сигнализацией и остановкой на смену тары.
Иногда глючат показания датчиков температуры, на короткое время может показать и >20000 градусов. Вроде и раньше они глючили, но программа раньше проходила все шаги постепенно. Может я что-то не так сделал? Очень прошу помощи у Брагина т.к.программа его и ему будет легче разобраться. Заранее огромное спасибо.
я ничего не понял с системой поплавка, фракции три, а вход один. и если окончание фракции определять по поплавку и переход на следующий шаг то делать это следует в строчках if (!is_h && Step==0) {Step++;} if (!is_b && Step==1) {Step++;}
или если поплавок переставляеться с банки на банку то лепить надо в if (T[1] > Th && Step==0) {Stop=4; tone(buzzer, 1000, 500); delay(200);tone(buzzer, 2000, 1000);} // отобрали головы if (T[1] > Tb && Step==1) {Stop=4; tone(buzzer, 2000, 500);delay(200); tone(buzzer, 1000, 5000);} // отобрали тело типа такого if (T[1] > Th && Step==0) {Stop=4; tone(buzzer, 1000, 500); delay(200);tone(buzzer, 2000, 1000);} // отобрали головы if (P4==0 && Step==0) {Stop=3; tone(buzzer, 1000, 500); delay(200);tone(buzzer, 2000, 1000);} // поплавок поднят, головы if (T[1] > Tb && Step==1) {Stop=4; tone(buzzer, 2000, 500);delay(200); tone(buzzer, 1000, 5000);} // отобрали тело if (P4==0 && Step==1) {Stop=3; tone(buzzer, 1000, 500); delay(200);tone(buzzer, 2000, 1000);} // поплавок поднят, хвосты
НО для помощи с логикой работы надо описать логику работы однозначно, без догадок
_k0t_
Бакалавр
Санкт-Петербург
56 22
Отв.990 08 Окт. 14, 23:28
Поплавок у меня только для определения полноты сосуда. Нет возможности поставить большую емкость, поэтому при срабатывании поплавка я просто меняю посуду. При этом не важно, какой шаг программы выполняется. Видимо я сделал не правильно, и у меня после срабатывания поплавка сбрасывается переменная step? Мне нужно, чтобы после того, как сработал поплавок, программа продолжила с момента срабатывания поплавка, не важно, какая фракция при этом отбиралась. Головы, - значит продолжить дальше отбирать головы, тело - так тело. Спасибо за помощь.
Брагин
Магистр
Краснодар
278 76
Отв.991 09 Окт. 14, 00:04 (через 36 мин)
попробуй за строчками case 5: lcd.print("water leakage"); break;
case 6: lcd.print("overheating"); break;
}
if (butPush == 2) {Stop=0; Menu(0);} if (butPush == 4) {Stop=0; running=1; Step++; Menu(0);}
добавить
if (butPush == 5) {Stop=0; running=1; Menu(0);}
по идее будет стоять, а продолжение банкета с этого же шага, но по кнопке "вниз"
все я спать
_k0t_
Бакалавр
Санкт-Петербург
56 22
Отв.992 09 Окт. 14, 00:36 (через 32 мин)
Спасибо. Завтра я на работу, а послезавтра обязательно попробую. Но то что это из-за поплавка - точно, я проверил. Кинул поплавок рядом, чтобы он не срабатывал, и вся программа прошла успешно. Попробую потом по кнопке вниз с добавлением этой строчки. Аппаратная платформа Arduino для автоматизации наших процессов. Автоматика.
_k0t_
Бакалавр
Санкт-Петербург
56 22
Отв.993 12 Окт. 14, 14:46
Добрался до аппарата только сегодня, все проверил, Брагину спасибо, все работает. Потом, если не будет лень, добавлю конструкцию if-else при нажатии кнопки "вправо". Наверно нужно будет еще какой нибудь "флаг" организовывать, на срабатывания поплавка. Ну то есть: если флаг - 0 - то step++, если 1 - тогда нет.
2014-10-27-417. Аппаратная платформа Arduino для автоматизации наших процессов. Автоматика.вот такой конструктив.В деле пока не пробовал, на столе работает отлично.Твёрдотельное реле без радиатора, не знаю как поведёт себя с 1.5 квт
zZombie
Магистр
Msk
293 71
Отв.996 28 Окт. 14, 16:15 (через 42 мин)
отлично! компоновку внутрЕ покажи.
msg31
Научный сотрудник
Барнаул
4.6K 2.5K
Отв.997 28 Окт. 14, 17:25
Твёрдотельное реле без радиатора, не знаю как поведёт себя с 1.5 квтLVit, 28 Окт. 14, 15:34
Перегреется и сгорит.
LVit
Специалист
город на Даугаве
134 60
Отв.998 28 Окт. 14, 20:15
Этто понятно что сгорит, посмотрю как греться будет, выключу если что. Внутрянку сфотаю завтра