Arduino: делаем самостоятельно датчик температуры
Arduino: осваиваем цифровой термодатчик и 1-Wire – «Хакер»
Моргания лампочки и замыкание контактов — дело интересное и полезное для первых шагов. Но, как все мы помним со школы, чем нагляднее эксперимент, тем он интереснее.
Я продолжу развивать проект из предыдущих серий, и сегодня мы прикрутим термодатчик 1-Wire для того, чтобы контролировать температуру в твоем многострадальном холодильнике.
Того и гляди, скоро у тебя появится «умный» холодильник :).
В предыдущих сериях
Так как я продолжаю повествование с некоей точки, а не с самого начала, то пройдусь по тому, что уже имеется. В нашем арсенале Arduino mega2560 с поднятой ОСРВ scmRTOS.
Прошивка позволяет моргать светодиодом L на плате в разных последовательностях в зависимости от «аварийного» или «нормального» состояния, а также «плеваться» в консоль грязными ругательствами (ведь ты именно такие выбрал?) в качестве уведомления об изменении состояния.
«Нормальность» состояния определяется замкнутостью контактного датчика. Последовательность можно менять из консоли. Исходники проекта выложены на GitHub.
Вдохнем новизны
Идея прикрутить термодатчик зародилась у меня еще до того, как я начал делать этот проект. Последовательность действий (а именно так и нужно действовать — последовательно и не пытаться забегать вперед) оттягивала этот момент, и я особо не забивал себе голову деталями. Но вот время пришло.
Так в чем проблема? А вот в чем: можно было взять обычный резистивный термодатчик и использовать встроенный АЦП микропроцессора.
Но! Я взялся за этот проект с правилом: минимум паяльника и дополнительного нестандартного оборудования, все из коробки.
При использовании же резистивного термодатчика необходимо городить делитель напряжения, а значит, требуется минимальное, но погружение в схемотехнику. Так что этот вариант отпал.
Остался второй вариант — цифровой термодатчик. Правда, с ним тоже беда. Цифровой термодатчик подключается по интерфейсу 1-Wire, а такого интерфейса на плате нет. Зато есть вариант минимальными усилиями сделать программную эмуляцию этого интерфейса.
Дополнительный бонус этого решения — термодатчиков можно посадить целый рассадник на одну проводную линию, в отличие от резистивного термодатчика (естественно, рекомендуется ознакомиться с матчастью, так как есть ограничения на длину линии, общее сопротивление и прочее).
Немного о самом 1-Wire
1-Wire — это так называемый однопроводный интерфейс. Примечателен он тем, что для обмена данными с устройствами по этому интерфейсу требуется всего один сигнальный провод и один провод «земли».
Что еще более примечательно, устройства спроектированы таким образом, что по этому же сигнальному проводу они и «кормятся» (то есть для питания устройства используется все тот же сигнальный провод), такой режим называется «паразитным питанием».
Для реализации такого способа питания в устройствах ставят достаточно емкий конденсатор.
Для того чтобы начать сессию обмена данными, необходимо сформировать сигнал «сброс». Для этого мастер передает в линию данных 0 на время не менее 480 мкс. После чего мастер отпускает линию данных и начинает слушать линию.
За счет резистора подтяжки линия данных установится в 1. Если на линии присутствует устройство (датчик), то он передаст мастеру подтверждение сброса, для этого он удерживает линию данных в 0 на время 60–240 мкс.
Считав состояние линии, мастер узнает о присутствии на шине устройств, готовых к обмену.
Старт обмена данными
1-Wire обладает еще одной особенностью: передача битов осуществляется не уровнями сигнала, а временными задержками.
Таким образом, чтобы передать 1, необходимо установить в линии 0 и держать его 15 мкс, после чего отпустить линию, которая за счет подтягивающего резистора перейдет в уровень 1.
Чтобы передать 0, необходимо установить в линии 0 на 15 мкс, а затем держать 0 на линии еще 60–120 мкс.
Передача данных 1-Wire
Честный 1-Wire
Предложенный вариант реализации интерфейса 1-Wire обладает одним недостатком. Точнее, двумя.
- Он жрет ресурсы (как любая программная эмуляция).
- Он неустойчив к помехам.
С первым недостатком можно еще как-то мириться, хотя по мере роста проекта ресурсов остается все меньше. Со вторым недостатком в боевом софте надо бороться семплированием сигнала. Что такое семплирование? Допустим, бит 1 передается 6 мкс.
Для того чтобы точно быть уверенным, что это 1, а не какая-то наводка, необходимо несколько раз в течение этих 6 мкс измерить состояние входного сигнала. Чем больше измерений ты проведешь, тем точнее будет твой результат и уверенность в правильности принятия данных. Однако 6 мкс — это ооочень мало, тут возникает вопрос разумности и аппаратных возможностей.
С разумностью, хочется верить, у тебя все в порядке, а вот с возможностями в нашем микропроцессоре неважненько. Первое, что приходит в голову, — натравить таймер с частотой 1 мкс и получить хотя бы пять семплов. Проблема только в том, что в данном железе на такую частоту настроить таймер не представляется возможным.
Настроить-то можно, но толку от этого не будет, так как надо учитывать накладные расходы на «проваливание» в прерывание, сохранение регистров, выход из прерывания. Другой вариант — мотание в цикле, но опять вопрос во времени. Такт процессора на частоте 16 МГц длится 1/16 мкс, то есть у тебя есть всего 16 тактов.
За это ничтожное время тебе надо прокрутить счетчик (цикл же), снять состояние сигнала, перейти к следующей итерации. С учетом оптимизации и прочих накладных расходов на СИ сделать это практически нереально. Выход один — использовать аппаратную микросхему интерфейса 1-Wire, подключаемую, например, по SPI-интерфейсу.
Железо
Итак, выбор пал на термодатчик компании Maxim, модель DS18S20 (что под рукой оказалось). Если ты полез гуглить, сразу предупреждаю: подавляющее количество примеров применения термодатчиков с Arduino построено на базе DS18B20. Он немного отличается, но в рамках нашего проекта разницы никакой.
Работа термометра
Для работы с термометром по 1-Wire необходимо выполнить (по крайней мере для знакомства с ним) всего три действия:
- запустить измерение;
- подождать время, необходимое АЦП термометра, чтобы зафиксировать показание;
- считать показание из памяти термометра.
Как и с обычными АЦП, чем выше точность, тем больше времени требуется для проведения измерения, тем дольше нужна задержка перед попыткой чтения показаний.
Термодатчик имеет два режима работы: постоянное питание или паразитное питание. Я буду использовать режим паразитного питания. В этом режиме термодатчик кушает через подтягивающий резистор (4,7 кОм) линии 1-Wire, когда линия «свободна» или передается высокий уровень. Как раз это вторая деталь, которую необходимо найти, резистор 4,7 кОм.
WARNING
Будь внимателен при подключении термодатчика, при ошибке подключения ты можешь его сжечь. Если сам не силен, попроси умеющего товарища спаять тебе проводки, ничего зазорного в этом нет :).
Схема подключения термодатчикаФото подключения термодатчика
Теперь, когда с подключением ты более или менее разобрался, приступим ко второй части нашего остросюжетного боевика. Нужно писать софт. Я, как и большинство программистов, создание ленивое, поэтому я вопросил у Всезнающего Гугла, что уже придумано до нас и надо ли изобретать велосипед.
Самое вразумительное, что я нашел, — это библиотека OneWire, рекомендуемая ардуиновцами. Также нам пригодится творчество еще одного товарища из ардуиновского сообщества — библиотека, реализующая протокол обмена данными с термодатчиком.
Можно просто взять, собрать все это в обычный скетч и прошить в железку, на чем и успокоиться. Но ты помнишь про холодильник? А значит, будем вкорячивать это добро в наш проект.
Ось зла
Начал я с простого — заставил хотя бы собираться библиотеки. Обе библиотеки используют ардуиновские функции, поэтому пришлось внести некоторые изменения. Для начала добавим файл OneWire_Port.h в проект (он будет портом библиотеки OneWire для проекта) и приинклюдим его в файл OneWire.h, а затем начнем причесывание. А именно:
- OneWire построена таким образом, что ей при создании экземпляра объекта скармливается номер ноги, на которой у тебя будет линия 1-Wire. Это тащит за собой кусочек мрака из недр библиотек Ардуино, поэтому я пошел простым путем и зашил хардкодом в конструктор класса OneWire нужные мне ноги. Да, теряем универсальность, но я пока не вижу применения с двумя шинами 1-Wire (хотя… ну да не сейчас). Исходя из схемы платы, я выбрал ногу PA6, которая выходит на колодку DIGITAL пин 28. PORTA &= ~_BV(PA6); DDRA &= ~_BV(PA6); bitmask = _BV(PA6); baseReg = &PINA;
- OneWire использует задержки в микросекундах для реализации протокола 1-Wire, подсунем библиотечную функцию _delay_us() в файл OneWire_Port.h #define delayMicroseconds(usec) _delay_us(usec)
- OneWire любит отключать прерывания во время выполнения очень маленьких задержек (несколько микросекунд), и я ее понимаю. Но сразу же оглянемся и подумаем о том, что у нас все-таки будет ось. А значит, включение прерываний разумнее проредить немного, чтобы случайно не потерять контекст выполнения на неопределенное время. Библиотека использует ардуиновские функции работы с прерываниями, подсунем ей стандартные через файл OneWire_Port.h: #define noInterrupts() __builtin_avr_cli() #define interrupts() __builtin_avr_sei()
- В драйвере термодатчика используется задержка, измеряемая в миллисекундах. Тут разумнее использовать вызов функции ОС, особенно учитывая размер этих задержек. Для замены sleep на вызов функции ОС пришлось немного погородить макросов в OneWire_Port.h, комментарии в коде. // Количество «тиков» операционной системы (переключений контекстов) в секунду #define __CLOCKS_PER_SEC 1000 //Период системного таймера операционной системы #define PERIOD_TIMER_MS ( 1000UL / __CLOCKS_PER_SEC ) // Макрос перевода миллисекунд в количество тиков операционной системы #define MSEC_TO_TICK( X ) ( X / PERIOD_TIMER_MS ) #define delay(msec) OS::sleep( MSEC_TO_TICK(msec))
Внедрение агента в банду
Теперь либы собираются, настал черед вкрутить их в код проекта. Как удостовериться, что оно заработало? Элементарно: создаем экземпляр класса OneWire, затем DallasTemperature с параметром шины, на которую подключены термодатчики, и начинаем все это активно использовать.
В проекте уже есть простенький терминал, добавляй туда команду, по которой будет производиться опрос термодатчика и вывод значения в терминал.
Для удобства я добавил еще одну команду — поиск термодатчиков, по этой команде опрашивается линия, ответившие термодатчики заносятся в «кеш» библиотеки, после чего для найденных термодатчиков можно получить адреса и вывести их в терминал.
Отмечу отдельно алгоритм поиска устройств на линии, очень увлекательный процесс, описан подробно в документации к iButton в разделе Network Capabilities.
Первый запуск
Выносим в отдельный поток
Собственно, теперь ты убедился, что библиотека работает, термодатчик тоже что-то измеряет (в данном случае комнатную температуру). Давай теперь подключим все это добро к нашей системе сигнализации. Для этого необходимо создать отдельный поток, в котором будет производиться периодический опрос термодатчика и при возникновении аварии отправляться сообщение.
Немного подумав, я решил, что лучше сделать целый класс — движок работы с термодатчиками, унаследовав его от класса process, чтобы все собрать в одну кучку: сделать имплементацию функции-потока, дать этой функции доступ к членам класса, выставить наружу основные функции работы с термодатчиками.
Однако тут я уткнулся в жадность. Мне хотелось оставить возможность опроса термодатчиков из консоли и иметь сигнализацию. Сразу же возникает необходимость разделять общие ресурсы, так как теперь два потока будут дергать один термодатчик (а точнее, шину 1-Wire). Лезь в класс OneWire и добавляй ему приватного мембера OS::TMutex _mutex;.
Здесь начинается интересное. Мьютекс мы завели, но пользоваться им внутри класса неразумно, так как библиотека работы с термодатчиком написана очень сильно интегрировано и на лету дергает функции байтовой, а не пакетной приема-передачи по 1-Wire. Для локализации массовых вызовов я создал два метода: open и close для шины 1-Wire.
Читайте также: Доводчик стекол автомобиля
void OneWire::open() { _mutex.lock(); } void OneWire::close() { _mutex.unlock(); }
Затем пришлось прошерстить всю библиотеку DallasTemperature и обернуть вызовы функций работы с шиной 1-Wire в оболочку _wire->open() -> _wire->close().
Реализация функции потока обработки показаний термодатчика совсем проста.
В цикле запрашивается температура, проверяется на вхождение ее в граничные диапазоны (которые сейчас захардкожены), при изменении состояния отправляется грязное ругательное сообщение.
Напомню, что в прошлой реализации аварийного потока я заложил код источника сообщения AI_ANALOG, который сейчас и использую. Приведу кусочек кода, чтобы не мучить тебя словами.
float val; AnalogState new_state; if (!TemperatureEngine::temperature_get(0, &val)) { if (state != lost && ++ lost_cntr > 10 ) { state = lost; TAlarmMessage msg; msg.state = state; msg.src = TAlarmMessage::AI_ALARM; AlarmMessageBox.push(msg); } continue; } lost_cntr = 0; if (val high_value) new_state = high; else new_state = normal; if (new_state != state) { TAlarmMessage msg; msg.state = new_state; msg.src = TAlarmMessage::AI_ALARM; AlarmMessageBox.push(msg); } state = new_state;
Дополнительно я решил добавить аварийное состояние при обрыве термодатчика, то есть когда непрерывно не удается получиться данные от термодатчика на протяжении некоторого времени, в данном случае десяти опросов.
Тут-то я и наступил на грабли. Я забыл про функцию инициации процесса измерения DallasTemperature::requestTemperatures. В ней стоят задержки для того, чтобы подождать, пока термодатчик производит измерение. Но я поставил _wire->close() перед этими задержками.
В итоге я получил странную картину: при запросе из терминала начинали скакать показания термодатчика.
А случалось вот что: поток движка термодатчиков запускал измерение, одновременно приходил я со своим запросом по терминалу, и в итоге мы оба читали какие-то неинициализированные значения.
Почесав затылок, я вынес отдельно функцию инициации процесса измерения и оставил ее вызов только внутри потока движка термодатчиков. Таким образом, при получении команды из терминала возвращается последняя измеренная температура. Работает даже быстрее, чем каждый раз дергать термодатчик и просить его померить вот прямо сейчас и прямо здесь.
Остается лишь добавить в поток обработки аварийных сообщений кейсы нового источника аварий.
template OS_PROCESS void TAlarmTask::exec() { for(;;) { TAlarmMessage msg; // Тут мы уснем до получения аварийного сообщения AlarmMessageBox.pop(msg); // Получили сообщение, теперь обработаем его if (TAlarmMessage::DI_ALARM == msg.src) { // Обработка аварий цифрового датчика }else if(TAlarmMessage::AI_ALARM == msg.src) { // Здесь вставляем код обработки аварий аналогового (термо)датчика } } }
Испытания огнем
Конечно же, огонь применять никто не собирается, пожаров нам только не хватает. Но полевые испытания провести стоит. Так как датчик достаточно инертный, то я решил извлечь хоть какую-то пользу от выделяемого компьютером тепла и засунул термодатчик под поток воздуха от процессорного кулера. Ура, температура поползла вверх!
Как только значения температуры перешагнули пороговое значение, тут же в терминал пришло ругательное сообщение. Следующим шагом была проверка на возврат в нормальное состояние.
Проверка срабатывания аварии
Заключение
Вот мы и сделали еще один сложный шаг к защите содержимого твоего холодильника не только от врагов, но и от разморозки. Теперь в твоем арсенале есть термодатчик, а так как используется линия 1-Wire, то ты уже самостоятельно можешь навесить и два, и три, и более термодатчиков.
Надеюсь, что материал этой статьи раскрыл для тебя новые и интересные возможности, казалось бы, игрушечного Arduino и подогрел интерес к программированию встраиваемых систем. Помни, что только написание кода даст тебе знание и умение. Тренируйся, больше практики, старайся воплощать самые свои сумасшедшие идеи, и знание придет.
Пиши, пиши, пиши! Железный привет, RESET :).
DANGER
Статическое электричество смертельно для микросхем, старайся избегать работы с микроконтроллерами в синтетической и шерстяной одежде, по возможности используй заземляющие браслеты.
WARNING
При работе с микроконтроллером постарайся убрать все металлические предметы, чтобы предотвратить случайное короткое замыкание и выход платы из строя.
WARNING
Редакция и автор не несут ответственности за возможный вред, причиненный здоровью и имуществу при несоблюдении техники безопасности работы с электроприборами.
Источник: https://xakep.ru/2015/05/10/arduino-digital-temp-wire/
Датчик температуры для Arduino
Материал просмотрен 736 раз(а)
Всем привет! Как и обещал, продолжаю обзоры различных элементов и взаимодействий с платформой Arduino. Сегодня мы будем использовать датчик температуры LM35 и светодиоды.
Что там потребуется:
Исходный код
Принцип действия схемы будет очень прост и понятен из исходника:
int rLED=13;//Пин красного светодиода
int gLED=12;//Пин зелёного
//Преднастройки void setup() { pinMode(rLED,OUTPUT); //Цифровой выход 13 для красного pinMode(gLED,OUTPUT); //Цифровой выход 12 для зелёного Serial.begin(9600); //Стартуем последовательный порт (для отслеживания состояния)
}
//Выполнение программы в цикле void loop() { int val; //под значение из датчика int dat; //под вычисленный результат температуры val=analogRead(0); //Считываем значение с 0-го аналогового входа dat=(125*val)>>8; //Преобразуем значение в человеческий вид if ((dat > 28) || (dat
}
//Мигание LED-ом. void blinkLED(int NLED) { digitalWrite(NLED,HIGH); delay(350); digitalWrite(NLED,LOW);
}
Схема проекта
Общее фото проекта:
Схема
Соединение
Соединяем следующим образом:
Аналоговые пины:
- A0 – на среднюю ногу датчика LM35;
- 5V – на первую ногу датчика LM35;
Цифровые пины:
- 12 – на сигнальную ногу зелёного светодиода;
- 13 – на сигнальную ногу красного светодиода;
- GND – на общую “землю”;
Резисторы используются от общей земли до “массы” диодов;
Идёт дополнительная линия общей земли на 3-ю ногу датчика LM35;
Принцип работы:
На датчик температуры подаётся напряжение 5В между первой и третьей ногой (+5 и GND соответственно);
Со средней ноги получаем напряжение относительно первой ноги по 10 мВ на каждый градус цельсия. То есть для 20 градусов напряжение будет 0.2В (200 мВ).
Это напряжение поступает на аналоговый вход A0, где оно преобразуется в значение от 0 до 1023 (поскольку на Arduino имеется 10-битный аналогово-цифровой преобразователь), как правило это напряжение от 0 до 5В, поделённое на 1024 шага, каждый из которых размера 0,0049В.
Далее, это числовое значение преобразуется в десятичное значение, в зависимости от которого и вызывается функция мигания светодиода того или иного цвета (операторы сравнения с константами).
Ну а мигание светодиода работает просто – посылается сигнал HIGH на + диода, либо сигнал LOW, что означает высокое напряжение или низкое. Цифровые выходы могут оперировать только двумя этими значениями. Высокое примерно равно 5В (или 3.3В в зависимости от платы), низкое примерно 0В. Вот и всё.
Видео работы
Источник: https://litl-admin.ru/zhelezo/datchik-temperatury-dlya-arduino.html
Подключаем аналоговый температурный сенсор к Arduino и калибруем его
У Arduino есть два типа температурных сенсоров – цифровые и аналоговые. Аналоговые имеют в своей основе терморезистор, или термистор – полупроводниковый резистор, у которого явно выражена зависимость сопротивления от температуры, и она представляет собой гладкую функцию. Соответственно, измеряя его сопротивление, можно измерять температуру среды.
Схема измерения температуры с термистором Мы помним, что на плате Arduino UNO есть шесть аналоговых входов, которые, по сути, являются каналами АЦП. В один из таких каналов мы и включим термистор.
Однако как померить его сопротивление, если АЦП умеет измерять только напряжение? Умные ребята придумали для этого использовать схему простого делителя:Здесь U0 – известное напряжение, R0 – известное сопротивление, RT – сопротивление, зависящее от температуры, Uизм – измеряемое напряжение.
Из рисунка очевидно, что для измеряемого напряжения справедливо соотношение:
Откуда сопротивление термистора выражается так:
Однако померить сопротивление мало, нам ведь нужно получить температуру!
Уравнение Стейнхарта-Харта
Типовая зависимость сопротивления термистора от температуры выглядит так:Уважаемые господа Джон Стейнхарт и Стэнли Харт в 1968 году опубликовали свою работу, посвященную калибровочным кривым термисторов, в которой экспериментально вывели уравнение, связывающее сопротивление и температуру полупроводниковых термисторов.
Вот это уравнение:Здесь a, b и с – калибровочные константы, так называемые коэффициенты Стейнхарта-Харта. Это уравнение аппроксимирует кривую с хорошей точностью при подобранных коэффициентах для конкретного термистора. Коэффициенты Стейнхарта-Харта могут указываться в даташите производителем термистора.
А могут вместо них указываться табличные значения температур и сопротивлений для конкретного устройства.
Я понятия не имею, какой термистор в моем сенсоре, кто его произвел, какая у него модель, какие характеристики. Поэтому коэффициенты я буду искать сам. Магазин, в котором я покупал сенсор, предлагает использовать какие-то коэффициенты, однако китайцы такие китайцы и им не стоит доверять.
Тем более, я читал, что если дисковые терморезисторы калибруются партиями на заводе, то каплевидные – вообще оторви да выбрось требуют индивидуальной калибровки.
Сенсор в студию
Мой аналоговый температурный сенсор выглядит так:Черная круглая блямба на переднем плане – и есть термистор. На нем написано “103”, а это значит что при комнатной температуре он имеет сопротивление 10 КОм (103=10*10^3). Далее идет микросхемка, которая есть ни что иное, как операционный усилитель LM358P.
Есть еще 2 простых резистора, на которых тоже написано 103, один из которых никуда не подключен. Еще помните формулу для RT? Вот мы и нашли для нее R0, оно равно 10 КОм. А U0 равно 5 В, я вам так скажу.
Больше на плате ничего нет!
Сенсор очень просто подключается к Arduino Sensor Shield, который, в свою очередь, надевается на Arduino [в этом соль Arduino, кто еще не понял], прям как у меня вот так:
Ну собственно все – железо готово к лабораторной работе.
Калибровочная установка
Для калибровки понадобится печка, которая показывает свою температуру, и держит ее при этом (!). Нет проблем – пошел в ИНХ СО РАН, их там в каждой лабе по несколько штук. Выбирай по цвету, что называется. Приглянулась мне вот такая:Вообще это типа нагревательный столик (30.
..300 градусов Цельсия), который суют под микроскоп и рассматривают всякие штуки, нагревая их. Вот почему такой странный дизайн.
Собираем установочку: Arduino в комп, сенсор в крышечку с водой, крышечку на печку, хвостик под лавочку, накрываем печку колпачком из кварца.
Ваши варианты проведения эксперимента прошу оставлять в комментариях. Сразу скажу, что без воды получается куда отстойнее, чем с водой.
Методика калибровки
Пристально смотрим на уравнение Стейнхарта-Харта и видим в нем три неизвестных. Это означает, что нам достаточно провести три измерения и получить, таким образом, три уравнения. Выбираем три точки на температурной шкале. Мне нравятся, например, 30, 40 и 50 градусов Цельсия.
Нагреваем печку до одной из температур, ждем 10 минут, чтобы все термодинамические процессы произошли и энтропия вселенной увеличилась, замеряем сопротивление. Потом повторяем все для второй и третьей температур. Составляем три уравнения и решаем систему (линейных кстати) уравнений.
Нам лениво и мы заставим это делать Mathcad, который нам таки-выдаст коэффициенты Стейнхарта-Харта. Думаю, тут все понятно.
Serial Communication
Есть у Arduino такая классная штука – serial communication. Это есть явление общения компа с Arduino во время выполнения программы. Происходит это через USB-порт, который эмулирует COM-порт. Это позволяет мониторить состояние платы в реальном времени и даже посылать на нее команды с компа.
Чтобы вызвать Serial monitor, выберите в меню Tools->Serial Monitor или нажмите хитрую комбинацию из трех клавиш ctrl+shift+M во время выполнения программы.
Чтобы заставить Arduino вывести что-то в последовательный поток, просто воспользуйтесь функцией Serial.println(число) или Serial.println(“текст”).
Последовательный обмен необходимо инициализировать в setup(){}, всунув туда команду Serial.begin(бодрейт). Бодрейт (baudrate) – количество информации, передаваемой в единицу времени (не путать с битрейтом).
Arduino предлагает на выбор: 300, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 115200 бод.
Вот что бывает, если не согласовать бодрейт в своей программе и в мониторе последовательного порта:
Читайте также: Новый контроллер для заряда батарей напряжением до 80 в от linear
У вас это и должно произойти, когда вы впервые откроете монитор. Не пугайтесь.
Кодим
Напишем коротенький код, чтобы мониторить измеряемое значение напряжения и вычисляемое значение сопротивления:
void setup() {
Serial.
begin(115200); //стартуем последовательное соединение
}
void loop() {
double rt; //измеряемая величина
Serial.
println(“voltage:”); //пишем в поток слово для красоты
rt=(analogRead(0)); //читаем значение с сенсора
Serial.println(rt); //выводим значение с сенсора в поток
rt = ((10240000/rt) – 10000); //вычисляем сопротивление по формуле
Serial.
println(“resistance:”); //пишем в поток еще одно слово для красоты
Serial.println(rt); //выводим значение сопротивления в поток
delay(5000); //ничего не делаем 5 секунд
}
В результате все красиво:
Вычисляем коэффициенты Стейнхарца-Харца
По описанной выше методике выписываем на листочек три значения сопротивления при трех разных температурах. Подставляем их попарно в три уравнения Стейнхарца-Харца и решаем систему.
Вот фотка моего маткадовского файлика:Обратите внимание, что я вместо коэффициента “c” написал “се” [цэ], потому что маткад не дает использовать символ “с” кроме как в значении скорости света.
Нижний вектор-столбец и есть наши искомые коэффициенты.
Еще раз кодим
Теперь напишем скетч, который позволит Arduino измерять температуру.
#include //подключаем свою библиотеку с блэкджэком и логарифмами
double Steinhart(int value) {
double Temp; //в итоге эта переменная станет температурой
Temp = log((10240000/value-10000)); //считаем логарифм
//считаем температуру из уравнения Стейнхарта-Харта
Temp = 1/(0.001768+0.00005719*Temp+0.
000001354*Temp*Temp*Temp);
Temp = Temp-273.15;//переводим температуру в градусы Цельсия
return Temp; //передаем температуру обратно в loop
}void setup() {
Serial.
begin(115200); //стартуем последовательное соединение
}
void loop() {
//передаем в функцию Steinhart измеренное значение и выводим температуру, которую она вернет
Serial.
println(int(Steinhart(analogRead(0))));
delay(2000); //ничего не делаем 2 секунды
}
Резюме
Температура меряется все равно корявенько, дает расхождение до трех градусов. Процесс калибровки – сложная штука в плане правильного нагрева термистора и поддержания определенной температуры. Улучшение методики калибровки – подключение дополнительных термопар, создание термостатированной камеры, возможно, сильно изменят результаты в лучшую сторону. Кстати, неплохая темя для курсовой физика-второкурсника. Если у вас есть знакомый физик-второкурсник, посоветуйте ему эту идею!
Совет всем – покупая терморезистор, убедитесь в том, что вы правильно знаете его марку и модель и можете найти в даташите его параметры и таблицу.
Источник: http://greenoakst.blogspot.com/2012/03/arduino.html
Самодельный датчик температуры и влажности DHT11 и DHT22 – подключение к Arduino | Каталог самоделок
Продолжаются уроки для тех людей, которые начинают работать с Arduino. В этой статье будет показана процедура подсоединения датчиков температуры DHT11 и влажности DHT22.
Эти два датчика имеют не высокую производительность, но зато имеют довольно простую конструкцию. Такие недорогие механизмы прекрасно подходят для занятия. Они состоят из двух элементов – сенсоров влажности и температуры. Они оснащены специальным чипом, который предназначен для аналогово-цифрового преобразования, а также трансляции сигнала, считываемого с помощью контроллера.
Какие компоненты необходимые для изготовления модели?
Чтобы собрать конструкцию, которая представлена в данной статье, необходимы такие детали:
- плата Arduino;
- сенсоры температуры DHT11 и влажности DHT22, которые можно приобрести на aliexpress;
- Breadboard;
- Резистор;
- Arduino IDE (скачать ее можно перейдя по ссылке).
датчик температуры и влажности DHT11 и DHT22
Отличия между DHT11 и DHT22
Эти два сенсора аналогичны. Несмотря на то, что они имеют одинаковую распиновку, их показатели существенно отличаются.
Особенности DHT11:
- измерение показателей влажности в диапазоне от 20 до 80 %;
- измерение температуры в диапазоне от 0°С до +50°С;
- частота измерений составляет 1 раз в секунду.
Особенности DHT22:
- измерение показателей влажности в диапазоне от 0 до 100 %;
- измерение температуры в диапазоне от -40°С до +125°С;
- частота измерения составляет 1 раз в 2 секунды.
Сравнив эти особенности, можно сделать вывод, что сенсор DHT22 является лучшим, и соответственно стоит намного больше. Снятие показаний больше одного раза не требуется.
Как подключить Arduino
Так как оба сенсора имеют стандартные выводы: питание, вывод данных и GND. Еще один вывод не употребляется. Их можно легко соединить с breadboard. Между питанием и выводом данных необходимо разместить резистор. Датчики сенсоров могут продаваться в виде готового устройства. При таком условии, выводы присоединяются без резистора, так как он уже установлен в плате.
Схема подключения сенсора с резистором выглядит так:
Схема подключения
Скетч для программы Arduino
Для начала следует загрузить библиотеку DHT h, которая разработана для DHT. После скачивания папки библиотеки, ее необходимо скопировать в libraries. Готовая программа, работающая с DHT22 представлена ниже:
#include “DHT.h”
#define DHTPIN 2 // номер пина, к которому подсоединен датчик
// Раскомментируйте в соответствии с используемым датчиком
// Инициируем датчик
DHT dht(DHTPIN, DHT22);
//DHT dht(DHTPIN, DHT11);
void setup() {
Serial.begin(9600);
dht.begin();
}
void loop() {
// Задержка 2 секунды между измерениями
delay(2000);
//Считываем влажность
float h = dht.readHumidity();
// Считываем температуру
float t = dht.readTemperature();
// Проверка удачно прошло ли считывание.
if (isnan(h) || isnan(t)) {
Serial.println(“Не удается считать показания”);
return;
}
Serial.print(“Влажность: “+h+” % “+”Температура: “+t+” *C “);
}
Если будет использоваться сенсор DHT11, то нужно закомментировать строку:
DHT dht(DHTPIN, DHT22);
А также раскоментировать:
//DHT dht(DHTPIN, DHT11);
Далее, следует загрузить скетч в контролер и проверить правильность выполненной процедуры. Для этого следует зайти в пункт «Монитор порта»:
Монитор порта
После этого на экране появятся показания температуры и влажности. Чтобы изменить значение, например влажности, нужно выдохнуть на датчик воздух.
Прикрепленные файлы: Программный код и библиотека DHTh
Источник: https://volt-index.ru/electronika-dlya-nachinayushih/samodelnyiy-datchik-temperaturyi-i-vlazhnosti-dht11-i-dht22-podklyuchenie-k-arduino.html
Беспроводные датчики температуры (Arduino pro mini + nRF24L01)
Я расскажу как подключить свои погодные датчики по радиоканалу.
Для этого нам понадобится
1. Сборка Arduino Pro Mini. Это будет станция, принимающая показания по радио.
2. Еще одна Arduino Pro Mini 3.3v для чтения показания температуры и предачи по радио на принимающую станцию.
3. Датчик температуры для улицы DS18B20:
4. Два радиомодуля nRF24L01:
Один радиомодуль подключим к приемнику, второй к передатчику. Датчик температуры по примеру подключим через резистор к выходу 4 передатчика.
Для соединения nRF24L01 и Arduino Pro Mini воспользуемся следующей таблицой:
Arduino Pro MininRF24L01
2 | IRQ |
7 | CE |
8 | CS |
11 | MOSI |
12 | MISO |
13 | SCK |
GND | GND |
VCC | VCC 3.3v |
Для наглядности, две картинки с распиновкой:
Arduino Pro Mini:
nRF24L01:
Три момента:
1. Радиомодуль питается от 3 вольт, поэтому я использовал версию Arduino Pro Mini с питанием от 3.3 вольт. Если у вас ардуина пятивольтовая и не имеет встроенного регулятора на 3.3 вольта, необходимо подключать радиомодуль к VCC через регулятор. Остальные пины, можно подключать напрямую, так как судя по даташиту на радиомодуль, его сигнальные пины толерантны к напряжению 5 вольт.
2. Пины SC и CE можно подключить и к другим свободным цифровым пинам Arduino Pro MIni. Их значения потом определяются в скетче. Для моего случа будет написано
3. Пин IRQ подключать не обязательно. Я его подключил к пину 2, на котором у Arduino Pro Mini есть обработчик прерываний. Его будем использовать для пробуждения радиомодуля из режима сна, в который будем погружать его для экономии питания.
Подсоединим по этой схеме радиомодули к принимающей и отправляющей ардуинам.
Теперь скетчи.
Для работы c радиомодулями nRF24L01 есть библиотека NRF24 и ее расширение для построения связанных mesh сетей без ограничения на количество устройств NRF24Network. Воспользуемся второй библиотекой.
Если при подключении радио, использовались другие пины CE и CS, укажите это в обоих скетчах в строке:
Теперь скетчи. Помимо них требуются библиотеки и еще неколько файлов.
Скетч погодного датчика (передающий модуль):
/* Copyright (C) 2011 James Coliz, Jr. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. */ #include #include #include #include #include #include “nodeconfig.h” #include “sleep.h” #define ONE_WIRE_BUS 5 // Data wire is plugged into digital pin 3 on the Arduino #define NumberOfDevices 8 // Set maximum number of devices in order to dimension OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices DallasTemperature sensors(&oneWire); // Pass our oneWire reference to Dallas Temperature. byte allAddress [NumberOfDevices][8]; // Device Addresses are 8-element byte arrays. char sn[NumberOfDevices][35]; byte totalDevices; // Declare variable to store number of One Wire devices // that are actually discovered. byte discoverOneWireDevices() { byte j=0; // search for one wire devices and // copy to device address arrays. while ((j 1 const wdt_prescalar_e wdt_prescalar = wdt_8s; const short sleep_cycles_per_transmission = 32; void setup(void) { Serial.begin(57600); sensors.begin(); totalDevices = discoverOneWireDevices(); for (byte i=0; i =0;k–) { char msg[3]; sprintf(msg,”%02X”,allAddress[i][k]); strcat(sn[i],msg); //DSstring[i]+=msg; }; sensors.setResolution(allAddress[i], 10); // and set the a to d conversion resolution of each. } this_node=1; if ( this_node > 0 ) Sleep.begin(wdt_prescalar,sleep_cycles_per_transmission); SPI.begin(); radio.begin(); network.begin(/*channel*/ 95, /*node address*/ this_node); } void loop(void) { // Pump the network regularly network.update(); // If we are not the base, send sensor readings to the base if ( this_node > 0 ) { sensors.requestTemperatures(); for (byte i=0; i “); } else Serial.println(“Error from sensor”); } // Power down the radio. Note that the radio will get powered back up // on the next write() call. radio.powerDown(); // Sleep the MCU. The watchdog timer will awaken in a short while, and // continue execution here. Sleep.go(); // Listen for a new node address nodeconfig_listen(); } }
Скетч погодной станции (принимающий показания модуль)
Источник: http://nrf24l01.pp.ua/nrf24l01/besprovodnye-datchiki-temperatury-arduino-pro-mini/
Термоконтроллер на Arduino
Уважаемые читатели!
Эта статья написана не мной, посему – прошу любить и жаловать: сегодня Vergellan поделится с вами опытом создания умного регулятора вращения вентиляторов, с участием термодатчика, LCD-дисплея и, конечно же, Arduino.
Читайте также: Система условных обозначений отечественных интегральных микросхем
Несколько месяцев назад я прочел ряд статей об Arduino и весьма заинтересовался данным девайсом, а вскоре решил приобрести. Надо отметить, что я далек от микроэлектроники, поэтому плата расположила к себе прежде всего относительной простотой в освоении.
Набаловавшись с LED-ами и «Hello world»-ами, захотелось сделать что-нибудь практичное, заодно более детально ознакомиться с возможностями Arduino. Памятуя об аномально жарком лете 2010 года, возникла идея собрать регулятор оборотов кулера в зависимости от температуры с выводом всех сопутствующих характеристик на LCD.
Надеюсь, что кому-нибудь данная схема или ее вариации смогут пригодиться, поэтому решил выложить свои наброски.
Для данной схемы нам понадобится:
- Собственно сама плата Arduino или аналог;
- Макетная плата для сборки компонентов схемы;
- Дисплей WH1601A-NGG-CT с подстроечным резистором на 20 кОм или аналогичный;
- Резисторы – 220 Ом, 10 кОм, 4.7 кОм;
- Биполярный транзистор SS8050D или аналогичный ему;
- Цифровой температурный датчик DS18B20;
- Диод 1N4148 или аналог;
- Вентилятор осевой трехпроводной (на 12В), например – компьютерный;
- Разъем гнезда питания 2,1/5,5 мм.
Компьютерный кулер имеет три провода, два из которых – красный (+12V) и черный (GND) используются для питания, а третий (желтый) связан с таходатчиком, построенном на элементе Холла.
К сожалению, 5V с платы нам явно недостаточно, но 6 цифровых выходов Arduino могут работать в режиме ШИМ (они отмечены на самой плате белыми квадратиками, либо буквами PWM), поэтому мы можем регулировать подачу сигнала с платы на реле, которое будет отвечать за изменение напряжения, подаваемого на вентилятор.
Получать информацию об оборотах мы будем с третьего провода от таходатчика, воспользовавшись модифицированным способом, основанным на реализации прерываний, которые у большинства Arduino могут приходить на цифровые pin 2 (прерывание 0) и 3 (прерывание 1). Кстати, у Arduino Mega наличествует еще 4 дополнительных пина с возможностью получения прерываний.
Теперь необходимо расположить цифровой датчик температуры, данные которого мы будем использовать для регулирования напряжения, подаваемого на цифровой выход с ШИМ, а следовательно для «открытия» канала напряжения вентилятора.
Для датчиков фирмы Dallas существует собственная библиотека Arduino – DallasTemperature, которую впоследствии мы и будем подключать в скетче. Библиотеку необходимо распаковать в каталог arduino-0018/libraries/.Осталось последнее – подключить LCD, где у нас будет отображаться вся текущая информация о температуре и скорости вентилятора.
Поскольку я использовал для сборки экран WH1601A, могут иметь место известные проблемы с отображением строк. Для их устранения мы воспользуемся библиотекой LiquidCrystalRus, которую необходимо также распаковать в каталог arduino-0018/libraries/.
//Подключаем библиотеку для термодатчика
#include
//Подключаем библиотеку для LCD
#include #define PowerPin 9 // pin для контроля питания вентилятора
#define HallSensor 2 // pin для датчика оборотов вентилятора (прерывание)
#define TempPin 7 // pin для датчика температуры LiquidCrystalRus lcd(12, 11, 10, 6, 5, 4, 3); //Подключение LCD
DallasTemperature tempSensor; int NbTopsFan, Calc, fadeValue; //целочисленные переменные для расчетов
float temper; //вещественная переменная для хранения температуры typedef struct{ // Вводим новый тип переменных для вентиляторов
char fantype;
unsigned int fandiv;
}fanspec; //Массив переменных нового типа
fanspec fanspace[3]={{0,1},{1,2},{2,8}}; //Переменная, отвечающая за выбор типа датчика вентилятора (1 – униполярный датчик Холла, 2 –биполярный датчик Холла)
char fan = 2; //Эта функция у нас будет вызываться при каждом прерывании
void rpm () {
NbTopsFan++;
} // Функция расчета подаваемого напряжения на цифровой pin с ШИМ
void temp () {
fadeValue = min(int(temper*7),255); // Умножаем температуру на коэффициент,
// берем от произведения целое число
} // Т.к. максимальное значение ШИМ составляет 255, то подавать больше не имеет смысла – берем минимум из двух void setup()
{
tempSensor.begin(TempPin); //Запускаем температурный датчик
lcd.begin(16, 2); //Задаем характеристики LCD
lcd.setDRAMModel(LCD_DRAM_WH1601); //И тип дисплея
pinMode(HallSensor, INPUT); // Настраиваем pin на получение прерываний
attachInterrupt(0, rpm, RISING); //Привязываем прерывание по номеру 0 к нашей функции, причем высчитываться она будет каждый раз при смене сигнала
} void loop ()
{
temper = tempSensor.getTemperature(); // Получаем температуру
temp(); // Высчитываем подаваемое напряжение на ШИМ
analogWrite(PowerPin, fadeValue); // Подаем его
NbTopsFan = 0; // Обнуляем переменную, содержащую обороты
delay (1000); //Ждем 1 секунду
Calc = ((NbTopsFan * 60)/fanspace[fan].fandiv); //Рассчитываем величину оборотов за 60 секунд, поделенную на множитель вентилятора
lcd.print (Calc, DEC); //Выводим рассчитанную величину в десятичном виде
lcd.print (” rpm – “); lcd.print(temper); //Выводим температуру
lcd.home(); }
У меня финальная схемка выглядит так (часть компонентов перенес с макетки на дополнительную плату, т.к. планирую сделать уже готовый регулятор в нормальном корпусе):
В завершение хотел бы выразить огромную благодарность Илье Данилову (idanilov) за «привитый» интерес к Arduino и за помощь в освоении данной платформы.
UPD: Последняя версия LiquidCrystalRus доступна на github.
Источник: http://mk90.blogspot.com/2010/08/arduino.html
Белоярский. Новости, комментарии. – Часы – термометр
После того, как мы вволю помигали диодами в прошлой статье, пора переходить к чему-нибудь более полезному в хозяйстве. Ну, например, сделать цифровой термометр, что-ли. Тем более, что с Ардуино – это совсем не так сложно, как было в “доконтроллерную эпоху”.
В те времена электронный термометр представлял собой сложную конструкцию из десятка микросхем, аналогового датчика, который нужно было еще откалибровать, и трансформаторного блока питания на несколько выходных напряжений.
Ну, и – соответствующей подготовки радиолюбителя, который задумает все это собрать. Сейчас с этим – все гораздо проще.
Разрешите представить – цифровой датчик температуры буржуинской фирмы “Dallas semiconductor” DS18B20.
Полностью функциональное устройство для точного (до нескольких знаков после запятой) измерения температуры в диапазоне от -55 до +120 градусов Цельсия.
Кроме того – имеется даже немного “мозгов” (ячеек памяти) для запоминания чего-нибудь полезного. Но пока что мы ими пользоваться не будем. Как видно на рисунке – выпускается в нескольких вариациях.
Самая распространенная и для нас удобная – та, где написано “ТО-92”.
Датчик имеет всего 3 вывода, на два из которых подается напряжение питания 5в, а средний вывод – для передачи данных. Все управление датчиком (подача на него команд, считывание измеренной температуры) идет по единственному проводнику, поэтому вся эта технология и протокол приема-передачи называется “1-Wire” или “One-Wire”.
Чтобы не сильно загружаться теорией, примерно рассмотрим вкратце процесс измерения температуры с помощью нашего датчика.
Каждый сеанс передачи или приема данных начинается с команды инициализации. Опять же не будем вдаваться в подробности общения Ардуины с термометром, за нас это сделали посторонние люди (мысленно скажем им спасибо). Просто передадим ей одну команду – “инициализация”, и она сама разберется, что надо сделать.
Далее, после инициализации, начинаем подавать управляющие команды. Тут надо заметить, что на одном управляющем проводке, теоретически, может находиться несколько устройств семейства “1-Wire”. Причем, не только датчики температуры.
Поэтому, есть возможность обращаться к каждому из них по уникальному серийному номеру. Но, поскольку у нас на проводе единственный датчик, то ни к чему другому мы не можем обратиться в принципе. Поэтому эти прелюдии пропускаются командой (передаваемым байтом “0хСС”).
Забыл сказать – здесь и далее используется шеснадцатиричная запись двоичных чисел (байтов).
После того, как определились с адресатом – передаем команду “измерить температуру” (“0х44”). После этого нужно оставить датчик в покое примерно на 1 секунду, пока он будет делать свои дела.
За это время “ds-ка” измерит температуру и запишет результаты в два байта, которые нам нужно у нее выудить и привести к человеческому виду. Начинаем, как всегда, с инициализации сеанса связи. Потом снова передаем команду “сброс передачи адреса” (“0хСС”). И тут же следом – сообщаем, что готовы принять результат измерения: (“0хВЕ”).
После этого Ардуина получает последовательно 2 байта (или двухбайтное число – кому как нравится) с результатами. Посмотрим, что это за результаты и как нам привести их к удобоваримому виду.
Опять же, чтоб не сильно грузиться, определимся с тем, что для нас важно. А именно – в младшем и, частично, в старшем байте находится результат измерения температуры с точностью до 4-го знака после запятой (нам такая точность – излишня). Знак температуры (“+” или “-“) определяется значением старшего бита старшего байта.
Но, довольно слов – пора заняться конструированием. Схема подключения DS18B20 к Ардуине не только проста – а элементарно проста:
Выводы питания датчика подключены к соответствующим выводам Ардуины, а вывод данных – к цифровому выходу “10”. Кроме того, вывод данных подключен к шине +5 вольт через резистор 3 – 5 килоом (так называемый “подтягивающий” резистор).
Заметьте, что цифровой выход “10”, хотя он будет работать и на выход, и на вход, нам уже не придется настраивать, как в предыдущем примере со светодиодами. Разработчики библиотеки “1-Wire” заботливо освободили нас от всякой черновой работы.
Спасибо им за это!
В-общем, у меня получилось, примерно, так:
Да! Совсем забыл! Библиотека “1-Wire” не входит в базовую поставку Arduino IDE, поэтому ее нужно скачать, например, отсюда. Распакуем архив и положим папку с библиотекой в директорию libraries, которая находится в папке, где установлена Arduino IDE. При следующем запуске среды разработки – библиотека будет доступна для использования. Вот где ее можно найти:
Однако, не будем использовать скетч из “Образцов”, там сильно всего наворочено. Лучше скопируем в Arduino IDE вот такой скетч:
#include
OneWire ds(10); //
void setup(void) {
Serial.begin(9600); //настраиваем последовательный порт для вывода результатов
}
void loop() {
byte data[2]; // объявляем массив из 2-х байт
ds.reset(); // инициализируем датчик
ds.write(0xCC); // пропускаем адресацию к конкретному датчику (у нас он один)
ds.
write(0x44); // даем команду измерять температуру
delay(1000); // ждем 1 секунду, пока измеряется температура
ds.reset(); // снова инициализируем датчик
ds.write(0xCC); // снова пропускаем адресацию
ds.
write(0xBE); // даем команду готовности считывать температуру
data[0] = ds.read(); //считываем младший
data[1] = ds.read(); // и старший байты
int Temp = (data[1] > 4; // к нужному виду.
Serial.
println(Temp); // выводим результат в последовательный порт.
}
Что мы тут видим… Сначала к скетчу подключается библиотека “OneWire”. Указываем, что наш датчик подключен к выводу “10” Ардуины. Затем настраивается последовательный порт для вывода результатов измерения. Все, подготовительные операции закончены, начинаем измерять.
Подготавливаем (резервируем и называем) 2 байта, куда будем записывать результат измерения температуры. Затем – подаем команды, как описывалось выше и, наконец, получаем 2 байта с нашей температурой. Затем происходит преобразование считанной информации и удаление лишних знаков после запятой с тем, чтобы получить целое значение температуры, без десятичных дробей.
Эта информация и выводится через последовательный порт. Где мы можем ее увидеть? А вот здесь:
Итак, загружаем этот скетч в Ардуину, открываем “Монитор последовательного порта” и наблюдаем каждую секунду измеренную температуру:
Ура! Заработало! Не будем вдаваться в подробности процесс преобразования полученных от датчика 2-х байт в целое число температуры, это тема для отдельной большой статьи. Скажу только, что полученное число – переменная Temp типа integer. То есть, она может принимать как положительные значения, так и отрицательные. Проверим работу нашего устройства на морозце:
Ну что же – показывает и отрицательные температуры. Даже прямо сразу со знаком. В дальнейшем, когда мы будем выводить температуру на различные индикаторы, надо будет запомнить эту особенность нашей программы. И предусмотреть дополнительно индикацию знака плюсовой температуры. Но про то – уже в следующих статьях.
Продолжение следует..
Источник: http://probelum.ru/index.php/izmeryaem-temperaturu
Благодарим за внимание к сайту!