Здравствуйте . Нашел код который почти подходит под мои требования ,единственная проблема что мне надо что бы реле выключалось при минус 15 гр . Если поставить как в оригинальном коде плюсовую температуру то все отрабатывает нормально . Поместив датчик в холодильную камеру и поправив в конце кода на минус 1 ,то в мониторе порта показывает минусовую температуру но реле не срабатывает .Оригинальный код можно посмотреть тут http://zelectro.cc/dallas-18b20 Код (C++): #include <OneWire.h> OneWire ds(10); void setup(void) { Serial.begin(9600); pinMode(3, OUTPUT); digitalWrite(3, LOW); } void loop(void) { byte i; byte present = 0; byte type_s; byte data[12]; byte addr[8]; float celsius, fahrenheit; if ( !ds.search(addr)) { Serial.println("No more addresses."); Serial.println(); ds.reset_search(); delay(250); return; } Serial.print("ROM ="); for( i = 0; i < 8; i++) { Serial.write(' '); Serial.print(addr[i], HEX); } if (OneWire::crc8(addr, 7) != addr[7]) { Serial.println("CRC is not valid!"); return; } Serial.println(); // the first ROM byte indicates which chip switch (addr[0]) { case 0x10: Serial.println(" Chip = DS18S20"); // or old DS1820 type_s = 1; break; case 0x28: Serial.println(" Chip = DS18B20"); type_s = 0; break; case 0x22: Serial.println(" Chip = DS1822"); type_s = 0; break; default: Serial.println("Device is not a DS18x20 family device."); return; } ds.reset(); ds.select(addr); ds.write(0x44, 1); delay(5000); present = ds.reset(); ds.select(addr); ds.write(0xBE); Serial.print(" Data = "); Serial.print(present, HEX); Serial.print(" "); for ( i = 0; i < 9; i++) { data[i] = ds.read(); Serial.print(data[i], HEX); Serial.print(" "); } Serial.print(" CRC="); Serial.print(OneWire::crc8(data, 8), HEX); Serial.println(); int16_t raw = (data[1] << 8) | data[0]; if (type_s) { raw = raw << 3; if (data[7] == 0x10) { raw = (raw & 0xFFF0) + 12 - data[6]; } } else { byte cfg = (data[4] & 0x60); if (cfg == 0x00) raw = raw & ~7; else if (cfg == 0x20) raw = raw & ~3; else if (cfg == 0x40) raw = raw & ~1; } celsius = (float)raw / 16.0; fahrenheit = celsius * 1.8 + 32.0; Serial.print(" Temperature = "); Serial.print(celsius); Serial.print(" Celsius, "); Serial.print(fahrenheit); Serial.println(" Fahrenheit"); if (celsius>-1){ digitalWrite(3, LOW); //Turn on relay }else{ digitalWrite(3, HIGH); //Turn off relay } Serial.print(celsius); }
для celsius тип указан корректно - float. Напишите своими словами какой реакции вы ждете от условия Код (C++): if (celsius > - 1 )
Нет, это означает , что реле включится по достижении температуры 0, и выше, т.е. +1, +2, +3 и т.д. Причем только по целым, без учета десятых. И обратного выключения реле при понижении температуры ниже ноля тоже не будет. P.S. реле включается каким сигналом - HIGH или LOW?
разобрался . сейчас работает , поправить надо так if (celsius>-1){ digitalWrite(3, LOW); //Turn on relay }else{ digitalWrite(3, HIGH); //Turn off relay } Serial.print(celsius); }
если LOW, то почти правильно. Код (C++): #define RELAY 9 #define ON LOW #define OFF HIGH ... if (celsius < -1.0) digitalWrite(RELAY, ON); //Turn on relay else digitalWrite(RELAY, OFF); //Turn off relay
Может ком пригодится . Прикрутил еще экран что бы видеть температуру . Код (C++): #include <DallasTemperature.h> #include <OneWire.h> #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27,16,2); #define ONE_WIRE_BUS 10 OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); OneWire ds(10); void setup(void) { lcd.init(); lcd.backlight(); sensors.begin(); pinMode(3, OUTPUT); digitalWrite(3, HIGH); Serial.begin(9600); } void loop(void) { byte i; byte present = 0; byte type_s; byte data[12]; byte addr[8]; float celsius ,fahrenheit; if ( !ds.search(addr)) { Serial.println(); ds.reset_search(); delay(750); return; } for( i = 0; i < 8; i++) if (OneWire::crc8(addr, 7) != addr[7]) ds.reset(); ds.select(addr); ds.write(0x44, 1); delay(750); present = ds.reset(); ds.select(addr); ds.write(0xBE); for ( i = 0; i < 9; i++) { data[i] = ds.read(); } int16_t raw = (data[1] << 8) | data[0]; if (type_s) { raw = raw << 3; if (data[7] == 0x10) { raw = (raw & 0xFFF0) + 12 - data[6]; } } else { byte cfg = (data[4] & 0x60); if (cfg == 0x00) raw = raw & ~7; else if (cfg == 0x20) raw = raw & ~3; else if (cfg == 0x40) raw = raw & ~1; } celsius = (float)raw / 16.0; fahrenheit = celsius * 1.8 + 32.0; Serial.print(" Temperature = "); Serial.print(celsius); Serial.print(" Celsius, "); sensors.requestTemperatures(); lcd.setCursor(0, 0); lcd.print(sensors.getTempCByIndex(0)); lcd.print(" C "); //выставляем нужную температуру if (celsius> 23 ){ digitalWrite(3, LOW); }else{ digitalWrite(3, HIGH); } }
осталоcь избавиться от delay(750), чтобы МК мог параллельно что-то еще делать. Все через это проходили И еще ошибка: у тебя при старте инициализируются две сущности: Код (C++): OneWire oneWire(ONE_WIRE_BUS); OneWire ds(10); а дальше в коде используется только ds
Спасибо ,сейчас глянем что сделать ,,как раз хочу добавить сюда 2 модуля протечки ,еще один ds и сим800л для информации . Проблема пока встала не могу узнать адрес 2 датчика ds и прикрутить к нему реле (что бы один датчик отвечал за одно реле .второй за другое ). сколько находил примеров все датчики на одном пине и по адресам (хотя для моих задачь можно и 2 пина использовать )
Еще нубский вопрос . Разобрался как узнать адрес датчика ds18b20 , подобрав подходящий код для 2 датчиков с выводом на экран я столкнулся с проблемой работы реле (не отрабатывает как в верхнем коде ,просто срабатывает и все ). Пните в нужном направлении .куда капать что бы реле работало как в предыдущем коде . Код (C++): #include <OneWire.h> #include <DallasTemperature.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27,16,2); OneWire oneWire(10); // вход датчиков 18b20 DallasTemperature ds(&oneWire); DeviceAddress sensor1 = {0x28, 0xF2, 0x21, 0x08, 0x00, 0x00, 0x80, 0xA7}; DeviceAddress sensor2 = {0x28, 0xE6, 0xBD, 0x3B, 0x05, 0x0, 0x0, 0xCF}; void setup() { // Serial.begin(9600); ds.begin(); pinMode(3, OUTPUT); digitalWrite(3, HIGH); lcd.init(); lcd.backlight(); } void loop() { ds.requestTemperatures(); // считываем температуру с датчиков lcd.setCursor(0, 0); lcd.print("Sensor 1: "); lcd.print(ds.getTempC(sensor1)); // отправляем температуру lcd.print("C"); lcd.setCursor(0, 1); lcd.print("Sensor 2: "); lcd.print(ds.getTempC(sensor2)); lcd.print("C"); if (sensor1> 23 ){ digitalWrite(3, LOW); }else{ digitalWrite(3, HIGH); } }
Код (C++): if (sensor1 > 23 ) потому что sensor1 - это адрес датчика (массив из 8 чисел), а 23 - это просто одно число. Сравниваешь несравнимое. Из предыдущего скетча куда-то пропала куча переменных. Потерялась по дороге? ds.requestTemperatures нельзя постоянно дергать (сейчас у тебя он вызывается несколько сот раз в секунду, а надо не менее 750 мс между вызовами).
Вырезал ) учусь помаленьку ,где просто методом народного тыка ,где программным путем ) кстати обрезанный скетч отрабатывает как мне нужно ,но захотелось еще прикрутить датчик с реле вот и полез в дебри . Спасибо что помогаете ) добавить delay(750) ?
Если посмотришь внимательно, то ты заметишь, что в верхнем примере ты для начала обозначил тип переменной отвечающей за хранение значения температуры потом из кельвинов преобразовал её в Цельсии И только после этого сравнивал с уставкой в последнем примере этого нет
if (ds.getTempC(sensor1)> 23 ){ digitalWrite(3, LOW); }else{ digitalWrite(3, HIGH); } добавил и заработало (более 23 градусов реле включается ) как и в верхнем скетче . надо протестировать еще на минусовой температуре (тз такое )
даю скелет правильной архитектуры программы: Код (C++): #define RELAY_PIN 3 // пин реле #define DS_PIN 9 // пин датчиков температуры #define LEAK1_PIN A0 // пин сенсора влажности float temperature1; // переменная для хранения данных с датчика температуры float temperature2; // переменная для хранения данных с датчика температуры unsigned int leak1; // переменная для хранения данных с сенсора протечки unsigned int leak2; // переменная для хранения данных с сенсора протечки const float maxTemperature1 = 42.0; // порог срабатывания для реле. Значение float всегда должно указываться с точкой, а не целое число const unsigned int sensUpdInterval = 800; // интервал обновления датчиков, мс void setup() { pinMode(LED_BUILTIN, OUTPUT); // активируем светодиод на плате Serial.begin(9600); } void loop() { static unsigned long sensLastUpd = 0; // переменная для хранения времени последнего обновления датчиков if (millis() - sensLastUpd >= sensUpdInterval) // если прошло больше 800 мс { sensLastUpd = millis(); // запоминаем время чтения сенсоров digitalWrite(LED_BUILTIN, HIGH); // показываем, что обращаемся к датчикам - включаем LED на плате readTemperature(); // считываем показания датчиков температуры readLeakage(); // считываем показания сенсоров протечки displayUpdate(); // выводим показания на ЖК serialUpdate(); // выводим показания в консоль delay(100); // временно, для отладки. Потом убрать digitalWrite(LED_BUILTIN, LOW); // отключаем LED } // здесь пихаем код, не требующий задержек (чтение кнопок и пр.) setRelay(); // управляем реле } void setRelay() { if (temperature1 > maxTemperature1) digitalWrite(RELAY_PIN, LOW); else digitalWrite(RELAY_PIN, HIGH); } void readTemperature() { static boolean updateNow = true; if (updateNow);// ds.requestTemperatures(); // даем команду на замер температуры else { temperature1 = ds.getTempC(sensor1)); // считываем температуру с датчиков temperature2 = ds.getTempC(sensor2)); } updateNow = !updateNow; } void readLeakage() { leak1 = analogRead(LEAK1_PIN); //leak2 = analogRead(LEAK2_PIN; } void displayUpdate() { lcd.setCursor(0, 0); lcd.print("Sensor 1: "); // и т.д. } void serialUpdate() { Serial.print("Temperature #1: "); Serial.print(temperature1); // и т.д. } Это только база, как сейчас есть - работать не будет (надо вписать пины, добавить библиотеки и пр.) Принцип простой - не надо сваливать все в кучу, каждый модуль (в скетче это функции void) должен отвечать только за свою работу: температура - отдельно, влажность - отдельно, дисплей - отдельно, реле - отдельно. Когда программа построена модульно - из "кубиков" - ее легче понять и обслуживать (вставить готовый кубик в новую программу)