DS18B20

Тема в разделе "Arduino & Shields", создана пользователем Perun61, 15 ноя 2012.

  1. arssev1

    arssev1 Гик

    Это не цифровой датчик, а аналоговый - обычный термистор NTC.
    Подключить можно - вам понадобится резистор на 10кОм и немного проводов. Из резистора и термистора формируете делитель напряжение и подключаете к аналоговому порту. Опорное напряжение для АЦП желательно брать 3.3В
    Для преобразования напряжения в температуру вам нужно вооружится формулой Штейнхарта-Харта https://en.m.wikipedia.org/wiki/Steinhart–Hart_equation и даташитом на ваш термистор.
    Даташита я боюсь вы не найдёте и придётся составлять график самому при помощи обычного термометра, термистора и Wolfram Alpha
     
  2. user999

    user999 Гик

    Подскажите, а как не явно указать пины в этой кострукции. Эти же шины создаются до setup().
    А у меня в setup получается информация о пинах с сервера. Как быть?
     
  3. avdeal

    avdeal Нуб

    добрый день. прошу помощи советом по поводу датчика ds18b20.
    ситуация такая:
    взял 3 датчика, скрутил одинаковые провода каждого датчика вместе, поставил 1 резистор 4.7кОм и подключил к одному пину ардуинки.
    опускаю все датчики в один стакан с водой , температура выводится 15.8, 20.5, 21.75.
    вопрос: нормальное ли это явление? возможна какая-либо калибровка?
    да. питание и через usb и пробовал через блок питания.
    в чужой код добавил только lcd.
    Код (C++):
    /*
    * Логика работы.
    * Заполните осмысленными названиями Массив NamesOut[sumRegul]
    * Разкомментируйте #define SEARCH_DS18B20
    * Залейте скетч.
    * Благодаря этому вы найдете адреса своих датчиков.
    * Нагревая (рукой к примеру) определите какой датчик соответствует какому названию
    * Заполните массив Thermometer[TEMP_SUM] в нужном порядке что бы соответствовали
    * названия и номер датчика. Физически дайте метки датчикам (бирки навешайте).
    * Закомментируйте #define SEARCH_DS18B20
    * Залейте скетч еще раз. И проверьте все ли правильно.
    * Теперь откопируйте массив Thermometer[TEMP_SUM] в основной скетч
    */

    #include "LCD_1602_RUS.h"                    // подключаем библиотеку для работы с LCD дисплеем
    LCD_1602_RUS lcd(0x27, 20, 4);               // объявляем  переменную для работы с LCD дисплеем, указывая параметры дисплея (адрес I2C = 0x27, количество столбцов = 16, количество строк = 2)
    #include <OneWire.h>
    #include <DallasTemperature.h>

    #define ONE_WIRE_BUS 11
    #define TEMP_SUM 3 // Количество датчиков

      // устанавливаем разрешение датчика 9 бит (может быть 9, 10, 11, 12)
      // на точность измерения температуры показатель не влияет.
    #define TEMPERATURE_PRECISION 12
    const int sumRegul = TEMP_SUM;

    // Настройка экземпляра oneWire для взаимодействия с любыми устройствами OneWire (а не только с температурными микросхемами Maxim/Dallas)
    OneWire oneWire(ONE_WIRE_BUS);

    // Передаем нашу ссылку oneWire на Даллас Температуру.
    DallasTemperature sensors(&oneWire);

    // Если #define SEARCH_DS18B20 раскоментирован то ищим Термометры и грубо говоря затераем новыми
    // адресами массив адресов DeviceAddress Thermometer[TEMP_SUM]
    // то есть то что ниже вы определите массив адресов на порядок
    // отоброжения датчиков влиять не будет, они будут в том
    // порядке в котором они найдуться. Вот.
    // #define SEARCH_DS18B20

    // массивы для хранения адресов устройств
    DeviceAddress Thermometer[TEMP_SUM] =
    {
      {0x28, 0xE6, 0xEF, 0x7D, 0x9F, 0x3C, 0x83, 0x5E},
      {0x28, 0x61, 0x15, 0x79, 0x97, 0x10, 0x03, 0x23},
      {0x28, 0x1B, 0x5B, 0x79, 0x97, 0x10, 0x03, 0x3F},
     
    };

    // Название реле (терморегуляторов)
    String NamesOut[sumRegul] = {
                                  "Вход",
                                  "Смешение",
                                 "Обратка",
                                 
                                };

    //**********************************************************
    // Функции
    // Вывод в сериал температуру
    void printTemperature(DeviceAddress deviceAddress)
    {
      float tempC = sensors.getTempC(deviceAddress);
      Serial.print("Temp C: ");
      Serial.print(tempC);
    }

    // Вывод в сериал адресса
    void printAddress(DeviceAddress deviceAddress)
    {
      for (uint8_t i = 0; i < 8; i++)
      {
        if (deviceAddress[i] < 16) Serial.print("0");
        Serial.print(deviceAddress[i], HEX);
      }
    }


    void setup()
    {
      lcd.init();                                // инициируем LCD дисплей
    lcd.backlight();                           // включаем подсветку LCD дисплея
      // start serial port
      Serial.begin(9600);
      Serial.println("Dallas Temperature IC Control Library Demo");

      // Количество датчиков на шине
      Serial.print("Locating devices...");
      sensors.begin();
      Serial.print("Found ");
      Serial.print(sensors.getDeviceCount(), DEC);
      Serial.println(" devices.");

      // report parasite power requirements
      // Определяет тип питания
      Serial.print("Parasite power is: ");
      if (sensors.isParasitePowerMode()) Serial.println("ON");
      else Serial.println("OFF");

    #ifdef SEARCH_DS18B20
              for (int i=0; i<TEMP_SUM; i++)
      {
        if (!sensors.getAddress(Thermometer[i], i))
        Serial.print("Unable to find address for Device ");
        Serial.println(i);
      }  
    #endif

    // устанавливаем разрешение датчика 9 бит (может быть 9, 10, 11, 12)
    // на точность измерения температуры показатель не влияет.
        for (int i=0; i < TEMP_SUM; i++)
      {
        sensors.setResolution(Thermometer[i], TEMPERATURE_PRECISION);
     
        Serial.print("Device 0 Resolution: ");
        Serial.print(sensors.getResolution(Thermometer[i]), DEC);
        Serial.println();
      }
    }//setup()

    void loop()
    {

      sensors.requestTemperatures(); // Send the command to get temperatures
     
      // It responds almost immediately. Let's print out the data
       for (int i=0; i < TEMP_SUM; i++)
        {
          Serial.print(NamesOut[i]);    // Название датчика
          Serial.print(" ");    
          printAddress(Thermometer[i]); // Адрес датчика
          Serial.print(" ");
          printTemperature(Thermometer[i]); // Температура датчика
          Serial.println();
        }
      Serial.println();
      delay(1000);
      for(int q=0;q< TEMP_SUM;q++)
      {lcd.setCursor(0, q);
       lcd.print(NamesOut[q]);
       lcd.setCursor(10, q);
       float tempW = sensors.getTempC(Thermometer[q]);
      lcd.print(tempW);
        }
    }
     
  4. ostrov

    ostrov Гуру

    Либо датчики кривые, либо что-то еще, например соединили не правильно. Попробуйте по примеру отсюда.
     
  5. Vovka

    Vovka Гик

    Легко! Вот пару дней назад была у меня проблема с датчиками. Оказалось, что все, 20 датчиков, присланных китайцем, не годные!!!
     
  6. Airbus

    Airbus Радиохулиган Модератор

    Ужос!
     
    DetSimen нравится это.
  7. avdeal

    avdeal Нуб

    Будет ли правильно применить поправки для показаний? Или их показания будут отличаться не линейно?
     
  8. Tomasina

    Tomasina Сушитель лампочек Модератор

    По отдельности каждый датчик как себя ведёт?
     
  9. b707

    b707 Гуру

    Для начала надо убедится, что вы правильно читаете температуру. CRC проверяете?

    Если все собрано верно, а датчики все равно врут на 5 и более градусов - видимо вы купили подделку. Вносить поправки бесполезно, датчики будут врать нелинейно.
     
  10. avdeal

    avdeal Нуб

    по отдельности датчики показывают такую же температуру как и вместе.
    при загрузке вот этого скетча не работает 1 датчик. два других показывают ту же температуру как и ранее.
    пойду искать что такое CRC, у тех датчиков что работают с этим скетчем они плавают.
    Код (C++):
    #include <OneWire.h>

    // OneWire DS18S20, DS18B20, DS1822 Temperature Example
    //
    // http://www.pjrc.com/teensy/td_libs_OneWire.html
    //
    // The DallasTemperature library can do all this work for you!
    // http://milesburton.com/Dallas_Temperature_Control_Library

    OneWire  ds(11);  // on pin 11 (a 4.7K resistor is necessary)

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

    void loop(void) {
      byte i;
      byte present = 0;
      byte type_s;
      byte data[12];
      byte addr[8];
      float celsius, fahrenheit;
     
      if ( !ds.search(addr)) {
        Serial.println("No more addresses.");
        Serial.println();
        ds.reset_search();
        delay(250);
        return;
      }
     
      Serial.print("ROM =");
      for( i = 0; i < 8; i++) {
        Serial.write(' ');
        Serial.print(addr[i], HEX);
      }

      if (OneWire::crc8(addr, 7) != addr[7]) {
          Serial.println("CRC is not valid!");
          return;
      }
      Serial.println();
      // the first ROM byte indicates which chip
      switch (addr[0]) {
        case 0x10:
          Serial.println("  Chip = DS18S20");  // or old DS1820
          type_s = 1;
          break;
        case 0x28:
          Serial.println("  Chip = DS18B20");
          type_s = 0;
          break;
        case 0x22:
          Serial.println("  Chip = DS1822");
          type_s = 0;
          break;
        default:
          Serial.println("Device is not a DS18x20 family device.");
          return;
      }

      ds.reset();
      ds.select(addr);
      ds.write(0x44, 1);        // start conversion, with parasite power on at the end
     
      delay(1000);     // maybe 750ms is enough, maybe not
      // we might do a ds.depower() here, but the reset will take care of it.
     
      present = ds.reset();
      ds.select(addr);  
      ds.write(0xBE);         // Read Scratchpad

      Serial.print("  Data = ");
      Serial.print(present, HEX);
      Serial.print(" ");
      for ( i = 0; i < 9; i++) {           // we need 9 bytes
        data[i] = ds.read();
        Serial.print(data[i], HEX);
        Serial.print(" ");
      }
      Serial.print(" CRC=");
      Serial.print(OneWire::crc8(data, 8), HEX);
      Serial.println();

      // Convert the data to actual temperature
      // because the result is a 16 bit signed integer, it should
      // be stored to an "int16_t" type, which is always 16 bits
      // even when compiled on a 32 bit processor.
      int16_t raw = (data[1] << 8) | data[0];
      if (type_s) {
        raw = raw << 3; // 9 bit resolution default
        if (data[7] == 0x10) {
          // "count remain" gives full 12 bit resolution
          raw = (raw & 0xFFF0) + 12 - data[6];
        }
      } else {
        byte cfg = (data[4] & 0x60);
        // at lower res, the low bits are undefined, so let's zero them
        if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
        else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
        else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
        //// default is 12 bit resolution, 750 ms conversion time
      }
      celsius = (float)raw / 16.0;
      fahrenheit = celsius * 1.8 + 32.0;
      Serial.print("  Temperature = ");
      Serial.print(celsius);
      Serial.print(" Celsius, ");
      Serial.print(fahrenheit);
      Serial.println(" Fahrenheit");
    }
     
  11. a1000

    a1000 Гуру

  12. avdeal

    avdeal Нуб

    Правильно ли я понимаю, что если crc не определяется то датчик лучше по назначению не использовать?
     
  13. DetSimen

    DetSimen Guest

    CRC не может "не определяться", она может быть либо правильная, либо неправильная. Если считал блок данных, посчитал контрольную сумму и она неправильная, то считывай еще раз. Если 5 раз подряд пришла неверная контрольная сумма - этта повод сирёзно задуматься о физическом и психическом здоровье твоего даччика, может даже уже пришло время его хоронить, орошая слезами.
    Хотя, у меня все эти китайские выкидыши прекрасно работают до -38 гра плюсминус 2, потом начинаются глюки (хотя в ТТХ написано до -55 ). А вода у меня кипит, если верить им, при 98.7 - 99.3 гра
     
    Последнее редактирование модератором: 24 сен 2019
  14. a1000

    a1000 Гуру

    Всё может быть. Температура кипения воды зависит от атмосферного давления. Возможно в момент замера оно было пониженным.
     
  15. parovoZZ

    parovoZZ Гуру

    Датчик не отъюстирован вот и всё.
     
  16. b707

    b707 Гуру

    И это отличный показатель, учитывая высоту Н-ска над уровнем моря :)
     
  17. DetSimen

    DetSimen Guest

    да в том то и дело, что никакая у Н-ска высота над морем. чотам, 100м всего.
    Ну я еще на +30м (10 эташ) мерил.
     
  18. b707

    b707 Гуру

    википедия пишет 150, да плюс твой этаж - как раз получается 99.2-99.3
     
    ostrov нравится это.
  19. DetSimen

    DetSimen Guest

    Нада, значить, еще на даче померить, там высота минимальна (дача в старом русле Оби стоИт).
     
  20. a1000

    a1000 Гуру

    И ещё учти текущее атмосферное давление на момент замера.