Два датчика DS18b20 и вывод на Lcd
- Войдите на сайт для отправки комментариев
Приветствую форумчан.
Задумал автоматизировать свое аквахозяйство на предмет контроля темпиратур воды и радиаторов светодиодных сборок а также включений самих сборок (без диммирования) и подачи Со2.
Для начала прикупил 2560R3 с Ali тамже IIC/I2C/TWI/SPI Serial Interface Board к 4-х стрчному дисплею (как потом выяснилось что библиотек к нему найти ой ка как непросто) релюшки и даллас-датчики. Пока жду часики для Ардуино решил с реле незаниматсья а выводить темпиратуры. Почитав форумы понял что датчики можно подключать паралельно и в мониторе найти их адреса. Все получилось и выводится в окне мониторинга порта. Однако при выводе на дисплей я получаю только одну темпиратууру которая выводится в оба поля для t1 и t2. Библотек неприлагаю, так как вопрос исключительно теоретический. Где я упустил код? Собственно вот скетчик
#include <Wire.h> #include <LiquidCrystal_I2C.h> #include <OneWire.h> LiquidCrystal_I2C lcd(0x27,20,4); int TSensorPin = 10; OneWire ds(TSensorPin); //-------------------------------------------------------------- void setup() { digitalWrite(TSensorPin,HIGH); Wire.begin(); lcd.init(); lcd.setBacklight(1); lcd.clear(); lcd.setCursor(0, 0); lcd.print("Temp. Controller"); lcd.setCursor(0, 1); lcd.print(" v1.0 "); delay(5000); lcd.clear(); lcd.setCursor(0, 1); lcd.print("t1="); lcd.setCursor(10, 1); lcd.print("t2="); } //-------------------------------------------------------------- void loop() { float temp = getTemp(); float temp2 = getTemp(); lcd.setCursor(3, 1); lcd.print(temp); lcd.setCursor(13, 1); lcd.print(temp2); } //-------------------------------------------------------------- float getTemp() { byte data[12]; byte addr[8]; if ( !ds.search(addr)) { lcd.setCursor(0, 0); lcd.print("NO more addrss!"); ds.reset_search(); return -1001; } if ( OneWire::crc8( addr, 7) != addr[7]) { lcd.setCursor(0, 0); lcd.print("CRC is not valid!"); return -1002; } if ( addr[0] != 0x10 && addr[0] != 0x28) { lcd.setCursor(0, 0); lcd.print("NOT recognizd!"); return -1003; } ds.reset(); ds.select(addr); ds.write(0x44,1); byte present = ds.reset(); ds.select(addr); ds.write(0xBE); for (int i = 0; i < 9; i++) { data[i] = ds.read(); } ds.reset_search(); byte MSB = data[1]; byte LSB = data[0]; float TRead = ((MSB<<8) | LSB); float Temperature = TRead / 16; return Temperature; }
Функция getTemp() честно возвращает при каждом вызове температуру первого датчика, все правильно. Для работы с несколькими датчиками есть два пути:
1. Сложный - считывать адреса всех датчиков, сидящих на пине, и обращаться затем к конкретному датчику за температурой.
2. Простой - второй датчик посадить на другой пин и сделать что-то типа
int TSensorPin1 = 10; int TSensorPin2 = 11;
OneWire ds1(TSensorPin1); OneWire ds2(TSensorPin2); , и далее работать с ds1 и ds2.
Второй я уже немного пробовал, однако решил все-же их на ОДНОМ пине пользовать. Вот таким счетчиком вывожу в монтор порта:
#include <Wire.h>
#include <OneWire.h>
#include <LiquidCrystal_I2C.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 10
OneWire oneWire(ONE_WIRE_BUS);
LiquidCrystal_I2C lcd(0x27,20,4);
DallasTemperature sensors(&oneWire);
DeviceAddress Thermometer1 = {
0x28, 0xF2, 0x29, 0xEB, 0x05, 0x00, 0x00, 0xE1 }; //адрес датчика DS18B20 28F229EB050000E1
DeviceAddress Thermometer2 = {
0x28, 0x86, 0x48, 0xEA, 0x05, 0x00, 0x00, 0xF6 }; //адрес датчика DS18B20 288648EA050000F6
void setup() {
Wire.begin();
sensors.begin();
sensors.setResolution(Thermometer1, 10);
sensors.setResolution(Thermometer2, 10);
lcd.init();
lcd.setBacklight(1);
Serial.begin(9600);
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("t1=");
lcd.setCursor(10, 1);
lcd.print("t2=");
}
void printTemperature(DeviceAddress deviceAddress) {
float tempC = sensors.getTempC(deviceAddress);
Serial.println(tempC);
lcd.setCursor(3, 1);
lcd.print(tempC);
}
void loop() {
sensors.requestTemperatures();
Serial.print("Temp1 ");
printTemperature(Thermometer1);
Serial.print("Temp2 ");
printTemperature(Thermometer2);
}
Паузы - кто делать будет? Зачем Вам нужна температура с частотой процессора? :) Это на считая того, что там всякие глюки начинают вылезать при частом считывании.
Эммм, признаться я полнейший пока "нуль" поэтому если незатруднит покажите что куда добавить. Однако я заметил что вывод значений во вторм моем скетче выглядит "жоско". И по сути - как же выводить второй датчик на дисплей по первому скетчуц (если возможно). Дальше то нужно будет использовать это значение для определния порога срабатывания реле. Дисплей по большому счёту нужен чисто номинально, однако сним намного всё нагляднее.
Господа подскажите-же куда добавить строки вида. Каждый датчик на своем пине можно но хочу имеено на одном. Весь инет перерыл - нетолько форум, никто невыводит таким образом. Даже в самомй популярной статейке http://arduino-project.net/podklyuchenie-ds18b20-arduino/ внизу коментарий один единственный с вопросом тоже без ответа.
Если делать хорошо и правильно, надо ваять цикл, сравнивающий текущее значение millis() с заданием таймаута опроса.
Попробовал сделать так:
В итоге темпиратура выводится на оба t1 и t2 однако показания снова равные, и вывод идет сначала первого датчика затем второго, :)
Попробовал сделать так:
В итоге темпиратура выводится на оба t1 и t2 однако показания снова равные, и вывод идет сначала первого датчика затем второго, :)
А зачем Вы все бездумно выносите в одну функцию? Сделайте сначала обычным текстом и для каждого датчика отдельно. Потом будете код оптимизировать...
япросто ЛОГИЧЕСКИ немогу понять ПОЧЕМУ в COM- порт выводится все прекрасно и с задержкой между показаниями а на экран иначе. Я так понимаю что получили тмпиратуру с первого t1 -вывели в порт, получили с освторого T2 -вывели. Почему же на LCD выводится только одно значение потом второе/
Кстати последний мой кусочек кода из стандартного ПРИМЕРА уже - я решил его использовать для понимания, но и тут несмог.
япросто ЛОГИЧЕСКИ немогу понять ПОЧЕМУ в COM- порт выводится все прекрасно и с задержкой между показаниями а на экран иначе.
Экран надо принудительно перерисовывать. Выведите два значения в одну строку, но чтобы у каждого было свое знако-место - увидите. Хотя нет, у Вас ошибка в том, что Вы два раза печатаете одну и ту же переменную
tempC
... А надо - принять от двух датчиков два разных значения в две разные переменные. Или в массив, но в разные позиции элементов.Всё, я сдался. Посадил два датчика на разные пины. Создал
int TSensorPin1 = 10;
int TSensorPin2 = 11;
OneWire ds(TSensorPin);
OneWire ds2(TSensorPin2);
Далее
//----------Вывод температуры на ЖК--------------
float temp = getTemp();
float temp2 = getTemp();
lcd.setCursor(3, 1);
lcd.print(temp);
lcd.setCursor(13, 1);
lcd.print(temp2);
Что мне поправить здесь:
Функции надо передавать адрес термометра. На т о она и функция, что как молоток лежит до поры, до времени, а потом Вы его берете и стучите куда надо.
Почитайте даташит на DS18 (есть на русском Чернова.Г.), поймете как работать с ним и с шиной.
попробуй так. у меня все работало
http://arduino.ru/forum/apparatnye-voprosy/ds18b20-pokazyvaet-127#commen...
попробуй так. у меня все работало
http://arduino.ru/forum/apparatnye-voprosy/ds18b20-pokazyvaet-127#commen...
Ну что сказать, ОГРОМНОЕ спасибо - ничего несказать, всё просто и доступно. Я понимаю МЕГА-Гуру с++ пытаются нам дать удочку а не рыбу, все правильно ОДНАКО - я сделал один проект с помощью или без, да и забыл. Парни ну неужели просто нельзя было "написать" или скопипастить в конце концов правильное решение :)
Я к чему, ниже код и благодаря jeka_tm всё пучком завелось и выводится и в порт и на дисплей. Как привязать значения термодатчиков к реле - другая задумка.
пожалуйста. тебе помогали люди. но порой мозг просто отказывается понимать, никак не укладывается в голове как ни пытаясь разобраться. по деталям вроде знаешь, а целой картины не получается
или понимаешь вроде все, а код неправильно работает. накололся недавно с радиомодулями
тогда проще дать кусок кода если он есть и писать с нуля не надо
Кстати а какой параметр в моем коде задает периоличность опроса темпиратуры и вывод его в (порт и дисплей). А также что задает размер значения температуры после запятой, с моим первым кодом значения значения были вида 25,06......25,12........25,18 тоесть с "точностью" до 0,06 град (хотя сам датчик не точнее 0,5 град вроде :) ) а сейчас 25,00....25,25.....25,50.....
Пока писал вопрос про время замеров temp пробежал по коду и нашёл.
Я добавил вот такой кусочек кода для отклонения темпиратуры от заданного (чтобы была некая инертность):
А также обработку для реле такой вот кусочек:
Теперь хочу, в установленное время подать на вход драйвера PT4115 (восьмая ножка) самый низкий уровень ШИМ,с пина к примеру 25 ардуинки , затем Включить одним из реле (всего их будет штук восемь) одну из трёх линий (подать напряжение на 10 штук 10Вт сборок) и спустя к примеру 10 секи далее поднимать его до значения 255 как я понял это будет соответствовать максимуму горения. Тоесть хочу максимально обесточить все светодиоды (зачем диммировать их если освещение к примеру вообще ненужно, правильно? )
Все это сделать с небольшим сдвигом для остальных двух. Под сдвигом я понимаю некоторую разницу на включений сборок от задней стенки к передней или от центра. Тоесть сделать некоторое подобие SunSet (расссвет - закат).
Пока я попробовал самый простой пример, взял пример из скетча про Fade (Изменяем яркость светодиода) и тупо через резистор в 1Ком подал с 11 пина на вход димвхода драйвера светоиода. Получилось, потому как при >0,5В начинает драйвер закрыватсья а при более 2,5В ток через светодиод максимален. Код правда сильно простой да и пробовал я это всё без использования часов а по условию. Ну это уже думаю создать другую ветку в форуме. Всем спасибо, кто пытался достучаться до меня и кто помогал. Всем добра.
а тут что получилось? должно быть приблизительно также
полградуса это очень точно. рэле может будет часто щелкать если система не инертна, например бак с водой и водонагревателем сильно инертная система
а керамический резистор ватт на 5 гораздно меньше, хоть и не мгновенно нагревается
можно почитать про пид регулятор
периодичность задаешь ты, но вот время на измерение задано в коде 1000 в функции DS18B20()
можно уменьшить до 750, по даташиту максимальное время измерения с максимальной точностью, насколько помню
хотя для интереса опрашивал каждые 100мс, разницы не заметил, просто смысла так часто опрашивать нет если датчик все равно новое значение температуры выдаст черзе 750мс
При постоянном опросе идет нагрев самого датчика. Точность у него 0,06 градуса, а допустимая погрешность 0,5.
Вот мой скетч для вывода температуры на LCD (два датчика на одной ноге)
Я новичок,изучаю Arduino первый день,поэтому не пинайте сильно за код,главное он работает и может кому пригодится.
//скетч от Александра
#include //Подключаем библиотеку для работы с LCD
#include
#include //Подключаем библиотеку датчика температуры
#define ONE_WIRE_BUS 9
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2); // инициализируем LCD, указывая управляющие контакты
OneWire OneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&OneWire);
DeviceAddress Thermometer1 = {
0x28, 0xC6, 0x28, 0xEB, 0x05, 0x00, 0x00, 0x1D }; // адрес первого датчика DS18B20
DeviceAddress Thermometer2 = {
0x28, 0xBE, 0x83, 0xEB, 0x05, 0x00, 0x00, 0x67 }; // адрес второго датчика DS18B20
void setup() {
sensors.begin();
sensors.setResolution(Thermometer1, 5);
sensors.setResolution(Thermometer2, 5);
Serial.begin(9600);
lcd.begin(16, 2);// задаем размерность дисплея
lcd.print("Bo" "\xE3" "a"); // выводим на дисплей ВОДА
lcd.setCursor(0, 1); // печатаем вторую строку
lcd.print("Ka" "\xBD" "a" "\xBB" "\xB8\xC7"); // выводим на дисплей КАНАЛИЯ
lcd.setCursor(8, 0); // печатаем вторую строку
lcd.print("ON");
lcd.setCursor(8, 1); // печатаем вторую строку
lcd.print("OFF");
}
// Задаём функцию для первого датчика и выводим на экран
void printTemperature(DeviceAddress deviceAddress) {
float tempC = sensors.getTempC(deviceAddress );
Serial.println(tempC);
lcd.setCursor(12, 0);
lcd.print(tempC);
delay (100);
}
//Задаём функцию для второго датчика и выводим на экран
void printTemperature2(DeviceAddress deviceAddress) {
float tempC = sensors.getTempC(deviceAddress );
Serial.println(tempC);
lcd.setCursor(12, 1);
lcd.print(tempC);
delay (100);
}
void loop() {
sensors.requestTemperatures();
Serial.print("Sensor1 ");
printTemperature(Thermometer1);
Serial.print("Sensor2 ");
printTemperature2(Thermometer2);
}
Уважаемые прошу вашей помощи, использую распространенный скетч
на дисплее отображается температура с сотыми частями, необходимо выводить только целое число.
заранее благодарен!!!
Используй
подскажите пожалуйста куда его вставлять) пока слабоват в програмировании
до смешного дошло, изменил позицию выводимой информации, теперь все в правом углу (21°С), но хотелось бы по правильному решить проблему!!!
Без округлений: lcd.print(переменная, 0);
Правда 25,9 будет равно 25. Можете просто перед выводом плюсовать 0,5.
можно так ещё без стремной библиотеки даллас
Огромное спасибо всем, кто здесь обитает. Благодаря Вам, оптимизировал под себя вывод температуры с 2-х датчиков ds18b20на LCD 1602
упростил скетч до минимума и вот что у меня получилось:
Извиняюсь, не знаю как убрать под кат.
У меня все это работает на связке ESP8266 NodeMCU + 2 DS18B20+LCD1602_I2C
Подскажите, кто знает, как в последнем скетче выводить на LCD1602 не сотые, а десятые доли градуса?
В 50 строке поменял
(
float
)raw / 16.0
на(
float
)raw / 10.0
, но на экране LCD сотые доли отображаются как нули, но мне надо убрать именно эти нули.спасибо заранее.
Подскажите, кто знает, как в последнем скетче выводить на LCD1602 не сотые, а десятые доли градуса?
В 50 строке поменял
(
float
)raw / 16.0
на(
float
)raw / 10.0
, но на экране LCD сотые доли отображаются как нули, но мне надо убрать именно эти нули.спасибо заранее.
вы офигели? вам не пришло в голову. что если поменять
(
float
)raw / 16.0
на(
float
)raw / 10.0 -
датчик будет выдавать совершенно неверные значения?? - математику в школе прогуливали?Изменение количества цифр, выводимых на дисплей - настраивается в коде дисплея, а не в коде получения температуры с датчика. Например так:
lcd.print(temperature, 1);
вы офигели? вам не пришло в голову. что если поменять
(
float
)raw / 16.0
на(
float
)raw / 10.0 -
датчик будет выдавать совершенно неверные значения?? - математику в школе прогуливали?lcd.print(temperature, 1);
Благодаря b707 удалось вывести на LCD температуру с датчиков до десятых долей градуса.
вот кусок измененного кода:
Если нужны сотые, написать двойку, а тысячные, тройку и т.д.
Если нужны сотые, написать двойку, а тысячные, тройку и т.д.
и главное - на этот вопрос в ветке вы уже отвечали 10 сообщениями выше :)
Если нужны сотые, написать двойку, а тысячные, тройку и т.д.
и главное - на этот вопрос в ветке вы уже отвечали 10 сообщениями выше :)
Хм, и впрямь. Что делать, в башке уже только локальные переменные умещаются, да и те без статика.))))
Если нужны сотые, написать двойку, а тысячные, тройку и т.д.
Предлагаю четвёрку - точность сразу будет в десятитысячных!
Про пятёрку я вообще молчу......
А что не так? Мне на ректификаторе в коллоне три знака отображает (можно два, но и четыре для него допустимо), а в баке и целых значений достаточно.