Проблема в коде стандартного скетча датчика температуры DS18B20
- Войдите на сайт для отправки комментариев
Чт, 23/10/2014 - 09:53
Решил сделать термометр с датчиком DS18B20 и выводом температуры на три семисегментные индикаторы через CD4026, но возникли ошибки на самом первом этапе- подключенеи DS18B20.
Прошу помочь, так как в эотм деле совсем новичек
Плата Arduini nano v3.0.
программа arduino-1.0.6.
датчик подключаю по следующей схеме 
загружаю примеры DallasTemperature и OneWare, при компиляции выдает ошибку
Код из скетча:
#include <OneWire.h>
/*
* получаем температуру от DS18S20
*/
OneWire ds(10); // линия 1-Wire будет на pin 10
void setup(void)
{
Serial.begin(9600);
}
void loop(void)
{
byte i;
byte present = 0;
byte data[12];
byte addr[8];
if ( !ds.search(addr)) {
//Serial.print("No more addresses.\n");
ds.reset_search();
return;
}
/*Serial.print("R=");
for( i = 0; i < 8; i++) {
Serial.print(addr[i], HEX);
Serial.print(" ");
}*/
if ( OneWire::crc8( addr, 7) != addr[7]) {
Serial.print("CRC is not valid!\n");
return;
}
if ( addr[0] != 0x10) {
Serial.print("Device is not a DS18S20 family device.\n");
return;
}
ds.reset();
ds.select(addr);
ds.write(0x44,1); // запускаем конвертацию
delay(5000); // скорее всего достаточно 750ms
// we might do a ds.depower() here, but the reset will take care of it.
present = ds.reset();
ds.select(addr);
ds.write(0xBE); // считываем ОЗУ датчика
/*Serial.print("P=");
Serial.print(present,HEX);
Serial.print(" ");*/
for ( i = 0; i < 9; i++) { // обрабатываем 9 байт
data[i] = ds.read();
//Serial.print(data[i], HEX);
//Serial.print(" ");
}
/*Serial.print(" CRC=");
Serial.print( OneWire::crc8( data, 8), HEX);
Serial.println();*/
// высчитываем температуру :)
int HighByte, LowByte, TReading, Tc_100;
LowByte = data[0];
//Serial.print("LB= ");Serial.print(LowByte,HEX);
HighByte = data[1];
//Serial.print(" HB= ");Serial.print(HighByte,HEX);
TReading = (HighByte << 8) + LowByte;
Tc_100 = TReading/2;
Serial.print(" T = ");Serial.print(Tc_100);
Serial.println();
}
Прочтите https://www.google.ru/?gws_rd=ssl#newwindow=1&q=onewire.cpp:66:24
http://arduino.ru/forum/obshchii/problema-s-izmereniem-temperatury-ds18b...
Я пользовался такой библиотекой.
я тоже пользовался именно этой библиотекой, результат видите сами
Вам trembo уже дал ссылки на решение проблемы.
Всем спасибо за помощь)
Работает)

Достаточно среду до 1.5.* обновить :)
Непойму, что тут не так:
#include <OneWire.h> byte i; byte present = 0; byte type_s; byte data[12]; byte addr[8]; float celsius; byte address_1[8] = {0x28, 0x57, 0x93, 0xD7, 0x20, 0x00, 0x00, 0x84}; //1 tw byte address_2[8] = {0x28, 0x4D, 0xCB, 0xD7, 0x20, 0x00, 0x00, 0xBB}; //2 tb OneWire ds (9); int p; void loop() { //############OneWire################ p = 0; while(p<2) { if(ds.search(addr) != 1) { ds.reset_search(); delay(150); for(byte i = 0; i < 10; i++) addr[i] = 0; return; } ds.reset(); ds.select(addr); ds.write(0x44, 1); delay(750); present = ds.reset (); ds.select(addr); ds.write(0xBE); // Read Scratchpad for(i = 0; i < 10; i++) data[i] = ds.read (); unsigned int 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 << 3; // 9 bit resolution, 93.75 ms else if(cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms else if(cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms } celsius = (float)raw / 16.0; if (!memcmp(address_1, addr, 8)) { tw = celsius; } if (!memcmp(address_2, addr, 8)) { tb = celsius; } p++; //Serial.println(p); } Serial.print ("TW = "); Serial.print(tw); Serial.print ("TB = "); Serial.println(tb); //############OneWire################Этот кусок кода работал хорошо и правильно. Температура датчиков на стенде определялась корректно.
Потом собрал реальную схему. И работать перестало. Показывает температуру датчиков 195.00 и 444.00 градусов цельсия. Если этот код убрать и воспользоваться обычным с подключением библиотеки от даллас, то показывает корректно.
Что с этим кодом не так?
Библиотеку от далласа использовать не могу, с ней скетч занимает больше места. Если подключить другие датчики со стенда, то они и с этим кодом корректно работают. Почему этот код перестаёт работать, когда кабель длинный (15 метров)?
Sirocco,
1. ответ очевиден. Вы что-то неправильно сделали!
2. фрагмент программы рассматривать бессмымленно
3. непоятна цель программы и какой пример работает
4. в строке 22 ошибка: array index out of range
5. как подключено там, где не работает?
Перелопатил код. Работает. Только ооочень тормозит веб интерфейс, настолько, что невозможно использовать. Изернет шилд на 28j60 чипе
//#########---OneWire---############ #include <OneWire.h> byte i; byte present = 0; byte type_s; byte data[12]; byte addr[8]; float celsius; byte address_1[8] = {0x28, 0x57, 0x93, 0xD7, 0x02, 0x00, 0x00, 0x84}; //1 tw Temperature window Температура трубы окна byte address_2[8] = {0x28, 0x4D, 0xCB, 0xD7, 0x02, 0x00, 0x00, 0xBB}; //2 tb Temperature balcony Температура трубы балкона OneWire ds (9); // Шина OneWire на Pin 9 float tw = 0; //Temperature window Температура трубы окна float tb = 0; //Temperature balcony Температура трубы балкона int p; //переменная счётчика циклов получения данных от DS18B20 int m = 0; // Переменная считающая циклы массива //#########---OneWire---############ //#########---ARRAY---############ float thArray[10]={0,0,0,0,0,0,0,0,0,0}; // Массив ДОМ температура float hhArray[10]={0,0,0,0,0,0,0,0,0,0}; // Массив ДОМ Влажность float tsArray[10]={0,0,0,0,0,0,0,0,0,0}; // Массив УЛИЦА температура float hsArray[10]={0,0,0,0,0,0,0,0,0,0}; // Массив УЛИЦА Влажность float twArray[10]={0,0,0,0,0,0,0,0,0,0}; // Массив Temperature window Температуры трубы окна float tbArray[10]={0,0,0,0,0,0,0,0,0,0}; // Массив Temperature balcony Температуры трубы балкона long previousMillis = 0; // храним время изменения long interval = 3000; //интервал 20минут=1.200.000 19минут30сек=1.170.000 /10 = 117.000 //long interval = 117000; //почти 2 минуты float th_s = 0; //средние значения float hh_s = 0; float ts_s = 0; float hs_s = 0; float tw_s = 0; float tb_s = 0; //#########---ARRAY---############ //###############--DHT--################## #include <dht.h> dht dthStreet; dht dthHome; #define DHT_Street_PIN 3 #define DHT_Home_PIN 5 //###############--DHT--################## //###################--Ethernet--################### #include <UIPEthernet.h> byte mac[] = {0x00, 0x00, 0x00, 0xAB, 0xCD, 0xEA }; IPAddress ip(192,168,1,110); EthernetServer server(80); //###################--Ethernet--################### void setup() { Serial.begin (9600); //-----------Ethernet--------------- Ethernet.begin(mac, ip); server.begin(); //---------------------------------- } void loop() { //############OneWire################ p = 0; while(p<2) { if(ds.search(addr) != 1) { ds.reset_search(); delay(150); return; } for( i = 0; i < 8; i++) { } 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; // 9 bit resolution, 93.75 ms else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms } celsius = (float)raw / 16.0; if (!memcmp(address_1, addr, 8)) { tw = celsius; } if (!memcmp(address_2, addr, 8)) { tb = celsius; } p++; } Serial.print ("TW = "); Serial.println(tw); Serial.print ("TB = "); Serial.println(tb); //############OneWire################ //###############--DHT--################## int chkStreet = dthStreet.read22(DHT_Street_PIN); int chkHome = dthHome.read22(DHT_Home_PIN); Serial.print("DHT_Street, \t"); Serial.print(dthStreet.humidity, 1); Serial.print(",\t"); Serial.print(dthStreet.temperature, 1); Serial.print(",\t"); Serial.println(); Serial.print("DHT_Home, \t"); Serial.print(dthHome.humidity, 1); Serial.print(",\t"); Serial.print(dthHome.temperature, 1); Serial.print(",\t"); Serial.println(); //delay(1000); //###############--DHT--################## unsigned long currentMillis = millis(); if(currentMillis - previousMillis > interval) //проверяем не прошел ли нужный интервал, если прошел то { previousMillis = currentMillis; // сохраняем время последнего переключения //Serial.print(" m = "); //Serial.print(m); //Serial.println(" "); thArray[m] = dthHome.temperature; //пишем текушее значение температруры в массив "х" в ячейку с номером "m" hhArray[m] = dthHome.humidity; tsArray[m] = dthStreet.temperature; hsArray[m] = dthStreet.humidity; twArray[m] = tw; tbArray[m] = tb; m++; if(m>=10) { th_s = (thArray[0] + thArray[1] + thArray[2] + thArray[3] + thArray[4] + thArray[5] + thArray[6] + thArray[7] + thArray[8] + thArray[9])/ 10; hh_s = (hhArray[0] + hhArray[1] + hhArray[2] + hhArray[3] + hhArray[4] + hhArray[5] + hhArray[6] + hhArray[7] + hhArray[8] + hhArray[9])/ 10; ts_s = (tsArray[0] + tsArray[1] + tsArray[2] + tsArray[3] + tsArray[4] + tsArray[5] + tsArray[6] + tsArray[7] + tsArray[8] + tsArray[9])/ 10; hs_s = (hsArray[0] + hsArray[1] + hsArray[2] + hsArray[3] + hsArray[4] + hsArray[5] + hsArray[6] + hsArray[7] + hsArray[8] + hsArray[9])/ 10; tw_s = (twArray[0] + twArray[1] + twArray[2] + twArray[3] + twArray[4] + twArray[5] + twArray[6] + twArray[7] + twArray[8] + twArray[9])/ 10; tb_s = (tbArray[0] + tbArray[1] + tbArray[2] + tbArray[3] + tbArray[4] + tbArray[5] + tbArray[6] + tbArray[7] + tbArray[8] + tbArray[9])/ 10; Serial.print(" TH-S "); Serial.print(th_s); Serial.println(" "); Serial.print(" HH-S "); Serial.print(hh_s); Serial.println(" "); Serial.print(" TS-S "); Serial.print(ts_s); Serial.println(" "); Serial.print(" HS-S "); Serial.print(hs_s); Serial.println(" "); Serial.print(" TW-S "); Serial.print(tw_s); Serial.println(" "); Serial.print(" TB-S "); Serial.print(tb_s); Serial.println(" "); m = 0; } } /* //Serial.println("ARRAY +++++++++ "); //Serial.println("ARRAY +++++++++ "); Serial.print("["); Serial.print(twArray[0]); Serial.print("] "); Serial.print("["); Serial.print(twArray[1]); Serial.print("] "); Serial.print("["); Serial.print(twArray[2]); Serial.print("] "); Serial.print("["); Serial.print(twArray[3]); Serial.print("] "); Serial.print("["); Serial.print(twArray[4]); Serial.print("] "); Serial.print("["); Serial.print(twArray[5]); Serial.print("] "); Serial.print("["); Serial.print(twArray[6]); Serial.print("] "); Serial.print("["); Serial.print(twArray[7]); Serial.print("] "); Serial.print("["); Serial.print(twArray[8]); Serial.print("] "); Serial.print("["); Serial.print(twArray[9]); Serial.println("]"); //Serial.println("ARRAY +++++++++ "); */ //###################--Ethernet--################### EthernetClient client = server.available(); if (client) { boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); if (c == '\n' && currentLineIsBlank) { client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); client.println(); //========== Мгновенные значения ========================== client.print("{\"data\":{"); //Открываем тег для API [мгновенные значения датчиков] //=====DTH=HOME======= client.print("\"th\":"); client.print(dthHome.temperature, 1); client.print(","); client.print("\"hh\":"); client.print(dthHome.humidity, 1); client.print(","); //=====DTH=STREET===== client.print("\"ts\":"); client.print(dthStreet.temperature, 1); client.print(","); client.print("\"hs\":"); client.print(dthStreet.humidity, 1); client.print(","); //=====t window===== client.print("\"tw\":"); client.print(tw); client.print(","); //=====t balcon===== client.print("\"tb\":"); client.print(tb); client.println("}}"); //Закрываем тег для API [мгновенные значения датчиков] //========== Мгновенные значения ========================== //========== Усреднённые значения для БД ================== client.print("{\"mean\":{"); //Открываем тег для API [средние значения за 20 минут] client.print("\"th_s\":"); // client.print(th_s); //ДОМ ТЕМПЕРАТУРА среднее client.print(","); // client.print("\"hh_s\":"); // Serial.print(hh_s); //ДОМ ВЛАЖНОСТЬ среднее client.print(","); // client.print("\"ts_s\":"); // Serial.print(ts_s); //УЛИЦА ТЕМПЕРАТУРА среднее client.print(","); // client.print("\"hs_s\":"); // Serial.print(hs_s); //УЛИЦА ВЛАЖНОСТЬ среднее client.print(","); // client.print("\"tw_s\":"); // Serial.print(tw_s); //Temperature window Температура трубы окна СРЕДНЕЕ client.print(","); // client.print("\"tb_s\":"); // Serial.print(tb_s); //Temperature balcony Температуры трубы балкона СРЕДНЕЕ client.print(","); // client.print("}}"); //Закрываем тег для API [средние значения за 20 минут] //========== Усреднённые значения для БД ================== break; } if (c == '\n') { currentLineIsBlank = true; } else if (c != '\r') { currentLineIsBlank = false; } } } delay(150); client.stop(); } //###################--Ethernet--################### }Что-то для ускорения сделать можно?
Кстати, как тут избежать переполнения счётчика?
//========== Усреднённые значения для БД ================== client.print("{\"mean\":{"); //Открываем тег для API [средние значения за 20 минут] client.print("\"th_s\":"); // client.print(th_s); //ДОМ ТЕМПЕРАТУРА среднее client.print(","); // client.print("\"hh_s\":"); // client.print(hh_s); //ДОМ ВЛАЖНОСТЬ среднее client.print(","); // client.print("\"ts_s\":"); // client.print(ts_s); //УЛИЦА ТЕМПЕРАТУРА среднее client.print(","); // client.print("\"hs_s\":"); // client.print(hs_s); //УЛИЦА ВЛАЖНОСТЬ среднее client.print(","); // client.print("\"tw_s\":"); // client.print(tw_s); //Temperature window Температура трубы окна СРЕДНЕЕ client.print(","); // client.print("\"tb_s\":"); // client.print(tb_s); //Temperature balcony Температуры трубы балкона СРЕДНЕЕ client.print(","); // client.print("}}"); //Закрываем тег для API [средние значения за 20 минут] //========== Усреднённые значения для БД ==================Так правильно
Добрый день.
Если не трудно, то подскажите пожалуйста, одну меленькую вещь.
Хочу при помощи реле включать и выключать тёплый пол. То есть если темперетура упала ниже 22 включить, а если поднялась выше 25, то отключить.
Ести код
#include <OneWire.h> OneWire ds(10); // Подключаем датчик к 10 цифровому пину void setup(void) { Serial.begin(9600); pinMode(3, OUTPUT); } void loop(void) { byte i; 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; } // Проверяем не было ли помех при передаче if (OneWire::crc8(addr, 7) != addr[7]) { Serial.println("CRC is not valid!"); return; } Serial.println(); // Определяем серию датчика switch (addr[0]) { case 0x10: Serial.println(" Chip = DS18S20"); 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(1000); 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("Temp = "); Serial.print(celsius); Serial.print(" C, "); Serial.print(fahrenheit); Serial.println(" F"); // Если температура опускается до 22, то включаем реле if (celsius < 22) { digitalWrite(3, HIGH); } // Если температура подымается до 25, то ОТКЛЮЧАЕМ реле if (celsius > 25) { digitalWrite(3, LOW); } }Возникла проблема, что если происходит обрыв провода датчика или Arduino по каким-то причинам перестаёт видить датчик, то реле включается на постоянку вне зависимомти от температуры. Если кто знает как програмно можно решить данную проблему (чтобы при отказе датчика, обрыве провода и тд. реле выключалось независимо от того в каком положении оно было до этого, вкл или выкл.)?
За ранее большое спасибо за помощь.
У вас реле точно с неинвертированным управлением?
Чему равна переменная
celsiusпри отключении датчика?Вам следует выделить опрос датчика в отдельную функцию, и управлять реле, только если опрос был успешным. Так-же вам следует задать дефолтное состояние реле.
скорее всего при обрыве датчика показания выдают отрицательную температуру и согласно строке 89, включается реле.
Большое спасибо, что оветили на мой вопрос.
В обвязке реле есть перемычка при помощи которой можно делать реле с инвертированным или с неинвертированным управлением.
Сам я в програмировании не силён и код брал с сайта (теперь уже и не найду от куда). Сам я только дописал пару строк про реле. Я предпологая что переменная
celsiusпри отключении датчика будет равна 0. Если это не так, то поправте меня, пожалуйста.Подскажите, если не трудно, как выделить опрос датчика в отдельную функцию?
Я праильно понимая, для того чтобы задать дефолтное состояние реле, нужно вписать в код вот такие строчки (2-я и последняя):
#include <OneWire.h> #define RELE_1 3 OneWire ds(10); // Подключаем датчик к 10 цифровому пину void setup(void) { Serial.begin(9600); pinMode(RELE_1, OUTPUT); digitalWrite(RELE_1, HIGH);За ранее спасибо за помощь.
неинвертированное управление логически более понятное - видя в коде
digitalWrite(RELE_1, HIGH); интуитивно считаешь, что оно должно включиться.
Если использовать макросы (если реле всего одно) или выделенные функции (если их несколько), это вообще перестает быть проблемой - сразу видишь явную команду: RELAY_ON; или relay(FLOOR, ON); .
Насколько я понимаю, в данном случае "дефолтное состояние реле" - это состояние, в которое оно должно принудительно или самостоятельно возвращаться, если возникает какая-то нештатная ситуация (не читается датчик температуры в течение N минут, пропало питание и пр.).
То есть примерно так (не проверено, компилировать не на чем, главное смотри архитектуру):
#include <OneWire.h> // Определяем пороговые величины #define MIN_TEMP 22.0 // температура, при которой включаем реле #define MAX_TEMP 25.0 // температура, при которой отключаем реле #define ERR_TEMP -30.0 // показания, ниже которых считаем что датчик неисправен #define LIM_TEMP 45.0 // показания, выше которых начинаем паниковать #define MAX_ERRORS 3 // число допустимых подряд сбоев датчика #define TIMEOUT1 30 // максимальная длительность включения обогрева, мин // Задаем соответствие пинов #define ONEWIRE_PIN 10 // пин для подключения датчика температуры #define RELAY1_PIN 3 // пин для подключения реле #define ERROR_LED 13 // пин для подключения индикатора неисправности // Макросы и синонимы для удобства и читаемости кода #define HEAT1_ON digitalWrite(RELAY1_PIN, HIGH); // для инвертированного реле надо LOW #define HEAT1_OFF digitalWrite(RELAY1_PIN, LOW); // для инвертированного реле надо HIGH enum Error{NOT_FOUND = 111, CRC_ERROR = 112}; float tempValue; // текущая температура, либо код ошибки unsigned long lastTime; byte errorCounter; // счетчик ошибок сенсора boolean stopHeat; // флаг запрета включения обогрева OneWire ds(ONEWIRE_PIN); // подключаем датчик к шине OneWire void setup() { Serial.begin(9600); pinMode(RELAY1_PIN, OUTPUT); stopHeat = false; // разрешаем включение реле HEAT1_OFF; // принудительно выключаем обогрев // нужно ли? Serial.println("Ready.\n"); } void loop() { tempValue = getTemp(); // получаем показания температуры // Обрабатываем показания if (tempValue == NOT_FOUND || tempValue == CRC_ERROR) // ошибка датчика { Serial.println("NO DATA: Please check temp sensor."); errorCounter++; } else if (tempValue < ERR_TEMP) // неправильные показания { Serial.println("INVALID VALUE: Please check temp sensor."); errorCounter++; // сразу реле не выключаем, вдруг это разовый сбой } else if (tempValue < MIN_TEMP) // прохладный пол { Serial.println("Heat ON"); if (stopHeat = false) // если разрешено влючение реле { HEAT1_ON; lastTime = millis(); // запоминаем время включения } } else if (tempValue > MAX_TEMP) // горячий пол { Serial.println("Heat OFF"); HEAT1_OFF; } if (tempValue > LIM_TEMP) // очень горячий пол или пожар { Serial.println("ALARM!! Fire!!"); stopHeat = true; // запрещаем дальнейшее включение обогрева HEAT1_OFF; } if (errorCounter > MAX_ERRORS) // датчик сбоит n раз подряд { Serial.println("Sensor not responded"); HEAT1_OFF; } if ((millis() - lastTime) > TIMEOUT1 * 1000L * 60L) // если реле слишком долго включено { Serial.println("TIMEOUT! Heat OFF"); stopHeat = true; // запрещаем дальнейшее включение обогрева, до перезагрузки HEAT1_OFF; } if (errorCounter || stopHeat) // если есть признаки неисправности { digitalWrite(ERROR_LED, HIGH); // включаем индикацию ошибки } else { digitalWrite(ERROR_LED, LOW); } } // читаем датчик температуры, возвращает значение температуры или код ошибки float getTemp() { byte i; 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 NOT_FOUND; } // Проверяем не было ли помех при передаче if (OneWire::crc8(addr, 7) != addr[7]) { Serial.println("CRC is not valid!"); return CRC_ERROR; } Serial.println(); // Определяем серию датчика switch (addr[0]) { case 0x10: Serial.println(" Chip = DS18S20"); 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 NOT_FOUND; } ds.reset(); ds.select(addr); // Выбираем адрес ds.write(0x44, 1); // Производим замер, в режиме паразитного питания delay(750); //!! позже надо перейти на архитектуру обработки данных без delay 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("Temp = "); Serial.print(celsius); Serial.print(" C, "); //Serial.print(fahrenheit); //Serial.print(" F"); Serial.println(); errorCounter = 0; // сбрасываем счетчик ошибок, т.к. показания корректные return celsius; }Для полного забывания понятия 0 или 1 включает реле я обычно пишу так:
#define RelayON digitalWrite ( RELE_1 , LOW ) // если включаем нулём
или
#define RelayON digitalWrite ( RELE_1 , HIGH ) // если включаем единицей
Соответственно пишутся RelayOFF
Tomasina Большое спасибо за помощь. Сам бы я никогда не додумался до этого.
Скетч компелируется, но есть маленькое "но". Реле не переключается. То есть как оно стоит по умолчании вкл, так оно и остаётся вкл. при любой температуре. И постоянно горит дид на pin 13. В мониторе последовательного порта пишит:
NO DATA: Please check temp sensor.
был пропущен else :)
Попробуй, у меня работает.
#include <OneWire.h> // Задаем пороговые величины #define MIN_TEMP 22.0 // температура, при которой включаем реле #define MAX_TEMP 25.0 // температура, при которой отключаем реле #define ERR_TEMP -30.0 // показания, ниже которых считаем что датчик неисправен #define ALARM_TEMP 45.0 // показания, выше которых начинаем паниковать #define MAX_ERRORS 3 // число допустимых подряд сбоев датчика #define TIMEOUT_HEAT1 30 // максимальная длительность включения обогрева, мин // Задаем соответствие пинов #define ONEWIRE_PIN 10 // пин для подключения датчика температуры #define RELAY1_PIN 3 // пин для подключения реле #define ERROR_LED 13 // пин для подключения индикатора неисправности // Макросы и синонимы для удобства и читаемости кода #define HEAT1_ON digitalWrite(RELAY1_PIN, HIGH); // для инвертированного реле надо LOW #define HEAT1_OFF digitalWrite(RELAY1_PIN, LOW); // для инвертированного реле надо HIGH enum Error{NOT_FOUND = 111, CRC_ERROR = 112}; float tempValue; // текущая температура, либо код ошибки unsigned long lastTime; byte errorCounter; // счетчик ошибок сенсора boolean stopHeat1; // флаг запрета включения обогревателя #1 OneWire ds(ONEWIRE_PIN); // подключаем датчик к шине OneWire void setup() { Serial.begin(9600); pinMode(RELAY1_PIN, OUTPUT); stopHeat1 = false; // разрешаем включение реле #1 HEAT1_OFF; // принудительно выключаем обогреватель #1 при сбое по питанию Serial.println("Ready.\n"); } void loop() { tempValue = getTemp(); // получаем показания температуры // Обрабатываем показания if (tempValue == NOT_FOUND || tempValue == CRC_ERROR) // ошибка датчика { Serial.println("NO DATA: Please check temp sensor!"); errorCounter++; } else if (tempValue < ERR_TEMP) // неправильные показания { Serial.println("INVALID VALUE: Please check temp sensor!"); errorCounter++; // сразу реле не выключаем, вдруг это разовый сбой } else { Serial.print("Temp = "); // выводим показания Serial.print(tempValue); Serial.print(" C\t\t"); if (tempValue < MIN_TEMP) // прохладный пол, надо включить обогреватель { Serial.println("Heat ON"); if (stopHeat1 = false) // если разрешено влючение реле { HEAT1_ON; // включаем реле lastTime = millis(); // запоминаем время включения } } else if (tempValue > ALARM_TEMP) // очень горячий пол или пожар { Serial.println("ALARM!! Fire!!"); stopHeat1 = true; // запрещаем дальнейшее включение обогрева HEAT1_OFF; } else if (tempValue > MAX_TEMP) // пол уже достаточно теплый, надо отключить обогреватель { Serial.println("Heat OFF"); HEAT1_OFF; } else if (tempValue > MIN_TEMP && tempValue < MAX_TEMP) // температура в заданных рамках { Serial.println("Comfortable"); } } if (errorCounter > MAX_ERRORS) // датчик сбоит n раз подряд { Serial.println("Sensor not responded"); HEAT1_OFF; } if ((millis() - lastTime) > TIMEOUT_HEAT1 * 1000L * 60L) // если реле слишком долго включено { Serial.println("Timeout! Power down for Heater#1"); stopHeat1 = true; // запрещаем дальнейшее включение обогрева, до перезагрузки HEAT1_OFF; } if (errorCounter || stopHeat1) // если есть признаки неисправности { digitalWrite(ERROR_LED, HIGH); // включаем индикацию ошибки } else { digitalWrite(ERROR_LED, LOW); } } // читаем датчик температуры, возвращает значение температуры или код ошибки float getTemp() { byte i; 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 NOT_FOUND; } // Проверяем не было ли помех при передаче if (OneWire::crc8(addr, 7) != addr[7]) { Serial.println("CRC is not valid!"); return CRC_ERROR; } Serial.println(); // Определяем серию датчика switch (addr[0]) { case 0x10: Serial.println(" Chip = DS18S20"); 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 NOT_FOUND; } ds.reset(); ds.select(addr); // Выбираем адрес ds.write(0x44, 1); // Производим замер, в режиме паразитного питания delay(800); //!! позже надо перейти на архитектуру обработки данных без delay 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; errorCounter = 0; // сбрасываем счетчик ошибок, т.к. показания корректные return celsius; }По умолчанию оно выкл (если прямое управление) или вкл (если инвертированное управление).
Tomasina, Огромное спасибо за помощь.
Не могли бы Вы немного пояснить что значит строчка 19 (
enumError{NOT_FOUND = 111, CRC_ERROR = 112};).А то у меня по какой-то причине постоянно идёт ошибка и диод на 13 pine моргает с частотой раз в секунду. Из-за чего реле не включается. В мониторе последовательного порта
Chip = DS18B20
enumError{NOT_FOUND = 111, CRC_ERROR = 112};).если датчик не найден (строка 119), то функция возвращает число 111 вместо реальной температуры, а NOT_FOUND - это всего лишь текстовый синоним этого числа, для удобочитаемости кода (через полгода фиг вспомнишь, что означает 111, а с синонимом нагляднее).
Попробуй закомментировать строку 125, где return.
Tomasina, Болшое спасибо, что не оставляете вопросы без ответа.
Когда закомпелировал строку 125, ничего не изменилось.
По прежнему реле проходит "один цикл" (то есть реле включается при температуре ниже 22, потом выключается при темперетуре больше 25, и потом больше не включается вообще). Диод на pin 13 моргает с частотой раз в секунду. В мониторе последовательного порта показывается правильная температура и в зависимости от температуры пишится "Heat OFF" или "Heat ON". Но реле не включается.
В чём может быть причина?
Если не трубно, то дайте ответ, пожалуйста.
Спасибо.