ESP, IoT 5 штук DS18B20 на одной шине в ESP32 - шумы? наводка?

Shrike1987

✩✩✩✩✩✩✩
1 Ноя 2023
5
0
В общем давно очень собрал прибор для отца для контроля температуры разных узлов холодильного оборудования. По сути логирование на карту памяти значения 5 датчиков температуры и токового датчика, доступ через веб-морду и на дисплее. Всё на ESP32. Схемы не делал, всё из головы.
Сначала использовал аналоговые датчики температуры. Но у них большой шум в измерениях, плюс за 2 года значения "уплыли" непонятно куда.
Сейчас заказал 5 штук DS18B20 и подключил к 32 пину по принципу следующей схемы:

Питается от общей 3.3В.
Библиотеку использую DallasTemperature v.3.9.0
В общем, есть такая проблема: достаточно часто считываются на датчиках -127 градусов и показания одного датчика присваиваются другим.
Что это может быть? Шумы, наводки? Как с этим бороться? Пробовал всякие программные костыли, часть из них помогла, часть нет.
Дальше графическое представление результатов.
График.jpg
Если присмотреться, то пиковые значения "шумов" всегда соответствуют значениям "соседних" датчиков.
Вот еще пример до внедрения фильтрации по адресу (ниже в коде будет пример).
Буфер обмена01.jpg

Примеры кода из скетча будут далее. Сразу простите за корявость кода и его оформление - я совсем не программист и Си не изучал. Ранее программировал только на Delphi.

Инициализация датчиков::
...
// Шина данных подключена к выводу
#define ONE_WIRE_BUS 32
#define USE_HSPI_PORT
// настройка объекта oneWire для связи с любым устройством OneWire
OneWire oneWire(ONE_WIRE_BUS);
// передать ссылку на oneWire библиотеке DallasTemperature
DallasTemperature sensors(&oneWire);
int deviceCount = 0;
float tempC;
float Temp1, Temp2, Temp3, Temp4, Temp5;       // рабочие значения температур
float LTemp1, LTemp2, LTemp3, LTemp4, LTemp5; // предыдущие значения температур
DeviceAddress AT1, AT2, AT3, AT4, AT5;          // адреса датчиков
...


void setup() {
...
  sensors.begin();    // запустить библиотеку
  for (int i = 0;  i < deviceCount;  i++) // перечисляет все найденные датчики, но использует только первые 5
  {
   if (i==0) sensors.getAddress(AT5, i); // один из адресов нужен на последнем месте (с коротким шнуром)
   if (i==1) sensors.getAddress(AT2, i);
   if (i==2) sensors.getAddress(AT3, i);
   if (i==3) sensors.getAddress(AT4, i);
   if (i==4) sensors.getAddress(AT1, i);
  }
  sensors.setWaitForConversion(false); // асинхронный режим
...
}
Код считывания с датчиков. Выполняется в цикле веб-сервера раз в секунду:
...
if ((P2 >= 1000)and(Disp < 9)) { // прошла ли секунда с предыдущего захода в эту часть кода
    DeviceAddress DevAddr;
    for (int i = 0;  i < deviceCount;  i++) // считать температуру с каждого датчика
        {
          tempC = sensors.getTempCByIndex(i); // получаем значение температуры на датчике         
          sensors.getAddress(DevAddr, i);   // и его адрес   
          if (memcmp(DevAddr, AT1, 8) == 0) Temp1 = tempC; // проверяем на соответствие конкретного адреса
          if (memcmp(DevAddr, AT2, 8) == 0) Temp2 = tempC;
          if (memcmp(DevAddr, AT3, 8) == 0) Temp3 = tempC;
          if (memcmp(DevAddr, AT4, 8) == 0) Temp4 = tempC;
          if (memcmp(DevAddr, AT5, 8) == 0) Temp5 = tempC;       
        }
      sensors.requestTemperatures(); // запрос на преобразование уже после считывания, чтобы было время на этот процесс к следующему опросу.
      if (Temp1> -100) LTemp1 = Temp1; else Temp1 = LTemp1; //фильтрация от случайных значений в -127, подставляется предыдущее значение
      if (Temp2> -100) LTemp2 = Temp2; else Temp2 = LTemp2;
      if (Temp3> -100) LTemp3 = Temp3; else Temp3 = LTemp3;
      if (Temp4> -100) LTemp4 = Temp4; else Temp4 = LTemp4;
      if (Temp5> -100) LTemp5 = Temp5; else Temp5 = LTemp5;
}
...
Прошу помощи с борьбой этих выбросов, может что не так делаю, может кто сталкивался с подобным.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,200
1,287
Москва
Лет 20 назад делал что то очень похожее на готовом контроллере с радиорынка , тоже 5 датчиков температуры, и было примерно то же самое, периодически часть датчиков отваливалась.
Что бы сделал сейчас :
1) Проверил напряжение в конце шины, есть вероятность, что идет просадка.
2) Попробовал бы использовать 2 пина, на 2 и 3 датчика. Костыль, но возможно это помогло бы сохранить функционал.
3) Можно делать несколько попыток получить температуру от датчика, не бесконечно, что бы не зависло, с паузами.
4) Больше разнести по времени чтение датчиков.
 

Shrike1987

✩✩✩✩✩✩✩
1 Ноя 2023
5
0
Спасибо за советы!
1. Такое понятие как "конец шины" мне не совсем понятно. В корпусе стоит ESP32, рядом с ней разъем с винтовыми зажимающими клеммами. К ним подключаются 4 3 метровых датчика и один двухметровый. Расковыривать герметичные датчики не хотелось бы, чтобы замерять напряжение питания на них.
2. Уже думал об этом, но пока не решаюсь, надеюсь, на разумное объяснение происходящего.
3. Как определить, что считалась верная температура с нужного датчика? Да и процесс повторного преобразования тоже не быстрый. это займёт гораздо больше времени, чем 1 сек.
4. Если добавить в цикл между sensors.getTempCByIndex(i) по delay, это же не изменит значение преобразованных значений температур в датчиках? Но всё равно стоит попробовать. Позже отпишусь о результате.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,200
1,287
Москва
1. Т.е. у вас идет звездой все подключения ? у меня было в линию.
3. Ну очевидно , что -127 это ошибочное значение. По времени получения значения это уже вам надо определить достаточную частоту. Может и раз в минуту хватит, если просто температура на балконе, а может и раз в секунду надо, если самогонный аппарат.
Надо работать в ассинхронном режиме. Наибольшая точность получается при вермени обработки что то около 0.8 сек. Значит что надо сделать: в самом конце setup запустить начало получения данных для каждого из датчиков, пусть с разницей в 0.2 секунды. Это будет 0.8 сек. запомнить время. Далее в цикле loop спустя 0.4 (потом сократить можно будет) считать 1-ое значение и сразу запустить получение. И далее тоже самое для каждого из датчиков. И так далее. Можно просто негодные данные не использовать и все.
Т.е. это esp32, то вообще можно запустить это все на одном ядре с delay, а веб сервер или что там запустить на другом.
 

bort707

★★★★★★✩
21 Сен 2020
2,922
868
Для начала попробовать уменьшить номинал резистора до 2-3к или даже ниже.
 

rkit

★★★✩✩✩✩
5 Фев 2021
484
116
1. Проверка на -127 должна быть всегда. Это штатный ответ библиотеки.
2. Чтобы порядок не путался, с датчиками нужно работать по адресам.

Всё это есть в примерах к библиотеке, читай внимательнее.
 

Shrike1987

✩✩✩✩✩✩✩
1 Ноя 2023
5
0
@Старик Похабыч, идея опрашивать по очереди хороша, нужно посмотреть, есть ли реализация такого метода в библиотеке.
@bort707, Спасибо, попробую.
@rkit, я вроде как раз по адресам и фильтрую: if (memcmp(DevAddr, AT1, 8) == 0) ... где DevAddr - считанный адрес, AT1 - сохраненный адрес.
Может я неправильно делаю, посмотрю, что есть в примерах. Спасибо!
 

Shrike1987

✩✩✩✩✩✩✩
1 Ноя 2023
5
0
По поводу частоты опроса датчиков (просто для информации):
1. Раз в секунду - для обновления на дисплее.
2. Каждая точка на графике - раз в 15 секунд.

Подведу промежуточный итог.
Переписал как посоветовал @rkit обращение к датчикам по адресам и опрос с задержками, как советовал @Старик Похабыч. Резистор по совету @bort707 пока не менял (устройство в гараже, а прошивку я обновляю по воздуху).
Как итог - вроде работает без путаницы, -127 - не знаю есть ли, т.к. программно фильтруется.
Код считывания с датчиков:
...
Temp1 = sensors.getTempC(AT1); // получаю уже преобразованный ответ
delay(20);
sensors.requestTemperaturesByAddress(AT1); // сразу ставлю задачу на новое преобразование
delay(20);
Temp2 = sensors.getTempC(AT2);
delay(20);
sensors.requestTemperaturesByAddress(AT2);
delay(20);
Temp3 = sensors.getTempC(AT3);
delay(20);
sensors.requestTemperaturesByAddress(AT3);
delay(20);
Temp4 = sensors.getTempC(AT4);
delay(20);
sensors.requestTemperaturesByAddress(AT4);
delay(20);
Temp5 = sensors.getTempC(AT5);
delay(20);
sensors.requestTemperaturesByAddress(AT5);
delay(20);   
//sensors.requestTemperatures(); // -общий запрос на преобразование закомментировал
...
Буфер обмена02.jpg
Конечно, пока мало опросов, посмотрим, как будет дальше. Обязательно отпишусь о результатах.
Всем огромное спасибо!
 

Эдуард Анисимов

★★★★★★✩
23 Сен 2019
2,304
949
58
Марий-Эл
Такое бывает, когда библиотека даёт неправильные тайминги.
У меня три библиотеки.
1. Софтварная - работает не на всех МК.
2. Тайминги сделаны на UART - работает на всех МК
3. Тайминги сделаны на UART+DMA - работает на всех МК, где есть DMA
 

Shrike1987

✩✩✩✩✩✩✩
1 Ноя 2023
5
0
Подведу окончательный итог - за 3 часа работы сбоев не наблюдается.
Благодарю всех участников в поиске решения проблемы!
Буфер обмена03.jpg