Почистил скетч примера работы с DS18B20 из библы OneWire..

Logik
Offline
Зарегистрирован: 05.08.2014

Любопытный случай смерти ds18b20 случился сегодня.

Имеется новое устройство на esp8266. К нему, на GPIO2, подключено 2 (в перспективе 3) датчика ds18b20 и вентилятор. Логика работы: опрашиваем датчики (по 2 сек на каждый), если разность температур датчиков превышает 1 градус вкл. вентилятор. Откл. вентилятора если разность температур стала менее нуля. Все это под системой логирования и с веб- интерфейсом. Ранее отработало дней 5 на отладке с одним датчиком. Вчера запустил с двумя в боевых условиях, и вот утром вижу.

Лог циклический, инфы ранее 8:28 нет. Данные за 7:00 вроде корректны, за 8:00 бредятина, датчики на балконе. Судя по логу вентилятор периодически включался и отключался, похоже показания скакали. При осмотре выяснилось что новый датчик коротит линию. Проработав правильно всю ночь до 7:00. Его закоротка выглядит для системы как корректный 0 градусов по всем датчикам. Это видно в таблице в 9:00. Код в студию:

void StartConvertDS18b20(AdrDS18b20 addr)
{
      ds.reset();
      ds.select(addr); // обращаемся по адресу
      ds.write(0x44, 1); //Команда на конвертацию 1 -паразитное питание
}

bool GetConvertDS18b20(AdrDS18b20 addr, int16_t* Val)
{
      ds.reset()
      ds.select(addr); // обращаемся по адресу
      ds.write(0xBE, 1); // чтение из памяти
      for (int i = 0; i < 9; i++) { 
        data[i] = ds.read ();
      }
      ds.reset_search();
      *Val = ((data[1] << 8) | data[0]);//=======Пересчитываем в температуру
      return ds.crc8(data, 8)==data[8];
}

Ниче необычного, контроль CRC присутствует но проблему не выявляет. Повторюсь, между StartConvertDS18b20 и GetConvertDS18b20 аж 2 секунды, я не спешу.

Оперативно дорабатываю

bool GetConvertDS18b20(AdrDS18b20 addr, int16_t* Val)
{
      if(!ds.reset())
        return false;
      ds.select(addr); // обращаемся по адресу
      ds.write(0xBE, 1); // чтение из памяти
.......

Теперь хоть не выдает ложные нули. 

Отключаю проблемный датчик - работает корректно.

Отсюда вывод - в примерах кода по теме необходимо добавить проверку ds.reset(). 

Ну а датчик - похоже совсем сдох. 

Но как могли получится температуры 65,5С по исправному датчику - загадка. И как с таким боротся?

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

М.б. 65535 было в результате вычислений преобразовано в 65.5?

Logik
Offline
Зарегистрирован: 05.08.2014

sadman41 пишет:

М.б. 65535 было в результате вычислений преобразовано в 65.5?

хммм....  Это мысль интересная, восстановить по 65,5 что с шины приехало.. Получается 0х0418 вроде... это в десятичной 1048*0,0625=65,5  Не полегчало (((

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

Похоже, что сюда приехали FF FF из шины.

*Val = ((data[1] << 8) | data[0]);//=======Пересчитываем в температуру

Или температура не здесь пересчитывается, вопреки комментарию?

Logik
Offline
Зарегистрирован: 05.08.2014

Не, не вопреки. Это пересчет из буфера в родной формат ds18b20. Цена младшего разряда 0,0625С. Он собственно везде и использован кроме вывода в html. В строку конвертится так.

void OutTemp(int16_t t, char* s)
{
  byte a=0;
  
  if(t<0)
  {
    s[0]='-';
    t=-t;
    a++;
  }
  itoa(t/16, s+a, 10);
  a=strlen(s);
//  itoa( 10000+(t&0x0f)*625,s+a,10); //0,0625    -  без округления
  itoa( (500+(t&0x0f)*625)/1000,s+a+1,10); //0,0625
  s[a]='.';
}

 

Если бы приехало 0xffff то имели бы 65535*0,0625=.. что не похоже

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

не знаю как нарот, а я вапще 4 дробных бита отбрасываю, присваивая результат сразу к int8_t. Дробная часть температуры мне нах не нужна. 

int8_t temp = (FDallasMemory[1] << 4) | (FDallasMemory[0] >> 4);

Logik
Offline
Зарегистрирован: 05.08.2014

Она интересна только в плане оценки динамики, сразу видно греемся или охлаждаемся. Смотри, сразу видно что греемся последние 2 часа. А без дробной - не видно

 

Время измерений Внутри Снаружи Радиатор
30-09-2020 11:00:00 17.2    
30-09-2020 12:00:00 17.5    
30-09-2020 13:00:00 17.5    

 

01-01-1970 02:00:09 dTim1601457723
30-09-2020 11:00:00 Температура: Внутри=17.2С

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

Logik пишет:

01-01-1970 02:00:09 dTim1601457723

30-09-2020 11:00:00 Температура: Внутри=17.2С

Нихрена чота не 2 часа разница :) 

Чесно говоря, мне что -34.5 С, что просто -34 С - один дубак. хоть и греемся типа :) 

Logik
Offline
Зарегистрирован: 05.08.2014

)))

Это время через сеть по SNTP берется. После ресета его сразу нет, значене 0 что для юникстайма есть 0:0:0 1-1-1970. Ну и +2часа для часового пояса. Оно при логировании в первую строку идет. Эта строка собственно - поправка dTim1601457723 к времени чтоб получить текущее 30-09-2020 11:00:00. С точностью до часа, а минуты в 0. Это чтоб отработали действия которые обычно  при смене часа. А дальше уже вторая поправка dTim1333 и время точное становится. Весь лог

01-01-1970 02:00:09 dTim1601457723

30-09-2020 11:00:00 Температура: Внутри=17.2С

30-09-2020 11:00:04 dTim1333

30-09-2020 11:34:34 New Client.

30-09-2020 11:34:34 Client disconnected.

30-09-2020 11:34:34

30-09-2020 11:34:37 New Client.

30-09-2020 12:00:00 Температура: Внутри=17.5С

30-09-2020 12:33:52 New Client.

30-09-2020 12:33:52 Client disconnected.

30-09-2020 12:33:52

30-09-2020 12:33:52 New Client.

30-09-2020 13:00:00 Температура: Внутри=17.5С

30-09-2020 13:24:04 New Client.

30-09-2020 13:24:04 Client disconnected.

30-09-2020 13:24:04

30-09-2020 13:24:04 New Client.

 

Кстати кварц esp8266 порадовал. Корректирую каждые 20мин по SNTP  и ни разу более 1сек коррекция не обнаружилась.

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

Logik, ну я изо всех сил надеялся, что ты понимаешь, что я пашутил. )))

Logik
Offline
Зарегистрирован: 05.08.2014

DetSimen пишет:

Logik, ну я изо всех сил надеялся, что ты понимаешь, что я пашутил. )))

Так я ж и посмеялся  сразу.  А затем разъяснил извращения алгоритма, они не очень очевидны. Правда еще момент забыл указать. SNTP не хочет стабильно в фоне работать. Точней она вроде как работает, а вебсервер уже через раз.  Потому я ее раз в 20 минут запускаю, жду 9 секунд, получаю время, а после стоплю. Так нормас вроде. Может конечно нормас, пока не попаду на этот процесс ))

Поменял датчика, работает.

 

 

Время измерений Внутри Снаружи Радиатор
30-09-2020 15:00:00 15.8    
30-09-2020 16:00:00 16.4 14.4  
30-09-2020 17:00:00 16.6 13.9  
30-09-2020 18:00:00 16.5 13.9  

 

 

01-01-1970 02:00:09 New Client.
01-01-1970 02:00:09 HTTP cmd: GET /4/aut
01-01-1970 02:00:09 Client disconnected.
01-01-1970 02:00:09
01-01-1970 02:00:09 dTim1601472611
30-09-2020 15:00:00 Температура: Внутри=15.8С

 

Но собственно выпал с поля зрения мысль о важности контроля результата ds.reset(). Чтоб отлавливать такие баги.

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

Ну,по крайней мере, ты теперь понимаешь, что не все так просто с далласами.  А то ты мне ж не верил, что мои, из одной партии, после -38 прекращают работать праильно . При корректнейшей некуда CRC.

Logik
Offline
Зарегистрирован: 05.08.2014

Так то ж совсем другое. У тя на экстремальной температуре и датчик сам себе только СRC считал. Думаю ему питалова не хватало.

Посмотрел CRC, по буферу из всех нулей  дает 0.

там реализация 

static const uint8_t PROGMEM dscrc_table[] = {
      0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
    157,195, 33,127,252,162, 64, 30, 95,  1,227,189, 62, 96,130,220,
     35,125,159,193, 66, 28,254,160,225,191, 93,  3,128,222, 60, 98,
    190,224,  2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
     70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89,  7,
    219,133,103, 57,186,228,  6, 88, 25, 71,165,251,120, 38,196,154,
    101, 59,217,135,  4, 90,184,230,167,249, 27, 69,198,152,122, 36,
    248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91,  5,231,185,
    140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
     17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
    175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
     50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
    202,148,118, 40,171,245, 23, 73,  8, 86,180,234,105, 55,213,139,
     87,  9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
    233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
    116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};

//
// Compute a Dallas Semiconductor 8 bit CRC. These show up in the ROM
// and the registers.  (note: this might better be done without to
// table, it would probably be smaller and certainly fast enough
// compared to all those delayMicrosecond() calls.  But I got
// confused, so I use this table from the examples.)
//
uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len)
{
	uint8_t crc = 0;

	while (len--) {
		crc = pgm_read_byte(dscrc_table + (crc ^ *addr++));
	}
	return crc;
}

 

Так что не удивительно, что  CRC сошлось на закороченной линии. Удивительно другое  CRC верно при "температуре" 65,5С. Это ж явно не  ноль, причем значение с исправного датчика. Выходит один датчик линию коротил, а это дало два эффекта: 1. Температуру 0 по всем датчикам что не ловит СRC. Зато это ловит проверка ds.reset() которой как правило нет в примерах. Решаемо в общем, но нужно делать.  2. Температура заведомо неверная с неисправного и с исправного датчиков при верном CRC. Вот это не понятно, и не ясно как бороться.

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

Я у себя после чтения скрэчпада проверяю весь пакет - если сплошняком нули, то сигнализирую ошибку. А вот второй вариант - выглядит мистикой.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Весело тут у вас

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013
AlexZR
Offline
Зарегистрирован: 08.02.2016

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

#include <OneWire.h>
OneWire  ds(2);
byte addr[8] = {0x28, 0x30, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x8E};
volatile int celsius;
void setup(void) {
  Serial.begin(57600);
  WDTCSR = (1 << WDCE) | (1 << WDE); //установить биты WDCE WDE (что б разрешить запись в другие биты
  WDTCSR = (1 << WDIE) | (1 << WDP2) | (1 << WDP1); // разрешение прерывания + выдержка 1 секунда
}

void loop(void) {
  Serial.print("  Temperature = ");
  Serial.println(celsius / 16.0);
}

ISR (WDT_vect) { //вектор прерывания WD
  static boolean n = 0; // флаг работы: запрос температуры или её чтение
  n = !n;
  if (n) {
    ds.reset();  // сброс шины
    ds.select(addr); // выбор адреса
    ds.write(0x44); // начать преобразование (без паразитного питания)
  }
  else   {
    ds.reset();
    ds.select(addr);
    ds.write(0xBE); // Read Scratchpad (чтение регистров)
    celsius =  ds.read() | (ds.read() << 8); //прочитаны 2 байта
  }
}

 

ratman
Offline
Зарегистрирован: 11.10.2015

AlexZR пишет:

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

А это ничего, что у ESP32 и Arduino с прерываниями всё совсем неодинаково? Возьмите обычный скетч из примеров. А вообще их здесь куча разных летало, при чём в этой же теме.

AlexZR
Offline
Зарегистрирован: 08.02.2016

ratman пишет:

А это ничего, что у ESP32 и Arduino с прерываниями всё совсем неодинаково? Возьмите обычный скетч из примеров. А вообще их здесь куча разных летало, при чём в этой же теме.

ну извините что не оправдал ваших надежд, не на столько я силен в программировании.. третий день ищу код без задержек для esp32, найти не смог ((( все что попадается, или с delay или не работает, если подскажите где есть такое, буду премного благодарен !

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

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

вот три датчика на esp обрабатываются, проблем нет )))

AlexZR
Offline
Зарегистрирован: 08.02.2016

ua6em пишет:
вот три датчика на esp обрабатываются, проблем нет )))

код нужен для одного датчика, опрос 1-2 раза в секунду, главное условие, без тормозов для остального кода...

ratman
Offline
Зарегистрирован: 11.10.2015

AlexZR пишет:

ratman пишет:

А это ничего, что у ESP32 и Arduino с прерываниями всё совсем неодинаково? Возьмите обычный скетч из примеров. А вообще их здесь куча разных летало, при чём в этой же теме.

ну извините что не оправдал ваших надежд, не на столько я силен в программировании.. третий день ищу код без задержек для esp32, найти не смог ((( все что попадается, или с delay или не работает, если подскажите где есть такое, буду премного благодарен !

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

Вы тему-то прочитайте. ЭТУ. Там есть примеры неблокирующих функций опроса датчиков. Без использования таймеров.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

AlexZR пишет:

ua6em пишет:
вот три датчика на esp обрабатываются, проблем нет )))

код нужен для одного датчика, опрос 1-2 раза в секунду, главное условие, без тормозов для остального кода...

существует 99 способов, к примеру паразитируя на ШИМ, устроит? (один пин займу)

AlexZR
Offline
Зарегистрирован: 08.02.2016

ua6em пишет:
существует 99 способов, к примеру паразитируя на ШИМ, устроит? (один пин займу)

помех приему от такого способа подключения нет ? при использования ШИМ на ардуино, от помех мне избавиться до конца не удалось (((

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

AlexZR пишет:

ua6em пишет:
существует 99 способов, к примеру паразитируя на ШИМ, устроит? (один пин займу)

помех приему от такого способа подключения нет ? при использования ШИМ на ардуино, от помех мне избавиться до конца не удалось (((

можно проверить, подключением к точке по WIFI и сбрасывая показания датчика в базу к примеру

AlexZR
Offline
Зарегистрирован: 08.02.2016

ладно, буду курить тему дальше...

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

AlexZR пишет:

ладно, буду курить тему дальше...

да что там курить, даже простейший таймер на миллисе решает эту проблему, вачдог всё таки ценный ресурс однако

AlexZR
Offline
Зарегистрирован: 08.02.2016

лишний раз убеждаюсь в мудрости русских пословиц, "хочешь сделать хорошо - сделай сам" )))

эх.. если бы я еще знал, что такое "вачдог"  )))

ушел на западные форумы, там точно помогут !

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

AlexZR, просто все содержание ISR из своего фрагмента поместите в фунцию... dsPoll(), например. Потом возьмите "blink без delay" и вместо мигания светодиодом вызывайте dsPoll().

Можно, конечно, на ESP-шный таймер подвесится, но если остальное написано без делеев получасовых, то и этот простой способ будет неплохо работать.

Только OneWire обновить надо, старые релизы с ESP-шками не совместимы.

AlexZR
Offline
Зарегистрирован: 08.02.2016

sadman41 пишет:
просто все содержание ISR из своего фрагмента поместите в фунцию... dsPoll(), например. Потом возьмите "blink без delay" и вместо мигания светодиодом вызывайте dsPoll().

спасибо! я вас понял, а вот с этим что делать ?

void setup(void) {
  Serial.begin(57600);
  WDTCSR = (1 << WDCE) | (1 << WDE); //установить биты WDCE WDE (что б разрешить запись в другие биты
  WDTCSR = (1 << WDIE) | (1 << WDP2) | (1 << WDP1); // разрешение прерывания + выдержка 1 секунда
}
ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

AlexZR пишет:

лишний раз убеждаюсь в мудрости русских пословиц, "хочешь сделать хорошо - сделай сам" )))

эх.. если бы я еще знал, что такое "вачдог"  )))

ушел на западные форумы, там точно помогут !

так сделано уже - функция в строках с 16 до 30, а по какому таймеру ее вызывать без разницы

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

Вызывайте эту функцию любым таймером, хоть на миллис, раз в секунду. При первом вызове будет подаваться команда на микросхему, при втором - считываться температура, которая помещается в глобальную переменную temperature, из которой ее можно взять в любой момент

void getTemperature()
{
  static bool flagDall = true; // Признак операции
  if (flagDall)
  {
    ds.reset();
    ds.write(0xCC); // Обращение ко всем датчикам
    ds.write(0x44); // Команда на конвертацию
  }
  else
  {
    int temp;
    ds.reset();
    ds.select(addr);
    ds.write(0xBE);                      // Считывание значения с датчика
    temp = (ds.read() | ds.read() << 8); // Принимаем два байта температуры
    temperature = round((float)temp / 16.0);
  }
  flagDall = !flagDall; // Инверсия признака операции для следующей итерации
}

 И никаких блокировок

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

Да ничего не делать, выкинуть весь вачдог авр-овский.

AlexZR
Offline
Зарегистрирован: 08.02.2016

вот теперь мне все более менее стало ясно ))) я благодарен всем за уделенное время и помощь!

AlexZR
Offline
Зарегистрирован: 08.02.2016

sadman41 пишет:
Только OneWire обновить надо, старые релизы с ESP-шками не совместимы.

не подскажите где скачать правильную, а то я с ними уже запутался (((

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

Да можно в менеджере библиотек обновить, думаю.
https://github.com/PaulStoffregen/OneWire/blob/master/util/OneWire_direc... - если в этом файле ESP32 упоминается, то все ок.

AlexZR
Offline
Зарегистрирован: 08.02.2016

sadman41 пишет:
Да можно в менеджере библиотек обновить, думаю.

благодарю! буду пробовать..

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

AlexZR пишет:

лишний раз убеждаюсь в мудрости русских пословиц

А что, были сомнения?

AlexZR пишет:

ушел на западные форумы, там точно помогут !

Заграница - она, конечно, поможет. Только вот русские пословицы что говорят? 

AlexZR пишет:
"хочешь сделать хорошо - сделай сам" )))
Вот и слушайте народную мудрость! Чем по заграничным форумам побираться :-)

AlexZR
Offline
Зарегистрирован: 08.02.2016

сделал так, поправьте если что..

#include <OneWire.h>
OneWire  ds(2);
byte addr[8] = {0x28, 0x30, 0xC5, 0xB8, 0x00, 0x00, 0x00, 0x8E};
volatile int temperature;
unsigned long timing;

void setup(void)
{
  Serial.begin(57600);
}

void loop(void) {

  if (millis() - timing > 1000)
  {
    timing = millis();
    getTemperature();
    Serial.print("  Temperature = ");
    Serial.println(temperature);
  }
}

void getTemperature()
{
  static bool flagDall = true; // Признак операции
  if (flagDall)
  {
    ds.reset();
    ds.write(0xCC); // Обращение ко всем датчикам
    ds.write(0x44); // Команда на конвертацию
  }
  else
  {
    int temp;
    ds.reset();
    ds.select(addr);
    ds.write(0xBE);                      // Считывание значения с датчика
    temp = (ds.read() | ds.read() << 8); // Принимаем два байта температуры
    temperature = round((float)temp / 16.0);
  }
  flagDall = !flagDall; // Инверсия признака операции для следующей итерации
}
ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

если с точностью до градуса устраивает, то почему бы и нет )))

AlexZR
Offline
Зарегистрирован: 08.02.2016

ua6em пишет:
если с точностью до градуса устраивает, то почему бы и нет )))

да, устраивает, еще вопрос, есть смысл отказаться от float ?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

AlexZR пишет:
еще вопрос, есть смысл отказаться от float ?
Этого если хватает и памяти и быстродействия, то не выпендривайтесь, если надо экономить - отказывайтесь.

AlexZR
Offline
Зарегистрирован: 08.02.2016

еще вопрос, как правильно запитать ds18b20, 3.3 вольта или 5 вольт ?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

AlexZR пишет:

еще вопрос, как правильно запитать ds18b20, 3.3 вольта или 5 вольт ?

Зачем задавать вопросы, ответы на которые Вам и так известны? В даташите что написано?

AlexZR
Offline
Зарегистрирован: 08.02.2016

залил прошивку, все равно, что то не так (((

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

AlexZR пишет:

да, устраивает, еще вопрос, есть смысл отказаться от float ?

Как я уже писал, вот мне, например, глубоко по-барабану, скока сейчас на улице, -27 или -27.2 °С  Тяпнуть для сугреву хочется одинаково. 

AlexZR
Offline
Зарегистрирован: 08.02.2016

ЕвгенийП пишет:
зачем задавать вопросы, ответы на которые Вам и так известны? В даташите что написано?

все знают только дураки...

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

AlexZR пишет:

ЕвгенийП пишет:
зачем задавать вопросы, ответы на которые Вам и так известны? В даташите что написано?

все знают только дураки...

Нет. Всё знают только васерманы. Дураки не умеют читать и не хотят учицца. 

AlexZR
Offline
Зарегистрирован: 08.02.2016

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

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

Матьтваю, тебе лень открыть и почитать даташит?  Дело 1 минуты.  Ты вопрос свой по клавишам долбишь дольше, чем можно прочитать в оф. документации.  Задумайся уже.