вторник, 26 января 2010 г.

Библиотека для цифрового термометра DS18B20

Захотелось мне тут порезвиться с этой замечательной микросхемой. И так как я страдаю фигнёй манией писать библиотеки для разного вида подобных устройств, библиотека была написана! Писал долго, потому как было мало свободного времени. К тому же очень хотелось чтобы она поддерживала весь функционал доступный программисту. А функционал у неё неплохой. Микруха такая стоит порядка 150-300руб. (как повезёт), и имеет следующие основные возможности:
  • Работа по интерфейсу 1-wire, который требует всего одной линии для связи с МК;
  • Возможность питания от одной линии данных;
  • Уникальный 64-битный ID для каждого датчика;
  • Возможность развёртывать целые микросети таких датчиков связанных одной шиной;
  • Неплохая точность, ±0.5°C в диапазоне -10°C до 85°C;
  • Оповещение о выходе температуры из заданных пределов;
  • Совместимость с DS1822;
Варианты подключения
Может питаться как от внешнего источника, так и от линии данных. На следующих рисунках показаны варианты подключения (слева-направо) от внешнего источника, от шины данных.
 

Особенности библиотеки
Разработанная библиотека поддерживает все возможности данного цифрового термометра, и занимает в памяти МК от 254 до 918 байт, в зависимости от выбранных настроек конфигурации. В минимальной конфигурации поддерживается:
  • Измерение температуры (convert);
  • Чтение температуры (readTemp);
  • Выбор датчика по его уникальному коду (selectSensor);
Полный вариант конфигурации поддерживает к тому же:
  • Дополнительные функции (такие как recall, readScratchpad, copyScratchpad, writeScratchpad, и др.);
  • Автоматическая проверка контрольной суммы при приёме данных;
  • Поддержка датчиков питающихся паразитным током;
  • Поиск устройств на шине а также датчиков чья температура выходит из заданных пределов (searchROM, searchAlarm);
  • Дополнительные функции для обработки значения температуры, с целью дальнейшего вывода на дисплей (extractInt, extractFract);
Примеры использования
Простой пример демонстрирующий вывод текущего значения температуры на дисплей:
#include "wh1602b/wh1602b.h"
#include "ds18b20/ds18b20.h"
#include <avr/pgmspace.h>

void conf_my_lcd();
void loop();

int main(void)
{
  conf_my_lcd(); // настроить вывод на жк-дисплей
  // выбрать текущий датчик (0 т.к. единственный у меня)
  if (!ds18b20_selectSensor(0)) {
    wh1602b_putsP(PSTR("Ошибка на линии!"));
    for (;;)
      ;
  }
  for (;;)
    loop(); // цикл обработки
}

void loop()
{
  ds18b20_convert();  // попросить у датчика измерить температуру
  wh1602b_move(0,0);
  wh1602b_putsP(PSTR("t="));
  int16_t t = ds18b20_readTemp(); // прочитать значение
  if (t < 0) // вывести минус если отрицательно
    wh1602b_putc('-');
  wh1602b_puth(1, ds18b20_extractInt(t)); // вывести целую часть на дисплей
  wh1602b_putc('.');
  wh1602b_puth(1, ds18b20_extractFract(t, 1)); // вывести дробную часть на дисплей
  wh1602b_putsP(PSTR("\1C"));
}

// <...>
Вот что получилось:

Следующий пример демонстрирует вывод уникального кода микросхемы на дисплей:
#include "wh1602b/wh1602b.h"
#include "ds18b20/ds18b20.h"
#include <avr/pgmspace.h>

void conf_my_lcd();

int main(void)
{
  conf_my_lcd(); // настроить вывод на жк-дисплей
  uint8_t id[8];
  if (!ds18b20_readROM(id)) { // прочитать уникальный код датчика в id
    wh1602b_putsP(PSTR("Ошибка CRC!")); // если ошибка
    for (;;)
      ;
  }
  wh1602b_putsP(PSTR("ROM Code ="));
  wh1602b_move(1,0);
  uint8_t i;
  for (i = 0; i < 8; ++i)
    wh1602b_puth(2, id[i]);
  for (;;)
    ;
}

// <...>
И результат:

Следующий пример демонстрирует поиск устройств на шине:
#define F_CPU 20000000ULL /* частота мк, гц (для delay) */
#include <avr/pgmspace.h>
#include <util/delay.h>

#include "wh1602b/wh1602b.h"
#include "ds18b20/ds18b20.h"

void conf_my_lcd();
void loop();

int main(void)
{
  conf_my_lcd(); // настроить вывод на жк-дисплей
  for (;;)
    loop();  // цикл обработки
}

void loop()
{
  uint8_t i, dc = 0, id[8];
  int8_t r;
  // поиск устройств на шине 1-wire
  while ((r = ow_searchROM(id))) {
    if (r < 0)
     continue; // повтор если ошибка crc
    wh1602b_move(0,0);
    // вывести уникальный код датчика на дисплей
    for (i = 0; i < 8; ++i)
      wh1602b_puth(2, id[i]);
    _delay_ms(2000); // пауза 2с.
    ++dc;
  }
  wh1602b_move(1,0);
  wh1602b_putn(dc); // вывести число датчиков
  wh1602b_putsP(PSTR(" devices."));
}

// <...>
И результат в моём случае:


Больше примеров можно будет найти в архиве с библиотекой, ссылка на который указана в разделе "скачать".

Настройка конфигурации
Перед компиляцией библиотеки необходимо задать порты к которым подключён дисплей, а также включаемые возможности. Для этого необходимо отредактировав файл ds18b20/conf.h:
#define F_CPU 20000000 /* частота мк, Гц */

#define USE_EXTRACTINT    /* поддержка ds18b20_extractInt() */
#define USE_EXTRACTFRACT  /* поддержка ds18b20_extractFract() */

// поддержка автоматической проверки данных контрольной суммой
#define SUPPORT_CHECKSUM
// поддержка возможности поиска устройств на шине
#define SUPPORT_ROMSEARCH
// поддержка датчиков питающихся паразитным током
#define SUPPORT_PARASITE_MODE
// поддержка некоторых дополнительных функций
#define SUPPORT_COMPLETE

/* порт к которому подключена линия данных */
#define DDR_SENSOR   _SFR_IO_ADDR(DDRD)
#define PIN_SENSOR   _SFR_IO_ADDR(PIND)
#define PORT_SENSOR  _SFR_IO_ADDR(PORTD)
/* ножка к которой подключена линия данных */
#define NPIN_SENSOR  PD2
Убрать лишние возможности тем самым уменьшив размер занимаемый библиотекой в памяти МК, можно закомментировав некоторые из строчек начинающихся с #define.

Полный перечень поддерживаемых функций
  • uint8_t ds18b20_selectSensor(const uint8_t id[8])
    Выбирает текущий датчик по его уникальному коду id. Если id = 0, то выбирается первое попавшееся устройство, которое должно быть единственным в сети. Если возвращаемое значение = 0, то вероятно линия данных не правильно настроена. В случае успеха возвращается значение > 0.
  • void ds18b20_convert()
    Отправляет команду текущему датчику чтобы тот начал измерение температуры.
  • uint8_t ds18b20_readROM(uint8_t id[8])
    Загружает уникальный код датчика в массив указанный аргументом id. В сети должно находиться только одно устройство, иначе возникнут коллизии. Если возвращаемое значение = 0, то вероятно линия данных не правильно настроена. В случае успеха возвращается значение > 0.
  • int16_t ds18b20_readTemp()
    Возвращает измеренное значение температуры текущего датчика в градусах. Младшие 4 бита определяют дробную часть, остальная часть - целое значение.
    Например, если возвращаемое значение = 0x0191 = 0000000110010001 = 2^4+2^3+2^0+2^-4 = +25.0625°C
  • uint8_t ds18b20_readPowerSupply()
    Возвращает 1 если текущий датчик использует внешнее питание, 0 - питание от линии данных (паразитное).
  • uint8_t ds18b20_readScratchpad(sspad* p)
    Загружает состояние внутренней памяти текущего датчика в *p. Проверяется контрольная сумма, и возвращается значение > 0 в случае успеха. Если 0, то вероятно контрольная сумма не совпала, либо линия данных не правильно настроена.
    Структура sspad определена в файле ds18b20/ds18b20.h и имеет следующее представление:
    typedef struct {
      uint8_t t_lsb;       // temperature LSB
      uint8_t t_msb;       // temperature MSB
      int8_t t_h;          // Th register
      int8_t t_l;          // Tl register
      uint8_t config;      // configuration register
      uint8_t reserved[3]; // reserved
    } sspad;
    
    Подробней о назначении каждого параметра можно почитать в официальной документации к ds18b20.
  • void ds18b20_writeScratchpad(const sspad* p)
    Записывает данные в *p в память текущего датчика.
  • void ds18b20_copyScratchpad()
    Копирует состояние памяти текущего датчика в его eeprom. EEPROM определяется как энергонезависимая память, и при каждом включении питания, данные из eeprom датчика будут загружаться в его оперативную память.
  • void ds18b20_recall()
    Восстанавливает состояние памяти текущего датчика из его eeprom.
  • int8_t ow_searchROM(uint8_t id[8])
    Выполняет поиск следующего из устройств на шине 1-wire, и передаёт его уникальный код в параметр на который указывает id. Если возвращаемое значение = 0, то поиск завершён. Если возвращаемое значение = -1, то это означает что контрольная сумма не совпала, и данные были повреждены при приёме. В случае успеха возвращается значение > 0.
  • int8_t ds18b20_searchAlarm(uint8_t id[8])
    Выполняет поиск следующего датчика у которого пороговое значение температуры вышло из заданных пределов, и передаёт его уникальный код в параметр на который указывает id. Если возвращаемое значение = 0, то поиск завершён. Если возвращаемое значение = -1, то это означает что контрольная сумма не совпала, и данные были повреждены при приёме. В случае успеха возвращается значение > 0.
  • uint16_t ds18b20_extractInt(int16_t t)
    Возвращает целую часть значения температуры из двухбайтовой величины t, получаемой при помощи вызова функции readTemp. Возвращаемое значение является абсолютным и представлено в двоично-десятичном формате (bcd).
  • uint16_t ds18b20_extractFract(int16_t t, uint8_t r)
    Возвращает дробную часть значения температуры из двухбайтовой величины t, получаемой при помощи вызова функции readTemp, округляя его до 1/10^r. Возвращаемое значение является абсолютным и представлено в двоично-десятичном формате (bcd).
Совместимость
Думаю что библиотека будет совместима с большинством микроконтроллеров AVR серии Mega (в моём случае был использован Atmega644).

Скачать
  • Исходный код библиотеки вместе с примером можно скачать здесь (или здесь). Лицензия GNU GPL v3+;
  • Официальная документация по ds18b20 от производителя;

8 комментариев:

Unknown комментирует...

У тебя файлы исходников не скачать(

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

Unknown комментирует...

Обнови, пожалуйста, файлы! Очень нужна библиотека для DS18b20 на AVR Studio...

Unknown комментирует...

Плиз закинь проэкт на мыло
g8y3e@ya.ru

Unknown комментирует...

Плиз закинь проэкт на мыло
g8y3e@ya.ru

anterior комментирует...

Используйте для скачивания эту ссылку: http://dl.dropbox.com/u/5459143/dl/blog/temphtest.tar.gz

YS комментирует...

Все отлично. Только вот если бы еще комментарии были на английском, было бы еще лучше. А то открыл в AVR Studio, а там сюрприз. Кириллица это грустно...

Unknown комментирует...

Уважаемый автор, при попытке компиляции библиотеки выскакивает ошибка Ошибка 1 constant value required начиная со строки 24 файла ds18b20_ext.S (movw ZL,p0l) и далее 31 ошибка, как быть?

Руслан комментирует...

Разясните как по шагам подключить єту библтотеку к Atmel Studio а то у меня не получается!