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

see_watson
Offline
Зарегистрирован: 03.11.2016
#include <OneWire.h>
OneWire  ds(2);
byte addr[8]={0x28,0xFF,0x8D,0xEF,0x8B,0x16,0x03,0xBB};
volatile int celsius;
void setup(void) {
Serial.begin(9600);
pinMode (13,OUTPUT);
WDTCSR=(1<<WDCE)|(1<<WDE); //установить биты WDCE WDE (что б разрешить запись в другие биты
WDTCSR=(1<<WDIE)| (1<<WDP2)|(1<<WDP1); // разрешение прерывания + выдержка 1 секунда
// (55 страница <a href="<a href="http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf" rel="nofollow">http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf</a>" rel="nofollow">даташита</a>)
// снять все ремарки если нужно поменять разрешение
  ds.reset(); // сброс шины
  ds.select(addr); //выставить адрес
  ds.write(0x4E); // разрешение записать конфиг
//  ds.write(0x7F); // Th контроль температуры макс 128грд
//  ds.write(0xFF); //Tl контроль температуры мин -128грд
  ds.write(0x60); // 0x60 12-бит разрешение, 0x00 -9бит разрешение
  //ds.write(0x3F); // точность 0,5гр = 1F; 0,25гр = 3F; 0,125гр = 5F; 0,0625гр = 7F тоже не работает

}

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 байта       
        }
}

попробовал с адресом, не работает.

 ds.write(0x3F); // точность 0,5гр = 1F; 0,25гр = 3F; 0,125гр = 5F; 0,0625гр = 7F тоже не работает

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

see_watson, если вы зашили в том виде, в котором сейчас скетч -то 17ой  строчкой вы установили аларм -предел макс. температуры

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

dimax пишет:

see_watson, если вы зашили в том виде, в котором сейчас скетч -то 17ой  строчкой вы установили аларм -предел макс. температуры

Отнюдь, 17-я как раз 12 бит разрешение. 
see_watson, а что на монитор выводит?
 

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

bwn, если вы помните -эти строчки  в начале топика я писал, стало быть немножко в курсе что за что отвечает :) Там засада в последовательности операций. Невозможно запрограмммировать разрядность не запрограммировав предварительно обе температуры. Поэтому в данном случаен (с закоментированными пердыдщими строками) 17 строка устанавливает верхнюю температуру аларма :) Поэтому я написал снять ВСЕ ремарки. А товарищ пренебрёг этим..

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

ОК, упустил.(((
Чет показалось, что одной строчкой менял, давно это было.)))

see_watson
Offline
Зарегистрирован: 03.11.2016

dimax и bwn, пробовал из примера dimax , пост 4 - 

ds.write(0x60); // 0x60 12-бит разрешение, 0x00 -9бит разрешение

там так и написано.

Если раскоментирую все строки

ds.reset(); // сброс шины
ds.select(addr); //выставить адрес
ds.write(0x4E); // разрешение записать конфиг
ds.write(0x7F); // Th контроль температуры макс 128грд
ds.write(0xFF); //Tl контроль температуры мин -128грд
ds.write(0x60); // 0x60 12-бит разрешение, 0x00 -9бит разрешение
 

и добавляю

ds.write(0x7F); // точность 0,5гр = 1F; 0,25гр = 3F; 0,125гр = 5F; 0,0625гр = 7F

вродебы сдвиги есть,

но в сериал выдает до сотых(25.78, 25.66 и тд итп)

 

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

see_watson, изучите внимаьтельно аргументы функции  http://arduino.ru/Reference/Serial/Print

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

see_watson пишет:

и добавляю

ds.write(0x7F); // точность 0,5гр = 1F; 0,25гр = 3F; 0,125гр = 5F; 0,0625гр = 7F

Откуда вы эту строку выкопали? 

see_watson
Offline
Зарегистрирован: 03.11.2016

bwn пишет:

see_watson пишет:

и добавляю

ds.write(0x7F); // точность 0,5гр = 1F; 0,25гр = 3F; 0,125гр = 5F; 0,0625гр = 7F

Откуда вы эту строку выкопали? 

пост 177.

Закрадывается вопрос???

По датущиту погрешность 0.5°C а разрядность запилить можно 0.0625°C.

Для чего???? Толку 0 с такой погрешностью.

Тогда получается что поставил по умолчанию до десятых ( азм есть) и забыл .

PS. dimax, разобрался с выводом в сериал, но помоему эффект нулевой последние разряды вообще не меняютя. СПС за совет,

PS2

Плюнул, оствил до десятых с такой погрешностью.

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

see_watson пишет:

По датущиту погрешность 0.5°C а разрядность запилить можно 0.0625°C.Для чего???? Толку 0 с такой погрешностью.

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

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

see_watson пишет:

По датущиту погрешность 0.5°C а разрядность запилить можно 0.0625°C.

Для чего???? Толку 0 с такой погрешностью.

PS. dimax, разобрался с выводом в сериал, но помоему эффект нулевой последние разряды вообще не меняютя. СПС за совет,

По изменению разрядности, в данном случае обе строки идентичны (меняем 5 и 6 бит), но применяем какую то одну.
Погрешность и точность не одно и тоже. Погрешность величина всегда постоянная для конкретного экземпляра, любой измерительный прибор ее имеет. Для получения идентичных результатов каждый прибор проходит периодическую поверку, полученный результат отклонения учитывается при последующих измерениях. Требуемая точность зависит от задачи, для измерения уличной температуры достаточно целых градусов, комнатной - 0,5гр., в ректификаторе мне потребовалась вся шкала. 
С сериалом, ищите ошибку, все должно выводиться правильно.

see_watson
Offline
Зарегистрирован: 03.11.2016

BWN СПАСИБО за объяснение , чё-то сглупил.

допилил вот так. вроде работает.

#include <OneWire.h>
OneWire  ds(2);
byte addr[8]={0x28,0xFF,0x8D,0xEF,0x8B,0x16,0x03,0xBB};
volatile int celsius;
void setup(void) {
Serial.begin(9600);
pinMode (13,OUTPUT);
WDTCSR=(1<<WDCE)|(1<<WDE); //установить биты WDCE WDE (что б разрешить запись в другие биты
WDTCSR=(1<<WDIE)| (1<<WDP2)|(1<<WDP1); // разрешение прерывания + выдержка 1 секунда
// (55 страница <a href="<a href="<a data-cke-saved-href="http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf" href="http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf" rel="nofollow">http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf</a>" rel="nofollow"><a data-cke-saved-href="http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf" href="http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf" rel="nofollow">http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf</a></a>" rel="nofollow">даташита</a>)
// снять все ремарки если нужно поменять разрешение
  ds.reset(); // сброс шины
  ds.select(addr); //выставить адрес
  ds.write(0x4E); // разрешение записать конфиг
  ds.write(0x7F); // Th контроль температуры макс 128грд
  ds.write(0xFF); //Tl контроль температуры мин -128грд
  
  ds.write(0x7F); // точность 0,5гр = 1F; 0,25гр = 3F; 0,125гр = 5F; 0,0625гр = 7F

}

void loop(void) {
Serial.print("  Temperature = ");
Serial.println(celsius/16.0, 4);
}
 
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 байта       
        }
}
 

 

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

Вы только строки 12-18 закомментируйте обратно, не надо при каждом запуске ROM скрести.

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

Попробовал применить, и кроме считывания температуры еще добавил, что нужно было, с контролем времени. Все работает, спасибо

По времени 1.5 и 3 миллисекунды. Ардуина в принципе ничем не занимается почти все время

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

Sanyaba пишет:

*конденсатор желательно с низким ESR

 

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

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

Диод заряжает конденсатор и не даёт ему разряжаться когда в линии проскакивают "нули".
Поэтому датчик превращается из двухпроводного в как-бы трёхпроводный.
Но по двум проводам.
 

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

ааа.. разве что так..  но стоит ли экономить на одном проводнике?

схема вверху какой  практически дает результат по дальности?

smile-777
Offline
Зарегистрирован: 26.05.2017

smile-777
Offline
Зарегистрирован: 26.05.2017

Датчик рассчитан на работу по двухпроводной схеме с паразитным питанием.

Там внутри и конденсатор и диод есть.

Зачем городить схему? Упростить код?

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

Первое :

Другая особенность  DS18B20 - способность работать без внешнего питания.
Эта возможность предоставляется через подтягивающий резистор.
Высокий сигнал шины заряжает внутренний конденсатор  (CPP), который питает прибор,
когда на шине низкий уровень .
Этот метод носит название  « Паразитное питание ».
При этом максимальная измеряемая температура при этом  + 100 °C.
Для расширения диапазона температур до  + 125 °C необходимо использовать внешнее питание.

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

Ну схему то все равно городить придется, если даташиту верить.

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

Вот попробовал сваять с проверками и прочим. Чтобы при работе с датчиком не было проблем "потери сигнала" от датчика. Как показала практика, если этого не делать, то на груглосуточно работающем девайсе, с проверкой раз в 3 минуты температуры - раз в месяц или реже но прилетает тревога  -0,06С

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

float getTemp() {int ii; ii = 0;  label: //Serial.println(ci);
if (ii < 6)  {   // возвращает температуру с датчика
  byte data[12];   // и останавливает программу на секунду
  byte addr[8];
    if ( !ds.search(addr)) {
    Serial.println F("No more addresses.");
    Serial.println(addr[8]);
    ds.reset_search();
    delay(250);
     ++ii; goto label;
  }

 if (OneWire::crc8(addr, 7) != addr[7]) {  //проверка массива адреса на срц
      Serial.println F("CRC is not valid!");
      ++ii; goto label;
  }
  
  ds.search(addr); // 
  ds.reset_search();
  ds.reset();
  ds.select(addr);
  ds.write(0x44);
  delay(1000); wdt_reset();
  ds.reset();
  ds.select(addr);
  ds.write(0xBE);
  for (int i = 0; i < 9; i++) data[i] = ds.read();

  if (OneWire::crc8(data, 8) != data[8]) { // проверка црц считанной температуры.
      Serial.println F("Data CRC is not valid!");
      ++ii; goto label;
  }
   
  int raw = (data[1] << 8) | data[0]; // Переводим в температуру
  if (data[7] == 0x10) raw = (raw & 0xFFF0) + 12 - data[6];
  return raw / 16.0;
 }
}

 

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

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

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

Также у меня используются датчики открытия дверей и окон на основе DS2406 и герконов. Написал код совместной работы с DS18B20.

За основу взят код автора темы. 

#include <OneWire.h>
OneWire  ds(2);  // выбор пина ардуино, на котором висит шина 1-wire 

// ниже перечисление температур 

typedef enum Temper_enum
{
    KuhnyaC,            //0
    VannaNizC,          //1
    FreezeC,            //2
    UlicaC,             //3 
    
    size_array_Temp     //4 size
                   
} Temper_ENUM;   



// ниже соответствие адресов датчиков определённым температурам
byte ADDR_DS18B20 [size_array_Temp][8] =
{
{0x28, 0xFF, 0xB1, 0x43, 0x52, 0x15, 0x01, 0xDB}, //KuhnyaC   0
{0x28, 0xFF, 0xBA, 0x6C, 0x52, 0x15, 0x01, 0x41}, //VannaNizC 1
{0x28, 0xEE, 0x9B, 0x4D, 0x25, 0x16, 0x02, 0xC5}, //FreezeC   2
{0x28, 0x9D, 0xE5, 0x70, 0x01, 0x00, 0x00, 0xEE}  //UlicaC    3
};


// ниже сами переменные температур, изначально ставим +20*С
volatile int8_t  Temper[size_array_Temp] = 
{
  20,     //KuhnyaC   0
  20,     //VannaNizC 1
  20,     //FreezeC   2
  20      //UlicaC    3
};

// например, чтобы использовать переменную температуры на улице, пишем так: Temper[UlicaC] = 


// ниже перечисление булевых значений для датчиков на основе ds2406
typedef enum Windows_enum
{
    Window1Prihozh,     //0
    Window2Prihozh,     //1
    Window1Zal,         //2
    Window2Zal,         //3 
    
    size_array_Windows //4 size
                   
} Windows_ENUM;

// ниже сами булевые переменные окон, по умолчанию ставим, что все закрыты ("1");

volatile bool  DoorsWindows[size_array_Windows] = 
{
  1,     //Window1Prihozh
  1,     //Window2Prihozh 
  1,     //Window1Zal
  1      //Window2Zal
};

//адреса датчиков ds2406
byte ADDR_DS2406[size_array_Windows][8] = {
{0x12, 0xA1, 0xEE, 0x47, 0x00, 0x00, 0x00, 0x58}, //Window1Prihozh
{0x12, 0xA1, 0x43, 0x5C, 0x00, 0x00, 0x00, 0x58}, //Window2Prihozh 
{0x12, 0xA1, 0xEE, 0x5C, 0x00, 0x00, 0x04, 0x58}, //Window1Zal
{0x12, 0xA1, 0xEE, 0x5C, 0x00, 0x00, 0x00, 0x58}  //Window2Zal
};


 

void setup() {



//ниже настройки прерывания вочдог в котором будет опрашиваться шина 1-wire

WDTCSR=(1<<WDCE)|(1<<WDE);               // для таймера вочдог, на котором висит измерение для датчиков шины 1-wire

WDTCSR=(1<<WDIE)|(1<<WDP2)|(1<<WDP1);    // обновление шины 1-wire раз в 1 сек (2 сек для датчиков t, т.к. через раз)
//WDTCSR=(1<<WDIE)|(1<<WDP3)|(1<<WDP1);  // обновление шины 1-wire раз в 4 сек (8 сек для датчиков t, т.к. через раз)
//WDTCSR=(1<<WDIE)|(1<<WDP3)|(1<<WDP0);  // обновление шины 1-wire раз в 8 сек (16 сек для датчиков t, т.к. через раз)




}

void loop() {

 
 }


ISR (WDT_vect){ //вектор прерывания WD . Здесь происходит опрос датчиков шины 1-Wire
static boolean n=0; // флаг работы: запрос температуры или её чтение
n=!n;
if (n) {ds.reset();  // сброс шины
        ds.write(0xCC);//обращение ко всем датчикам
        ds.write(0x44);// начать преобразование (без паразитного питания)  
       }
else   {
  for (byte i = 0; i < size_array_Temp; i++){// цикл фор перебирает все датчики t 
        int Temper_= 20;  
        byte buff[9];
        
        ds.reset();
        ds.select(ADDR_DS18B20[i]);    //выбор адреса DS18B20
        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]){ // если CRC верна
        Temper_ =  buff[0] | (buff[1]<<8);   // читаем температуру из первых двух байт (остальные были нужны для проверки CRC)
        Temper_ = Temper_ / 16;
                if  (Temper_ < 150 && Temper_ > -50 && Temper_ !=85 && Temper_!=-127)  // ещё раз перестраховываемся от дерьмовых значений
                     {
        Temper[i] =  (int8_t) Temper_; // всё, тут уже пишем температуру в переменную
                     }
                                              }
        
        
  } 
  
}



for (byte h = 0; h<size_array_Windows; h++ ){// этот цикл фор перебирает все адреса ds2406
byte counteR = 0;
for (byte p = 0; p<5; p++){                  // этот цикл фор делает 5 измерений для каждой переменной для надёжности
 byte buf[7];
  
  ds.reset();
  ds.select(ADDR_DS2406[h]);    // выбор адреса ds2406
    
  buf[0] = 0xF5; // байты
  buf[1] = 0x45; // запроса 
  buf[2] = 0xFF; // на 2406

  ds.write_bytes(buf, 3);
  ds.read_bytes(buf+3, 4);     // 3 cmd bytes, 1 data byte, 1 0x00, 2 CRC16
  ds.reset();
  
  if (OneWire::check_crc16(buf, 5, &buf[5])) {
     //если контрольная сумма верна - измеряем 
  if (bitRead(buf[3], 2)) {DoorsWindows[h] = 1; break; }
  else counteR++;  
  }
  
  
  }
  if (counteR == 5) DoorsWindows[h] = 0; // если все 5 раз было 0, то переменную делаем 0. 
}
   
}

 

b707
Offline
Зарегистрирован: 26.05.2017

MaksVV - критика принимается?

Во-первых, мелкая ошибка - в описании массива DoorsWindows (строка 55) - вы берете размер по числу датчиков температуры, а не по числу датчиков окон.

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

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

Критика приветствуется. Спасибо за мелкую ошибку. исправил. И да, согласен на счет прерывания. Но у меня система модульная, ничего другого данный мк, в общем то и не делает. Имеет смысл переложить просто на миллис. Остальное думаю может кого заинтересует. Имею ввиду проверка CRC и считывание PIO ds2406.

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

пример на миллис

#include <OneWire.h>
OneWire  ds(2);  // выбор пина ардуино, на котором висит шина 1-wire 

// ниже перечисление температур 

typedef enum Temper_enum
{
    KuhnyaC,            //0
    VannaNizC,          //1
    FreezeC,            //2
    UlicaC,             //3 
    
    size_array_Temp     //4 size
                   
} Temper_ENUM;   



// ниже соответствие адресов датчиков определённым температурам
byte ADDR_DS18B20 [size_array_Temp][8] =
{
{0x28, 0xFF, 0xB1, 0x43, 0x52, 0x15, 0x01, 0xDB}, //KuhnyaC   0
{0x28, 0xFF, 0xBA, 0x6C, 0x52, 0x15, 0x01, 0x41}, //VannaNizC 1
{0x28, 0xEE, 0x9B, 0x4D, 0x25, 0x16, 0x02, 0xC5}, //FreezeC   2
{0x28, 0x9D, 0xE5, 0x70, 0x01, 0x00, 0x00, 0xEE}  //UlicaC    3
};


// ниже сами переменные температур, изначально ставим +20*С
int8_t  Temper[size_array_Temp] = 
{
  20,     //KuhnyaC   0
  20,     //VannaNizC 1
  20,     //FreezeC   2
  20      //UlicaC    3
};

// например, чтобы использовать переменную температуры на улице, пишем так: Temper[UlicaC] = 


// ниже перечисление булевых значений для датчиков на основе ds2406
typedef enum Windows_enum
{
    Window1Prihozh,     //0
    Window2Prihozh,     //1
    Window1Zal,         //2
    Window2Zal,         //3 
    
    size_array_Windows //4 size
                   
} Windows_ENUM;

// ниже сами булевые переменные окон, по умолчанию ставим, что все закрыты ("1");

bool  DoorsWindows[size_array_Windows] = 
{
  1,     //Window1Prihozh
  1,     //Window2Prihozh 
  1,     //Window1Zal
  1      //Window2Zal
};

//адреса датчиков ds2406
byte ADDR_DS2406[size_array_Windows][8] = {
{0x12, 0xA1, 0xEE, 0x47, 0x00, 0x00, 0x00, 0x58}, //Window1Prihozh
{0x12, 0xA1, 0x43, 0x5C, 0x00, 0x00, 0x00, 0x58}, //Window2Prihozh 
{0x12, 0xA1, 0xEE, 0x5C, 0x00, 0x00, 0x04, 0x58}, //Window1Zal
{0x12, 0xA1, 0xEE, 0x5C, 0x00, 0x00, 0x00, 0x58}  //Window2Zal
};


uint32_t prev1Wire_polling = 0;
byte interval_1wire = 4;  // интервал опроса шины 1-wire, сек. (для датчиков t умножить на 2)
boolean n=0;

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

void loop() {


if (millis() - prev1Wire_polling > (uint32_t)interval_1wire*1000){ // Здесь происходит опрос датчиков шины 1-Wire
 // флаг работы: запрос температуры или её чтение
n=!n;
if (n) {ds.reset();  // сброс шины
        ds.write(0xCC);//обращение ко всем датчикам
        ds.write(0x44);// начать преобразование (без паразитного питания)  
       }
else   {
  for (byte i = 0; i < size_array_Temp; i++){// цикл фор перебирает все датчики t 
        int Temper_= 20;  
        byte buff[9];
        
        ds.reset();
        ds.select(ADDR_DS18B20[i]);    //выбор адреса DS18B20
        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]){ // если CRC верна
        Temper_ =  buff[0] | (buff[1]<<8); // читаем температуру из первых двух байт (остальные были нужны для проверки CRC)
        Temper_ = Temper_ / 16;  
                if  (Temper_ < 150 && Temper_ > -50 && Temper_ !=85 && Temper_!=-127)  // ещё раз перестраховываемся от дерьмовых значений
                     {
        Temper[i] =  (int8_t) Temper_; // всё, тут уже пишем температуру в переменную
                     }
                                              }
        
        
  } 
  
}



for (byte h = 0; h<size_array_Windows; h++ ){// этот цикл фор перебирает все адреса ds2406
byte counteR = 0;
for (byte p = 0; p<5; p++){                  // этот цикл фор делает 5 измерений для каждой переменной для надёжности
 byte buf[7];
  
  ds.reset();
  ds.select(ADDR_DS2406[h]);    // выбор адреса ds2406
    
  buf[0] = 0xF5; // байты
  buf[1] = 0x45; // запроса 
  buf[2] = 0xFF; // на 2406

  ds.write_bytes(buf, 3);
  ds.read_bytes(buf+3, 4);     // 3 cmd bytes, 1 data byte, 1 0x00, 2 CRC16
  ds.reset();
  
  if (OneWire::check_crc16(buf, 5, &buf[5])) {
     //если контрольная сумма верна - измеряем 
  if (bitRead(buf[3], 2)) {DoorsWindows[h] = 1; break; }
  else counteR++;  
  }
  
  
  }
  if (counteR == 5) DoorsWindows[h] = 0; // если все 5 раз было 0, то переменную делаем 0. 
}
   

Serial.print ("Temper AntiFreeze = "); Serial.println (Temper[FreezeC]); 
Serial.print ("Window2Zal = "); Serial.println (DoorsWindows[Window2Zal]); 

 prev1Wire_polling = millis();
}



 }


 

OLEGKARAS
Offline
Зарегистрирован: 19.02.2019

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

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

OLEGKARAS пишет:

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

Если речь идет о датчиках DS на протоколе One Wire, то и библиотеку нужно OneWire.h, чтобы записать в EEPROM - библиотеку EEPROM.h. Адрес датчика занимает 8 байт. В программе желательно предусмотреть возможность считывания адреса датчика и записи ее в EEPROM. Про библиотеки почитайте в гугле.

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

OLEGKARAS пишет:

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

а зачем для этого в еепром писать? ну отключите вы один, ничего особо и не изменится. Вот, например, можно так опрашивать далласы #24. Дополнительных библиотек не нужно, только Onewire.h

OLEGKARAS
Offline
Зарегистрирован: 19.02.2019

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

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

У датчиков OneWire нет номеров, у них есть идентификаторы, которые выжжены в них на заводе. Они не могут измениться от отключения или подключения доп. датчиков.

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

да

OLEGKARAS
Offline
Зарегистрирован: 19.02.2019

sadman41 пишет:

У датчиков OneWire нет номеров, у них есть идентификаторы, которые выжжены в них на заводе. Они не могут измениться от отключения или подключения доп. датчиков.


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

OLEGKARAS
Offline
Зарегистрирован: 19.02.2019

Да, забыл, если какой то татчик сломался или его отключили в этом примере есть вывод аварии датчика через терминал?

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

Гарантированно неизменны только ID в термометрах. Вся остальная относительная нумерация и её валидность - на совести программиста. Если таковой задачи не стояло при создании ПО, то внутрипрограммные индексы могут перестать соответствовать идентификаторам (а следовательно - местам установки) термометров. Так же - для получения проблем достаточно просто изъять один и поставить другое устройство OneWire.

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

Друзья, а не кажется Вам, что данная тема не предназначена для обучения работы с далласами?
То olegkaras, предлагаю создать СВОЮ тему в песочнице и там задать все интересующие вопросы. ИМХО.

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

OLEGKARAS пишет:
Если я отключу какойто датчик или заменю его другим то остальные датчки останутся под своими номерами как и до отключения или замены ?

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

ВН
Offline
Зарегистрирован: 25.02.2016

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

А то помню, как мы с дружком раз играли в шахматы в слепую, и как потом оказалось, оба белыми

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

Гражданин начальник ругается, конечно, и скоро ссаными тряпками нас гонять будет, как алегира, но сошлюсь на datasheet: "Each DS18B20-PAR has a unique 64-bit identification code...". Там же написано, что "The match ROM command followed by a 64–bit ROM code sequence allows the bus master to address a specific" - отсюда и простонародный "адрес", как я понимаю.

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

sadman41 пишет:

Гражданин начальник ругается, конечно, и скоро ссаными тряпками нас гонять будет, как алегира, 

Неа, здесь dimax главный, ему решать.

ivlermak
Offline
Зарегистрирован: 01.04.2020

Здравствуйте!

Меняю в скетче 15 строку на паразитное питание с изменением в схеме, температура не измеряется.

Стандартный пример из библиотеки OneWare работает с паразитным питанием прекрасно.

Сделать на delay вместо millis не вариант, т.к. есть много кода, который должен в это время исполняться.

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

Сильно не пинайте, начинающий я.

И еще: aruino pro ide уже можно использовать или он слишком сырой пока?

#include <OneWire.h>
OneWire ds(6); // На каком пине Создаем объект OneWire для шины 1-Wire, с помощью которого будет осуществляться работа с датчиком температуры
float temperature = 0; // Переменная для хранения значение температуры с датчика DS18B20
uint32_t LastTempUpdateTime = 0; // Переменная для хранения времени последнего считывания с датчика
const int TempUpdateTime = 1000; // Определяем периодичность проверок температуры. ПРОЦЕДУРА ПРОИСХОДИТ ДОЛЬШЕ ОСТАЛЬНЫХ, НА НЕЕ НЕОБХОДИМО ПРИМЕРНО 750 МС.

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

void detectTemperature() {
  byte data[2]; // Место для значения температуры
  ds.reset(); // Начинаем взаимодействие со сброса всех предыдущих команд и параметров
  ds.write(0xCC); // Даем датчику DS18b20 команду пропустить поиск по адресу. В нашем случае только одно устрйоство
  ds.write(0x44, 1); // Даем датчику DS18b20 команду измерить температуру. Само значение температуры мы еще не получаем - датчик его положит во внутреннюю память
  ds.reset(); // Теперь готовимся получить значение измеренной температуры
  ds.write(0xCC);
  ds.write(0xBE); // Просим передать нам значение регистров со значением температуры
  data[0] = ds.read(); // Читаем младший байт значения температуры
  data[1] = ds.read(); // А теперь старший
  // Формируем итоговое значение: "склеиваем" значение, затем умножаем его на коэффициент, соответсвующий разрешающей способности (для 12 бит по умолчанию - это 0,0625)
  temperature =  round(((data[1] << 8) | data[0]) * 0.0625 * 10) / 10.0; // умножить на 10 и округлить для избавления от сотых, затем разделить на 10
}

void loop(){
   if (millis() - LastTempUpdateTime > TempUpdateTime) // отсчитываем временной интервал для измерения температуры
    {
      LastTempUpdateTime = millis();
      detectTemperature(); // Определяем температуру от датчика DS18b20
    }
  Serial.println(temperature); // Выводим полученное значение температуры
}

 

b707
Offline
Зарегистрирован: 26.05.2017

ivlermak пишет:

Меняю в скетче 15 строку на паразитное питание с изменением в схеме, температура не измеряется.

И что вы изменили? Единичку после 0х44 поставили. что ли?

ivlermak
Offline
Зарегистрирован: 01.04.2020

b707 пишет:

ivlermak пишет:

Меняю в скетче 15 строку на паразитное питание с изменением в схеме, температура не измеряется.

И что вы изменили? Единичку после 0х44 поставили. что ли?

да

b707
Offline
Зарегистрирован: 26.05.2017

ну так у вас паразитное питание включается в строке 15 и практически мгновенно сразу выключается в 17. Этого недостаточно, так работать не будет.

это потому что вы запрос и чтение температуры делаете подряд.

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

 

ivlermak
Offline
Зарегистрирован: 01.04.2020

b707 пишет:

ну так у вас паразитное питание включается в строке 15 и практически мгновенно сразу выключается в 17. Этого недостаточно, так работать не будет.

это потому что вы запрос и чтение температуры делаете подряд.

Спасибо! Помогли разобраться.

iStarCom
Offline
Зарегистрирован: 21.06.2020

Всем привет.

Пришли три разные партии датчиков (c гильзой и без, все с али) все с ядром С4.

Решил проверить их на погрешность при 25 *С и мал мал офигел от результата, все врут в минус от 0,6 до 1,3 *С, китай однако отжигает в 2020.

Вопрос:

Можно влезть в 12 битный режим и поправить там переменную 0,0625 не добавляя к результату константу коррекции?

Или есть биты для коррекции датчика в + или -?

Чем черевато сие вмешательство? Проверил, меняя  переменную можно подогнать РЛО к реальной температуре!

b707
Offline
Зарегистрирован: 26.05.2017

Как подгоняете?

iStarCom
Offline
Зарегистрирован: 21.06.2020

Код чисто тест, меняю константу в сторону увеличения с 0.0625 на 0.0672. То есть с 25.00 подогнал к фактической 26.88 °C. Или я заблуждаюсь?

#include <Wire.h>
#include <OneWire.h>

OneWire  ds(5);

float  temperature = 0 ;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(57600);
}

void loop() {
  // put your main code here, to run repeatedly:
  //----- Определяем температуру на датчике.
  byte data[2]; // Место для значения температуры
  ds.reset(); // Начинаем взаимодействие со сброса всех предыдущих команд и параметров
  ds.write(0xCC); // Даем датчику DS18b20 команду пропустить поиск по адресу. В нашем случае только одно устрйоство
  ds.write(0x44); // Даем датчику DS18b20 команду измерить температуру. Само значение температуры мы еще не получаем - датчик его положит во внутреннюю память
  ds.reset(); // Теперь готовимся получить значение измеренной температуры
  ds.write(0xCC);
  ds.write(0xBE); // Просим передать нам значение регистров со значением температуры
  data[0] = ds.read(); // Читаем младший байт значения температуры
  data[1] = ds.read(); // А теперь старший
  temperature =  ((data[1] << 8) | data[0]) * 0.0672;  //----- Определяем температуру на датчике и подгоняем температуру под эталонную (0.0672) < Так!.
  Serial.println(temperature);
}

 

iStarCom
Offline
Зарегистрирован: 21.06.2020

Кстати по датчикам, Левыми оказались только с гильзами!

Поддельный датчик не поддерживает 9,10-битное разрешение и не сохраняет значения в регистрах аварийных сигналов. Кроме того, у моего поддельного датчика одно и тоже время преобразования - 487 мс при всех режимах преобразования, обычному датчику требуется около ~ 750 мс при 12 бит.

Тестировал по данной методе, вернее кодом) - https://github.com/Deimos1994/Ds_Fake_Tester

Мой мод :)

#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define ONE_WIRE_BUS 5

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

DeviceAddress tempDeviceAddress; // We'll use this variable to store a found device address

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

uint8_t deviceCount = 0;
const uint8_t PARASITE = 0;
uint8_t highAlarmValue = 25;
uint8_t lowAlarmValue = 10;
uint32_t timeCon = 0;
uint8_t resol = 12;
uint32_t millChngRes = 0;

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

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for (;;); // Don't proceed, loop forever
  }
  // Clear the buffer
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.print(F("DS18B20"));
  display.setCursor(0, 20);
  display.print(F("FakeFinder v2.0"));
  display.setCursor(0, 30 );
  display.print(F("mod by iStarCom 2020"));
  display.setCursor(0, 40 );
  display.print(F("add Address print."));
  display.setCursor(0, 50 );
  display.print(F("no data Serial print."));
  display.display();
  delay(5000);
}

void loop() {

  if (resol == 13) {
    resol = 9;
  }

  sensors.begin();
  //deviceCount = sensors.getDS18Count();
  deviceCount = sensors.getDeviceCount();

  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("Dev.#: " + String(deviceCount));
  display.setCursor(0, 9);
  display.println("Addr: " + String(Address_r()));
  display.setCursor(0, 17);
  display.println(SetResolution(resol));

  delay(50);

  uint32_t startMillis = millis();
  sensors.requestTemperatures(); // Request temperature mesurments
  timeCon = millis() - startMillis; // calculate time

  delay(50);

  display.setCursor(0, 27);
  display.println("SET alarm: " + method2());
  display.setCursor(0, 37);
  display.println("GOT alarm: " + readDevicesMethod2());
  display.setCursor(0, 47);
  display.println("TEMP: " + String(sensors.getTempCByIndex(0)) + " C");
  display.setCursor(0, 57);
  display.println("TimeCon: " + String(timeCon) + " ms");
  display.display();

  delay(50);



  // change resolution every xx sec
  if (millis() >  millChngRes + 5000 && millis() > 12000) {
    resol++;
    millChngRes = millis();
  }
}

//================================================
String method2() {  // using direct OneWire write commands
  String msg;

  highAlarmValue++;
  lowAlarmValue++;
  oneWire.reset_search();
  uint8_t addr[8];
  while (oneWire.search(addr)) {
    if (OneWire::crc8(addr, 7) == addr[7]) {
      oneWire.reset();
      oneWire.select(addr);
      oneWire.write(0x4E);           // Write to scratchpad
      oneWire.write(highAlarmValue); // Write high alarm value
      oneWire.write(lowAlarmValue);  // Write low alarm value
      oneWire.write(0x7F);           // Write configuration register, 12 bit temp res
      delay(30);  // dallas temp lib doesn't delay

      oneWire.reset();
      oneWire.select(addr);
      oneWire.write(0x48, PARASITE);  //copy scratchpad to eeprom, 1 - parasite power
      delay(20);                      // need at least 10ms eeprom write delay
      if (PARASITE) delay(10);
      msg = String(highAlarmValue) + " / " + String(lowAlarmValue);
    } else {
      msg = "Bad device addr!";
    }
  }
  return msg;
}

//================================================
String readDevicesMethod2() {  // using direct OneWire write commands
  uint8_t hAlarmValue;
  uint8_t lAlarmValue;
  uint8_t addr[8];
  uint8_t data[9];
  String msg;
  oneWire.reset_search();
  while (oneWire.search(addr)) {
    if (OneWire::crc8(addr, 7) == addr[7]) {
      oneWire.reset();
      oneWire.select(addr);
      oneWire.write(0xB8);        // Copy eeprom to scratchpad cmd, missing from DallasTemperature library
      delay(50);
      oneWire.reset();
      oneWire.select(addr);
      oneWire.write(0xBE);        // Read scratchpad cmd
      delay(50);
      for (uint8_t i = 0; i < 9; i++) {
        data[i] = 0;
        data[i] = oneWire.read();
      }
      hAlarmValue = data[2];   // byte 2 is high temp alarm
      lAlarmValue = data[3];    // byte 3 is low temp alarm
      msg = String(hAlarmValue) + " / " + String(lAlarmValue);
    } else {
      msg = "Bad device addr!";
    }
  }
  return msg;
}

//================================================
// Loop through each device, print out address
String SetResolution(uint8_t resSet) {
  String msg;
  for (int i = 0; i < deviceCount; i++)
  {
    // Search the wire for address
    if (sensors.getAddress(tempDeviceAddress, i))
    {
      // set the resolution to TEMPERATURE_PRECISION bit (Each Dallas/Maxim device is capable of several different resolutions)
      sensors.setResolution(tempDeviceAddress, resSet);

      msg += "SetTo/Real: ";
      msg += String(resSet, DEC);
      msg += " / ";
      msg += String(sensors.getResolution(tempDeviceAddress), DEC);

    } else {
      msg = "Err.";
    }
  }
  return msg;
}
//================================================

String Address_r() {
  String msg;
  for (int i = 0; i < deviceCount; i++)
  {
    // Search the wire for address
    if (sensors.getAddress(tempDeviceAddress, i))
    {
      for (uint8_t i = 0; i < 8; i++)  {
        msg += String(tempDeviceAddress[i], HEX);
      }
    }
    else {
      msg = "Err.";
    }
  }
  return msg;
}
//================================================

 

iStarCom
Offline
Зарегистрирован: 21.06.2020

b707 пишет:
Как подгоняете?

Что скажете?