breadcrumbs_revolution_theme

DS18B20

проверка датчика

Дата материала: 12.02.2023


DS18B20 это датчик температуры от американской компании Dallas Semiconductor

Это точный цифровой датчик для измерения температуры в диапазоне от -55 до +125°C, при этом, в диапазоне от -10 до +85°C достигается наивысшая точность с ошибкой до ±0.5°C. Принцип работы: отправляем команду на выполнение температурного преобразования, ждем 750мс (при максимальном разрешении 12 бит) и в результате получаем температуру в двоичном(десятичном) виде. Наиболее распространенный вариант исполнения датчика: зонд в виде стальной (сталь 304) гильзы длиной 50mm, диаметром 6mm и длиной провода 2 метра (между проводом и зондом находится термоусадка, которая занимает 15mm длины гильзы).

Использование датчика

  • системы умного дома (Home Assistant / Sonoff eWelink)
  • контроллеры (Arduino / ESP32 / STM32 / Raspberry Pi / Wiren Board)
  • системы вентиляции и кондиционирования
  • инкубаторы, теплицы
  • бани, сауны
  • датчик для ректификационной колонны(самогоноварение)
  • датчик для терморегулятора

Исполнение датчика

  • герметичное в стальной гильзе
  • зонд с креплением под винт
  • зонд в виде винта
  • корпус TO-92
  • корпус SO8 (SOIC-8)

Адрес датчика

  • каждый датчик имеет 64 битный код(адрес)
  • пример адреса: 28-62-8D-62-A3-21-01-4A
  • маска адреса: 28-xx-xx-xx-xx-00-00-crc (оригинала)
  • первые 8 бит - код семейства: 28h
  • следующие 48 бит - уникальный серийный номер
  • следующие 8 бит - контрольная сумма CRC
  • код(адрес) хранится в ПЗУ(ROM), записывается в момент производства и его нельзя изменить

Преимущество перед термистором (ntc 10k)

  • уникальный адрес у каждого датчика - на один порт можно подключить более 100 датчиков
  • не требуется АЦП, только два цифровых входа
  • высокая точность - датчик откалиброван и рассчитан на ошибку 0.5°C, термистор же необходимо откалибровать с помощью эталонного термометра и при подключении использовать прецизионный точный резистор
  • длина провода для подключения датчика может достигать нескольких десятков метров

Таблица 1: список характеристик, источник: DataSheet или DataSheet на русском языке

Характеристика Значение
модель DS18B20
назначение датчик температуры
температурный диапазон -55...+125°C
максимальная ошибка (отклонение или погрешность)

диапазон [-55...-9°C] = ±2°C

диапазон [-10...+85°C] = ±0.5°C

диапазон [+86...+125°C] = ±2°C

разрешение9/10/11/12 бит (выбирается пользователем)
9 бит (0.48°C)< 93.75 ms (время температурного преобразования)
10 бит (0.25°C)
< 187.5 ms (время температурного преобразования)
11 бит (0.125°C)< 375 ms (время температурного преобразования)
12 бит (0.0625°C)< 750 ms (время температурного преобразования)
калибровкадатчики откалиброваны в момент производства
напряжение питания

min 3.0V DC

max 5.5V DC

потребляемый ток (в состоянии покоя) < 5 uA
потребляемый ток (запрос данных) < 1.5 mA
интерфейс 1-Wire
адресация

каждый датчик имеет уникальный 64-битный код,

что позволяет подключить несколько датчиков к одной шине

схемы подключения

№1: внешнее питание (основная)

№2: паразитное питание

3-pin подключение

Vdd (Vcc) =  +5V DC

DQ =  data

GND = -5V DC

резистор

рекомендуется использовать 4.7кОм

резистор разместить ближе к микроконтроллеру

максимальная длина проводадля неэкранированных кабелей(например витая пара) до 20 метров, для экранированных до 100 метров, свыше 100 метров через повторители 1-Wire

Карта памяти SCRATCHPAD

  • карта памяти хранит в оперативной памяти 8 байт информации
  • Byte0 и Byte1 хранит значение температуры, при подаче питания и до команды requestTemperatures() хранит значение 85°С (Byte0 = 0x50 / Byte1 = 0x05). Если при работе с датчиком периодически появляется неверное значение температуры равное 85°С - это значит что есть проблемы с питанием и датчик перезапускается
  • Byte2(нижний предел ALARM) и Byte3(верхний предел ALARM) хранит информацию о диапазоне температур для аварийного оповещения, использовать эту функцию разумно только тогда когда у вашего микроконтроллера не хватает памяти для реализации контроля температуры и вы хотите чтобы эту функцию выполнял DS18B20 
  • Byte4 хранит "регистр конфигурации" - разрешающую способность (9/10/11/12 бит), которая влияет на точность измерения температуры и время температурного преобразования и соответственно чем вы выше точность, тем выше длительность температурного преобразования.
  • Byte5 = 0xFF, Byte6 = 0x0C, Byte7 = 0x10 это зарезервированные байты, значения которых не должны меняться. При этом значение байта 6 = 0x0C в datasheet не указано.
  • Byte8 - контрольная сумма CRC
  • Byte2, Byte3, Byte4 - значение этих байтов хранится в энергонезависимой памяти EEPROM
  • тестирование датчика на соответствие характеристикам оригинала в том числе выполняется с попыткой перезаписать информацию в этих байтах

Информация по копиях (подделках) датчика DS18B20

  • информация о подделках датчика появилась в 2018-2019 годах
  • факт №1: сайт drive2.ru
  • факт №2: сайт github.com
  • факт №3: сайт habr.com
  • факт №4: сайт kernelchip.ru
  • далее ниже по тексту будем называть "подделки" - копиями
  • копии существуют разного качества, некоторые копии пригодны для использования
  • понятие "оригинала" выходит за рамки соответствия датчика характеристикам оригинала и связано, в том числе, с покупкой у официальных дилеров компании Maxim Integrated
  • шанс купить оригинальный датчик очень низкий, максимум можно купить копию которая будет соответствовать некоторым(или всем) признакам оригинального датчика 

Список отличий копии от оригинала

  1. 1. группа отличий, которые можно проверить экспериментальным методом
    1. 1.1 некорректная работа по схеме паразитного питания
    2. 1.2 "зависает" - перестает отвечать на запросы спустя некоторое время
    3. 1.3 "неуверенный отклик" - отвечает на запросы через раз
    4. 1.3 ошибка(погрешность) выше заявленной, то есть выше чем ±0.5°C (при температуре -10..+85°C)
    5. 1.4 высокое потребление тока в момент температурного преобразования, между температурными преобразованиями
    6. 1.5 при температуре выше 95°C - зависание, перезапуск
  2. 2. группа отличий, которые можно проверить программным способом
    1. 2.1 есть два способа проверки - скетч discover_fake_DS18B20.ino или скетч classify_fake_DS18B20.ino - оба для arduino совместимых плат. Первый выполняет некоторые безопасные тесты, второй использует недокументированные функции датчика и во время проверки может его повредить. Результат проверки второго скетча - отнесение датчика к семейству копий - является более интересным.
    2. 2.2 для проверки понадобится - устройства: плата Arduino UNO R3 или ESP32 или подобная, резистор 4.7 kОм
    3. 2.3 для проверки понадобится - программное обеспечение: Arduino IDE 1.8 или Arduino 2.0, драйвер: CH340 или CP2102 (зависит от того - какую плату используете), Arduino IDE 1.8 - ввести дополнительные ссылки для менеджера плат(если используете ESP32), Arduino IDE 1.8 - установить библиотеку OneWire.h
    4. 2.4 в скетче в строке "#define pin_onewire 25" по необходимости, указать иной PIN подключения контакта DQ датчика DS18B20
    5. 2.5 схема подключения: можно использовать эту схему (внешнее питание, резистор между Vdd и DQ, порт для подключения ESP32 - G25)
    6. 2.6 когда все подключено - необходимо загрузить скетч в плату и запустить монитор порта на скорости 115200 бод. Результат тестирования будет выведен в монитор порта, по необходимости, нажмите кнопку RESET на плате для повторного тестирования. Для скетча classify_fake_DS18B20.ino после вывода первых сообщений в монитор порта - необходимо нажать кнопку ENTER
  3. 3. проверка скетчем(программой) discover_fake_DS18B20.ino для arduino (esp32)
    1. 3.1 первый скетч из основной темы про копии на сайте github.com
    2. 3.2 скетч выполняет несколько безопасных тестов и показывает отклонение от оригинального датчика DS18B20 (работает только по схеме подключения датчика с внешним питанием)
    3. Таблица 2: алгоритм проверки датчика из скетча discover_fake_DS18B20.ino

      Проверяемое значение Условие Результат
      ScratchPad: Byte8 попытка перезаписать контрольную сумму CRC при удачной перезаписи: ошибка
      64 битный адрес датчика

      проверка на соответствие маске:

      28-xx-xx-xx-xx-00-00-crc

      Byte0=28   Byte5=00   Byte6=00

      не соответствует: ошибка
      ScratchPad: Byte8 проверяем контрольную сумму CRC не совпадает: проверьте соединение датчика
      ScratchPad: Byte2, Byte3, Byte4

      сравнение со значениями по умолчанию:

      Byte2 = 0x4b

      Byte3 = 0x46

      Byte4 = 0x7f

      в случае расхождений: это не является ошибкой, так как в этих байтах хранятся настройки, которые могут быть изменены пользователем
      ScratchPad: Byte5 Byte5 = 0xFF не совпадает: ошибка, так как это зарезервированный байт, значение которого указано в datasheet
      ScratchPad: Byte6 сложное условие не совпадает: ошибка
      ScratchPad: Byte7 Byte7 = 0x10 не совпадает: ошибка, так как это зарезервированный байт, значение которого указано в datasheet
      ScratchPad: Byte2, Byte3 попытка изменить верхнюю и нижнюю границы ALARM не удается изменить: ошибка
      ScratchPad: Byte4 попытка изменить разрешение(регистр конфигурации) на 10 бит не удается изменить: ошибка
      ScratchPad: Byte5, Byte6, Byte7 сравниваем значения зарезервированных байтов до изменения разрешения и после не совпадает: ошибка, так как зарезервированные байты не должны изменятся
      ScratchPad: Byte4 попытка изменить разрешение(регистр конфигурации) на 12 бит не удается изменить: ошибка
      ScratchPad: Byte5, Byte6, Byte7 сравниваем значения зарезервированных байтов до изменения разрешения и после не совпадает: ошибка, так как зарезервированные байты не должны изменятся
    4. 3.3 результат проверки: после запуска скетча в монитор порта(115200 бод) выводится адрес датчика(ROM), ScratchPad, результат каждой проверки (ok или Error) и в итоге общий результат с количеством ошибок. 
  4. 4. проверка скетчем(программой) classify_fake_DS18B20.ino для arduino (esp32)
    1. 4.1 второй скетч из основной темы про копии на сайте github.com
    2. 4.2 скетч классифицирует датчик и относит к одному из семейств копий (при тестировании используются недокументированные функции, которые могут повредить датчик и он перестанет работать, соответственно используйте на свой страх и риск)
    3. Таблица 3: семейства копий датчика DS18B20

      Family Расшифровка
      A1

      оригинальный датчик (Genuie Maxim)

      время температурного преобразования(12бит): 580-615 ms

      A2

      копия

      значительное количество датчиков со смещением(погрешностью) ±0.5°С при 0°С

      время температурного преобразования(12бит): 325-505 ms

      B1

      копия

      некоторые байты ПЗУ (ROM) могут быть изменены программно

      время температурного преобразования(12бит): 585-730 ms

      B2

      копия

      значительное количество датчиков со смещением(погрешностью) ±0.5°С при 0°С

      время температурного преобразования(12бит): 585-730 ms

      D1

      копия

      не работает в паразитном режиме или нестабильно работает в паразитном режиме

      показания температуры сразу после включения составляют 25°C, а не 85 °C

      датчик не выполняет преобразование температуры с низким разрешением быстрее

      зарезервированные Byte5 и Byte7 отличаются от datasheet

      некоторые байты ПЗУ (ROM) могут быть изменены программно

      значительное количество датчиков со смещением(погрешностью) ±0.5°С при 0°С

      время температурного преобразования(12бит): 11 ms

      D2

      копия

      не работает в паразитном режиме или нестабильно работает в паразитном режиме

      показания температуры сразу после включения составляют 25°C, а не 85 °C

      датчик не выполняет преобразование температуры с низким разрешением быстрее

      зарезервированные Byte5 и Byte7 отличаются от datasheet

      значительное количество датчиков со смещением(погрешностью) ±0.5°С при 0°С

      время температурного преобразования(12бит): 460-525 ms

      C

      копия

      EEPROM: количество циклов перезаписи очень мало <10 раз

      разрешение 12 бит невозможно изменить

      время температурного преобразования(12бит): 28-30 ms

    4. 4.3 результат проверки: после запуска скетча в монитор порта(115200 бод) нажать кнопку ENTER и в результате - напротив адреса датчика будет написано семейство копий, например Family B1 (Clone) или Family A1 (Genuie Maxim то есть оригинал)
    5. 4.4 какой вариант выбрать ?
    6. Кроме оригинального семейства А1, семейство B1 имеет схожие характеристики - работает по схеме паразитного питания, несколько худшая точность чем А1, разброс показаний между датчиками семейства B1 совпадает с разбросом показаний семейства A1.
    7. Не рекомендовано к покупке: А2 из-за большой погрешности, D1 / D2 / D3 из-за большой погрешности, нестабильной работы по схеме паразитного питания и множества других проблем, C из-за малого количества циклов перезаписи EEPROM
    8. Итого: покупаем А1 (это оригинал, или копия соответствующая всем признакам оригинала), покупаем B1(лучшая из копий, не сильно уступающая оригиналу)
    9. Потребление тока копией - семейство B1 - в момент температурного преобразования составляет около 4мА

Схема подключения №1: внешнее питание

Основная схема подключения Vdd питание 3V DC+, DQ данные, GND земля 3V DC-. При подключении необходимо использовать резистор 4.7 kОм. На один порт(pin) можно подключить несколько датчиков. 

Схема подключения №2: паразитное питание

Датчик подключается двумя проводами: питание(DC+) на датчик приходит по линии связи (DQ), контакт GND(DC-) необходимо соединить с контактом Vdd. При подключении необходимо использовать резистор 4.7 kОм. На один порт(pin) можно подключить несколько датчиков. В режиме преобразования температуры или работы с EEPROM датчик может потреблять ток 1.5 mA и при паразитном питании необходимо обеспечить достаточный ток для корректной работы. При температурах свыше +100°С из-за более высокого тока утечки использовать паразитное питание не рекомендуется из-за невозможности обеспечить достаточный уровень тока. 

Подключение DS18B20 к ESP32 (ESP32_DS18B20.ino)

cписок устройств: отладочная плата ESP32, датчик DS18B20, резистор 4.7 kОм.

cхема подключения: с внешним питанием

программное обеспечение: Arduino IDE 1.8 или Arduino 2.0, драйвер CP2102, дополнительные ссылки для менеджера плат ESP32, библиотека OneWire.h, библиотека DallasTemperature.h

скетч ESP32_DS18B20.ino (pin для подключения одного или нескольких датчиков ds18b20: G25, OutputType = 1 вывод данных в порт текстом, Output = 2 вывод графика в плоттер, SetSensorResolution = 0 не изменять разрешение датчика, SetSensorResolution = 12 изменить разрешение на заданное значение, temp_check_period = 100 миллисекунд интервал между запросами на температурное преобразования)

#include <OneWire.h>
#include <DallasTemperature.h>

#define PIN_DQ 25 //G25 - ESP32

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

unsigned long temp_check_lasttime;//last time check temperature

uint8_t sensors_addresses[256][8]; //save all sensors addresses
uint8_t sensors_count=0;

int request_number=0;

//Settings
uint8_t OutputType = 2;// 1 - serial text, 2 - serial plotter (graph)
uint8_t SetSensorResolution = 0; //0 - no change, 9 - 9 bit, 10 - 10 bit, 11 - 11 bit, 12 - 12 bit
const unsigned long temp_check_period = 100; //time between check temperature (1000 = 1 seсond)

void setup()
{
  Serial.begin(115200);
  if (OutputType == 1) Serial.println("");
  if (OutputType == 1) Serial.println("-------------");
  if (OutputType == 1) Serial.println("1. ESP32 start");
  if (OutputType == 1) Serial.println("2. Search all sensors");

  uint8_t sensor_address[8];
  uint8_t scratchpad[9];
  uint8_t sensor_resolution = 0;
  
  bool check_scratchpad;
  while(oneWire.search(sensor_address)){
    sensors_count++; 
    Serial.print("2.");
    Serial.print(sensors_count);  
    if (OutputType == 2) Serial.print(", "); 
      
    if (OutputType == 1) Serial.print(" adress: ");
    for (uint8_t i = 0; i < 8; i++)
      {
        sensors_addresses[sensors_count][i] = sensor_address[i];
        if (OutputType == 1) Serial.print("0x");
        if (sensor_address[i] < 0x10) {if (OutputType == 1) Serial.print("0");}
        if (OutputType == 1) Serial.print(sensor_address[i], HEX);
        if (i < 7) {if (OutputType == 1) Serial.print(", ");}
      }
      
    if (OutputType == 1) Serial.print(" SCRATCHPAD: ");
    sensors.readScratchPad(sensor_address,scratchpad);
    check_scratchpad = true;
    for (uint8_t i = 0; i < 9; i++)
      {
        if (OutputType == 1) Serial.print("0x");
        if (scratchpad[i] < 0x10) {if (OutputType == 1) Serial.print("0");}
        if (OutputType == 1) Serial.print(scratchpad[i], HEX);
        if (i == 5 && scratchpad[i] != 0xFF) check_scratchpad = false;
        if (i == 6 && scratchpad[i] != 0x0C) check_scratchpad = false;
        if (i == 7 && scratchpad[i] != 0x10) check_scratchpad = false; 
        if (i < 8) {if (OutputType == 1) Serial.print(", ");}
      } 

    sensor_resolution = sensors.getResolution(sensor_address); 
    if (OutputType == 1) Serial.print(" res: ");
    if (OutputType == 1) Serial.print(sensor_resolution);
    if (OutputType == 1) Serial.print(" bit");
    
    if (SetSensorResolution == 0) {
      
    }
    else if (SetSensorResolution !=sensor_resolution) {
      sensors.setResolution(sensor_address,SetSensorResolution); 
      if (OutputType == 1) Serial.print("-->");
      if (OutputType == 1) Serial.print(SetSensorResolution);
      if (OutputType == 1) Serial.print(" bit"); 
    }
    
    if (OutputType == 1) Serial.print("\n");
  }

  if (OutputType == 2) Serial.println();
  
  if (sensors_count==0) 
  {
  if (OutputType == 1) Serial.print("Sensors not found. Check ESP32: PIN" + String(PIN_DQ));
  }
    else
  {
    if (OutputType == 1) Serial.print("3. Checking temperature... [1 time in " + String(temp_check_period/1000) + " sec] or [1 time in " + String(temp_check_period) + "ms]");
    sensors.begin();
  }
}


void loop()
{ 
  unsigned long request_time;
  unsigned long all_request_time;
  float t;
  if (millis() - temp_check_lasttime > temp_check_period) 
  { 
    request_number++;

    if (OutputType == 1) Serial.println();

    all_request_time = millis();
    sensors.requestTemperatures();

    for (uint8_t i = 1; i <= sensors_count; i++) 
    {
      request_time = millis();
      if (true) //(sensors.requestTemperaturesByAddress(sensors_addresses[i])) 
      {
       t = sensors.getTempC(sensors_addresses[i]);
       request_time = (millis() - request_time);
       if (OutputType == 1) {
        Serial.print("\nSensor 2." + String(i) + " temperature: " + String(t) + " (Celsius)");// RequestTime: " + String(request_time) + " ms");
       }
       else {
        Serial.print(t);
       }
      }
      else
      {
       if (OutputType == 1) Serial.print("\nSensor 2." + String(i) + " temperature: n/a");
       else Serial.print(-60);  
      }
      if ((OutputType == 2) && (i!=sensors_count)) Serial.print(" ");
      if ((OutputType == 2) && (i==sensors_count)) Serial.println();
    } 
    
    all_request_time = (millis() - all_request_time);
    if (OutputType == 1) Serial.print("\nRequest №" + String(request_number) + " time: " + String(all_request_time) + " ms");
    
    temp_check_lasttime = millis(); 
  }
}

Режим работы: 1 (OutputType = 1) вывод данных в последовательный порт

Режим работы: 2 (OutputType = 2) вывод данных в плоттер для построения графика

Скачать