DS18b20 показывает -127

did5
Offline
Зарегистрирован: 11.03.2014

Всем привет,

нужна помощь. Собрал простенькую схему - Arduino UNO, 3 датчика DS18b20 (один водонепронецаемый). Подключил, как подказано на схеме.

Простой скетч:

#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 10
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void setup(void){
Serial.begin(9600);
sensors.begin();
} 

void loop(void){
sensors.requestTemperatures();
Serial.print("T0=");
Serial.println(sensors.getTempCByIndex(0)); 
delay(200);
Serial.print("T1=");
Serial.println(sensors.getTempCByIndex(1));
delay(200);
Serial.print("T2=");
Serial.println(sensors.getTempCByIndex(2));
} 

Залил на Ардуино, открыл монитор, все работает, 3 температуры отображаются. Для теста один из датчиков (водонепронецаемый, который потом будет висеть на улице) засунул в морозилку. Температура начала падать, перешла в минус, но когда дошла до -15,75 произошел какой-то глюк. Следующее значение температуры датчик показал -127.00. Остальные два датчика продолжали отображать комнатную температуру. Когда вытащил датчик из морозилки, температура начала повышаться и он снова начал показывать нормальное значение -15.75, -13,26 и т.д.

От сюда возникает вопрос - что за напасть? Почему датчик тупит, когда температура становится ниже минус 16 градусов?

 

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

did5 пишет:

От сюда возникает вопрос - что за напасть? Почему датчик тупит, когда температура становится ниже минус 16 градусов?

Я бы попробовал другой датчик или пару. Возможно в этом где-то контакты расходятся при охлаждении...

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

delay(1000);

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

Возможно стоит добавить паузу после 13 строки.

did5
Offline
Зарегистрирован: 11.03.2014

Пробовал разные варианты: другой датчик ставить, отключить все кроме одного, использовал другой скетч (взял стандартный из примеров) и т.д. Результат тот же самый.

did5
Offline
Зарегистрирован: 11.03.2014

Попробую увеличить задержку, отпишусь

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

исходник билиотеки содержит:

// Error Codes
#define DEVICE_DISCONNECTED -127

Попробуйте подключить по трём проводам.

pka_ua
Offline
Зарегистрирован: 03.11.2014

Если посмотреть на Вашу схему, то Data от датчика присоединена к 9 пину. А строка

#define ONE_WIRE_BUS 10

указывает на 10-й пин.

did5
Offline
Зарегистрирован: 11.03.2014

Схему взял с инета, чтобы не рисовать самому. У меня датчик подключен к 10 пину. 

did5
Offline
Зарегистрирован: 11.03.2014

toc пишет:
исходник билиотеки содержит: // Error Codes #define DEVICE_DISCONNECTED -127 Попробуйте подключить по трём проводам.

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

А разве у меня подключено не по 3-м проводам?

pka_ua
Offline
Зарегистрирован: 03.11.2014

Вот здесь http://forum.arduino.cc/index.php?topic=252071.0 обсуждалась именно эта проблема. Если коротко, то обсуждающие решили, что всему виной поддельные китайские датчики.

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

did5, попробуйте еще вариант без DallasTemperature, на OneWire. А вдруг ?..

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

did5, извиняюсь. Перепутал с темой про термореле. Там на картинке два провода.

did5
Offline
Зарегистрирован: 11.03.2014

pka_ua пишет:

Вот здесь http://forum.arduino.cc/index.php?topic=252071.0 обсуждалась именно эта проблема. Если коротко, то обсуждающие решили, что всему виной поддельные китайские датчики.

Прочитал обсуждение по ссылке, полноценного решения они там так и не нашли. Но есть один вариант, можно попробовать библиотеки отсюда - http://www.hacktronics.com/Tutorials/arduino-1-wire-tutorial.html. Кому-то помогло. 

a5021
Offline
Зарегистрирован: 07.07.2013

Вот полный текст процедуры из библиотеки OneWire

uint8_t OneWire::read_bit(void)
{
	IO_REG_TYPE mask=bitmask;
	volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg;
	uint8_t r;

	noInterrupts();
	DIRECT_MODE_OUTPUT(reg, mask);
	DIRECT_WRITE_LOW(reg, mask);
	delayMicroseconds(3);
	DIRECT_MODE_INPUT(reg, mask);	// let pin float, pull up will raise
	delayMicroseconds(10);
	r = DIRECT_READ(reg, mask);
	interrupts();
	delayMicroseconds(53);
	return r;
}

Критическая, на мой взгляд, величина передается процедуре delayMicroseconds(10).  В разном коде (разных библиотек или просто реализаций)  я наблюдал значения от 6 до 12. Попробуйте эту десятку уменьшить или увеличить немного.

did5
Offline
Зарегистрирован: 11.03.2014

did5 пишет:

Прочитал обсуждение по ссылке, полноценного решения они там так и не нашли. Но есть один вариант, можно попробовать библиотеки отсюда - http://www.hacktronics.com/Tutorials/arduino-1-wire-tutorial.html. Кому-то помогло. 

Заработало! Скачал библиотеку DallasTemperature с этого сайта http://www.hacktronics.com/Tutorials/arduino-1-wire-tutorial.html. Версия у этой библиотеки и моей совпали, но при детальном сравнении выявились различия. С новой библиотекой датчик DS18B20 стал показывать корректную температуру ниже -15.75.

a5021
Offline
Зарегистрирован: 07.07.2013

И что за различия, если не секрет?

did5
Offline
Зарегистрирован: 11.03.2014

a5021 пишет:

И что за различия, если не секрет?

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

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

did5 пишет:

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

По-хорошему, надо диффы различающихся файлов, либо md5 чексумму рабочего архива на худой конец...

Gummi_bear
Offline
Зарегистрирован: 23.11.2014

Я тоже напоролся на этот баг, добрался уже до работы с DS18B20 напрямую, по 1-wire, даже что-то получилось :-)

Хотя по сути, получилось что я писал подобие библиотеки Dallas на свой лад, и пришлось бы еще код перелопачивать :-( т.к. в тепле все работало, а при испытаниях на морозе вылез этот глюк.

Времени и нервов убил х.з. сколько :-(

Теперь буду ждать морозов, и испытывать библиотеку!

Автору благодарность, особенно если в облако выложит оба архива с библиотеками, на всякий случай.

 

По результатам отпишусь! (если кому интересно)

did5
Offline
Зарегистрирован: 11.03.2014

Вот обе библиотеки, выложил на Яндекс.Диск:

1. DallasTemperature.zip - с этой библиотекой нормально отображается минусовая температура (https://yadi.sk/d/DsfPqoqsd7g8f)

2. DallasTemperature(-127).zip - с этой библиотекой при температуре меьше -16 датчик показывает -127. (https://yadi.sk/d/g9SMy6fMd7gMS)

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

а я делал так, только на морозе не тестил. кто то кидал код, я немного переделал

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

#include <OneWire.h>

OneWire ds (A5);
byte addr[8];

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

void loop(){
  if (ds.search(addr)!=1){//==========================================Поиск устройств
    ds.reset_search  ();
    delay  (250);
    return;
  }
  Serial.print("{");
  for(byte i=0;i<7;i++) {
    Serial.print("0x");
    if(addr[i]<10) Serial.print("0");
    Serial.print(addr[i], HEX);
    Serial.print(", ");
  }
  Serial.print("0x");
  if(addr[7]<10) Serial.print("0");
  Serial.print (addr[7], HEX);
  Serial.println("};");
  delay(1000);
}



адреса постоянно шлются в терминал, повторяются. копируешь свои и вставляешь в этот код

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

#include <OneWire.h>

OneWire ds (A5);
byte data[12];
byte addr1[8] = {0x28, 0x97, 0xC5, 0xD5, 0x03, 0x00, 0x00, 0xBE};
byte addr2[8] = {0x28, 0xFF, 0xFE, 0x24, 0x61, 0x04, 0x00, 0x07};
unsigned int raw;
float temp1, temp2;

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

void loop(){
  temp1 = DS18B20(addr1);
  temp2 = DS18B20(addr2);
  
  Serial.print("Temp1=");
  Serial.print(temp1);
  Serial.print("\t");
  Serial.print("Temp2=");
  Serial.println(temp2);
  Serial.flush(); //очищаем значения порта
}

//==================================================================================
//                             Считывание температуры
//==================================================================================
float DS18B20(byte *adres){
  ds.reset();
  ds.select(adres);
  ds.write(0x44,1); // start conversion, with parasite power on at the end
  delay(1000);
  ds.reset();
  ds.select(adres);
  ds.write(0xBE); // Read Scratchpad
  for (byte i = 0; i < 9; i++) { // we need 9 bytes
    data[i] = ds.read ();
  }
  raw =  (data[1] << 8) | data[0];//=======Пересчитываем в температуру
  float celsius =  (float)raw / 16.0;
  return celsius;
}

 

dmw
Offline
Зарегистрирован: 24.03.2013

did5 пишет:
Вот обе библиотеки, выложил на Яндекс.Диск:

1. DallasTemperature.zip - с этой библиотекой нормально отображается минусовая температура (https://yadi.sk/d/DsfPqoqsd7g8f)

2. DallasTemperature(-127).zip - с этой библиотекой при температуре меьше -16 датчик показывает -127. (https://yadi.sk/d/g9SMy6fMd7gMS)

Это абсолютно идентичные архивы. Выложите еще раз пожалуйста.

did5
Offline
Зарегистрирован: 11.03.2014

dmw пишет:

Это абсолютно идентичные архивы. Выложите еще раз пожалуйста.

 

С чего Вы взяли? Хеши (MD5) у них разные:

1. DallasTemperature(-127).zip - 0855BF104D427C2880DD7BA0B69EB819

2. DallasTemperature.zip - 1E4EC2201A8FCD4D16B06E317EC0C7BA

KVadik
KVadik аватар
Offline
Зарегистрирован: 15.06.2014

Берите крайнюю версию. Ну и OneWire тоже. Кстати одной OneWire более чем достаточно, смотрите её примеры.

dmw
Offline
Зарегистрирован: 24.03.2013

did5 пишет:

С чего Вы взяли? Хеши (MD5) у них разные:

1. DallasTemperature(-127).zip - 0855BF104D427C2880DD7BA0B69EB819

2. DallasTemperature.zip - 1E4EC2201A8FCD4D16B06E317EC0C7BA

Скачал, распаковал, сравнил исходники построчно - абсолютно идентичные.

capup
Offline
Зарегистрирован: 27.12.2014

У меня тоже было "-127"

Спасибо toc от 05/11/2014 - 09:09

/ Error Codes
#define DEVICE_DISCONNECTED -127

Это значит, что минусовый провод отвалился

Если температура 0 - то резистора между  +  и сигналом забыл

Конечно должно насторожить -127 - байт "наоборот"

Всем спасибо!

msng
Offline
Зарегистрирован: 07.06.2012

did5 пишет:

Вот обе библиотеки, выложил на Яндекс.Диск:

1. DallasTemperature.zip - с этой библиотекой нормально отображается минусовая температура (https://yadi.sk/d/DsfPqoqsd7g8f)

2. DallasTemperature(-127).zip - с этой библиотекой при температуре меьше -16 датчик показывает -127. (https://yadi.sk/d/g9SMy6fMd7gMS)

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

на просторах интернета нашел нужную библиотеку  (ссылка на источник) я так понимаю вы ее тоже тут нашли

проблема решилась, поправте ссылку в сообщении 20, на библиотеку на яндекс диске.

Еще раз спасибо!!!!

 

dmw пишет:

Это абсолютно идентичные архивы. Выложите еще раз пожалуйста.

посмотрите на ссылку в моем сообщении проблема думаю должна решиться, по крайне мере у меня решилась

ZEMLEKOP
Offline
Зарегистрирован: 24.12.2014

Плиз реальную схему . Или фото в студию. На чем вывод организован? Если не секрет.

Тема заинтересовала есть над чем подумать и поучится. Спасибо .

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

ZEMLEKOP пишет:

Плиз реальную схему . Или фото в студию. На чем вывод организован? Если не секрет.

Тема заинтересовала есть над чем подумать и поучится. Спасибо .

Реальную схему чего, простите?

ZEMLEKOP
Offline
Зарегистрирован: 24.12.2014

В конечном плане вывод температуры куда (дисплей или передача дальше)  считать это половина идеи а вся ?

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

ZEMLEKOP пишет:

В конечном плане вывод температуры куда (дисплей или передача дальше)  считать это половина идеи а вся ?

Да вы на схему гляньте, похоже ТС какой то народный мониторинг с МК90 ваял.

dmw
Offline
Зарегистрирован: 24.03.2013

msng пишет:

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

на просторах интернета нашел нужную библиотеку  (ссылка на источник) я так понимаю вы ее тоже тут нашли

проблема решилась, поправте ссылку в сообщении 20, на библиотеку на яндекс диске.

Еще раз спасибо!!!!

Вот с этой библиотекой все заработало верно! Спасибо.

skyspirit
Offline
Зарегистрирован: 27.02.2015

А как такой скеч доработать чтоб на экране LCD 5110 выводить данные

 
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <OneWire.h>
OneWire ds(9);
 
void setup() {
Serial.begin(9600);
}
 
void loop() {
 
byte data[2];
ds.reset();
ds.write(0xCC);
ds.write(0x44);
delay(750);
ds.reset();
ds.write(0xCC);
ds.write(0xBE);
data[0] = ds.read();
data[1] = ds.read();
int Temp = (data[1]<< 8)+data[0];
Temp = Temp>>4;
Serial.println(Temp);
}

 

maksim
Offline
Зарегистрирован: 12.02.2012

Так же как и доработать этот:

void setup() {
}

void loop() {
  delay(1000);
  delay(1000);
}

, что бы стал мигать светодиод.

skyspirit
Offline
Зарегистрирован: 27.02.2015
Вот кому интересно разобрался с выводом на экран.
Небольшой вопрос зачем эта функция  myGLCD.clrScr();  без неё то же все работает? 
 
#include <OneWire.h> // библиотека датчика температуры
#include <LCD5110_Graph.h> // библиотека экрана
OneWire ds(10); // вывод подключения датчика
LCD5110 myGLCD(4, 5, 6, 8, 7); //выводы Ардуино
// pin 4 - Serial clock out (SCLK)
// pin 5 - Serial data out (DIN)
// pin 6 - Data/Command select (D/C)
// pin 8 - LCD chip select (CS)
// pin 7 - LCD reset (RST)
 
 
extern unsigned char SmallFont[];
extern unsigned char BigNumbers[];
 
void setup() {
  
  myGLCD.InitLCD(65);//контраст экрана
 
  myGLCD.setFont(SmallFont);
  myGLCD.setFont(BigNumbers);
 
Serial.begin(9600); 
}
 
void loop() {
  
byte data[2];
ds.reset(); 
ds.write(0xCC);
ds.write(0x44);
delay(750);
ds.reset();
ds.write(0xCC);
ds.write(0xBE);
data[0] = ds.read(); 
data[1] = ds.read();
int Temp = (data[1]<< 8)+data[0];
Temp = Temp>>4;
Serial.println(Temp);
 
  myGLCD.clrScr(); // Очистка экрана
  myGLCD.setFont(SmallFont);
  myGLCD.print("Temperature", CENTER, 10); 
  
  myGLCD.setFont(BigNumbers); //вывод крупных цыфр
  myGLCD.printNumF(Temp,0, CENTER, 23);
  
  myGLCD.update(); // Вывод вместимого буфера на дисплей
 delay (100); // Задержка 0,1 с
}
 
 
SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

jeka_tm , можешь подсказать ?   
на примере этого

#include <OneWire.h>

OneWire ds (A5);
byte data[12];
byte addr1[8] = {0x28, 0x97, 0xC5, 0xD5, 0x03, 0x00, 0x00, 0xBE};
byte addr2[8] = {0x28, 0xFF, 0xFE, 0x24, 0x61, 0x04, 0x00, 0x07};
unsigned int raw;
float temp1, temp2;

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

void loop(){
  temp1 = DS18B20(addr1);
  temp2 = DS18B20(addr2);
  
  Serial.print("Temp1=");
  Serial.print(temp1);
  Serial.print("\t");
  Serial.print("Temp2=");
  Serial.println(temp2);
  Serial.flush(); //очищаем значения порта
}

//==================================================================================
//                             Считывание температуры
//==================================================================================
float DS18B20(byte *adres){
  ds.reset();
  ds.select(adres);
  ds.write(0x44,1); // start conversion, with parasite power on at the end
  delay(1000);
  ds.reset();
  ds.select(adres);
  ds.write(0xBE); // Read Scratchpad
  for (byte i = 0; i < 9; i++) { // we need 9 bytes
    data[i] = ds.read ();
  }
  raw =  (data[1] << 8) | data[0];//=======Пересчитываем в температуру
  float celsius =  (float)raw / 16.0;
  return celsius;
}

вообще-то датчиков = три
задача - определить присутствие датчиков
- первый ( управляющий ) - при неполадке систему выключить , включить тревогу
- второй и третий ( информационные ) - при неполадке уведомить , но систему не выключать

по схеме "один пин - один датчик" всё понятно , ds.reset();  возвращает 1 при отклике датчика , иначе 0
как определить присутствие каждого датчика в схеме "один пин - гирлянда из трёх датчиков" ?
какой из датчиков откликнется на 
ds.reset(); ?

в процедуре float DS18B20(byte *adres) первый ds.reset();  обнуляет все датчики ?
а второй 
ds.reset(); - только адресуемый датчик ?

или надо проверять присутствие датчика после строки ds.select(adres); новым ds.reset(); ?
датчик же уже адресован...

В наличии пока один датчик , опыты проводить не на чем...
Спасибо :)

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

SU-27-16, а что тебя в нем смущает?

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

bwn пишет:

SU-27-16, а что тебя в нем смущает?

извини , дописывал сообщение....

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

Просто проверь через перебор доступных адресов. Типа:

//***Проверка количества датчиков Даллас******
void colDall(){
  while ( ds.search(addr) ){ //Цикл перебора адресов датчиков
    flag[0]++; //Увеличение переменной числа датчиков
    ledBlink(1000);
  }
  if (flag[0] > 5) { //Условие превышения максимального количества
  //Если мало, увеличить размерность массива
    Serial.println("Mnogo datchikov"); //Здесь сообщение и обработка ошибки
    delay (5000); //Задержка для перезагрузки
  }
} 
//***----------------------------------------------------------------------------------

Это огрызок из скетча автоматического определения количества и принадлежности. Через ds.search(addr) можешь сверять все адреса последовательно. Она начинает считывать с минимального адреса последовательно.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

SU-27-16 честно сказать не знаю 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

ещё...
 

//==================================================================================
//                             Считывание температуры
//==================================================================================
float DS18B20(byte *adres){
  ds.reset();
  ds.select(adres);
  ds.write(0x44,1); // start conversion, with parasite power on at the end
  delay(1000);
  ds.reset();
  ds.select(adres);
  ds.write(0xBE); // Read Scratchpad
  for (byte i = 0; i < 9; i++) { // we need 9 bytes
    data[i] = ds.read ();
  }
  raw =  (data[1] << 8) | data[0];//=======Пересчитываем в температуру
  float celsius =  (float)raw / 16.0;
  return celsius;
}

эта штука тормозит систему на секунду для каждого датчика...
думаю переделать её так
- сброс , опрос датчиков , пересчёт температуры , сброс , старт конверсии
- вызывать процедуру по миллис с периодичностью 750....2000 mS
- система будет свободна же , пока датчики конвертируют температуру ?
при первом проходе лупа все датчики вернут 4095,9 градусов , но потом покажут же правильно ?

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

bwn пишет:

Просто проверь через перебор доступных адресов. Типа:

//***Проверка количества датчиков Даллас******
void colDall(){
  while ( ds.search(addr) ){ //Цикл перебора адресов датчиков
    flag[0]++; //Увеличение переменной числа датчиков
    ledBlink(1000);
  }
  if (flag[0] > 5) { //Условие превышения максимального количества
  //Если мало, увеличить размерность массива
    Serial.println("Mnogo datchikov"); //Здесь сообщение и обработка ошибки
    delay (5000); //Задержка для перезагрузки
  }
} 
//***----------------------------------------------------------------------------------

Это огрызок из скетча автоматического определения количества и принадлежности. Через ds.search(addr) можешь сверять все адреса последовательно. Она начинает считывать с минимального адреса последовательно.

кататак ?

поиск датчика_1 по адресу
нашли - замер Т
не нашли - авария

поиск датчика_2,3 по адресу

нашли - замер Т

не нашли - информирование

спасибо , буду пробовать :)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

jeka_tm пишет:

SU-27-16 честно сказать не знаю 

дык , всё равно - спасибо :)

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

Давай одну команду на общую конвертацию, а потом считывай.

//***Функция считывания температуры c Далласов*****
void dallRead(unsigned long interval){
  static unsigned long prevTime = 0;
  if (millis() - prevTime > interval) { //Проверка заданного интервала
  static boolean flagDall = 0; //Признак операции
  prevTime = millis();
  flagDall =! flagDall; //Инверсия признака
  if (flagDall) {
    ds.reset();
    ds.write(0xCC); //Обращение ко всем датчикам
    ds.write(0x44); //Команда на конвертацию
    flag[1] = 1; //Время возврата в секундах
  }
  else {
    byte i;
    int temp;
    for (flag[0] = 0; flag[0] < EEPROM.read(1023); flag[0]++){ //Перебор количества датчиков
        adresDall(flag[0]); //Получение адреса датчика
     ds.reset();
     ds.select(addr);
     ds.write(0xBE); //Считывание значения с датчика
     temp = (ds.read() | ds.read()<<8); //Принимаем два байта температуры
     Temp[flag[0]][0] = temp*100/4/4; //Температура в целочисленном формате *100
     //два знака после запятой.
     flag[1] = 10; //Время возврата в секундах
     }
   }
  }
}
//--------------------------------------------------

Производим  вход в функцию с разными интервалами flag[1].

P/S у меня адреса в епроме, 17-18 строка берут оттуда.

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

SU-27-16 пишет:

bwn пишет:

Просто проверь через перебор доступных адресов. Типа:

//***Проверка количества датчиков Даллас******
void colDall(){
  while ( ds.search(addr) ){ //Цикл перебора адресов датчиков
    flag[0]++; //Увеличение переменной числа датчиков
    ledBlink(1000);
  }
  if (flag[0] > 5) { //Условие превышения максимального количества
  //Если мало, увеличить размерность массива
    Serial.println("Mnogo datchikov"); //Здесь сообщение и обработка ошибки
    delay (5000); //Задержка для перезагрузки
  }
} 
//***----------------------------------------------------------------------------------

Это огрызок из скетча автоматического определения количества и принадлежности. Через ds.search(addr) можешь сверять все адреса последовательно. Она начинает считывать с минимального адреса последовательно.

кататак ?

поиск датчика_1 по адресу
нашли - замер Т
не нашли - авария

поиск датчика_2,3 по адресу

нашли - замер Т

не нашли - информирование

спасибо , буду пробовать :)

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

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

а адреса датчиков фиксированные? Или надо предусмотреть возможность их замены без перепрошивки (автоопределение)?

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

наикорявейший код , "левой ногой набирал"
газКотёл с подачей , например 60 градусов ( уставка - мембранно-капиллярный регулятор ) - отстой , короче
сигнал на включение от радиоТермометра из любой зоны дома
очень часто подача и обратка падают аж до 20 градусов :)

ТЗ :
- включать котёл на подачу 60 гр по команде от радиоТермометра
- поддерживать Т подачи , например 35 гр не зависимо от команд радиоТермометра
- показывать Т подачи , обратки , наружного воздуха
- управлять Т подачи ( + 0....8 гр ) в обоих режимах в зависимости от Т 
наружного воздуха
  ( это на следОтопСезон )

Проблема - если котёл включился и датчик отсох - реле управления котлом НЕ ОТКЛЮЧАЕТСЯ :(
пока не отключается..... , кажися с вашей помощью будет отключаться :)

Состав устройства :
- нано
- реле упрКотлом ( он требует полной гальванической развязки ) , PC817 хотел - придётся отказаться
- RGB - синий = сохранение Т воды , красный - рулит радиоМодуль , зелёный проблесковый - опрос датчиков
- проблесковый красный - авария датчика - НО КАКОГО ? ( по версии ЭТОГО кода ) :)
- пин анализа активности радиоТермометра

.....отвлёкся для понимания вами чего мне хочется :)

#include <OneWire.h>
OneWire DS ( 8 );
byte data[ 12 ];
// 1447C4+233AA - датчик подачи
byte addrOUTheater[ 8 ] = { 0x28 , 0xFF , 0x86 , 0x69 , 0x63 , 0x14 , 0x02 , 0x36 };
// 1447C4+233AA - датчик обратки
byte addrINheater[ 8 ]  = { 0x28 , 0xFF , 0x86 , 0x69 , 0x63 , 0x14 , 0x02 , 0x36 };
// 1447C4+233AA - датчик уличный
byte addrOUThome[ 8 ]  = { 0x28 , 0xFF , 0x86 , 0x69 , 0x63 , 0x14 , 0x02 , 0x36 };
float temperOUTheater;
float temperINheater;
float temperOUThome;
//#########################################################################
float setTemperWater = 28.0;  // уставка подачи по воде                   #
float setHisterWater =  1.0;  // гизтерезис уставки подачи по воде        #
float setTemperAir =   60.0;  // уставка подачи по воздуху                #
float setHisterAir =    2.0;  // гизтерезис уставки подачи по воздуху     #
//#########################################################################
boolean statusKOTELoffOn = 0;      // выкл = 0 , вкл = 1
#define pinRelay 6
#define pinRFtx  7
boolean statusKOTELwaterAir = 0;   // по воде = 0 , по воздуху = 1
#define pinLedGreen A0             // контроль работы системы
#define pinLedBlue  A1             // контроль по воде
#define pinLedRed   A2             // контроль по воздуху
//==================================================================================
//                          Считывание температуры
//==================================================================================
float DS18B20( byte *adress )
{
  unsigned int raw;
  DS.reset();
  DS.select( adress );
  DS.write( 0x44 , 1 );
  delay( 740 );
  digitalWrite( pinLedGreen , LOW );
  delay( 10 );
  digitalWrite( pinLedGreen , HIGH );
  DS.reset();
  DS.select( adress );
  DS.write( 0xBE );
  for ( byte i = 0; i < 9; i++ )
  {
    data[ i ] = DS.read();
  }
  raw = ( data[ 1 ] << 8 ) | data[ 0 ];
  float celsius = ( float ) raw / 16.0;
  return celsius;
}
//==================================================================================
void setup()
{
  Serial.begin( 115200 );
  pinMode( pinRelay , OUTPUT );
  digitalWrite( pinRelay , HIGH );
  pinMode( pinRFtx , INPUT );
  digitalWrite( pinRFtx , HIGH );
  pinMode( pinLedGreen , OUTPUT );
  digitalWrite( pinLedGreen , HIGH );
  pinMode( pinLedBlue , OUTPUT );
  digitalWrite( pinLedBlue , HIGH );
  pinMode( pinLedRed , OUTPUT );
  digitalWrite( pinLedRed , HIGH );
  delay( 1000 );
}
//==================================================================================
void loop()
{
boolean present = DS.reset();
while( ! present )
{
  digitalWrite( pinRelay , HIGH );
  Serial.println( " Error DS18B20 " );
  present = DS.reset();
  digitalWrite( pinLedRed , HIGH );
  digitalWrite( pinLedGreen , HIGH );
  digitalWrite( pinLedBlue , HIGH );
  delay( 50 );
  digitalWrite( pinLedRed , LOW );
  delay( 50 );
}
  temperOUTheater = DS18B20( addrOUTheater );
  temperINheater  = DS18B20( addrINheater );
  temperOUThome   = DS18B20( addrOUThome );
  statusKOTELwaterAir = ! digitalRead( pinRFtx );
  if ( ! statusKOTELwaterAir )
  {
    if ( temperOUTheater < setTemperWater - setHisterWater )
    {
      statusKOTELoffOn = 1;
    }
    if ( temperOUTheater > setTemperWater + setHisterWater )
    {
      statusKOTELoffOn = 0;
    }
  }
  else
  {
    if ( temperOUTheater < setTemperAir - setHisterAir )
    {
      statusKOTELoffOn = 1;
    }
    if ( temperOUTheater > setTemperAir + setHisterAir )
    {
      statusKOTELoffOn = 0;
    }
  }
  if ( statusKOTELoffOn )
  {
    if ( statusKOTELwaterAir )
    {
      digitalWrite( pinLedBlue , HIGH );
      digitalWrite( pinLedRed ,  LOW );
    }
    else
    {
      digitalWrite( pinLedBlue , LOW );
      digitalWrite( pinLedRed ,  HIGH );
    }
  }
  else
  {
    digitalWrite( pinLedBlue , HIGH );
    digitalWrite( pinLedRed ,  HIGH );
  }
  digitalWrite( pinRelay , ! statusKOTELoffOn );
///*
  Serial.print( " OUT = " );
  Serial.print( temperOUTheater , 1 );
  Serial.print( "   IN = " );
  Serial.print( temperINheater , 1 );
  Serial.print( "   STREET = " );
  Serial.println( temperOUThome , 1 );
  Serial.print( " SET WATER = " );
  Serial.print( setTemperWater , 1 );
  Serial.print( "  HISTER =  " );
  Serial.println( setHisterWater , 1 );
  Serial.print( " SET   AIR = " );
  Serial.print( setTemperAir , 1 );
  Serial.print( "  HISTER =  " );
  Serial.println( setHisterAir , 1 );
  if ( statusKOTELoffOn )
  {
    Serial.print( "   KOTEL >>> ON" );
    if ( statusKOTELwaterAir )
    {
      Serial.println( "   CONTROL >>> AIR" );
    }
    else
    {
      Serial.println( "   CONTROL >>> WATER" );
    }
  }
  else
  {
    Serial.println( "   KOTEL >>> OFF" );
  }
  Serial.println( "=====================================================================" );
//*/
}
//==================================================================================

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

bwn пишет:

Давай одну команду на общую конвертацию, а потом считывай.

//***Функция считывания температуры c Далласов*****
void dallRead(unsigned long interval){
  static unsigned long prevTime = 0;
  if (millis() - prevTime > interval) { //Проверка заданного интервала
  static boolean flagDall = 0; //Признак операции
  prevTime = millis();
  flagDall =! flagDall; //Инверсия признака
  if (flagDall) {
    ds.reset();
    ds.write(0xCC); //Обращение ко всем датчикам
    ds.write(0x44); //Команда на конвертацию
    flag[1] = 1; //Время возврата в секундах
  }
  else {
    byte i;
    int temp;
    for (flag[0] = 0; flag[0] < EEPROM.read(1023); flag[0]++){ //Перебор количества датчиков
        adresDall(flag[0]); //Получение адреса датчика
     ds.reset();
     ds.select(addr);
     ds.write(0xBE); //Считывание значения с датчика
     temp = (ds.read() | ds.read()<<8); //Принимаем два байта температуры
     Temp[flag[0]][0] = temp*100/4/4; //Температура в целочисленном формате *100
     //два знака после запятой.
     flag[1] = 10; //Время возврата в секундах
     }
   }
  }
}
//--------------------------------------------------

Производим  вход в функцию с разными интервалами flag[1].

P/S у меня адреса в епроме, 17-18 строка берут оттуда.

круто ! копирую , спасибо !

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Tomasina пишет:

а адреса датчиков фиксированные? Или надо предусмотреть возможность их замены без перепрошивки (автоопределение)?

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

 

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

Делаешь:  while ( ds.search(addr) ), сравниваешь считанный и записанный адрес побайтово, если байт не равен, возвращаем байт с номером признака датчика - 9й. Номер признака присваешь сам - адрес+байт признака. Массив с адресами должен быть отсортирован по возрастанию. На выходе из цикла не забывать команду ds.reset_search();