Проблема в коде стандартного скетча датчика температуры DS18B20

makler_tsk
Offline
Зарегистрирован: 23.10.2014

Решил сделать термометр с датчиком 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();
}

 

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011
Radjah
Offline
Зарегистрирован: 06.08.2014

Я пользовался такой библиотекой.

makler_tsk
Offline
Зарегистрирован: 23.10.2014

я тоже пользовался именно этой библиотекой, результат видите сами

Araris
Offline
Зарегистрирован: 09.11.2012

Вам trembo уже дал ссылки на решение проблемы.

makler_tsk
Offline
Зарегистрирован: 23.10.2014

Всем спасибо за помощь)

Работает)

Radjah
Offline
Зарегистрирован: 06.08.2014

Достаточно среду до 1.5.* обновить :)

Sirocco
Offline
Зарегистрирован: 28.09.2013

Непойму, что тут не так:

#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 метров)?

toc
Offline
Зарегистрирован: 09.02.2013

Sirocco,
1. ответ очевиден. Вы что-то неправильно сделали!
2. фрагмент программы рассматривать бессмымленно
3. непоятна цель программы и какой пример работает
4. в строке 22 ошибка: array index out of range
5. как подключено там, где не работает?

Sirocco
Offline
Зарегистрирован: 28.09.2013

Перелопатил код. Работает. Только ооочень тормозит веб интерфейс, настолько, что невозможно использовать. Изернет шилд на 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--###################

    

}

Что-то для ускорения сделать можно? 

Кстати, как тут избежать переполнения счётчика?

Sirocco
Offline
Зарегистрирован: 28.09.2013
//========== Усреднённые значения для БД ==================
         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 минут]
//========== Усреднённые значения для БД ==================

Так правильно

DenLiss
Offline
Зарегистрирован: 26.04.2015

Добрый день.

Если не трудно, то подскажите пожалуйста, одну меленькую вещь.

Хочу при помощи реле включать и выключать тёплый пол. То есть если темперетура упала ниже 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 по каким-то причинам перестаёт видить датчик, то реле включается на постоянку вне зависимомти от температуры. Если кто знает как програмно можно решить данную проблему (чтобы при отказе датчика, обрыве провода и тд. реле выключалось независимо от того в каком положении оно было до этого, вкл или выкл.)?

За ранее большое спасибо за помощь.

 

 

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

У вас реле точно с неинвертированным управлением?

Чему равна переменная celsius при отключении датчика?

Вам следует выделить опрос датчика в отдельную функцию, и управлять реле, только если опрос был успешным. Так-же вам следует задать дефолтное состояние реле.

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

скорее всего при обрыве датчика показания выдают отрицательную температуру и согласно строке 89, включается реле.

DenLiss
Offline
Зарегистрирован: 26.04.2015

Большое спасибо, что оветили на мой вопрос.

В обвязке реле есть перемычка при помощи которой можно делать реле с инвертированным или с  неинвертированным управлением.

Сам я в програмировании не силён и код брал с сайта (теперь уже и не найду от куда). Сам я только дописал пару строк про реле. Я предпологая что переменная 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);

 

За ранее спасибо за помощь.

 

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

неинвертированное управление логически более понятное - видя в коде
 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;
}

 

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Для полного забывания понятия 0 или 1 включает реле я обычно пишу так:

#define RelayON  digitalWrite ( RELE_1 ,  LOW ) // если включаем нулём
или
#define RelayON  digitalWrite ( RELE_1 , HIGH ) // если включаем единицей

Соответственно пишутся  RelayOFF

DenLiss
Offline
Зарегистрирован: 26.04.2015

 Tomasina Большое спасибо за помощь. Сам бы я никогда не додумался до этого.

Скетч компелируется, но есть маленькое "но". Реле не переключается. То есть как оно стоит по умолчании вкл, так оно и остаётся вкл.  при любой температуре. И постоянно горит дид на pin 13. В мониторе последовательного порта пишит:

NO DATA: Please check temp sensor.

ALARM!! Fire!!
TIMEOUT! Heat OFF
 
  Chip = DS18B20
S18B20
Temp = 24.12 C, 
TIMEOUT! Heat OFF
No more addresses.
 
NO DATA: Please check temp sensor.
ALARM!! Fire!!
TIMEOUT! Heat OFF
 
  Chip = DS18B20
 
 
В чём причина разобратся не могу. Ели вдруг у Вас будет свободное время, может посмотрите вчём причина.
 
За ранее спасибо.
 
 

 

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

был пропущен 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;
}

По умолчанию оно выкл (если прямое управление) или вкл (если инвертированное управление).

DenLiss
Offline
Зарегистрирован: 26.04.2015

Tomasina, Огромное спасибо за помощь.

Не могли бы Вы немного пояснить что значит строчка 19 (enum Error{NOT_FOUND = 111, CRC_ERROR = 112};).

А то у меня по какой-то причине постоянно идёт ошибка и диод на 13 pine моргает с частотой раз в секунду. Из-за чего реле не включается. В мониторе последовательного порта 

  Chip = DS18B20

Temp = 22.81 C Comfortable
No more addresses.
 
NO DATA: Please check temp sensor!
 
  Chip = DS18B20
Temp = 22.81 C Comfortable
No more addresses.
 
С железом всё в порядке (реле, датчик и тд), проверял на простеньком скетче.
 
Очень блогодарен за помощь.

 

 

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

DenLiss пишет:
 что значит строчка 19 (enum Error{NOT_FOUND = 111, CRC_ERROR = 112};).

если датчик не найден (строка 119), то функция возвращает число 111 вместо реальной температуры, а NOT_FOUND - это всего лишь текстовый синоним этого числа, для удобочитаемости кода (через полгода фиг вспомнишь, что означает 111, а с синонимом нагляднее).

Попробуй закомментировать строку 125, где return.

DenLiss
Offline
Зарегистрирован: 26.04.2015

Tomasina, Болшое спасибо, что не оставляете вопросы без ответа.

Когда закомпелировал строку 125, ничего не изменилось.

По прежнему реле проходит "один цикл" (то есть реле включается при температуре ниже 22, потом выключается при темперетуре больше 25, и потом больше не включается вообще). Диод на pin 13 моргает с частотой раз в секунду. В мониторе последовательного порта показывается правильная температура и в зависимости от температуры пишится "Heat OFF" или "Heat ON". Но реле не включается.

В чём может быть причина?

Если не трубно, то дайте ответ, пожалуйста.

Спасибо.