Ардуино термометр на основе датчика температуры ds18b20
Содержание:
- Считывание данных с устройства типа 1-Wire
- Термометр через последовательный монитор
- Открытый сток
- ↑ Общение с датчиком
- Протокол 1-Wire
- Связанные материалы
- Features
- Камрад, рассмотри датагорские рекомендации
- 5Управление устройством по шине IIC
- Выносим в отдельный поток
- Итого: как всё это используется на практике в АСУ ТП
Считывание данных с устройства типа 1-Wire
Чтобы прочесть данные с устройства типа 1-Wire, нужно выполнить несколько шагов. Каких именно шагов – зависит от самого устройства, т.к. разные устройства могут отсылать разные значения. Популярный DS18B20, к примеру, считывает данные о температуре, а DS2438 – о напряжении, силе тока и температуре.
Два основных этапа при считывании данных
Конверсия
Эта команда шлется устройство, чтобы оно начало выполнять операцию конверсии. В случае DS18B20 этой командой будет байт 0x44 (команда «Convert T»). В библиотеке OneWire за это отвечает функция ds.write(0x44), где ds – это экземпляр класса OneWire. После получения этой команды устройство начинает считывать данные с внутреннего АЦП, а затем копирует их в регистры оперативной (scratchpad) памяти.
Длительность процесса конверсии варьируется в зависимости от разрешения и указана в даташите устройства. Согласно даташиту, у датчика DS18B20 конверсия температуры может занимать от 94 (разрешение 9 бит) до 750 (разрешение 12 бит) миллисекунд. Во время выполнения конверсии девайс можно опрашивать, то есть использовать, к примеру, функцию ds.read(), чтобы проверить успешность выполнения конверсии.
Чтение оперативной (scratchpad) памяти
Конвертированные данные копируются в оперативную (scratchpad) память, откуда их можно прочитать. Причем эту команду можно вызывать и без команды конверсии – это может пригодиться, к примеру, если вы забыли, какие данные были прочитаны в прошлый раз (поскольку они по-прежнему хранятся в оперативной памяти). Кроме того, с помощью этой команды можно прочитать данные о разрешении устройства и конфигурационные настройки (зависят от устройства).
Синхронные и асинхронные запись/считывание
Большинство программ и скетчей для девайсов типа 1-Wire (в особенности те, что написаны для Arduino) используют простой алгоритм «конверсия, ожидание, считывание» – даже при использовании нескольких устройств. Это может стать причиной ряда проблем:
Синхронизация с другими функциями
Если в скетче жестко прописано время ожидания, то ведущее устройство во время конверсии должно просто остановиться и ждать (за исключением случаев, когда используется многопоточность). Это влечет серьезную проблему и в том случае, если в скетче есть другие процессы, привязанные к времени, и в том случае, если их нет – многим программам нужно ждать ввода данных, обработки данных и выполнения многих других операций, которые не терпят задержек, необходимых для конверсии температурных данных. Как упоминалось выше, 12-битная конверсия в DS18B20 требует задержки в 750 миллисекунд. Поэтому в использовании ожидания, пока датчик выполнит процесс конверсии, никакого смысла нет. Гораздо разумнее будет послать команду конверсии, а за ее результатом вернуться позже, когда конверсия уже будет завершена – прочитав этот результат при помощи команды «Read Scratchpad».
Скорость опроса нескольких устройств
Еще одна проблема метода «конверсия, ожидание, считывание» – время, затрачиваемое на считывание данных с нескольких устройств. То есть, если ничего не менять, то эти три действия будут выполняться для каждого устройства по отдельности. Но гораздо эффективней было бы сначала отправить запрос на конверсию (или всем устройствам сразу, или по отдельности), затем сделать одну единственную задержку (сразу для всех), а потом по очереди считывать данные с каждого из этих устройств. Более подробно читайте тут.
Подгонка времени ожидания ко времени конверсии
Самый эффективный и быстрый способ считывания информации с девайса типа 1-Wire – это учитывать еще и время конверсии, что можно делать при помощи функции ds.read(). К примеру, в одном из скетчей ниже указана в задержка в 1000 миллисекунд, тогда как в даташите максимальным временем конверсии указано 750 миллисекунд, а фактически это происходит за 625 миллисекунд или меньше. Но важнее то, что это значение должно соответствовать разрешению, с которым происходит конверсия. Конверсия с разрешением 9 бит, например, занимает до 94 миллисекунд, поэтому ожидание в течение 1000 миллисекунд просто не имеет смысла.
Как упоминалось выше, самый эффективный способ опроса девайса – делать это во время считывания. Благодаря этому вы всегда будете знать, готов ли результат, а если готов, то сможете в тот же момент его прочитать.
Обсуждение и примеры кода, затрагивающие эту тему, можно посмотреть здесь.
Термометр через последовательный монитор
Чтобы отобразить данные на последовательном мониторе, подключите датчик DS18B20 к Arduino, используя перемычки и макет, и не забудьте подключить или припаять резистор 4.7k между контактом 2 и 3 датчика.
Затем скачайте, откройте и загрузите файл .ino, который называется — DS18B20_Serial, ниже.
Если все в порядке, вы должны увидеть измеренную температуру на серийном мониторе Arduino IDE.
#include <OneWire.h> #include <DallasTemperature.h> // Провод данных подключен к контакту 2 на Arduino #define ONE_WIRE_BUS 2 // Настройка oneWire для связи с любыми устройствами OneWire // (не только Maxim/Dallas температурные IC) OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); void setup(void) { // Старт серийного порта Serial.begin(9600); Serial.println("Dallas Temperature IC демо"); // Запуск библиотеки sensors.begin(); } void loop(void) { // запрашиваем sensor.requestTemperatures() для получения глобальной температуры // запрос всех устройств на шине Serial.print(" Запрашиваем температуру..."); sensors.requestTemperatures(); // Отправляем команды для получения температуры Serial.println("DONE"); Serial.print("Температура: "); Serial.print(sensors.getTempCByIndex(0)); // Почему "byIndex"? // У вас может быть несколько IC на одной шине. // 0 относится к первой IC delay(1000); }
Открытый сток
Определяющей особенностью I2C является то, что каждое устройство на шине, должно подключаться к линиям тактового сигнала (сокращенно SCL) и сигнала данных (сокращенно SDA) через выходные драйверы с открытым стоком (или открытым коллектором). Давайте посмотрим, что это на самом деле означает. Сначала рассмотрим типовой CMOS (инвертирующий) выходной каскад:
Если на входе присутствует высокий логический уровень, NMOS транзистор открыт, а PMOS транзистор закрыт. Таким образом, выход имеет низкоомное соединение с землей. Если на входе присутствует низкий логический уровень, ситуация меняется на противоположную, а выход имеет низкоомное соединение с VDD. Это называется двухтактным выходным каскадом, хотя это название не особенно информативно, поскольку оно не подчеркивает низкое сопротивление соединений, которые управляют выходом. В общем случае вы не можете напрямую соединять два двухтактных выхода, поскольку ток будет свободно протекать от VDD до земли, если на одном выходе выдается логическая единица, а на другом – логический ноль.
Теперь рассмотрим схему с открытым стоком:
PMOS транзистор был заменен резистором, внешним по отношению к микросхеме. Если на входе присутствует высокий логический уровень, NMOS транзистор обеспечивает низкоомное соединение с землей. Но если на вход подается низкий логический уровень, NMOS транзистор выглядит как разомкнутая цепь, а это означает, что выход подтягивается к VDD через внешний резистор. Такой механизм приводит к двум важным отличиям. Во-первых, появляется неочевидное рассеивание мощности, когда на выходе низкий логический уровень, поскольку ток протекает через резистор, через канал NMOS транзистора на землю (в двухтактной схеме этот ток блокируется высоким сопротивлением закрытого PMOS транзистора). Во-вторых, выходной сигнал ведет себя по-другому, когда на выходе высокий логический уровень, так как выход подключен к VDD через гораздо более высокое сопротивление (обычно не менее 1 кОм). Эта особенность позволяет напрямую соединять два (и более) устройства с открытым стоком: даже если на одном из них низкий логический уровень, а на другом – высокий логический уровень, то подтягивающий резистор гарантирует, что ток не протекает свободно от VDD на землю.
Некоторые последствия использования на шине схемы с открытым стоком:
- Сигналы всегда по умолчанию находятся в состоянии логической единицы. Напримем, если ведущее устройство I2C пытается связаться с ведомым устройством, которое вдруг перестало функционировать, сигнал данных никогда не войдет в неопределенное состояние. Если ведомое устройство не управляет сигналом, то он будет считан как логическая единица. Аналогично, если ведущее устройство выключается в середине передачи, линии SCL и SDA вернутся в состояние логической единицы. Другие устройства могут определить, что шина доступна для новых передач, наблюдая, что и SCL, и SDA находятся в состоянии логической единицы в течении определенного периода времени.
- Любое устройство на шине может безопасно приводить сигналы в состояние логического нуля, даже если другое устройство пытается привести их в состояние логической единицы. Это является основой функции «тактовой синхронизации» или «растяжки тактового сигнала» на шине I2C: ведущее устройство генерирует последовательность тактовых импульсов, но при необходимости ведомое устройство может удерживать линию SCL на низком уровне и тем самым уменьшать тактовую частоту.
- Устройства с различными напряжениями питания могут сосуществовать на одной и той же шине, пока устройства с более низким напряжением не будут повреждены более высоким напряжением. Например, устройство 3,3 В может связываться с устройством 5 В, если SCL и SDA подтянуты до 5 В – схема с открытым стоком приводит к тому, что высокий логический уровень достигает напряжения 5 В, хотя устройство 3,3 В с типовым двухтактным каскадом не может управлять линией 5 В.
↑ Общение с датчиком
- 0x33h – считать ромкод (уникальное имя каждого устройства). Применение возможно только, если на шине всего одно устройство.
- 0x55h – обратиться по ром коду к конкретному устройству. После необходимо также передать 64 битный ром код. Только устройство у которого переданный код совпадет с записанным в него на заводе останется на шине, остальные отключатся.
- 0xCCh — После приема данной команды все устройства останутся активными на шине. Удобно использовать если устройство одно или есть однотипные.
- 0x44h – Запуск преобразования температуры. Если датчик питает не от линии данных, то после можно прочитать состояние шины 0 – если преобразование не завершено и 1 – если преобразование завершено.
- 0xBEh – Считать 8 байт данных. Первые два байта – вычисленная температура.
- 0x4Eh – запись в память датчика. Необходимо передать три байта – верхнюю границу термостата, нижнюю границу термостата и значение контрольного регистра.
- 0x1Fh — 9 бит (±0,5 градуса Цельсия), преобразование примерно 94 миллисекунды;
- 0x3Fh — 10 бит (±0,25 градуса Цельсия), преобразование примерно 188 миллисекунд;
- 0x5Fh — 11 бит (±0,125 градуса Цельсия), преобразование примерно 375 миллисекунд;
- 0x7Fh — 12 бит (±0,0625 градуса Цельсия), преобразование примерно 750 миллисекунд;
Настройка датчика:
термостатСчитываем температуру.Исключён фрагмент. Полный вариант статьи доступен меценатам и полноправным членам сообщества. Читай условия доступа.
Функция выдачи ром кода на шину:
Протокол 1-Wire
Протокол 1-Wire – это протокол, используемый для управления устройствами, которые производятся компанией Dallas Semiconductor (ныне Maxim). Хотя 1-Wire является приприетарным протоколом и торговой маркой Dallas, программисты, использующие драйверы 1-Wire, не обязаны делать за это никаких выплат.
Сеть 1-Wire, которую Dallas называет MicroLan (торговая марка), состоит из одного ведущего устройства, к которому при помощи единственной линии передачи данных подключено одно или несколько ведомых устройств. Эту линию, помимо прочего, можно использовать для электропитания ведомых устройств (ситуацию, когда устройства подпитываются через шину 1-Wire, называют «паразитным питанием»).
Более подробно о 1-Wire можно почитать в руководствах (этом и этом) Тома Бойда.
Среди прочих устройств, работающих через протокол 1-Wire, особенно популярны температурные датчики – они недороги, просты в использовании и позволяют напрямую считывать откалиброванные цифровые температурные данные. Кроме того, они терпимы к длинным проводам, которыми часто приходится пользоваться при создании цепи с Arduino. Один из примеров ниже демонстрирует, как работать с 1-Wire на примере цифрового термометра DS18S20. Многие чипы 1-Wire могут работать и через паразитное, и через нормальное питание.
Связанные материалы
Программная реализация протокола SPI на AVR в CodeVisionAVR…
Всем коллегам и согражданам привет! Увлёкся я изучением протоколов. Про реализацию протокола I2C у…
Несколько функций для програмной реализации протокола I2C на AVR…
Добрый день, дорогие друзья! Решил поделиться с вами несколькими функция для работы по протоколу…
Визуализация для микроконтроллера. Часть 4. Android…
Вообще то я планировал рассказать сегодня про дисплей на базе ILI9481. Однако, он настолько похож…
USB адаптер для чтения и программирования цифровых термостатов MAXIM/DALLAS DS1821…
В статье описано, как за час сделать простой USB-адаптер для чтения/записи цифровых термометров…
Работа с датчиком DHT11. Строим термометр-гигрометр на ATMEGA8…
Привет любителям электроники! Сегодня я решил познакомиться с датчиком влажности DHT11, который…
Универсальный контроллер управления 7-сегментными LED индикаторами по двум проводам (Atmega16)…
Занялся я конструированием нового устройства и встал вопрос — на чем отображать данные….
Простой цифровой термометр на ATmega8535 + DS18B20…
Доброго времени суток! Представляю простой, цифровой термометр на индикаторе ИЖЦ21-4/7,…
Программная реализация протокола I2C на AVR в CodeVisionAVR…
Пару лет назад, изучая Atmega8, я захотел программно реализовать работу с устройствами на шине i2c,…
Arduino shield: акселерометр на LIS302DL…
Собрал недавно arduino на atmega8, поморгал диодом, захотелось большего. Начал изучать различные…
Texas Instruments. Руководство по выбору компонентов для аналоговых схем…
Операционные усилители, компараторы, буфферы, ЦАП/АЦП преобразователи данных, интерфейсы, схемы…
10 практических устройств на AVR-микроконтроллерах. Книга 1. А.В. Кравченко…
10 практических устройств на AVR-микроконтроллерах. Книга 1. А.В. Кравченко Издательство: Москва,…
Грызем микроконтроллеры. Урок 4….
Мигалки – это хорошо, по новогоднему… Но ведь нельзя останавливаться на достигнутом! Пора сделать…
Features
-
All bus activities are performed respecting open-drain character of the 1-wire
protocol.During normal 1-wire activities, the master MCU GPIO controlling the bus is
never set high (providing direct voltage source on the bus) instead the GPIO
is switched to the reading mode causing the high state seen on the bus via
the pull-up resistor. -
1-wire touch support.
The 1-wire touch may substantially simplify complex bus activities consisting
of write-read pairs by combining them into a single touch activity. See examples
for details. -
Parasite powering support.
The 1-wire bus may be powered directly by the master MCU GPIO or via a switching
transistor controlled by a dedicated MCU GPIO, if the target platform’s GPIOs
(in the output mode) work in the open-drain mode only. More details
. -
Search filtering.
Search algorithm allows efficient filtering basing on a selected set of family
codes. Maximum size of the set is configurable by
configuration macro-define. -
Overdrive (high-speed) mode support.
The overdrive mode enables speed up the 1-wire communication by a factor of 10.
Only limited number of 1-wire devices support this mode (e.g. DS2408, DS2431). -
Clear and flexible architecture.
The code architecture allows fast and easy porting for new Arduino platforms
or even usage of the core part of library outside the Arduino environment.
Камрад, рассмотри датагорские рекомендации
Внимание! 800 рублей для новичков на Aliexpress Регистрируйтесь по нашей ссылке. Если вы впервые на Aliexpress — получите 800.00₽ купонами на свой первый заказ.. Цифровой осциллограф DSO138
Кит для сборки
Цифровой осциллограф DSO138. Кит для сборки
Функциональный генератор. Кит для сборки
Настраиваемый держатель для удобной пайки печатных плат
Алексей (teXnik)
Россия, Тула
Список всех статей
Профиль teXnik
Студент политехнического университета, увлекаюсь радиэлектроникой и модернизацией авто (подготовка для джип триала). Паять люблю. Переделал амфитоны 25 ас 27 и усилитель под них на тдашке.Собрал уазик с мотором v8.На сайт пришел для разватия своих навыков и умений
5Управление устройством по шине IIC
Рассмотрим диаграммы информационного обмена с цифровым потенциометром AD5171, представленные в техническом описании:
Рассмотрим диаграммы чтения и записи цифрового потенциометра AD5171
Нас тут интересует диаграмма записи данных в регистр RDAC. Этот регистр используется для управления сопротивлением потенциометра.
Откроем из примеров библиотеки «Wire» скетч: Файл Образцы Wire digital_potentiometer. Загрузим его в память Arduino.
#include <Wire.h> // подключаем библиотеку "Wire" byte val = 0; // значение для передачи потенциометру void setup() { Wire.begin(); // подключаемся к шине I2C как мастер } void loop() { Wire.beginTransmission(44); // начинаем обмен с устройством с I2C адресом "44" (0x2C) Wire.write(byte(0x00)); // посылаем инструкцию записи в регистр RDAC Wire.write(val); // задаём положение 64-позиционного потенциометра Wire.endTransmission(); // завершаем I2C передачу val++; // инкрементируем val на 1 if (val == 63) { // по достижении максимума потенциометра val = 0; // сбрасываем val } delay(500); }
После включения вы видите, как яркость светодиода циклически нарастает, а потом гаснет. При этом мы управляем потенциометром с помощью Arduino по шине I2C.
По ссылкам внизу статьи, в разделе похожих материалов (по тегу), можно найти дополнительные примеры взаимодействия с различными устройствами по интерфейсу IIC, в том числе примеры чтения и записи.
Выносим в отдельный поток
Собственно, теперь ты убедился, что библиотека работает, термодатчик тоже что-то измеряет (в данном случае комнатную температуру). Давай теперь подключим все это добро к нашей системе сигнализации. Для этого необходимо создать отдельный поток, в котором будет производиться периодический опрос термодатчика и при возникновении аварии отправляться сообщение.
Немного подумав, я решил, что лучше сделать целый класс — движок работы с термодатчиками, унаследовав его от класса process<>, чтобы все собрать в одну кучку: сделать имплементацию функции-потока, дать этой функции доступ к членам класса, выставить наружу основные функции работы с термодатчиками.
Однако тут я уткнулся в жадность. Мне хотелось оставить возможность опроса термодатчиков из консоли и иметь сигнализацию. Сразу же возникает необходимость разделять общие ресурсы, так как теперь два потока будут дергать один термодатчик (а точнее, шину 1-Wire). Лезь в класс OneWire и добавляй ему приватного мембера .
Здесь начинается интересное. Мьютекс мы завели, но пользоваться им внутри класса неразумно, так как библиотека работы с термодатчиком написана очень сильно интегрировано и на лету дергает функции байтовой, а не пакетной приема-передачи по 1-Wire. Для локализации массовых вызовов я создал два метода: и для шины 1-Wire.
Затем пришлось прошерстить всю библиотеку DallasTemperature и обернуть вызовы функций работы с шиной 1-Wire в оболочку -> .
Реализация функции потока обработки показаний термодатчика совсем проста. В цикле запрашивается температура, проверяется на вхождение ее в граничные диапазоны (которые сейчас захардкожены), при изменении состояния отправляется грязное ругательное сообщение. Напомню, что в прошлой реализации аварийного потока я заложил код источника сообщения , который сейчас и использую. Приведу кусочек кода, чтобы не мучить тебя словами.
Дополнительно я решил добавить аварийное состояние при обрыве термодатчика, то есть когда непрерывно не удается получиться данные от термодатчика на протяжении некоторого времени, в данном случае десяти опросов.
Тут-то я и наступил на грабли. Я забыл про функцию инициации процесса измерения . В ней стоят задержки для того, чтобы подождать, пока термодатчик производит измерение. Но я поставил перед этими задержками. В итоге я получил странную картину: при запросе из терминала начинали скакать показания термодатчика. А случалось вот что: поток движка термодатчиков запускал измерение, одновременно приходил я со своим запросом по терминалу, и в итоге мы оба читали какие-то неинициализированные значения.
Почесав затылок, я вынес отдельно функцию инициации процесса измерения и оставил ее вызов только внутри потока движка термодатчиков. Таким образом, при получении команды из терминала возвращается последняя измеренная температура. Работает даже быстрее, чем каждый раз дергать термодатчик и просить его померить вот прямо сейчас и прямо здесь.
Остается лишь добавить в поток обработки аварийных сообщений кейсы нового источника аварий.
Итого: как всё это используется на практике в АСУ ТП
Естественно, видовое разнообразие современных промышленных протоколов передачи данных намного больше, чем мы описали в этой статье. Некоторые привязаны к конкретному производителю, некоторые, напротив, универсальны. При разработке автоматизированных систем управления технологическим процессом (АСУ ТП) инженер выбирает оптимальные протоколы, с учетом конкретных задач и ограничений (технических и по бюджету).
Если говорить о распространенности того или иного протокола обмена, то можно привести диаграмму компании HMS Networks AB, которая иллюстрирует доли рынка различных технологий обмена в промышленных сетях.
Как видно на диаграмме, PRONET и PROFIBUS от Siemens занимают лидирующие позиции.
60% рынка занимали протоколы PROFINET и Ethernet/IP
В таблице ниже собраны сводные данные по описанным протоколам обмена. Некоторые параметры, например, производительность выражены абстрактными терминами: высокая /низкая. Числовые эквиваленты можно отыскать в статьях по анализу производительности.
EtherCAT |
POWERLINK |
PROFINET |
EtherNet/IP |
ModbusTCP |
|
Физический уровень |
100/1000 BASE-TX |
100/1000 BASE-TX |
100/1000 BASE-TX |
100/1000 BASE-TX |
100/1000 BASE-TX |
Уровень передачи данных |
Канальный (Ethernet-фреймы) |
Канальный (Ethernet-фреймы) |
Канальный (Ethernet-фреймы), Сетевой/транспортный(TCP/IP) |
Сетевой/транспортный(TCP/IP) |
Сетевой/транспортный(TCP/IP) |
Поддержка реального времени |
Да |
Да |
Да |
Да |
Нет |
Производительность |
Высокая |
Высокая |
IRT – высокая, RT – средняя |
Средняя |
Низкая |
Длина кабеля между узлами |
100м |
100м/2км |
100м |
100м |
100м |
Фазы передачи |
Нет |
Изохронная + асинхронная |
IRT – изохронная + асинхронная, RT – асинхронная |
Нет |
Нет |
Количество узлов |
65535 |
240 |
Ограничение сети TCP/IP |
Ограничение сети TCP/IP |
Ограничение сети TCP/IP |
Разрешение коллизий |
Кольцевая топология |
Тактовая синхронизация, фазы передачи |
Кольцевая топология, фазы передачи |
Коммутаторы, топология “звезда” |
Коммутаторы, топология “звезда” |
Горячая замена |
Нет |
Да |
Да |
Да |
В зависимости от реализации |
Стоимость оборудования |
Низкая |
Низкая |
Высокая |
Средняя |
Низкая |
Области применения описанных протоколов обмена, полевых шин и промышленных сетей очень разнообразны. Начиная от химической и автомобильной промышленности и заканчивая аэрокосмическими технологиями и производством электроники. Быстродействующие протоколы обмена востребованы в системах real-time позиционирования различных устройств и в робототехнике.