Работа с датчиком температуры DS18B20


• О проекте
• Обратная связь
• Полезные ссылки
• Полезные программы
• Друзья сайта


Последние комментарии

Александр: Работа с датчиком температуры DS18B20
Температуру с дат...

Алексей: Работа с датчиком температуры DS18B20
Адрес битый. Пере...




           

Библиотека для AVR





AXLIB Генератор





Помощь сайту


   
				

Работа с датчиком температуры DS18B20

	
	
	

Дата: 15 Мая 2014. Автор: Алексей

	
	
В библиотеке AXLIB есть набор функций для работы с данным датчиком.

Весна в полном разгаре. Скоро лето, жара. А жара это сколько? Надо померить. А как? Вот и решил я поработать с датчиком температуры DS18B20. Благо он дешевый и его можно купить где угодно. И еще под этот датчик в CVAVR есть библиотека. Но.... После ковыряния с этим датчиком и библиотекой от CVAVR я окончательно решил слезть с этой пакости. Я пол дня угробил на состыковку библиотечных функция с динамической индикацией. Все вроде работает нормально, но когда доходит до опроса датчика, то индикация спотыкается на секунду. Жуть!!! Короче пообщавшись с умными людьми на форуме, я залез внутрь библиотеки и нарыл тело функции чтения температуры и о чудо! Там за каким-то лешим после команды на старт преобразования стоит пауза на 550 мс. Зачем? Для тех кто все же останется преданным CVAVR, эту паузу можно стереть. Заработало немного быстрее. Еще остался вопрос, а где лежат функции для работы с шиной 1-wire? Только хедер и все. Просто возник еще вопрос. Если при динамической индикации использовать таймер и в прерывании выводить цифры, то фигня выходит. Терзают меня смутные сомнения, что при обработке функций шины 1-wire запрещаются прерывания. Короче мне эти непонятки надоели и я переехал на AVRStudio 6.1 и ни капли не сожалею. Ну и еще получил пинок для изучения принципа работы шины 1-wire.

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

Для начала определимся с планом действий. Задача: Один датчик, берем из него температуру и по необходимости выводим куда-нибудь. Алгоритм из мануала на датчик.


Теперь все по порядку.
Перед тем как начать рассказ о командах, давайте пробежимся по физике шины. У датчика есть три ноги, две для питания(возможна работа от паразитного питания, но о ней мы пока говорить не будем. Считаем что у нас есть полноценное питание и оно подведено к датчику). Третья нога как раз для передачи данных. Но тут есть свой нюанс. Просто дергать ногу верх и вниз нельзя. Между этой ножкой и плюсом питания стоит резистор на 4,7К, который подтягивает ногу к плюсу питания. То есть если мы шину не трогаем(нет передачи) то на линии висит плюс питания. Также надо запомнить, что все начала передач инициируем мастер. Датчик всегда сидит и нюхает шину, а как только там что-то появилось, отвечает.

Подаем команду сброса.
Для того чтобы подать команду сброса, нужно прижать линию данных к нулю и удержать в таком состоянии не менее 480 мкс. Потом просто отпустить линию. Тот резистор, о котором я говорил ранее, подтянет шину к плюсу питания. Далее после того как мы отпустили шину ждем 15 мкс и смотрим. Если шина упала к нулю и так продержалась не менее 60 мкс, то значит на шине висит датчик и он нам ответил " Я тут". Если на шине после выжидания 15 мкс ноль не появился, значит на шине кроме мастера никого больше нет. Вот и вся команда. Если на шине никого нет, то забиваем на все и занимаемся чем-нибудь другим, а вот если кто-то есть, а скорее всего наш датчик, то мы имеем полное право ему дать команду.

Следующая команда по очереди должна быть чтение РОМ кода. Что такое РОМ код. Это группа из 8 байтов которая несет в себе некую информацию, а именно: Младший байт содержит код семейства. В мануале написано что равен 0х28, но я почему-то получал 0х10. Следующие 6 байтов это идентификационный номер датчика. Как я понял он уникален или фирма выпустила больше 281474976710655 датчиков. Я даже не знаю как это число произнести)). И последний байт это CRC контрольная сумма предыдущих байт. Получить ее можно подав команду 0х33. Но тут тоже не все так просто. Команда 0х33 это запрос РОМ кода если датчик один, а чтоб выудить их из кучи датчиков, то нужно сказать 0хF0. Мудрено? Да... Но если вспомнить что мы хотим общаться с одним датчиком, то нам этот РОМ код ваще читать не надо. Но мануал требует обязательного чтения РОМ кода. Что делать? А вот что. Есть такая команда под названием "Гей хлопцы се кричим!". То есть пишем 0хСС. Это означает пропустить РОМ код и всем устройствам на шине принять команду. В научном мире это называется широковещательная передача. То есть не важно сколько там устройств на шине, следующая после 0хСС команда одресованна всем.

Замечательно, подготовили устройство к получению команды и оно напряглось. Что дальше. А дальше нам нужно сказать ему "А нука друг измерий ка мне температурку. И шлем ему код 0х44. Тот получив приказ, тут же подрывается на работу. Вопрос. А как узнать когда датчик измерил температуру? А просто. Пока он меряет, то прижимает шину к нулю. Отсюда мы нюхаем шину и как только получили единицей по носу, о! Измерил.

Получение температуры. Датчик туп как пробка. Получив приказ измерить температуру он это сделал и положил данные в память. А дальше выпучив глаза ждет очередной команды. Мы в ту же очередь, получив единицей по носу, говорим 0хВЕ. Датчик получив эту команду понимает что надо передать данные из памяти. А какие? Память датчика состоит из 9 байт. Первые два это температура. Потом два байта тревог по превышению верхнего или нижнего предела температуры.(некий термостат). Следующий байт это конфигурационный регистр. Ну мол как цифровать температуру. Далее три байта в резерве. И наконец последний CRC. Помним что это). Так вот при подачи команды 0хВЕ датчик не будет думать о том что надо передать, а просто вывалит все девять байт в шину. Но мы все получать не будем. Мы получим только первые два байта. Ведь мы работаем только с одним датчиком и нас интересует только температура. Получив первые два байта переходим к их дешифровке, а остальные байты пускай затеряются на шине.

Преобразование данных в человеческий вид. Получив два байта нам нужно сделать из них температуру. Ну для начала надо понять что температура бывает как положительной, так и отрицательной. А с учетом того что у нас два байта, то и выделять под переменную нам надо типа int. Далее вроде все просто. Младший байт в младший инта, а старший в старший. Да не все так просто. Я долго вкуривал в это безумие и так и не понял)) Но всеми известный научный метод тыка пока не кто не отменял. Короче берем старший байт и кладем его как есть в старший байт инта, а младший сначала умножаем на 5, а потом кладем в младший байт того же инта. Все, вот наша температура правда умноженная на 10. То есть если температура 23,5 гр. то в инте будет 235. А если температура отрицательная? Во подстава. Глядя в таблицу температур датчика я понял что ее передают в, как по научному вроде, обратной нотации что ли. Короче, после получения данных от датчика, нужно проверить старший бит у старшего байта на 0. Если ноль, значит плюс, а если единица, значит зима) А дальше склеиваем как плюсовую, а потом инвертируем каждый бит. То есть те что были нулями должны стать единицами, а единицы нулями. После прибавляем единицу и получаем температуру так сказать по модулю. Выводим как плюсовую, только не забываем поставить знак минус.

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

DS18B20 плюсовая температура

DS18B20 минусовая температура

Программный код я здесь выкладывать не буду, так как это лишнее. Я выкладываю архив в котором лежат файлы основной программы и подключаемого хедера с функциями передачи команд. Каждая строка подробно закоментированна. Если все же возникнут вопросы, то я на связи.
Удачи!

В библиотеке AXLIB есть набор функций для работы с данным датчиком.

Архив с файлами.



jon    29.09.14

Алексей, вопрос - я могу с помощью команды читать ROM, определить наличие датчика? Скажем, выдать 0x33, и прочитать в первом байте код семейства DS18B20. Если он не равен 0x28 - значит, датчика нет. Или так не не годится?

Алексей    29.09.14

А чем не устраивает команда сброса? Или на шине еще что-то висит?

jon    30.09.14

Но, ведь по команде сброса можно только определить - есть ли любые устройства 1- wire или нет. А хотелось бы именно удостовериться в отсутствии термодатчика DS18B20. Есть чужой исходник на ассемблере на два термометра с батарейным питанием на разных шинах, захотелось кое-что переделать по своему вкусу. Лезть в сами процедуры работы с датчиком особо не хочется, вроде нормально и так работает. Поэтому и возникла идея - дать команду 0x33, потом принять первый байт из 8, и его проанализировать на наличие кода семейства. Типа, если там есть 0x28 -

Алексей    30.09.14

Хорошо. Если есть два датчика НО НА РАЗНЫХ шинах, то какая разница как определить наличие датчика. Подали команду сброса и все. Датчик ответил, значит все в порядке. Не ответил, увы. Команды на обнаружение по семейству нужно подавать только тогда, когда на шине висит больше одного датчика. А если один, то зачем такие сложности. Или я что-то не понимаю в вашем вопросе.

АНОНИМ    01.10.14

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

Алексей    01.10.14

Собственно, а почему нет. Если известен адрес датчика и он ответил на любую команду значит он априори жив и здоров.

jon    01.10.14

Меня как раз интересовал способ, при котором неизвестен адрес датчика, сидящего на отдельной шине. Зачем полностью читать все 64 бита идентификации, вполне хватит и 8-ми бит, в которых есть код семейства. Например, 0x28 для DS18B20. Если принят любой другой код - значит, датчика нет, он не тот, или неисправен, что в конкретном случае почти одинаково.

Алексей    01.10.14

Стоп, стоп, стоп. Это сработает при широковещательном запросе при условии только одного датчика на шине. С тем же успехом можно и команду сброса подать. Если будет больше устройств на шине, то на широковещательный запрос ответят все. Иначе по адресу. Ну это же логично. Если вы отправите письма с запросом нескольким людям, они все вам и ответят. А если просто одному человеку в комнате крикните, "Эй, ты!". Он один и ответит.

jon    01.10.14

Правильно, я и написал - "...датчика, сидящего на отдельной шине...". У меня как раз ситуация, когда каждый датчик термометра - сидит на отдельной шине. Именно поэтому и возник такой вопрос. И потом, стоит задача определения наличия именно DS18B20, мало ли что там народ еще может подключить. А так - датчик ответил кодом 0x28, значит все в порядке.

jon    01.10.14

Алексей, еще поясните такую вещь, если не трудно, а то что-то в даташите про это нигде не сказано. Я подал команду записать в датчик 0x33 (чтение ROM), затем должен сколько-то подождать, или могу сразу читать с датчика? Где-то в сети народ жаловался на то, что типа, пока не поставил между командами записи-чтения задержку около 1 миллисекунды - датчик не отзывался вовсе, или вывдавал всякую белиберду.

Алексей    01.10.14

А это зависит от дискретизации(точности) измерений. При запросе на вычисления температуры датчик может, зависать аж по моему до 750 мс. Давненько я с ним не работал не помню. Проще шину нюхать. Если после команды на преобразования шина в нуле, значит не готов. Как шина к поднялась к единице, можно читать температуру. С этой проблемой часто сталкиваются те кто выводит температуру на динамический индикатор.

jon    02.10.14

Когда нужна температура, задержка обычно подразумевается. Потому что делать поллинг (опрос бита готовности), не всегда удобно. А вот когда пишется команда, не связанная с преобразованием температуры? Например, та же 0x33 - чтение ROM.

Алексей    02.10.14

Ну я не знаю. Вообще задержка не нужна. Ради собственного удовлетворения то пару миллисекунд вляпать можно. Если это не дипломная работа, то я бы воспользовался импирикой и не парил себе мозг. :)

krokodandi    20.10.14

Есть желание немножко усложнить конструкцию? Я очень хочу поработать с вами вместе. Передо мной была поставлена интересная задача. Денежкой поделюсь. Жду ответа тут

Алексей    20.10.14

А по конкретнее какая задача. Точнее ТЗ.

Как-тотак    20.10.14

Нужно сделать два термометра МК1 и МК2. На мк1 навшано BT модуль HC-05, ds18b20,радио NRF24L01. На мк2 ds18b20,радио NRF24L01. ----------------мк1----------------- мк 1 измеряет temp_mk1 пишем в РОН инициируем подключение по радио NRF, если есть подключение, кидаем ему общую уставку Y и просим передать temp_mk2 c MK2 (пишем в POH) -инициируем подключение по БТ,если есть отправляем temp_mk1 и temp_mk2 и просим получить уставку Y(получаем и копируем в РОН) - считаем ошибку температуры мк1, если отрицательная включаем реле. -------------Мк2---------------- Измеряем температуру и пишем в РОН слушаем эфир NRF, если есть отправляем _температуру и просим уставку. Сравниваем, результат в ошибку. Если отрицательная, включаем реле. Это регулятор для фуры отца. Будет греть прицеп. Говорит, мол не обойтись. Платит мне 10К а я все нее могу с модулями и ассемблером разобраться. Нашел ваш терморегулятор. Разбираю ваш пример пока. Изложение мысли понравилось.

krokodandi    20.10.14

Такой регулятор...Как связаться с вами?

krokodandi    20.10.14

Отлаживаю на плате STK500 в связке с STK502. Примерную схему я набросал в ИГЛКАД Для связи могу предложить скайп. Мой логин : 819 готов отдать 7К

Алексей    20.10.14

Честно, я ничего не понял. avrki@avrki.ru моя почта. Можно более подробно и сформулировано объяснить что нужно сделать. И при чем здесь РОН? Обязательно на ассемблере? Какой МК рулить всем этим будет? Нужна конкретика, ТЗ. Напишите поверхностный псевдо-код, что должно происходить в течении работы устройства. На какой шине висят радио модуль и ВТ модуль. Зачем вообще ВТ? Связь с телефоном?

Григорий    18.05.18 16:10

Здравствуйте, а скажите насколько точно он меряет температуру. У меня он по ощущениям на 3-4 градуса завышает. Минусовую вроде точно выводит. Также хочу заметить, что нет смысла выводить десятые доли градуса при такой точности. Тогда температуру можно получать так temper = (temp_0>>4)+(temp_1<<4)-4; здесь отнимаю 4 так как он завышает температуру. Мне сказали, что он разогревается из-за того, что я его часто опрашиваю, нужно мол не чаще 2 раз в минуту.

Алексей    19.05.18 15:08

В документации на датчик написано, что погрешность составляет ±0.5° при измерении между -10° и +85°, а при измерении между -55° и +125° будет ±2°. Страница 2, таблица DC Electrical Characteristics, строка Thermometer Error.

Андрей    04.09.18 15:07

Можете подсказать что не так?



owire_init();
owire_write(0xCC); owire_write(0x44); _delay_ms(250); owire_init(); owire_write(0xCC); owire_write(0xBE); temp[0]=owire_read(); temp[1]=owire_read(); znak=0; if(temp[1]&0x80)
{
temp[0] = (~temp[0])+1;
temp[1] = ~temp[1]; znak=1; }

temper = ((temp[1]<<8)|(temp[0]*5));
lcd_clear();
sprintf(lcd_buffer,"Temp=%i" "C ",temper);

lcd_gotoxy(0,0);
lcd_str_out(lcd_buffer);
_delay_ms(500);



Так вот выводится Temp=5C

Алексей    05.09.18 18:24

В aixlib есть готовые функции для датчика))

Андрей    05.09.18 19:37

Фантастика Алексей, а я по Вашему какую либу использую?

Алексей    06.09.18 19:41

Вот кино.

Николай    26.10.18 16:12

Добрый день! Перехожу с CodeVision на Atmel studio 7, неделю писал свои библиотеки, потом случайно наткнулся на ваши. Большое спасибо за огромный труд!!! Но не все так гладко: ваша функция ds1820_all() не поддерживает датчик ds18B20 - а это сейчас наиболее популярный датчик. В общем в протеусе на датчике установлена температура 34.4, а функция считывает 42.0 и только при 1-м чтении, при последующих всегда 0.00.

Алексей    26.10.18 16:43

Точно так и есть. Поэтому лучше использовать функцию WORD ds1820_read_t(BYTE *rom);

Николай    29.10.18 09:18

Спасибо за ответ! Переделал - но стало еще хуже. Теперь показывает 85.0, хотя на датчике 34.4. Причем показывает 85.0 только если вторая строка закоментирована:
ds1820_rom_code(rom);
//sprintf(str, "%02X %02X %02X %02X %02X %02X %02X %02X", rom[0], rom[1], rom[2], rom[3], rom[4], rom[5], rom[6], rom[7]);

если ее раскоментировать - то показывает 0.00. В Virtual terminal выводит адрес датчика нормально.

Как я понимаю это компилятор ведет себя неадекватно - я с таким уже столкнулся, когда писал свои функции - если я их вызывал вначале программы - работали, если в конце - то возвращали неожиданные результаты. Может в этой студии где размер стека надо увеличить?
Еще - при попытке вывода в USART заметил что на частоте 1Мгц выводилась хрень, а на 8Мгц - норм.
Если в студии что-то подобное #if _MCU_CLOCK_FREQUENCY_ == 8000000 ?

Николай    29.10.18 09:26

Последний вопрос снимаю - есть же #define F_CPU 8000000UL

Алексей    29.10.18 19:45

Вообще 85.0 датчик выводит при первом запросе после подачи питания. Это температура у него в регистре до первого преобразования. Вообще функции запроса ром кода и температуры должны работать как часы. Я их дорабатывал фиг знает сколько раз.

Николай    30.10.18 09:57

Подскажи еще пожалуйста:
sprintf(str, "T %0.1f", (ADATA)(temperatura/10));
выводит на LCD если на датчике 34.4 :
34.0
0.000
68.00
34.0.0
162.0
34.00
34.0.0
34.000
34.06.0
но я еще ни разу не видел 34.4, подозреваю что где-то поддержку float надо включить - но где?

Николай    30.10.18 10:30

В общем дело не в sprintf - в самой переменной temperatura значение 340, соответсвенно и выводит 34.
Но почему не 344?? В CVAVR выводит корректно - 34.4

Алексей    30.10.18 15:15

Потому что датчик настроен на вывод температуры с точностью до 0,5°.

Борис    06.01.19 12:21

какое время должно пройти между командой считывания температуры и самим считыванием.

Алексей    07.01.19 09:39

750мс

Борис    07.01.19 14:02

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

Алексей    07.01.19 15:09

Именно миллисекунды. Вообще по хорошему нужно код пересмотреть. С разрешением +/- 0.5 градуса датчик должен преобразовывать очень быстро.

Алексей    07.01.19 15:11

В доке написано что при 9-ти битном режиме преобразование длится 94 миллисекунды.

Александр    15.01.19 19:21

Можно ли повторно залить видео. Похоже что видео удалено. Заранее спасибо!

Алексей    15.01.19 22:23

Того видео больше нет. На моем Ютуб канале есть серия видео про библиотеку. Вот ссылка.

Александр    17.01.19 19:39

Ребята кто разобрался с ds18b20 прошу помощи. Потратил три дня и никак не вижу температуру только -0.1 с реальным датчиком и в проеус всо тоже самое. Может кто глянет проект https://yadi.sk/d/ELDUjp1PaBl8Rg

Александр    17.01.19 20:04

Температуру с датчика ds18s20 читает корректно. Сломал голову. Может проблема с библиотекой 1w.h

Алексей    18.01.19 07:48

Адрес битый. Переходи на форум и я там тебе помогу.




Чтобы вставить ссылку используйте форму вида[url]http://www.адрес.ru[/url][text]текст ссылки[/text]
Чтобы вставить код используйте форму вида[code]код[/code]

Имя:   





  







Рейтинг@Mail.ru Яндекс.Метрика