В продолжение темы 1-Wire рассмотрим температурный 1-Wire датчик — DS18S20 🙂
DS18S20 – высокоточный цифровой термометр с интерфейсом 1-Wire (High Precision 1-Wire Digital Thermometer) от DALLAS Semiconductor (Maxim).
Для подключения датчика достаточно двух проводов – линии данных и заземления;
питание элемента в этом случае называется «паразитным»/фантомным (Parasite power mode) и осуществляется по линии данных за счёт накопления энергии во встроенном конденсаторе во время высокого уровня напряжения
(не рекомендуется при температуре свыше +100 С из-за быстрого разряда конденсатора).
Нормальный режим питания (external supply), заключается в подключении к датчику источника питания (3V-5V).
В обоих случаях рекомендуется использовать подтягивающий резистор в 4.7k
Характеристики DS18S20:
Интерфейс 1-Wire
Измеряемая температура от -55 до +125 °C
Точность 0.5 °C в диапазоне от -10 до +85 °С
Температура считывается 9-ю битами данных
Время на конвертацию температуры — 750 ms (максимальное)
Как и любое 1-Wire устройство — каждый DS18S20 содержит уникальный 64-битный ROM
Первые 8 бит — код серии ( для DS18S20 код — 10h, а для DS18B20 — 28h ).
Затем 48 бит уникального номера, и в конце 8 бит CRC-кода.
Однако, самое интересное — данные о температуре хранятся в оперативной памяти(scratch-pad memory) датчика.
Память состоит из оперативной ROM и энергонезависимой EEPROM:
Первые два байта – содержат данные об измеренной температуре,
Третий и четвёртый байты хранят верхний (TH) и нижний (TL) пределы температуры.
Пятый и шестой – не используются.
Седьмой и восьмой – байты – счётчики – могут использоваться для более точного измерения температуры.
Девятый байт хранит CRC-код предыдущих восьми 🙂
Теперь осталось разобраться с тем – какие команды может выполнять этот датчик.
Кроме уже знакомых нам:
Поиск адресов — Search ROM [F0h]
Чтение адреса устройства — Read ROM [33h]
Выбор адреса — Match ROM [55h]
Игнорировать адрес — Skip ROM [CCh]
Добавились:
Поиск Тревоги — Alarm Search [ECh] – операция этой команды идентична операции поиска адресов [F0h], за исключением того, что в данном случае ответят только те датчики, у которых, при последнем измерении, температуры вышла за установленные пределы (выше TH или ниже TL).
И команды работы со scratch-pad memory:
Конвертировать температуру — Convert T [44h] – датчик произведёт измерение и запись данных о текущей температуре. Если ведущее устройство будет за этой командой слать тайм-слоты чтения, то пока конвертация не закончена — DS18S20 будет выдавать в линию «0», а после завершения конвертации «1».
Если датчик работает в режиме паразитного питания, то не позже 10 мкс после подачи команды устройство управления должно установить высокий уровень на шине на время продолжительности преобразование (не менее 750 ms)
Запись в память — Write Scratchpad [4Eh] – эта команда позволяет записать 3 байта в память датчику. Первый байт запишется в TH, второй в TL, а третий байт запишется в пятый байт памяти – у DS18S20 – он не используется, а у DS18B20 – это байт конфигурации
Чтение памяти — Read Scratchpad [BEh] – позволяет нам считать память датчика. В ответ на эту команду датчик вернёт 9 байт своей памяти, начиная с 0-го байта TEMPERATURE LSB и заканчивая восьмым – CRC.
Копировать память — Copy Scratchpad [48h] – датчик скопирует содержимое ОЗУ — TH и TL в EEPROM
Если датчик работает в режиме паразитного питания, то не позднее 10 мкс после подачи этой команды устройство управление должно установить высокий уровень на шине и поддерживать его в течении не менее 10ms.
Производители обещают, что EEPROM датчика DS18S20 должен выдержать минимум 50000 циклов перезаписи и будет хранить данные 10 лет при T = +55°C.
Повторная загрузка — Recall E2 [B8h] – загружает данные из EEPROM в ОЗУ. Эта операция выполняется автоматически, как только на датчик подаётся напряжение.
Вид электропитания датчика — Read Power Supply [B4h] – с помощью этой команды можно определить – какой вид питания использует датчик. Если датчик выставит на шине «0» — значит он использует паразитное питание. Если же датчик использует внешнее питание, то он ответит «1».
Теперь становится понятно, что нужно сделать, чтобы получить от датчика данные о температуре 🙂
После RESET-а и поиска устройств на линии 1-Wire, нужно выдать команду
0x44 , чтобы запустить конвертацию температуры датчиком.
Подождать не менее 750 ms и выдать команду
0xBE , чтобы считать ОЗУ датчика.
Данные о температуре будут в первых двух байтах.
Остаётся только сложить эти два байта, предварительно сдвинув старший байт на 8 бит влево:
TReading = (HighByte << 8) + LowByte;
Температуру получим просто разделив на 2 (шаг ведь в пол-градуса)
Tc_100 = TReading/2;
Однако, датчик ведь называется «высокоточный»! Поэтому предусмотрена процедура для получения более точных данных о температуре:
0. Считать данные с датчика: LSB, MSB, COUNT_REMAIN, COUNT_PER_C
1. Получить данные о температуре с точностью в пол-градуса. (Tc_100)
2. Уточнённые данные о температуре высчитываются по формуле:
Temperature = Tc_100 – 0.25 + (COUNT_PER_C - COUNT_REMAIN)/ COUNT_PER_C
Как помним, для работы с датчиками с интерфейсом 1-Wire можно использовать библиотеку Jim Studt-а – OneWire. скачать
Соответственно, скетч для получения температуры от DS18S20 будет таким:
#include <OneWire.h> /* * получаем температуру от DS18S20 */ OneWire ds(10); // линия 1-Wire будет на pin 10 void setup(void) { Serial.begin(9600); } void loop(void) { byte i; byte present = 0; byte data[12]; byte addr[8]; if ( !ds.search(addr)) { Serial.print("No more addresses.\n"); ds.reset_search(); return; } Serial.print("R="); for( i = 0; i < 8; i++) { Serial.print(addr[i], HEX); Serial.print(" "); } if ( OneWire::crc8( addr, 7) != addr[7]) { Serial.print("CRC is not valid!\n"); return; } if ( addr[0] != 0x10) { Serial.print("Device is not a DS18S20 family device.\n"); return; } ds.reset(); ds.select(addr); ds.write(0x44,1); // запускаем конвертацию delay(1000); // скорее всего достаточно 750ms // we might do a ds.depower() here, but the reset will take care of it. present = ds.reset(); ds.select(addr); ds.write(0xBE); // считываем ОЗУ датчика Serial.print("P="); Serial.print(present,HEX); Serial.print(" "); for ( i = 0; i < 9; i++) { // обрабатываем 9 байт data[i] = ds.read(); Serial.print(data[i], HEX); Serial.print(" "); } Serial.print(" CRC="); Serial.print( OneWire::crc8( data, 8), HEX); Serial.println(); // высчитываем температуру :) int HighByte, LowByte, TReading, Tc_100; LowByte = data[0]; Serial.print("LB= ");Serial.print(LowByte,HEX); HighByte = data[1]; Serial.print(" HB= ");Serial.print(HighByte,HEX); TReading = (HighByte << 8) + LowByte; Tc_100 = TReading/2; Serial.print(" T = ");Serial.print(Tc_100); Serial.println(); }
Этот скетч можно опробовать даже не собирая схемы 🙂
Элемент DS18S20 есть в базе протеуса, поэтому можно набросать схему в нём:
Загрузив в МК полученный после компиляции hex и запустив симуляцию увидим в окошке терминала:
Соответствующая температура выставляется на виртуальном датчике кнопками со стрелочками вверх и вниз .
А вот что будет в порту, если попробуем подключить реальный датчик DS18S20
80 комментариев на «“Практическое программирование Arduino/CraftDuino — температурный 1-Wire датчик DS18S20”»
Жаль что библиотека OneWire не катит под последнюю arduino-0018
Побыстропу не пофиксить, нужно править либу.
или просто воспользоваться 0017 😉
Как то не по фэншую 🙂
а на основании чего был сделан вывод, что библиотека не работает под 0018? 🙂
Пробовал скомпилить, вывалилась ошибка.
Ошибка касательно digital_pin_to_port и т.п. что связано с пинами. Теперь работа с ними немного другая, поэтому старых структур просто нет (в этом то и ошибка).
Я конечно могу ошибаться, потому что предыдущие версии не видел, ибо обзавелся контроллером только на днях, поэтому заюзал сразу последнюю версию. Но порывшись в сурсах библиотек для дуины, пришел именно к такому выводу.
странно — сейчас специально проверил — под 0018 всё нормально скомпилировалось. Может просто версия самой библиотеки старая?
Ну как бы скачал по ссылке в топике… Там последняя?
попробуйте эту версию —robocraft.ru/files/library/OneWire.zip
Вот эта уже под последние версии сделана. Скомпилилась нормально.
Жаль датчик у меня не DS18S20 а DS18B20 и этот пример не работает на нем, пишет всегда: No more addresses.
Спасибо за либу.
На 18В20 всё должно работать. Проверьте подключение датчика. На паразитном питании у меня считывает температуру на 20-метровом кабеле и с нескольких датчиков.
Датчик работает, юзаю его нормально с другим скетчем. Дело в коде. Или вы тоже такой датчик юзаете и все ок?
да, у меня 18В20.
Там кода то — 5 строк, где у вас вылетает 🙂
у меня это работает. Ошибка может только тут быть:
Больше мест не вижу.
Кстати, <b> внутри <code> тут не работает 😉
Да и закрытие тегов не отслеживается…
Ругается:
Может здесь подругому нужно проверять на нашем датчике?
Заккоментил это место, вроде прошло, но температуру показывает не правильно, на улице -23 а он мне -187 показывает.
Заменил расчет температуры на другой, из рабочего скетча:
И вуала, работает нормально 🙂
Но все же мне не нравится косяк на проверке… почему не определился датчик?
потому что это другая модель датчика, и у неё, разумеется, другой код серии 😉
Так это совсем другая ошибка 🙂
Да, для B20 надо так:
Дома поподробнее еще гляну эту статью… Вообще с данным датчиком делал термометр на Arduino Duemilanove — про CraftDuino, к сожалению, только вчера узнал… Делал вывод на сборку из 4-х семисегментников… Если кому интересно — могу, в принципе, выложить…
конечно интересно! выкладывайте 🙂
здравствуйте, купил датчик DS18B20… ds.search(addr) возвращает все время 0… схему проверял несколько раз… как можно проверить работоспособность датчика?? в чем может быть проблема?
там же вся схема — это четыре проводка и резистор О_о
и что значит возвращает 0?
в том то и проблема
происходит цикл в это ифе. то есть arduino не видит датчик.
попробуйте проверить схему подключения наключе-таблетке iButton
Спасибо за помощь, я так и не понял, что было не так, но сейчас заработало.
Как подключить библиотеку Onewire?
1. распаковать
2. поместить директорию библиотеки в библиотечную директорию Arduino IDE (\hardware\libraries\) или создать в папке своих скетчей такую же библиотеку libraries и поместить её туда
3. перезапустить IDE
см.Программирование Arduino — создание своей библиотеки.
Вопрос таковой:
А если нужно считывать с 3-х датчиков одновременно температуру, то как это реализовать и еще сделать приделы, то есть при 30 и выше подается питание на 13 пин, а если меньше — LOW.
и так с 3-мя датчиками и контактами 13,12,10 соответственно??
помогите пожалуйста=)
Всем спасибо за помощь. Вообщем я переписал код под оба датчика (надеюсь 🙂 ), у меня работает.
Вот если кому интересно:
Работает с DS18B20. Спасибо.
Не подскажете, где найти простую программу для фиксации показаний датчика в файле компьютера?
Каким образом можно считывать температуру на 20-метровом кабеле и с нескольких датчиков?
На счет проги не знаю, помоему проще самому накидать в этом случае.
А в кабеле сколько жил? 🙂
Три жилы. 10 датчиков.
Тут нужно углублятся в OneWire интерфейс. Я честно говоря не знаю, поддерживает ли он последовательное/параллельное подключение девайсов.
Где-то читал, что DS18B20 можно вешать параллельно на кабель и опрашивать любой по их уникальному адресу.
Для этого надо в программе заранее считать адреса всех датчиков на кабеле и тогда опрашивать любой.
На то он и 1wire 🙂 Можно вешать кучу датчиков и даже разных. И термометр и гигрометр и iButton и чёрта в ступе 🙂
программку можно накидать самостоятельно — налюбом языке программирования.выкладывать на сайт (используется скрипт на питоне) 🙂
Причём, можно не просто сохранять в файл, а и
Выкладывать на сайт — этим наверно воспользуюсь позже. Тем более, имеется готовое решение.
Пробую управлять с помощью Wiring. Для начала хватает. Да, и на сайтах много готовых программ.
В каких случаях может потребоваться Питон? Когда без него не обойтись?
обойтись можно — если предпочитаете программировать на чём-то другом 😉
Я просто уточнил, что в примере (для опрашивания COM-порта ардуины со стороны ПК) используется скрипт на питоне.
Для опрашивания COM-порта можно использоватьhttp://www.processing.org
Он позволит, при желании, и в файл сохранить, и графику нарисовать.
И ноги у них растут из одного места — Wiring/Arduino IDE/Processing…
разумеется можно — просто там ближе к java 🙂
Надеюсь Вы простите новичка за сжатость изложения…
В конструкции использован четырехразрядный моноблочный семисегментный индикатор с десятичными точками CA04-41SRWA от Kingbright. Разряды выполнены по схеме с общим анодом так же 2 старших разряда объединены между собой катодами сегментов и так же 2 младших.
Для реализации схемы все соответствующие катоды были объединены между собой в результате чего для целей индикации было задействованно 12(1-8 сегменты с точками 9-12 разряды) цифровых «портов». И 1(0) порт был использован под чтение с датчика…
Для операций была утянута библиотекаDallasTemperature , Найденная дрейфовым поиском по родному сайту Arduino…
Дальше, собственно, используя 2 таймер и прерывание от данного таймера по переполнению была реализованна классическая схема динамической индикации.
Как мне кажется — наименования переменных и функций говорят сами за себя, но если есть вопросы — отвечу…
большое спасибо! хотя, такой подробный комментарий лучше было бы оформить в виде отдельной статьи 😉
Попробую попозже оформить статьей…
Извиняюсь — накосячил с картинками, надеюсь администрация поправит…
Спасибо за пример, давно уже искал аналогичное. Только при компилировании появляются ошибки:
Библиотеку DallasTemperature.h установил и проверил, а в этом примере ошибка почему то.
Еще нигде ничего не нашел про библиотеку
Её нужно отдельно устанавливать или она уже предустановлена?
aspire89
Для понимания работы с библиотеками ArduinoIDE глянь тут
Библиотека должна находиться:
{arduinoinstalldir}/hardware/libraries/DallasTemperature/
Когда положите ее на место она станет доступна из ArduinoIDE через Sketch->Import Library->DallasTemperature
#include <avr/interrupt.h> идет в составе avr-gcc и WinAvr и информацию по работе с ней лучше черпать на сайте Atmel иavr-libc
Посмотрел еще на всякий случай в Ubuntu 9.10 — пакеты avr-gcc и avr-libc идут раздельно и, если мне не изменяет мой склероз, при установке avr-gcc второй пакет зависиммостями не прихватывается и его приходится устанавливать отдельно…
Спасибо, разобрался. Проблема была в следующем. У меня была установлена библиотека DallasTemperature.h, но не та которая выложена выше и после замены все запускается.
Только индикатор у меня с общим катодом. И если я правильно понимаю, то мне нужно все значения HIGH заменить на LOW и наоборот?
Да. Где в программе напрямую указаны LOW и HIGH — «проинвертировать» их и в таблице digits 0 и 1 поменять…
Либо дождаться вечера — постараюсь сегодня вечерком программку рихтануть чтоб указывать только в одном месте тип включения индикатора…
Спасибо огромное. Также если не трудно прокомментируйете пожалуйста эти строчки:
int cdigit = 0; — разряд индикатора обрабатываемый в текущем цикле обработки
int odigit = 0; — разряд индикатора обработанный в прошлом цикле обработки
int displ[] = {0, 8, 4, 9}; — собственно массив куда записана информация для отображения на дисплей… 0 8 4 9 — начальная инициализация, от балды, пока писал саму индикацию — проверял, что правильно отображается… В него записывается порядковый номер элемента из таблицы digits. Если в данном разряде надо отобразить точку — то записывается отрицательное значение… например при
{7,7,7,7} на экране будет 7777, а при {-7,-7,-7,-7} на экране будет 7.7.7.7.
int displ[] = {0, 8, 4, 9} должно отобразиться на дисплее как 9480…
void displayErr(int err) {
displ[0] = err;
displ[1] = -13;
displ[2] = -13;
displ[3] = -12;
}
Отображает E.r.r.{err} при текущем размере digits [15][8] — err не должно быть больше 14…
Писал то программульку чисто для себя — поэтому проверки на ошибки отсутствуют…
Да, и еще — как понимаете -0 — это нонсенс — посему 14 элемент массива digits как раз и предназначен чтоб можно было 0. отобразить на дисплее…
Да, и еще — как понимаете -0 — это нонсенс — посему 14 элемент массива digits как раз и предназначен чтоб можно было 0. отобразить на дисплее…
Т.е. для отображения 0.25 надо заполнить displ[] = {5, 2, -14, 10}
Вчера вечером руки не дошли. Быстренько поправил сидя на работе…
Вобщем, если нигде ничего не пропустил — должно все нормально работать. Для индикаторов с общим катодом надо снять комментарий со строчки
Вообще, как идея, надо попробовать сделать автоматическое определение типа индикатора… Если в ближайшее время дойдут руки — попробую…
собственно сама идея в следующем:
допустим мы включаем диод между 0 и 1 портами
0 порт в статусе INPUT
1 в статусе OUTPUT
при включении 0-К 1-А вне зависимости от состояния порта 1 — с нулевого должна читаться HIGH.
при включении 0-А 1-К при состоянии 1 LOW на 0 должно считаться LOW, а при HIGH — HIGH…
Соответственно, если я не ошибся — в функции setup можно проверить поведение индикатора, допустим между rdigs[0] и rsegs[0] и провести соответствующие изменения переменных, которые сейчас у меня сделаны за счет директив препроцессора…
Спасибо огромное. Теперь на индикаторах отображаются правильные цифры, но так и не смог разобрать температуру. Попробовал запустить пример из архива библиотеки:
Выдает сообщение Invalid CRC, хотя написано, что датчик DS1820 поддерживается. Есть возможность проверить DS18B20, как попробую, так отпишусь.
Тут я тебе ничего не подскажу — у меня нет эксперементальной базы — посмотреть неначем… Тут только доки вычитывать и библиотеку проверять, липо поискать версию посвежее…
Пока решил вывести температуру с ЦП.
На индикаторы для проверки вывожу 1 2 3 4:
Работает отлично.
Написал приложение на питоне для передачи температуры, в ардуино получаю значение следующим образом:
В serial monitor вижу значение температуры. Но вместо 1 2 3 4 уже отображается ‘1 (зеркальная 9) 9 4. Только закомментирую все, что связано с serial и на индикаторах 1 2 3 4.
Вот весь код:
Даже не знаю в чем может быть проблема.
Проблема может быть в работе с прерываниями…
Ругалось на этой строчке:
исправил на:
компилируется, но проблема осталась.
Проверил вчера дома — да проблемка присутствует… Причем начинается с Serial.begin();…
Судя по HardwareSerial.cpp — надо копать в сторону приоритетов и маскирования прерываний… Вобщем читать доку по камушку…
Спасибо огромное за помощь, без Вас мне не прикрутить было бы 4 семисегментных индикатора. В планах приобретение LCD дисплея. Может кто нибудь посоветует какой лучше выбрать?
Подключил TFT WF43BTIBED0…
Но эксперименты еще не закончены…
Посему подробности позже…
Если кого заинтересует — подробности постараюсь сделать позже…
Нашел статью про прерывания, может кому нибудь пригодитсяcommunity.livejournal.com/ru_arduino/16056.html
Попробуй:
Есть неплохая библиотека предназначенная как раз для работы с датчиками компании dallas milesburton.com/index.php?title=Dallas_Temperature_Control_Library#Latest поддерживает следующие модели
DS18B20
DS1822
DS18S20*
DS1820
а пример кода выглядит так
тут видно что это по сути обертка над библиотекой onewire, и здесь нет необходимости побитно разбирать ответ чтобы узнать температуру
Привет всем! Есть три датчика DS18B20, все сидят на одной линии. Как получать температуру с трёх? Может кто привести пример кода? Помогите пожалста, сам допереть не могу.
Можете воспользоваться кодом из примера который я привел выше. Там собственно запрашиваются все датчики висящие на одной линии.А вот эта строчка
собственно выводит показания первого из датчиков, а если подставите вместо нуля 1 или 2 то получите значения со второго или третьего датчика. В примере из основной статьи тоже производится поиск по всем устройствам на линии.Можно взять от туда.
Спасибо за содержательный ответ.
А есть возможность хранить данные прямо в ардуине? Тоесть записывать показания температуры, например раз в 5 минут, и потом скидывать данные на комп? Freeduino Mega+ v.1.22, около 100 кб свободной флеш памяти.
Что-то не рабочий вариант… Ошибки лезут в строке DallasTemperature sensors(&oneWire);
А у меня выводит следующее:
далее то же самое в цикле. В чем может быть причина?
Специально сфоткал:img-fotki.yandex.ru/get/4405/oleamm.2/0_556ce_5f737cf9_XXXL
Видно что первой ножкой датчик подключен к земле, второй ножкой к 12 пину (в коде тоже поправил) и через резистр к питанию. Контакты между собой где не надо не замыкаются (на фото можно подумать иначе).
Подключил к другом ардуино, выдает примерно то же:
Помогите поправить библиотеку OneWire для Arduino 1.x
Ошибки компиляции:
Спасибо!
Подскажите по поводу формата вывода чисел:
например, во Franklin’е когда я хочу определить конкретный формат вывода числа пишу
Тем самым указывая наличие знака, формат числовой переменной, количество знаков до и после запятой, саму переменную.
В wiringe не нашел подобного варианта.