В продолжение темы
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
Ссылки
http://www.arduino.cc/playground/Learning/OneWire
Комментарии (82)
RSS свернуть / развернутьПобыстропу не пофиксить, нужно править либу.
SWAT
noonv
SWAT
noonv
Ошибка касательно digital_pin_to_port и т.п. что связано с пинами. Теперь работа с ними немного другая, поэтому старых структур просто нет (в этом то и ошибка).
Я конечно могу ошибаться, потому что предыдущие версии не видел, ибо обзавелся контроллером только на днях, поэтому заюзал сразу последнюю версию. Но порывшись в сурсах библиотек для дуины, пришел именно к такому выводу.
SWAT
noonv
SWAT
noonv
Жаль датчик у меня не DS18S20 а DS18B20 и этот пример не работает на нем, пишет всегда: No more addresses.
Спасибо за либу.
SWAT
boa
SWAT
Там кода то — 5 строк, где у вас вылетает :)
у меня это работает. Ошибка может только тут быть:
Больше мест не вижу.
boa
Да и закрытие тегов не отслеживается…
boa
Может здесь подругому нужно проверять на нашем датчике?
Заккоментил это место, вроде прошло, но температуру показывает не правильно, на улице -23 а он мне -187 показывает.
Заменил расчет температуры на другой, из рабочего скетча:
И вуала, работает нормально :)
Но все же мне не нравится косяк на проверке… почему не определился датчик?
SWAT
Да, для B20 надо так:
boa
admin
Вот если кому интересно:
SWAT
Не подскажете, где найти простую программу для фиксации показаний датчика в файле компьютера?
Каким образом можно считывать температуру на 20-метровом кабеле и с нескольких датчиков?
velvol
А в кабеле сколько жил? :)
SWAT
velvol
SWAT
Для этого надо в программе заранее считать адреса всех датчиков на кабеле и тогда опрашивать любой.
velvol
boa
Причём, можно не просто сохранять в файл, а и
noonv
Пробую управлять с помощью Wiring. Для начала хватает. Да, и на сайтах много готовых программ.
В каких случаях может потребоваться Питон? Когда без него не обойтись?
velvol
Я просто уточнил, что в примере (для опрашивания COM-порта ардуины со стороны ПК) используется скрипт на питоне.
noonv
Он позволит, при желании, и в файл сохранить, и графику нарисовать.
И ноги у них растут из одного места — Wiring/Arduino IDE/Processing…
vvvictor
noonv
vvvictor
noonv
В конструкции использован четырехразрядный моноблочный семисегментный индикатор с десятичными точками CA04-41SRWA от Kingbright. Разряды выполнены по схеме с общим анодом так же 2 старших разряда объединены между собой катодами сегментов и так же 2 младших.
Для реализации схемы все соответствующие катоды были объединены между собой в результате чего для целей индикации было задействованно 12(1-8 сегменты с точками 9-12 разряды) цифровых «портов». И 1(0) порт был использован под чтение с датчика…
Для операций была утянута библиотека
Дальше, собственно, используя 2 таймер и прерывание от данного таймера по переполнению была реализованна классическая схема динамической индикации.
Как мне кажется — наименования переменных и функций говорят сами за себя, но если есть вопросы — отвечу…
vvvictor
vvvictor
noonv
vvvictor
vvvictor
Библиотеку DallasTemperature.h установил и проверил, а в этом примере ошибка почему то.
Еще нигде ничего не нашел про библиотеку Её нужно отдельно устанавливать или она уже предустановлена?
aspire89
Библиотека должна находиться:
{arduinoinstalldir}/hardware/libraries/DallasTemperature/
Когда положите ее на место она станет доступна из ArduinoIDE через Sketch->Import Library->DallasTemperature
#include <avr/interrupt.h> идет в составе avr-gcc и WinAvr и информацию по работе с ней лучше черпать на сайте Atmel и
vvvictor
vvvictor
aspire89
aspire89
Либо дождаться вечера — постараюсь сегодня вечерком программку рихтануть чтоб указывать только в одном месте тип включения индикатора…
vvvictor
aspire89
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.
vvvictor
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…
Писал то программульку чисто для себя — поэтому проверки на ошибки отсутствуют…
vvvictor
vvvictor
Т.е. для отображения 0.25 надо заполнить displ[] = {5, 2, -14, 10}
vvvictor
Вобщем, если нигде ничего не пропустил — должно все нормально работать. Для индикаторов с общим катодом надо снять комментарий со строчки
Вообще, как идея, надо попробовать сделать автоматическое определение типа индикатора… Если в ближайшее время дойдут руки — попробую…
vvvictor
допустим мы включаем диод между 0 и 1 портами
0 порт в статусе INPUT
1 в статусе OUTPUT
при включении 0-К 1-А вне зависимости от состояния порта 1 — с нулевого должна читаться HIGH.
при включении 0-А 1-К при состоянии 1 LOW на 0 должно считаться LOW, а при HIGH — HIGH…
Соответственно, если я не ошибся — в функции setup можно проверить поведение индикатора, допустим между rdigs[0] и rsegs[0] и провести соответствующие изменения переменных, которые сейчас у меня сделаны за счет директив препроцессора…
vvvictor
Выдает сообщение Invalid CRC, хотя написано, что датчик DS1820 поддерживается. Есть возможность проверить DS18B20, как попробую, так отпишусь.
aspire89
vvvictor
На индикаторы для проверки вывожу 1 2 3 4:
Работает отлично.
Написал приложение на питоне для передачи температуры, в ардуино получаю значение следующим образом:
В serial monitor вижу значение температуры. Но вместо 1 2 3 4 уже отображается '1 (зеркальная 9) 9 4. Только закомментирую все, что связано с serial и на индикаторах 1 2 3 4.
Вот весь код:
Даже не знаю в чем может быть проблема.
aspire89
vvvictor
vvvictor
исправил на:
компилируется, но проблема осталась.
aspire89
Судя по HardwareSerial.cpp — надо копать в сторону приоритетов и маскирования прерываний… Вобщем читать доку по камушку…
vvvictor
aspire89
Но эксперименты еще не закончены…
Посему подробности позже…
vvvictor
Если кого заинтересует — подробности постараюсь сделать позже…
vvvictor
aspire89
vans239
и что значит возвращает 0?
noonv
происходит цикл в это ифе. то есть arduino не видит датчик.
vans239
noonv
vans239
Alexandr
2. поместить директорию библиотеки в библиотечную директорию Arduino IDE (\hardware\libraries\) или создать в папке своих скетчей такую же библиотеку libraries и поместить её туда
3. перезапустить IDE
см.
noonv
DS18B20
DS1822
DS18S20*
DS1820
а пример кода выглядит так
тут видно что это по сути обертка над библиотекой onewire, и здесь нет необходимости побитно разбирать ответ чтобы узнать температуру
cradleguard
Siroc-co
собственно выводит показания первого из датчиков, а если подставите вместо нуля 1 или 2 то получите значения со второго или третьего датчика. В примере из основной статьи тоже производится поиск по всем устройствам на линии.Можно взять от туда.
cradleguard
Siroc-co
Siroc-co
Siroc-co
cradleguard
Можно попробовать такое реализовать на примере
Так же для Arduino есть проект
noonv
далее то же самое в цикле. В чем может быть причина?
oleamm
Видно что первой ножкой датчик подключен к земле, второй ножкой к 12 пину (в коде тоже поправил) и через резистр к питанию. Контакты между собой где не надо не замыкаются (на фото можно подумать иначе).
Подключил к другом ардуино, выдает примерно то же:
oleamm
А если нужно считывать с 3-х датчиков одновременно температуру, то как это реализовать и еще сделать приделы, то есть при 30 и выше подается питание на 13 пин, а если меньше — LOW.
и так с 3-мя датчиками и контактами 13,12,10 соответственно??
помогите пожалуйста=)
ZuZzZa
Ошибки компиляции:
provincial
admin
Подскажите по поводу формата вывода чисел:
например, во Franklin'е когда я хочу определить конкретный формат вывода числа пишу
Тем самым указывая наличие знака, формат числовой переменной, количество знаков до и после запятой, саму переменную.
В wiringe не нашел подобного варианта.
provincial
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.