Главная » Arduino
Призовой фонд
на декабрь 2017 г.
1. Спектроанализатор Arinst SSA-TG LC
Крокс
2. Термометр Relsib WT51
Рэлсиб
3. 1000 руб
PCBWay
4. 100 руб.
От пользователей

Считываем показания датчика DS18B20 (DS18S20)

Рассмотрим как при помощи Arduino считывать показания с цифрового датчика температуры DS18B20 или DS18S20. В настоящий момент м/с DS18B20 фирмы Dallas является наиболее распространенным и доступным цифровым датчиком температуры. Работает по протоколу 1-wire. Даташит датчика: DS18B20

Распиновка DS18B20

Датчик может запитываться двумя способами - внешним питанием (3 провода) или паразитным (питание от шины, 2 провода). Расписывать эти режимы не буду, все есть в документации. Отмечу лишь то, что в данном проекте мы будем использовать нормальное (внешнее) питание датчика.

Схема подключения датчика DS18B20 к Arduino приведена ниже. Подтягивающий Pull-Up резистор номиналом 4.7 кОм (5 кОм) включается между выводом DQ (Data) и питанием датчика Vdd.

Подключение DS18B20 к Arduino

Рабочий скетч представлен ниже. Необходима библиотека OneWire, последнюю версию которой можно скачать здесь.

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

Данные с датчика через Serial Monitor

#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(10);  // on pin 10 (a 4.7K resistor is necessary)

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

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");
}

Теги:

taliban Опубликована: 2011 г. 0 1
Я собрал 0 0
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 0 Проголосовало: 0 чел.

Комментарии (27) | Я собрал (0) | Подписаться

0
Николай #
Доброго времени суток! Очень полезны оказались ваши программы! Подскажите пожалуйста, как написать код, только для 3 датчиков такого типа! Спасибо!
Ответить
0
Павел #
А что делает выражение (data[1]<<8)+data[0]?
Ответить
0
user #
Из 2-х восьмибитных чисел получает одно 16-битное. Для этого биты старшего байта двигаем влево на 8 разрядов. В освободившиеся биты записываем младший байт.
Ответить
0
dima #
При компиляции вибивает error: 'pinMode' was not declared in this scope
Ответить
0
Евгений #
У вас библиотека OneWire для старых версий ArduinoIDE. Скачайте свежую библиотеку (Version 2.1): http://www.pjrc.com/teensy/arduino_libraries/OneWire.zip
И всё заработает.
Ответить
0
Андрей #
Спасибо! Получилось!
Ответить
0
Артур #
А что значит CRC is not valid? Температура не выводится, только это сообщение
Ответить
0
Павел #
А автор статьи точно уверен, что его программа будет работать с заявленным DS18B20? Здесь ее вообще хоть кто-нибудь собрал на этот датчик?!
Строчка:
if ( addr[0] != 0x10) {
Serial.print("Device is not a DS18S20 family device.\n");
return;
}
однозначно отметает этот тип датчика. Либо исправьте заголовок и текст либо скетч. DS18B20 - 0x28. И обработку температуры я бы попросил исправить в соответствии с требованиями на датчик DS18B20.
Ответить
0
talibanich #
Скриншоты SerialPrint взяты с датчика DS18B20. Все отлично работает, данный скетч был использован на других устройствах не раз.
По поводу вывода ошибки DS18S20 поправьте скетч как вам нужно, там поменять одну строчку.
Ответить
0
Павел #
Скриншоты SerialPrint взяты с датчика DS18B20. Все отлично работает, данный скетч был использован на других устройствах не раз.
По поводу вывода ошибки DS18S20 поправьте скетч как вам нужно, там поменять одну строчку.

Ну как приведенный скетч может работать с ds18b20, если как раз эта ошибка и блокирует работу?! Тогда надо описать так:
switch (addr[0]) {
case 0x10:
Serial.println(" Chip = DS18S20");
break;
case 0x28:
Serial.println(" Chip = DS18B20");
break;
case 0x22:
Serial.println(" Chip = DS1822");
break;
default:
Serial.println("Device is not a DS18x20 family device.");
return;
}
Взято с изменениями из скетча-примера OneWire.
Если снять блокировку, то лог выводит T=180.
Ответить
0
1 #
Пробуйте залить снова, у меня получилось на 2-ю попытку
Ответить
0
Сергей #
Это не пример придуманный автором. Это корявая обработка примера из состава библиотеки OneWire.
Ответить
0
Egor #
По ссылке архив с библиотекой и скетчем для LCD и ds18b20. Отключена проверка, вывод сразу на экран. Обратите внимание на указание ног для LCD.
Ответить
0
Максим #
для ds18b20 строки
TReading = (HighByte >4)|((HighByte&7)
Ответить
0
mikka #
При компилировании выдает много ошибок.
[i]sketch_may17a:6: error: 'OneWire' does not name a type
sketch_may17a.cpp: In function 'void loop()':
sketch_may17a:21: error: 'ds' was not declared in this scope
sketch_may17a:33: error: 'OneWire' has not been declared
sketch_may17a:43: error: 'ds' was not declared in this scope
sketch_may17a.cpp: At global scope:
sketch_may17a:77: error: expected unqualified-id before '
В чем здесь дело?
В Libraries добавил OneWire
Ответить
0
Виталий #
Имя библиотеки чувствительно к регистру
#include //в примере
#include //у меня
Посмотрите у себя как файл называется и исправьте
Ответить
0
Владимир #
Надо строку под номером 74: Tc_100 = TReading/2; поменять на Tc_100 = TReading/16;
Тогда все идёт как надо.
Ответить
0
Пушной звер #
Вы DS18S20 от DS18B20 отличить можете?
Ответить
0
Дмитрий #
Автор просто выдернул кусок кода и сам в нём не разобрался. С DS18B20 работать не будет. Отрицательные температуры показывать не будет.
Ответить
0
vvsector85 #
Хм.. у меня с DS18B20 работает
Ответить
0
alex #
Код работает, но датчик при нагреве руками выдает максимум 30 градусов. Вроде как 36+ должен показать. Может ли это быть брак датчика?
Ответить
0
Игорь #
Для проверки датчика, температурой собственного тела, установите его ректально. После этого, полжалуйста, напишите, что показал датчик и ваши ощущения. Если температура 36-37 градусов и ощущения были приятные, то датчик исправен. Если температура отличалась больше чем на градус - то пробемы с контактом или в самом сенсоре. Если вы испытывали неприятные ощущения (легкое покалывания, дискомфорт, раздражение) - то налицо дефект корпуса датчика. При обнаружении брака, осторожно извлеките датчик из ануса и промойте
Ответить
0
Андрей #
!) 5 баллов. у меня всеж не запускается этот пример, почему-то. No more addresses и все тут. Пробовал разные датчики из одной партии. Как еще проверить то?
Ответить
0
Александр #
Нормальный пример. Запустился сразу без проблем. Проверял на двух датчиках
Ответить
0
Стас #
No more adresses.
Что делать?
Ответить
0
Алексей #
Проверьте цепи питания и данных. Проверьте номинал подтягивающего резистора. Проверьте правильность его подключения: он ставится между питанием (+5В) и шиной данных. Причем ставить его надо как можно ближе к контроллеру. Проверьте длину проводов и исключите возможные помехи. В самом крайнем случае, понизьте частоту шины в библиотеке OneWare
Ответить
0
Shurovik #
Почему-то показывает отрицательную температуру (-34.хх град.) на всех подключенных датчиках...
Ответить
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется электрическое сопротивление?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

Raspberry Pi 2
Raspberry Pi 2
Набор для сборки - УНЧ 2х60 Вт на TDA7294 Набор начинающего радиолюбителя
вверх