ESP, IoT Опрос DS18B20: зависает, перезагружается на 13 датчике.

ilya7zz

✩✩✩✩✩✩✩
16 Мар 2021
19
1
Суздаль
www.drive2.ru
Собственно не понимаю почему происходит ошибка.
C 12ю датчиками работает стабильно, при инициализации 13го датчика (раскоментировании 55 строки), всегда на восьмом цикле (опросе датчиков) вылетает с дисплея показания temp_0 и происходит перезагрузка.
Примерно в 1 случае из 10 зависает экран и перестаёт реагировать на reset, но измерения продолжают поступать в консоль на serial, уже не приводя к перезагрузкам.
Если передёрнуть питание экрана, то reset срабатывает.

Рабочий режим (на дисплей выводятся только 10 датчиков + среднее) После 8 цикла пропал temp_6, далее перезагрузка или зависание lcd
ESP-8266-12E:
/* Групповой тест датчиков Dallas */
// D1 (gpio5) - SCL
// D2 (gpio4) - SDA
// D3 (gpio0) - flash
#include <LiquidCrystal_I2C.h>
#include <SimpleTimer.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 0 // DS18B20 подключаем к GPIO0 (D3)
#define BLYNK_PRINT Serial
float temp_0,temp_1,temp_2,temp_3,temp_4,temp_5,temp_6,temp_7,temp_8,temp_9,temp_10,temp_11,temp_12,sum;
float avr;
byte grad[8] = {B01110,B01010,B01110,B00000,B00000,B00000,B00000,}; //символ °
SimpleTimer timer;
LiquidCrystal_I2C lcd(0x27,20,4); //начало работы, с указанием размерности экрана
OneWire oneWire(ONE_WIRE_BUS); // Настраиваем oneWire для связи
DallasTemperature DS18B20(&oneWire); // Передаем нашу ссылку oneWire в Dallas Temperature.

void setup() {
  Serial.begin(115200); // запускаем последовательный порт
  DS18B20.begin(); // Запускаем библиотеку (инициализация датчика)
  timer.setInterval(1000L, getData);
  timer.setInterval(10000L, avrData);
  Serial.println(" ");
  Serial.println("Тестирование датчиков температуры");

  lcd.begin(20, 4); // Начало работы, с указанием размерности экрана
  lcd.init();
  lcd.backlight();
  lcd.createChar(0, grad); // Инициализируем массив
  lcd.setCursor(2,0);
  lcd.print("Testing  Dallas!");
  delay(1000);
}

void loop()  {
  timer.run(); // Initiates SimpleTimer
}

void getData()
{
  DS18B20.requestTemperatures(); // Cчитываем температуру с датчиков ~160ms на датчик
  temp_0 = DS18B20.getTempCByIndex(0);
  temp_1 = DS18B20.getTempCByIndex(1);
  temp_2 = DS18B20.getTempCByIndex(2);
  temp_3 = DS18B20.getTempCByIndex(3);
  temp_4 = DS18B20.getTempCByIndex(4);
  temp_5 = DS18B20.getTempCByIndex(5);
  temp_6 = DS18B20.getTempCByIndex(6);
  temp_7 = DS18B20.getTempCByIndex(7);
  temp_8 = DS18B20.getTempCByIndex(8);
  temp_9 = DS18B20.getTempCByIndex(9);
  temp_10 = DS18B20.getTempCByIndex(10);
  temp_11 = DS18B20.getTempCByIndex(11);
//  temp_12 = DS18B20.getTempCByIndex(12);

  Serial.print("t0: ");
  Serial.print(temp_0);
  Serial.print("°C t1: ");
  Serial.print(temp_1);
  Serial.print("°C t2: ");
  Serial.print(temp_2);
  Serial.print("°C t3: ");
  Serial.print(temp_3);
  Serial.print("°C t4: ");
  Serial.print(temp_4);
  Serial.print("°C t5: ");
  Serial.print(temp_5);
  Serial.print("°C t6: ");
  Serial.print(temp_6);
  Serial.print("°C t7: ");
  Serial.print(temp_7);
  Serial.print("°C t8: ");
  Serial.print(temp_8);
  Serial.print("°C t9: ");
  Serial.print(temp_9);
  Serial.print("°C t10: ");
  Serial.print(temp_10);
  Serial.print("°C t11: ");
  Serial.print(temp_11);
  Serial.print("°C t12: ");
  Serial.print(temp_12);
  Serial.println("°C");

lcd.setCursor(0,0);
lcd.print("                    "); //20 пробелов, очистка строки
  lcd.setCursor(0,0);
  lcd.print(temp_0);
  lcd.write(byte(0));  // выводим надстр. символ °
  lcd.print(",");
  lcd.print(temp_1);
  lcd.write(byte(0));
  lcd.print(",");
  lcd.print(temp_2);
  lcd.write(byte(0));

lcd.setCursor(0,1);
lcd.print("                    ");
  lcd.setCursor(0,1);
  lcd.print(temp_3);
  lcd.write(byte(0));
  lcd.print(",");
  lcd.print(temp_4);
  lcd.write(byte(0));
  lcd.print(",");
  lcd.print(temp_5);
  lcd.write(byte(0));

lcd.setCursor(0,2);
lcd.print("                    ");
  lcd.setCursor(0,2);
  lcd.print(temp_6);
  lcd.write(byte(0));
  lcd.print(",");
  lcd.print(temp_7);
  lcd.write(byte(0));
  lcd.print(",");
  lcd.print(temp_8);
  lcd.write(byte(0));

lcd.setCursor(0,3);
lcd.print("       ");
  lcd.setCursor(0,3);
  lcd.print(temp_9);
  lcd.write(byte(0));
}

void avrData() // измерение среднего значения
{
  sum = 0;
  sum += temp_0;
  sum += temp_1;
  sum += temp_2;
  sum += temp_3;
  sum += temp_4;
  sum += temp_5;
  sum += temp_6;
  sum += temp_7;
  sum += temp_8;
  sum += temp_9;
//  sum += temp_10;
//  sum += temp_11;
//  sum += temp_12;
  avr = sum / 10;
  lcd.setCursor(9,3);
  lcd.print("           ");
  lcd.setCursor(9,3);
  lcd.print("avr:");
  lcd.print(avr);
  lcd.write(byte(0));
}
Ошибка:
Тестирование датчиков температуры
t0: 23.25°C t1: 23.00°C t2: 23.06°C t3: 22.88°C t4: 22.56°C t5: 23.25°C t6: 22.50°C t7: 23.00°C t8: 22.81°C t9: 22.88°C t10: 23.00°C t11: 22.81°C t12: 22.63°C
t0: 23.25°C t1: 23.00°C t2: 23.00°C t3: 22.88°C t4: 22.56°C t5: 23.31°C t6: 22.50°C t7: 23.00°C t8: 22.88°C t9: 22.88°C t10: 23.00°C t11: 22.88°C t12: 22.63°C
t0: 23.25°C t1: 23.00°C t2: 23.00°C t3: 22.88°C t4: 22.56°C t5: 23.25°C t6: 22.50°C t7: 22.94°C t8: 22.81°C t9: 22.88°C t10: 23.00°C t11: 22.88°C t12: 22.56°C
t0: 23.25°C t1: 23.00°C t2: 23.06°C t3: 22.88°C t4: 22.56°C t5: 23.31°C t6: 22.50°C t7: 23.00°C t8: 22.81°C t9: 22.88°C t10: 23.00°C t11: 22.81°C t12: 22.56°C
t0: 23.25°C t1: 22.94°C t2: 23.00°C t3: 22.88°C t4: 22.56°C t5: 23.25°C t6: 22.50°C t7: 22.94°C t8: 22.88°C t9: 22.88°C t10: 23.00°C t11: 22.88°C t12: 22.56°C
t0: 23.25°C t1: 22.94°C t2: 23.00°C t3: 22.88°C t4: 22.56°C t5: 23.25°C t6: 22.50°C t7: 23.00°C t8: 22.88°C t9: 22.88°C t10: 23.00°C t11: 22.88°C t12: 22.63°C
t0: 23.25°C t1: 22.94°C t2: 23.06°C t3: 22.88°C t4: 22.56°C t5: 23.31°C t6: 22.50°C t7: 22.94°C t8: 22.81°C t9: 22.88°C t10: 23.00°C t11: 22.81°C t12: 22.56°C
t0: 23.25°C t1: 22.94°C t2: 23.06°C t3: 22.88°C t4: 22.56°C t5: 23.25°C t6: 22.50°C t7: 22.94°C t8: 22.88°C t9: 22.88°C t10: 23.00°C t11: 22.81°C t12: 22.56°C

--------------- CUT HERE FOR EXCEPTION DECODER ---------------

Soft WDT reset

[QUOTE]>>stack>>>[/QUOTE]

ctx: cont
sp: 3ffffcc0 end: 3fffffc0 offset: 01a0
3ffffe60:  3ffee754 00000001 3ffee754 402038e0
3ffffe70:  00000001 00000180 00000002 402039a4
3ffffe80:  00000001 00000004 3ffee754 40203a46
3ffffe90:  3ffee58b 00000027 3ffee754 3ffe8701
3ffffea0:  00000001 3ffee42c 3ffee589 3ffe8702
3ffffeb0:  00000021 3ffee42c 3ffee589 40203c10
3ffffec0:  00000009 3ffee42c 3ffee578 40201be0
3ffffed0:  40100429 00000001 3ffee578 40201c08
3ffffee0:  00000001 3ffee42c 00000001 402016ed
3ffffef0:  00000001 3ffee42c 00000021 40201771
3fffff00:  00000000 00000200 3ffee42c 402017a7
3fffff10:  3ffe870e 3ffee42c 00000007 402017cf
3fffff20:  00000001 00000940 3ffee42c 4020549e
3fffff30:  3ffe86fa 3ffe870f 3ffee42c 3ffee570
3fffff40:  4020546c 3ffee42c 3ffe86fa 40202949
3fffff50:  3ffe86fa 3ffe870f 3ffee42c 40202960
3fffff60:  007a1200 3ffee574 3ffee6ac 402014ec
3fffff70:  00000000 3ffee81c 000003e8 3ffee714
3fffff80:  3ffee43c 00000000 3ffee43c 40201d5a
3fffff90:  3fffdad0 00000000 3ffee6d4 402010e0
3fffffa0:  feefeffe 00000000 3ffee6d4 4020301c
3fffffb0:  feefeffe feefeffe 3ffe84f0 40100e75
<<<stack<<<

--------------- CUT HERE FOR EXCEPTION DECODER ---------------

ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 3584, room 16
tail 0
chksum 0xb0
csum 0xb0
v2843a5ac
~ld

Тестирование датчиков температуры
t0: 23.25°C t1: 23.00°C t2: 23.00°C t3: 22.94°C t4: 22.63°C t5: 23.25°C t6: 22.44°C t7: 22.94°C t8: 22.81°C t9: 22.88°C t10: 23.00°C t11: 22.88°C t12: 22.56°C
t0: 23.25°C t1: 23.00°C t2: 23.00°C t3: 22.88°C t4: 22.56°C t5: 23.25°C t6: 22.50°C t7: 22.94°C t8: 22.88°C t9: 22.88°C t10: 23.00°C t11: 22.88°C t12: 22.63°C
IMG_2056all.jpg
 
Изменено:

IamNikolay

★★★✩✩✩✩
15 Янв 2020
820
175
это конденсатор?! зачем поставили?
для этих датчиков только подтягивающий резистор нужен
1618686050931.png
 

ilya7zz

✩✩✩✩✩✩✩
16 Мар 2021
19
1
Суздаль
www.drive2.ru
@IamNikolay, да 220nF. Привычка фильтровать питание, на длинных линиях очень выручает. Тут его поставил т.к. питается от сборки от 3V выхода линейного стаба, чтобы не словить помеху от ESP. Полагаю к вопросу этот конденсатор никаким боком :) Ибо 12 датчиков считываются более суток без сбоя, а считывая 13й - сразу глюк, какое-то переполнение... Ведь инициализируются они все корректно, даже после зависания LCD. Т.к. я новичок в этом деле, то даже не понимаю с чего начать отладку.
 

IamNikolay

★★★✩✩✩✩
15 Янв 2020
820
175
@ilya7zz, на есп своих конденсаторов достаточно. Что касается проблемы - увеличьте интервал опроса датчиков
 
  • Лойс +1
Реакции: ilya7zz

poty

★★★★★★✩
19 Фев 2020
3,233
942
Скорее всего дело в ограничении библиотеки OneWire (например, не может проиндексировать больше допустимого количества устройств на шине). Возможно также, что не хватает мощности пина датчика при параллельном соединении множества устройств. Неплохо бы проверить, все ли устройства обеспечены питанием? Библиотека имеет метод, позволяющий определить, сколько устройств она нашла на шине, возможно, стоит им воспользоваться, а не просто пытаться обращаться к 12-му термометру.
 

ilya7zz

✩✩✩✩✩✩✩
16 Мар 2021
19
1
Суздаль
www.drive2.ru
@IamNikolay, Датчики опрашиваются сразу все 13, одной командой и из сказанного ранее очевидно, что частота опроса никак не влияет на появления ошибки. (после зависания дисплея датчики опрашиваются и выводятся в консоль стабильно долго, без ошибок!) Ошибка появляется при присвоении переменным более 12 датчиков.
Пробовал изменить время getData до 10 секунд, а avrData до 30 секунд: зависает и/или перезагружается спонтанно от 10 до 60 секунд.
Сильно улучшает стабильность если использую повторный запрос инициализации всех датчиков, может проработать от 1 до 10 минут и уходит в ошибку.
summer average:
  sum = 0;
  DS18B20.requestTemperatures();
  sum += DS18B20.getTempCByIndex(0);
  sum += DS18B20.getTempCByIndex(1);
  sum += DS18B20.getTempCByIndex(2);
  sum += DS18B20.getTempCByIndex(3);
  sum += DS18B20.getTempCByIndex(4);
  sum += DS18B20.getTempCByIndex(5);
  sum += DS18B20.getTempCByIndex(6);
  sum += DS18B20.getTempCByIndex(7);
  sum += DS18B20.getTempCByIndex(8);
  sum += DS18B20.getTempCByIndex(9);
  sum += DS18B20.getTempCByIndex(10);
  sum += DS18B20.getTempCByIndex(11);
  sum += DS18B20.getTempCByIndex(12);
  avr = sum / 13;
Хочется использовать имеющиеся данные в переменных чтобы не городить лишних времяотжирающих процессов.
Необходимо максимально оперативное обновление данных с датчиков.

@poty, библиотека индексирует 13 датчиков без проблем. Проблемы возникают после присвоения данных датчика переменным. Каким образом изменение 55 строки кода оказывает влияние на мощночть, которая составляет 0,5 Вт вместе с подсветкой? Я хотел сделать тестер разных датчиков для определения погрешности и измерений, поэтому предварительное определение устройств мне не совсем походит.
а не просто пытаться обращаться к 12-му термометру.
Вероятно, вы не прочитали написанное ранее и не смотрели код, сделав этот вывод и другие предположения.

на есп своих конденсаторов достаточно
Расскажите это связке ESP с 10 метровым кабелем и датчиком на радиаторе, которые без них периодически, кратковременно отваливаются. Рабочее решение - увеличение тока подтяжки (уменьшение сопротивления резистора подтяжки до тока 2-3mA и установка конденсатора вблизи датчика). Схемотехнику способов подключения датчиков с целью борьбы с помехами изучил достаточно глубоко на старой работе, пару лет назад, когда пошли помехи на 25 метровый кабель из бассейна.
PS: кашу конденсаторами не испортишь! ;) А в данной теме вопрос посвящён ошибкам работы программы в ESP.

@IamNikolay, ваши предположения о задержке верны.
В диагностических целях напихал delay (100); после каждого абзаца :) Диагностика займёт прилично времени, чтобы определиться с причинным местом. Но сам факт вылетания не есть хорошо и проблему нужно искать как-то иначе, без увеличения задержки выполнения кода...
Около 20 минут и 500 запросов – полёт нормальный!

delay (100); – выделенные строки:
/* Групповой тест датчиков Dallas */
// D1 (gpio5) - SCL
// D2 (gpio4) - SDA
// D3 (gpio0) - flash
#include <LiquidCrystal_I2C.h>
#include <SimpleTimer.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 0 // DS18B20 подключаем к GPIO0 (D3)
#define BLYNK_PRINT Serial
float temp_0,temp_1,temp_2,temp_3,temp_4,temp_5,temp_6,temp_7,temp_8,temp_9,temp_10,temp_11,temp_12,sum;
float avr;
byte grad[8] = {B01110,B01010,B01110,B00000,B00000,B00000,B00000,}; //символ °
SimpleTimer timer;
LiquidCrystal_I2C lcd(0x27,20,4); //начало работы, с указанием размерности экрана
OneWire oneWire(ONE_WIRE_BUS); // Настраиваем oneWire для связи
DallasTemperature DS18B20(&oneWire); // Передаем нашу ссылку oneWire в Dallas Temperature.

void setup() {
  Serial.begin(115200); // запускаем последовательный порт
  DS18B20.begin(); // Запускаем библиотеку (инициализация датчика)
  timer.setInterval(1000L, getData);
  timer.setInterval(10000L, avrData);
  Serial.println(" ");
  Serial.println("Тестирование датчиков температуры");
 
  lcd.begin(20, 4); // Начало работы, с указанием размерности экрана
  lcd.init();
  lcd.backlight();
  lcd.createChar(0, grad); // Инициализируем массив
  lcd.setCursor(2,0);
  lcd.print("Testing  Dallas!");
  delay(1000);
}

void loop()  {
  timer.run(); // Initiates SimpleTimer
}

void getData()
{
  DS18B20.requestTemperatures(); // Cчитываем температуру с датчиков ~180ms на датчик
  delay (100);
  temp_0 = DS18B20.getTempCByIndex(0);
  temp_1 = DS18B20.getTempCByIndex(1);
  temp_2 = DS18B20.getTempCByIndex(2);
  temp_3 = DS18B20.getTempCByIndex(3);
  temp_4 = DS18B20.getTempCByIndex(4);
  temp_5 = DS18B20.getTempCByIndex(5);
  temp_6 = DS18B20.getTempCByIndex(6);
  temp_7 = DS18B20.getTempCByIndex(7);
  temp_8 = DS18B20.getTempCByIndex(8);
  temp_9 = DS18B20.getTempCByIndex(9);
  temp_10 = DS18B20.getTempCByIndex(10);
  temp_11 = DS18B20.getTempCByIndex(11);
  temp_12 = DS18B20.getTempCByIndex(12);
  delay (100);
  Serial.print("t0: ");
  Serial.print(temp_0);
  Serial.print("°C t1: ");
  Serial.print(temp_1);
  Serial.print("°C t2: ");
  Serial.print(temp_2);
  Serial.print("°C t3: ");
  Serial.print(temp_3);
  Serial.print("°C t4: ");
  Serial.print(temp_4);
  Serial.print("°C t5: ");
  Serial.print(temp_5);
  Serial.print("°C t6: ");
  Serial.print(temp_6);
  Serial.print("°C t7: ");
  Serial.print(temp_7);
  Serial.print("°C t8: ");
  Serial.print(temp_8);
  Serial.print("°C t9: ");
  Serial.print(temp_9);
  Serial.print("°C t10: ");
  Serial.print(temp_10);
  Serial.print("°C t11: ");
  Serial.print(temp_11);
  Serial.print("°C t12: ");
  Serial.print(temp_12);
  Serial.println("°C");

lcd.setCursor(0,0);
lcd.print("                    "); //20 пробелов, очистка строки 
  lcd.setCursor(0,0);
  lcd.print(temp_0);
  lcd.write(byte(0));  // выводим надстр. символ °
  lcd.print(",");
  lcd.print(temp_1);
  lcd.write(byte(0));
  lcd.print(",");
  lcd.print(temp_2);
  lcd.write(byte(0));
delay (100);
lcd.setCursor(0,1);
lcd.print("                    ");
  lcd.setCursor(0,1);
  lcd.print(temp_3);
  lcd.write(byte(0));
  lcd.print(",");
  lcd.print(temp_4);
  lcd.write(byte(0));
  lcd.print(",");
  lcd.print(temp_5);
  lcd.write(byte(0));
delay (100);
lcd.setCursor(0,2);
lcd.print("                    ");
  lcd.setCursor(0,2);
  lcd.print(temp_6);
  lcd.write(byte(0));
  lcd.print(",");
  lcd.print(temp_7);
  lcd.write(byte(0));
  lcd.print(",");
  lcd.print(temp_8);
  lcd.write(byte(0));
delay (100);
lcd.setCursor(0,3);
lcd.print("       ");
  lcd.setCursor(0,3);
  lcd.print(temp_9);
  lcd.write(byte(0));
delay (100);
}

void avrData() // измерение среднего значения
{
  sum = 0;
  sum += temp_0;
  sum += temp_1;
  sum += temp_2;
  sum += temp_3;
  sum += temp_4;
  sum += temp_5;
  sum += temp_6;
  sum += temp_7;
  sum += temp_8;
  sum += temp_9;
  sum += temp_10;
  sum += temp_11;
  sum += temp_12;
  avr = sum / 13;
  delay (100);
  lcd.setCursor(9,3);
  lcd.print("           ");
  lcd.setCursor(9,3);
  lcd.print("avr:");
  lcd.print(avr);
  lcd.write(byte(0));
  delay (100);
}
 

IamNikolay

★★★✩✩✩✩
15 Янв 2020
820
175
@ilya7zz, после
C++:
DS18B20.requestTemperatures();
задержка обязательна (вплоть до 1 сек.), это необходимо для замера температуры и помещения результата в память датчика
 

ilya7zz

✩✩✩✩✩✩✩
16 Мар 2021
19
1
Суздаль
www.drive2.ru
@IamNikolay, возможно.
Тогда не совсем понятно почему работало корректно 12 датчиков более суток без задержки?
Продолжает выводить данные всех 13 датчиков в терминал даже если дисплей завис?
При моём запросе, время обработки одного датчика около 180мс*13датчиков=2,3с выполняется инициализация. Сценарий ждёт пока инициализация завершится, лишь затем начинает присваивать значения переменным, зачем тогда задержка?.. В моём понимании, чтобы не измерять чаще установленного значения, т.е. 1 сек.
 

IamNikolay

★★★✩✩✩✩
15 Янв 2020
820
175
@ilya7zz, возможно показания считывались до того как датчик произведет замер, т.е. выводились данные предыдущего замера.
Можете еще библиотеку таймера проверить, если она на прерываниях, с интервалом замеров 1 сек., а время запросов датчиков вышло 2,3 сек., то это могло прерывать общение датчиков и контроллера.
Попробуйте отказаться от таймера и построить все на delay или millis
 

ilya7zz

✩✩✩✩✩✩✩
16 Мар 2021
19
1
Суздаль
www.drive2.ru
@IamNikolay, так ведь SimpleTimer и построен на millis, поэтому никаких прерываний не происходит и не происхдило. 12 датчиков считает стабильно, 13 тоже, но только в консоли после зависания дисплея. Не кажется нелогичным такое предположение?
 

IamNikolay

★★★✩✩✩✩
15 Янв 2020
820
175
@ilya7zz, есть несколько библиотек с таким названием, какая именно у вас - неизвестно. Если на миллисекундах, то проблема была не в прерываниях.
 

poty

★★★★★★✩
19 Фев 2020
3,233
942
Возможно я неправ, но где Вы проверяете, сколько датчиков у Вас проиндексировалось (getDeviceCount)?
getTempCByIndex при отсутствии датчика выдаёт -127, это тоже никак не проверяется.
Теперь по поводу requestTemperatures. Это для Вас она одна строка, если посмотреть в код библиотеки, то увидим, что сначала на линию данных посылается сигнал reset, только потом выполняется чтение. Но чтение выполняется по прерываниям, по крайней мере, имеется специальная функция blockTillConversionComplete, но то ли я неправильно понял, то ли в ней действительно ошибка: результат задержки в этой функции не зависит от количества устройств на шине. Тем не менее, устройства опрашиваются последовательно и в какой-то момент мы вываливаемся из requestTemperatures, а в фоне работают прерывания шины 1Wire. Потом Вы выводите в Serial результаты конверсии - это даёт небольшую задержку (вижу также delay(100) там же), а потом на шину I2C начинает претендовать экран, куда Вы выводите результаты. Если чтение всех датчиков успевает закончится к этому моменту - всё ОК, но, видимо, в какой-то момент всё же не успевает и происходит сбой в передаче команд на экран (задержка, вызванная прерываниями, либо конфликт запретов прерываний).
Предлагаю попробовать вместо requestTemperatures использовать requestTemperaturesByIndex перед каждым getTempCByIndex.
 
  • Лойс +1
Реакции: ilya7zz

IamNikolay

★★★✩✩✩✩
15 Янв 2020
820
175
@ilya7zz, если прерываний не видно, то это не означает что их нет)

blockTillConversionComplete, но то ли я неправильно понял, то ли в ней действительно ошибка: результат задержки в этой функции не зависит от количества устройств на шине
команда на замер отправляется сразу всем датчикам(по типу сброса)
Предлагаю попробовать вместо requestTemperatures использовать requestTemperaturesByIndex перед каждым getTempCByIndex.
не очень хороший вариант, т.к. только увеличит время.

многое еще от разрешения зависит, вообще, @ilya7zz, посмотрите даташит про тайминги выполнения операций датчиком, будет понятнее
1618701813514.png
 
  • Лойс +1
Реакции: ilya7zz

ilya7zz

✩✩✩✩✩✩✩
16 Мар 2021
19
1
Суздаль
www.drive2.ru
при отсутствии датчика выдаёт -127, это тоже никак не проверяется.
Проверяется, в консоли (или на дисплее), т.к. выводятся переменные всех 13 датчиков и если какого-то не окажется, библиотека вернёт -127 – так я и узнаю.
IMG_1995.jpg
а потом на шину I2C начинает претендовать экран, куда Вы выводите результаты
Вот тут кажется вы ближе всего к правде. Надо разбираться, мне это пока даётся с трудом, изучаю платформу всего 4й день :)

90 минут – работает стабильно:
delay (10); - задержка в этом месте кажется решила проблему:
void getData()
{
  DS18B20.requestTemperatures(); // Cчитываем температуру с датчиков ~180ms на датчик
  temp_0 = DS18B20.getTempCByIndex(0);
  temp_1 = DS18B20.getTempCByIndex(1);
  temp_2 = DS18B20.getTempCByIndex(2);
  temp_3 = DS18B20.getTempCByIndex(3);
  temp_4 = DS18B20.getTempCByIndex(4);
  temp_5 = DS18B20.getTempCByIndex(5);
  temp_6 = DS18B20.getTempCByIndex(6);
  temp_7 = DS18B20.getTempCByIndex(7);
  temp_8 = DS18B20.getTempCByIndex(8);
  temp_9 = DS18B20.getTempCByIndex(9);
  temp_10 = DS18B20.getTempCByIndex(10);
  temp_11 = DS18B20.getTempCByIndex(11);
  temp_12 = DS18B20.getTempCByIndex(12);
delay (10); // защита от зависания при работе более 12-ти датчиков!!!
  Serial.print("t0: ");
  Serial.print(temp_0);
  Serial.print("°C t1: ");
  Serial.print(temp_1);
  Serial.print("°C t2: ");
  Serial.print(temp_2);
  Serial.print("°C t3: ");
  Serial.print(temp_3);
  Serial.print("°C t4: ");
  Serial.print(temp_4);
  Serial.print("°C t5: ");
  Serial.print(temp_5);
Предлагаю попробовать вместо requestTemperatures использовать requestTemperaturesByIndex перед каждым getTempCByIndex.
C++:
bool requestTemperaturesByIndex(uint8_t);
// посылает команду для одного устройства для преобразования температуры по индексу
Если верно понял, то эта команда пересчитает все датчики в каждом запросе, а это 2,3с*13шт=30 сек на одно обновление.
(вижу также delay(100) там же)
Эти delay(100) были тестовыми, от непонимания причины зависания. Круг поиска сузился до строки 17 в предыдущем посте. Причины на данный момент не понимаю.
 
Изменено:

bort707

★★★★★★✩
21 Сен 2020
3,058
910
@ilya7zz, немного не по теме... вам не надоедает по тринадцать раз набирать одно и то же?
C++:
temp_0 = DS18B20.getTempCByIndex(0);
  temp_1 = DS18B20.getTempCByIndex(1);
  temp_2 = DS18B20.getTempCByIndex(2);
  temp_3 = DS18B20.getTempCByIndex(3);
  temp_4 = DS18B20.getTempCByIndex(4);
  temp_5 = DS18B20.getTempCByIndex(5);
  temp_6 = DS18B20.getTempCByIndex(6);
  temp_7 = DS18B20.getTempCByIndex(7);
  temp_8 = DS18B20.getTempCByIndex(8);
  temp_9 = DS18B20.getTempCByIndex(9);
  temp_10 = DS18B20.getTempCByIndex(10);
  temp_11 = DS18B20.getTempCByIndex(11);
  temp_12 = DS18B20.getTempCByIndex(12);
про массивы и циклы ничего не слыхали?
 
  • Лойс +1
  • Ахах! +1
Реакции: rGlory и ilya7zz

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

★★★★★★★
14 Авг 2019
4,263
1,302
Москва
Если сделать запрос к датчику и тут же забрать температуру , то он вернет предыдущее показание, т.е. получать температуру с частотой больше 0.7 секунды смысла нет, т.к. она не обновиться. 0.76с это время обновления на самом точном уровне.
Отсюда второй вопрос. На сколько нужно точно получать температуру ? каждое снижение точности на 1 бит сокращает время получения запроса в 2 раза. Т.е. следующая точность требует 0.38с, далее 0.190 и 0.095 на самом низком. Время не точное, я такое для себя определил с небольшим запасом.

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

Сам столько датчиков не пихал. Брал 3 штуки максимум.
 
  • Лойс +1
Реакции: ilya7zz

poty

★★★★★★✩
19 Фев 2020
3,233
942
команда на замер отправляется сразу всем датчикам(по типу сброса)
да, это я понял, согласен, что данное утверждение не очень подходит.
не очень хороший вариант, т.к. только увеличит время.
зато можно проверить, не является ли групповая команда причиной такого поведения. Я поясню. Исходя из кода библиотеки, команда getTempCByIndex не проверяет, завершился ли реально процесс измерения температуры (это ещё одна команда, которая должна быть выдана перед использованием этой функции - isConversionAvailable). requestTemperatures также этого не проверяет. А вот requestTemperaturesByIndex проверяет.
эта команда пересчитает все датчики в каждом запросе,
нет, из существующего массива данных вынимается адрес датчика.
Проверяется, в консоли (или на дисплее), т.к. выводятся переменные всех 13 датчиков и если какого-то не окажется, библиотека вернёт -127 – так я и узнаю.
Я немного не о том. Вот, допустим, происходит сбой (отвалился датчик, например), переменная с одного из датчиков не выводится, Вы этого уже не увидите. Наверное, для тестирования этого достаточно. Но в реальном коде это вряд ли допустимо.
Круг поиска сузился до строки 17 в предыдущем посте. Причины на данный момент не понимаю.
Это уже результат! Причина, очевидно, в том, что в одной из библиотек (предположительно - I2C, используемая экраном) происходит блокирующая прерывания (перезагрузка по вотчдогу) или блокирующая шину (прекращение работы I2C) активность. Что происходит быстрее, то Вы и видите.
@Старик Похабыч, согласен, точность = 0,5 градуса, даже без учёта дрифта. Если учитывать, что предел ADC 3 сигма, то такой точности можно добиться с помощью 10 бит легко. Большая точность нужна для относительных измерений (изменение температуры), здесь же - абсолютные (значение температуры).
 
  • Лойс +1
Реакции: ilya7zz

IamNikolay

★★★✩✩✩✩
15 Янв 2020
820
175
Избыточное цитирование
зато можно проверить, не является ли групповая команда причиной такого поведения. Я поясню. Исходя из кода библиотеки, команда getTempCByIndex не проверяет, завершился ли реально процесс измерения температуры (это ещё одна команда, которая должна быть выдана перед использованием этой функции - isConversionAvailable). requestTemperatures также этого не проверяет. А вот requestTemperaturesByIndex проверяет.
после requestTemperatures следует ставить задержку до 1 сек. в зависимости от разрешения датчика, об этом писал ранее:
после
C++:
DS18B20.requestTemperatures();
задержка обязательна (вплоть до 1 сек.), это необходимо для замера температуры и помещения результата в память датчика
(даже в примерах работы с датчиком эту задержку видел)
так что смысла проверять измерилась температура или нет - особо и нет, т.к. при максимальном разрешении замер составит 750 мс., тем самым после 1 сек. задержки температура 100% будет измерена (если датчик рабочий).

Но можно сделать проверку, если разрешение не большое или меняется пользователем уже не в коде, так время паузы будет динамическим в зависимости от выставленного пользователем разрешения.
 
  • Лойс +1
Реакции: ilya7zz

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

★★★★★★✩
23 Сен 2019
2,410
976
58
Марий-Эл
Я вот что подумал.
Обращение к датчику проводится по индексу а не по реальному адресу.
Значит, что бы считать температуру, каждый раз запускается сканирование датчиков и только после этого чтение.
Посмотрите код библиотеки. Так это или нет.
Может в этом ещё загвоздка? Ведь сканирование непростая процедура и отнимает время.

Ещё столкнулся с такой фигнёй. Пять датчиков собранные группой исправно работают. Те же датчики разнесённые по 12 метров равномерно у же на определяются.
 
Изменено:

poty

★★★★★★✩
19 Фев 2020
3,233
942
после requestTemperatures следует ставить задержку до 1 сек.
Нет, задержка предусмотрена внутри функции, я об этом тоже писал:
имеется специальная функция blockTillConversionComplete, но то ли я неправильно понял, то ли в ней действительно ошибка: результат задержки в этой функции не зависит от количества устройств на шине.
Другое дело, что она там выбрана минимальной, соответствующей паспортным данным.
что бы считать температуру, каждый раз запускается сканирование датчиков и только после этого чтение
Нет, в функции begin все датчики собираются в массив индекс-адрес. Потом это уже не пересканируется до окончания работы или вызова специальной функции.
 
  • Лойс +1
Реакции: ilya7zz

IamNikolay

★★★✩✩✩✩
15 Янв 2020
820
175
Нет, задержка предусмотрена внутри функции, я об этом тоже писал:
полагаете имеете ввиду эту функцию
C++:
/ returns number of milliseconds to wait till conversion is complete (based on IC datasheet)
int16_t DallasTemperature::millisToWaitForConversion(uint8_t bitResolution){

    switch (bitResolution){
    case 9:
        return 94;
    case 10:
        return 188;
    case 11:
        return 375;
    default:
        return 750;
    }

}
есть функция
C++:
void DallasTemperature::setOneWire(OneWire* _oneWire){

    _wire = _oneWire;
    devices = 0;
    parasite = false;
    bitResolution = 9;
    waitForConversion = true;
    checkForConversion = true;

}
где bitResolution = 9, таким образом задержка по функции выше составит 94 мс.
однако, есть еще функция запроса температуры, в которой
C++:
bitResolution = getResolution(deviceAddress);
т.е. запрашивается для каждого датчика.

В общем, лучше в коде сразу выставить одинаковое разрешение для всех датчиков иначе на общий запрос измерения температуры быстрее всего придет ответ от датчика с меньшим разрешением и продолжится выполнение, в то время как остальные датчики не успеют измерить температуру
 
  • Лойс +1
Реакции: ilya7zz

poty

★★★★★★✩
19 Фев 2020
3,233
942
C++:
void DallasTemperature::setOneWire(OneWire* _oneWire)
вызывается из конструктора класса, после, во время инициализации:
C++:
void DallasTemperature::begin(void){
    ...
    while (_wire->search(deviceAddress)){
        ...
        bitResolution = max(bitResolution, getResolution(deviceAddress));
        ...
    }
}
определяется максимальное разрешение среди всех найденных устройств. Потом используется именно это значение. С этой точки зрения, вроде, ошибок нет.

Но я бы тоже вынес чтение (с предварительным контролем доступности значений) и вывод значений в начало функции, вызываемой таймером, а запрос обновления - в конец. Тогда и не было бы никаких вопросов однозначно, так как таймер вызывается раз в секунду.
 
  • Лойс +1
Реакции: ilya7zz