18b20 не стабильно работает -127

Jink
Offline
Зарегистрирован: 24.09.2019

Доброго времени суток коллеги. Уже не первый год воюю с датчиками 18b20. Что на esp8266 что на разных ардуинах, проблема все та же. Периодически при замере температуры датчики выдают -127. В данный момент у меня два устройства для экспериментов. ESP в качестве датчика умного дома. На ней висит два датчика на одном проводе. Питание полноценное но 3.3, что посути в норме. Подтяжка стоит 4.7к. Провод в сумме 2 метра (витая пара). Периодически, примерно раз в 10 замеров, проскакивают приславутые -127. Скетч сейчас показать не могу, но он основан на примерах библиотеки DallasTemperature. Задержки на опрос прописаны в самой библиотеке, но я сам добавляю задержку две секунды. Результата ноль. Приходится фильтровать результаты.

Второе устройство, это контроллер твердотопливного котла. В коде прописано два датчика 18b20 и одна термопара. 18b20 стоят на разных пинах. Но имею все ту же проблему. Периодически -127. Экспериментировал с разной точностью датчика, разными задержками, все без толку. Причем алгоритм таков, что контроллер термопарой меряет температуру дымохода и в зависимости от нее шимом тормозит вентилятор, чтоб не перестарался, когда тяга ещё плохая. а при перегреве вентилятор отключается при помощи реле. Так вот что я заметил. ошибки чаще выскакивают когда дымоход холодный. Хотя термопара ж к 18б20 никакого отношения не имеет. И плюс включение вентилятора тоже добавляет вероятность ошибок. 

И третье, если запустить симуляцию этого кода в протеусе, там почти постоянно -127.

Вот сам код:


#include "max6675.h"

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display

#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS_1 13
#define ONE_WIRE_BUS_2 12

OneWire oneWire_in(ONE_WIRE_BUS_1);
OneWire oneWire_out(ONE_WIRE_BUS_2);


DallasTemperature sensor_in(&oneWire_in);
DallasTemperature sensor_out(&oneWire_out);

#define pump 8
#define air 2
#define fan 9 

int thermoDO = 4;
int thermoCS = 5;
int thermoCLK = 6;

int pipe;
int pipemax = 105;
int pipemin = 40;

int waterneed = 55;
int waterin;
float waterout;
float wateroutt;
int error;

int fanspeed = 0;
byte fans;
boolean rejim;
int regulator;

MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);





void setup() {
  lcd.init();  
   // Print a message to the LCD.
  lcd.backlight();
  lcd.setCursor(3,0);
  lcd.print("Kotel Kontrol");
  lcd.setCursor(5,1);
  lcd.print("V k3.0");
   lcd.setCursor(3,2);
  lcd.print("Powered by:");
   lcd.setCursor(6,3);
  lcd.print("Jink");
  
  delay (2000);
  // use Arduino pins 
  pinMode(pump, OUTPUT); digitalWrite(pump, HIGH);
  pinMode(air, OUTPUT); digitalWrite(air, HIGH);
   pinMode(fan, OUTPUT); analogWrite (fan, 255);
  
  // wait for MAX chip to stabilize
  delay(500);
  sensor_in.begin();
    sensor_out.begin();
sensor_in.setResolution(9);
    sensor_out.setResolution(9);

   lcd.clear();
   rejim = false;
   error = 0;
}

void loop() {
    
   pipe = thermocouple.readCelsius(); 
   delay (200);
  
     if (pipe >= pipemax) {
     digitalWrite(air, HIGH);
     }
   
     if (pipe <= pipemax-10 && waterout <= waterneed-2) {
     digitalWrite(air, LOW);
     }
   
   fans = map(pipe, -10, 300, 180,50);
   analogWrite (fan, fans);
   
   sensor_in.requestTemperatures();
   sensor_out.requestTemperatures();
  
   
   waterin = sensor_in.getTempCByIndex(0);    
   wateroutt = sensor_out.getTempCByIndex(0);

   if (wateroutt > -50){
    waterout = wateroutt;
    error = 0;
    }
    else {
      error ++;
      while (error >= 180) {
        digitalWrite(air, HIGH);
        DispUpdate();
        }
      }


    if (waterout >= 30 && pipe >= 50 ) {
      rejim = true;
      }

  if (rejim == true && pipe <= 25 && waterout <= 26  ) {
         while (1 ) {
      digitalWrite(air, HIGH);
      digitalWrite(pump, LOW);
      lcd.clear();
  
   lcd.setCursor(0,0);
  lcd.print("PUSTO");

  delay (10000);
  
      }
      } 
      
      if (waterout >= waterneed+1) {
      digitalWrite(air, HIGH);
      }
      if (waterout <= waterneed-2 && pipe <= pipemax-20) {
      digitalWrite(air, LOW);
      }

      regulator = analogRead (A1);
      waterneed = map(regulator, 0, 1023, 35,70);
   
   DispUpdate();  //Функция обновления дисплея
}



void DispUpdate(void) //Функция обновления дисплея
{

  lcd.clear();
   
   lcd.setCursor(0,0);
  lcd.print("pipe ");
  lcd.print(pipe);

 lcd.setCursor(11,0);
  lcd.print("rejim ");
  lcd.print(rejim);

   lcd.setCursor(0,1);
  lcd.print("fans ");
  lcd.print(fans);

    lcd.setCursor(0,2);
  lcd.print("out ");
  lcd.print(waterout);
  lcd.setCursor(10,2);
   lcd.print("er ");
  lcd.print(error);

   lcd.setCursor(0,3);
  lcd.print("need");
  lcd.print(waterneed);
  
}

 

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

#define DEVICE_DISCONNECTED_C -127

Это строка из     DallasTemperature.h

MaksVV
Offline
Зарегистрирован: 06.08.2015

опрашивать датчики так, и всё будет гуд

byte DSaddress[] = {0x28, 0xFF, 0xA6, 0x19, 0xA8, 0x15, 0x01, 0xD2};  // адрес датчика ds18b20
#include <OneWire.h>
OneWire ds(2);   // далласы на 2 пин 


int Temper = 20;

void setup()
{

}


void loop()
{
Temperature ();  
  
// тут остальной код  
  
}




void Temperature () { 
  static uint32_t lasttime = 0;
     if (millis() - lasttime>5000)
{
     static boolean p=0; // флаг работы: запрос температуры или её чтение
   p=!p;
   if (p) {ds.reset();      // сброс шины
           ds.write(0xCC);  // обращение ко всем датчикам
           ds.write(0x44);  // начать преобразование (без паразитного питания)  
          }
       else   
      {
 
        int Temper_= 20;  byte buff[9];
        ds.reset();
        ds.select(DSaddress);    
        ds.write(0xBE); // Read Scratchpad (чтение регистров)  
        for (byte j = 0; j<9; j++) buff[j]= ds.read(); //читаем все 9 байт от датчика 
        ds.reset();
        if (OneWire::crc8(buff, 8) == buff[8]){        // если контрольная сумма совпадает
        Temper_ =  buff[0] | (buff[1]<<8);             // читаем температуру из первых двух байт (остальные были нужны для проверки CRC)
        Temper_ = Temper_ / 16;
        if  (Temper_ < 150 && Temper_ > -50 && Temper_ !=85 && Temper_!=-127)  Temper =  Temper_;
                 
                                              }
                                                      
      }
lasttime = millis();
}
   }

 

Jink
Offline
Зарегистрирован: 24.09.2019

trembo пишет:

#define DEVICE_DISCONNECTED_C -127

Это строка из     DallasTemperature.h


Это то понятно. Но датчик то работает. Ошибка появляется раз из десяти замеров.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Jink пишет:
trembo пишет:

#define DEVICE_DISCONNECTED_C -127

Это строка из     DallasTemperature.h

Это то понятно. Но датчик то работает. Ошибка появляется раз из десяти замеров.

а с какой частотой ты его др.чишь?

Jink
Offline
Зарегистрирован: 24.09.2019

Спасибо за код. Вечером буду у котла попробую. Только при проверке допишу, чтоб ошибки посчитало. Вот только хочется универсальности. Не хочу привязываться к конкретному датчику. Есть как то возможность как у меня привязаться к пину, с горячей заменой датчика?

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

Я давно делал соседу погодный регулятор для котла.
Мерял раз в 5 секунд с усреднением по десяти измерениям.
Естественно всякие случайные -127, если они были, срезались сразу.
И естественно не 12 битный режим.

Jink
Offline
Зарегистрирован: 24.09.2019

Вообще особо роли не играет. Хоть раз в секунду, хоть раз в пять минут. Пробовал по всякому. Грешу всеже на библиотеку даллас темприче. Вечером попробую без нее. С ней просто удобный код получается. Да и в ней задержки по даташиту прописанны. Проверял.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Jink пишет:
Не хочу привязываться к конкретному датчику. Есть как то возможность как у меня привязаться к пину, с горячей заменой датчика?

есть.  только даччик должен быть на проводе один.  при чтении даешь команду SkipROM и читаешь свой единственный подключенный датчик.  Згарел - включаешь другой такой же, программа разницы не заметит

sadman41
Offline
Зарегистрирован: 19.10.2016

С напряжением проблема, а виновата опять библиотека.

Jink
Offline
Зарегистрирован: 24.09.2019

trembo пишет:
Я давно делал соседу погодный регулятор для котла. Мерял раз в 5 секунд с усреднением по десяти измерениям. Естественно всякие случайные -127, если они были, срезались сразу. И естественно не 12 битный режим.

Я то тоже режу ошибочные. а счетчик их считает. Если было определенное количество ошибок подряд (в моем случае 90), то котел уходит в ошибку и останавливается. Такое бывает редко, но бывает. Чаще всего при холодном дымоходе. Как прогреется, то ошибки редко. Подряд проскочат максимум 4, а так 1.

Jink
Offline
Зарегистрирован: 24.09.2019

DetSimen пишет:

 

 при чтении даешь команду SkipROM и читаешь свой единственный подключенный датчик.  

Спасибо

Jink
Offline
Зарегистрирован: 24.09.2019

sadman41 пишет:

С напряжением проблема, а виновата опять библиотека.

Поясните пожалуйста. В чем может быть проблема с питанием. Оно полноценное а не паразитное. Провод 2 метра. Ситуация одинаковая на разных ардуинах и на ЕСП 8266. То есть, что 5 вольт, что 3,3, разницы никакой.

bwn
Offline
Зарегистрирован: 25.08.2014

Перебирайте питание, провода и разъемы, проверьте нет ли влаги на лапках, чудес не бывает. ИМХО.
На задержки датчику нас-ть (кроме самого первого замера), дальше он возвращает последний результат сохраненный в регистрах. 
На предмет помех, отключите цепь вентилятора и посмотрите как будет работать.

Jink
Offline
Зарегистрирован: 24.09.2019

Все на пайке. Повторюсь, устройства разные пробовал. Один из них просто меряет и шлет по MQTT. Но все же на котле с выключенным вентилятором действительно ошибок меньше в разы. Появилась идея попробовать повесить кондер на питание датчика. В общем метод научного тыка в действии))). Но с другой стороны в Протеусе та же фигня. Какие там помехи то?!

bwn
Offline
Зарегистрирован: 25.08.2014

Берете код для датчика, запускаете его, считаете ошибки. Если их нет, добавляете функционал, пока ошибки не начнут проявляться. Если есть сразу, то дербаните всю сеть, пока не исчезнут. Конденсатор вешаю всегда, возле самого дальнего датчика.

sadman41
Offline
Зарегистрирован: 19.10.2016

Рядом с большими моторами ловили проблемы на DS-ках... Наводки там по DQ были что ли...

Jink
Offline
Зарегистрирован: 24.09.2019

Докладываю первые испытания. Собрал на уне тестовый стенд. Накидал скетч из примера Dallas Temperature на два пина. Повесил два датчика и LCD с I2C. В скетче прописал два счетчика ошибок. Пока полет нормальный. Никаких кондеров не вешал. Только полноценное питание датчиков и подтяжка 4,7. Кстати ради эксперимента один из датчиков питается от цифрового пина. Пока полет нормальный. Проблем нет. После обеда попытаюсь тоже самое повесить на ESP. Если все будет хорошо, то буду добавлять обвязку и код. Похоже что все таки это помехи. Хотя, надо попробовать на нано собрать. На котле именно Нано.

 

С ESP8266 тоже все работает. Что то интересное! Может партия датчиков нормальная? Это судя по маркировке что на котле, что тут у меня на стенде одна и та же партия.

MaksVV
Offline
Зарегистрирован: 06.08.2015

Jink пишет:
Вот только хочется универсальности. Не хочу привязываться к конкретному датчику.

я не пойму, в чём проблема получить адрес датчика в стандартном примере? Дело одной минуты. Вы собираетесь каждый день датчики менять?  По-моему нужно один раз все настроить и забыть про эти датчики. У меня проблемы ушли полностью, когда стал применял такой код (#2). Хотя датчики подключены физически довольно коряво. сеть звездой (что нельзя по идее) 4 жильным телефонным проводом . Лучей 7 наверное, длиной метров по 10. 

bwn
Offline
Зарегистрирован: 25.08.2014

Jink пишет:
Вот только хочется универсальности. Не хочу привязываться к конкретному датчику.

Это имеет смысл только при одном датчике на линии. Если их несколько, то сортируются по возрастанию адреса, что почти наверняка, при замене, приведет к несоответствию точки измерения датчику. А значит, считали, сверили с записанными в епром, если все соответствуют, продолжаем работу дальше. Если нет, считываем, прописываем вновь считанные в епром, требуем идентификации - последовательно по точкам нагреть каждый датчик и записать его признак в епром. Как-то так, для универсальности. Может проще можно, но чет не придумывается.

 

Jink
Offline
Зарегистрирован: 24.09.2019

Написал новый скетч. Полностью пересобираю контроллер управления котлом. Пока вроде работает. На выходных поставлю на котел, посмотрим что выйдет))))

По размещению датчиков. Для меня психологически критична максимальная ремонтопригодность. Каждый датчик на своем пине. Их три. Все можно на горячую выдернуть и всунуть, и все пока что работает.