Термометр на Arduino с температурным датчиком LM35. Цифровой термометр DS18B20 и ARDUINO UNO

О цифровых термометрах на основе Arduino было сказано немало. Все они либо подключались к компьютеру, либо выводили температуры сразу на дисплей.
Но мне был нужен уличный термометр, который автономно и отправляет данные на сайт. Итак, приступим.

Что нам понадобится:
  • Arduino Duemilanove (Freeduino 2009)
  • Ethernet Shield v2
  • цифровой датчик температуры - DS18B20
  • вентилятор для корпуса (120 мм)
  • банка от водоэмульсионки или клея ПВА (2 литра)
  • светодиод
  • витая пара
Задачи
Опрашивать датчик температуры по шине 1-Wire и каждые 3 секунды самостоятельно отправлять результаты на Web-сервер, на котором они будут храниться.
Алгоритм работы устройства:
  1. присваиваем нашему Ethernet Shield`у MAC адрес и ip-адрес
  2. инициализируем соединение с сервером на 80 порт
  3. получаем данные с цифрового датчика температуры, по 1-Wire шине
  4. формируем GET запрос
  5. отправляем GET запрос
  6. разрываем соединение
Исходный код скетча:
Комментарии по ходу кода должны внести ясность.
include
// Библиотеки ниже нет в стандартной поставке среды разработки Arduino.
// придётся её скопировать.
include

// MAC-адрес нашего устройства
byte mac = { 0x00, 0x3A, 0xF1, 0x19, 0x69, 0xFC };
// ip-адрес устройства
byte ip = { 192, 168, 1, 156 };
// ip-адрес удалённого сервера
byte server = { 79, 140, 28, 20 }; // измените на свой
char temp;
byte isdata=0;

Client client(server, 80); // 80-порт.
DallasTemperature tempSensor;

void setup()
{
Ethernet.begin(mac, ip); // Инициализируем Ethernet Shield
tempSensor.begin(7); // Датчик температуры на 7-й пин
Serial.begin(9600); // Скорость консольного порта 9600 (пригодится для отладки)
}

void loop()
{
delay(3000); // задержка в 3 сек.
// Соединяемся
if (client.connect()) {
Serial.println("connecting..." ); // Serial.println для отладки. Лучше его оставить, на всякий случай, потом будет легче понять, в чём проблема.
// Обработчик ошибок датчика
switch (tempSensor.isValid())
{
case 1:
Serial.println("Invalid CRC" ); // ошибка контрольной суммы
tempSensor.reset(); // сбросить девайс
return ;
case 2:
Serial.println("Invalid device" ); // какой-то "левый" датчик:)
tempSensor.reset(); // сбросить девайс
return ;
}

Serial.println("connected" );
char buf;
float f=tempSensor.getTemperature(); // получаем температуру

Serial.println(tempSensor.getTemperature());

// Ниже извращения с отделением дробной части и целой. Почему-то Arduino не хочет работать с float.
// Вместо числа вставляет вопросик. Наверное, виной тому отсутствие аппаратной поддержки работы с
// числами с плавающей запятой в Arduino. Буду рад увидеть более красивое решение в комментариях.
int temp1 = (f - (int )f) * 100; // выделяем дробную часть
// Составляем GET запрос. Переменная code нужна для того, чтобы вражеский термометр не слал какие попало значения.
// проверяется на стороне Web-сервера.
sprintf(buf, "GET /class/backend/meteo.php?temp=%0d.%d&code=123456 HTTP/1.0" , (int )f, abs(temp1));

Serial.println(buf);
client.println(buf); // Отправляем GET запрос
client.println("Host: opck.info" ); // Указываем, какой конкретно host на данном ip нас интересует.
client.println();

} else {
Serial.println("connection failed" );
}

while (client.available()) {
isdata=1;
char c = client.read(); // Читаем, что нам ответил Web-сервер
Serial.print(c);

if (!client.connected()) {
isdata=0;
Serial.println();
Serial.println("disconnecting." );
client.stop(); // Завершаем соединение
}
}


Сборка устройства:
  1. первую «ногу» датчика цепляем на «минус» GND
  2. вторую «ногу» (DQ) на 7-й пин
  3. третью на «плюс»
  4. вторую и третью нужно соединить резистором на ~ 4,7 К. Но я заменил резистор на светодиод и получил индикатор обращения к шине датчика (ВНИМАНИЕ! Без резистора или светодиода работать ничего не будет. Не забудьте!)

По идее, вот и всё. Должно работать.
Работает, но боевые условия показали, что когда падает солнечный свет на датчик, тот может нагреваться и показывать температуру гораздо выше реальной. Всё правильно - он покажет температуру на солнце. А нам нужна температура воздуха.

В первый раз для этого был собран корпус из-под банки от кофе, обёрнутый в фольгу. Но это ничем не помогло.

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

Делаем корпус для датчика
Подходящей по размеру оказалась банка от водоэмульсионной краски (такие же бывают из-под клея ПВА, объёмом 2-3 литра). В нижней части банки делаем отверстие под вентилятор. И прикрепляем его к банке. В центре банки размещаем площадку под датчики, диаметром немного меньшим самой банки, чтобы воздух мог циркулировать.
Несколько фото:

Как вы помните, резистор я заменил светодиодом, поэтому делаем и для него отверстие, чтобы всегда было видно работу устройства.

Крышка от банки нам не нужна, вместо неё нужен навес, такой, чтобы и воздух пропускал, и чтобы атмосферные осадки не попадали внутрь (датчик-то будет расположен на улице).

Корпус для Arduino я сделал из пластмассовой коробки от mp3-плеера Explay C360.

Backend, принимающий данные:
На стороне сервера работает скрипт, к которому обращается термометр. Скрипт проверяет правильность секретного кода, чтобы показания нельзя было подменить.
А затем добавляет новую запись в таблицу MySql. Потом эти данные можно выводить как угодно. При этом каждую минуту данные за прошедшую минуту усредняются и добавляются в другую таблицу.
Нужно это для того, чтобы:
1. проще было делать выборки в базе (не правда ли, удобнее указать конкретную минуту и получить результат)
2. выборки были быстрее (за год ~500 000 записей вместо 10 000 000)

Во время длительной работы датчика обнаружилась проблема, иногда он самопроизвольно (раз в 3-4 часа) выдаёт рандомное значение. Поэтому я добавил проверку на изменение температуры больше чем на 1 градус в течении 15 секунд. Такие значения игнорируются.

Недостатки:
Точность датчика 0.5* С, что для меня недостаточно. Но есть способ улучшить его характеристики. Понадобится ещё один, или более датчиков (желательно из разных партий). Получаем данные со всех датчиков и считаем среднее арифметическое. Так можно добиться точности до сотых градуса.
Планы на будущее:
  • датчик влажности
  • датчик давления
  • датчик скорости ветра
  • датчик освещённости
  • поставить несколько таких в городе и делать свои прогнозы погоды
  • питать Arduino по Power over Ethernet
  • автоматизировать включение и частоту вращения вентилятора в зависимости от освещения
  • удалённое управление
  • сброс данных на случай отсутствия связи (для меня это критично)
Известные мне недостатки:
- высокая цена - 2180 руб. (Freeduino 2009 (800 р.) + Ethernet Shield v2 (1300 р.) + 1 датчик (80 р.))
- если вентилятор включить слишком быстро, то он сам вносит погрешность в температуру, обдувая датчик. Он не должен сдувать, а лишь проталкивать воздух.

Узнайте, как использовать RF модуль 433 МГц совместно с ATMega328P-PU. В данной статье мы соберем схему из датчика DHT11 и радиочастотного передатчика. А также соберем приемное устройство с радиоприемником 433 МГц и LCD дисплеем.

Что нам потребуется

  • компьютер с установленной Arduino IDE (я использую версию 1.6.5);
  • библиотека VirtualWire (ссылка ниже);
  • ATMega328P;
  • программатор AVR MKII ISP;
  • датчик температуры и относительной влажности воздуха DHT11 ;
  • компоненты из перечня элементов, приведенного ниже.

Введение

В данной статье я покажу вам, как собрать устройство, которое измеряет температуру и относительную влажность воздуха и посылает измеренные значения с помощью стандартного радиочастотного модуля 433 МГц. Датчик температуры и влажности, используемый в устройстве, - это DHT11.

Существует множество способов передачи небольшого объема данных с помощью Arduino или контроллеров ATMega. Один из них использует уже готовую библиотеку, подобную RCSwitch, Radiohead или VirtualWire. Кроме того, можно отправить необработанные данные с помощью встроенного в микроконтроллер модуля UART. Но использовать встроенный модуль UART не рекомендуется, так как приемник будет собирать и все помехи, и микроконтроллер будет работать не так, как предполагалось. В данной статье для передачи и приема данных я использую библиотеку VirtualWire. Эта библиотека работает с Arduino IDE 1.6.2 и 1.6.5.

Модуль передатчика 433 МГц, когда не передает данные, всё равно излучает радиочастотные колебания и передает шум. Он также может создавать помехи другим радиочастотным устройствам. Чтобы не допустить этого, я включаю его, когда необходимо передать данные, и выключаю его, когда передача закончена.

Аппаратная часть

Нам необходимы две структурные схемы. Одна для передающего устройства, вторая для приемного.

Передатчик

Нам необходимы:

  • способ прошивки микроконтроллера → ISP;
  • датчик для измерения температуры и влажности → DHT11;
  • микроконтроллер для обработки данных → ATMega32p;
  • способ беспроводной передачи данных → радиочастотный модуль 433 МГц.

Приемник

Нам необходимы:

  • способ приема радиосигнала → радиочастотный модуль 433 МГц;
  • способ обработки принятых данных → Arduino Mega;
  • способ отображения температуры и влажности → 16x2 LCD.

Принципиальные схемы

Передатчик


Передающая часть беспроводного термометра на ATMega328p
()

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

Приемник



(для увеличения масштаба можно кликнуть по картинке правой кнопкой мыши и выбрать «Открыть ссылку/изображение в новой вкладке/новом окне» )

Пожалуйста, обратите внимание, что приемник построен на базе платы Arduino Mega, которая не изображена на схеме. Для подключения платы Arduino Mega соедините с ней радиочастотный модуль и LCD дисплей согласно метка на схеме.

Перечень элементов

Передатчик


Перечень элементов передающей части беспроводного термометра на ATMega328p
(для увеличения масштаба можно кликнуть по картинке правой кнопкой мыши и выбрать «Открыть ссылку/изображение в новой вкладке/новом окне» )

Приемник



(для увеличения масштаба можно кликнуть по картинке правой кнопкой мыши и выбрать «Открыть ссылку/изображение в новой вкладке/новом окне» )

Программа

Программа передатчика

Сперва рассмотрим программу передающей части:

#include // Определение #define dhtPin 4 #define dhtType DHT11 #define txPowerPin 8 // Использование библиотеки DHT DHT dht(dhtPin, dhtType); // Переменные char msg0; char msg1; int tem = 0; int hum = 0; // Функция первоначальной настройки - выполняется только один раз при включении void setup() { pinMode(txPowerPin, OUTPUT); pinMode(txPowerPin, LOW); vw_setup(4800); // Скорость соединения VirtualWire vw_set_tx_pin(9); // Вывод передачи VirtualWire } // Функция цикла - выполняется всегда void loop() { digitalWrite(txPowerPin, HIGH); hum = dht.readHumidity(); // Переменная хранит влажность tem = dht.readTemperature(); // Переменная хранит температуру itoa(hum, msg1, 10); // Преобразование влажности в массив char itoa(tem, msg0, 10); // Преобразование температуры в массив char strcat(msg0, msg1); // Сложение/объединение двух массивов vw_send((uint8_t *)msg0, strlen(msg0)); // Передача сообщения vw_wait_tx(); // Ждем завершения передачи digitalWrite(txPowerPin, LOW); delay(5000); // Ждем 5 секунд и повторяем всё снова }

Для передачи влажности и температуры в одном сообщении я соединяю их вместе. Сначала данные считываются в переменную как целые числа, потом целые числа преобразовываются в массив символов, а затем они соединяются друг с другом. На приемной стороне данные будут разделены на отдельные символы. Делая это, я ограничиваю себя двумя цифрами градусов. Если датчик находится в среде с температурой менее 10°C, я буду получать на дисплее символы мусора. Например, если температура составляет 20°C, а влажность - 45%, то будет передаваться сообщение 2045, и всё хорошо. Если температура равна 9°C, а влажность - 78%, то передастся сообщение 978x, где «x» - случайный символ. Поэтому, если вы будете собирать данный беспроводной термометр, я советую вам изменить программу для передачи правильных данных, когда температура будет меньше 10°C.

Программа приемника

// Подключаем необходимые библиотеки #include #include // Определение подключение LCD #define RS 9 #define E 10 #define D4 5 #define D5 6 #define D6 7 #define D7 8 LiquidCrystal lcd(RS, E, D4, D5, D6, D7); // Отрисовка символа градусов byte degreesymbol = { B01100, B10010, B10010, B01100, B00000, B00000, B00000, B00000 }; // Переменные int tem = 0; int i; // Функция первоначальной настройки - выполняется только один раз при включении void setup() { lcd.begin(16,2); // Инициализация LCD lcd.createChar(1, degreesymbol); // Создание символа градусов в месте 1 Serial.begin(9600); // Для отладки vw_setup(4800); // Скорость соединения VirtualWire vw_rx_start(); // Готовность для приема vw_set_rx_pin(2); // Вывод приема VirtualWiore lcd.clear(); // Очистить LCD } // Функция цикла - выполняется всегда void loop() { uint8_t buf; // Переменная для хранения принятых данных uint8_t buflen = VW_MAX_MESSAGE_LEN; // Переменная для хранения длины принятых данных lcd.setCursor(0,0); lcd.print("Temp: "); if (vw_get_message(buf, &buflen)) // Если данные приняты { for (i=0;i<2;i++) // Получить два первых байта { Serial.write(buf[i]); // Для отладки lcd.write(buf[i]); // Вывести первые байты на LCD } Serial.println(); // Для отладки lcd.write(1); // Вывести символ градусов на LCD lcd.print(" C"); lcd.setCursor(0,1); lcd.print("Hum: "); for (i=2;i<4;i++) // Получаем последние два байта { Serial.write(buf[i]); // Отладка lcd.write(buf[i]); // Вывести последние байты на LCD } lcd.print("% RH"); } }

Интересный способ использования библиотеки LiquidCrystal - это создание пользовательских символов. С помощью createChar я создал символ градусов. Таким же способом вы можете создать и свои собственные символы. Чтобы создать пользовательский символ или значок, вам необходимо объявить его, как массив из восьми байт, и «нарисовать», какие пиксели будут включены (1 - включен, 0 - выключен).

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

Характеристика температурного модуля DS18B20

Нельзя не упомянуть о ещё одном преимуществе модулей DS18B20. Каждый датчик данного типа использует для работы уникальный последовательный 64-битный код. Это значит, что все подобные компоненты могут функционировать на одной шине типа 1 Wire, по которой, как отмечалось выше, передается вся информация. Таким образом, для управления несколькими модулями понадобится всего один микропроцессор, причем сами температурные датчики могут быть разбросаны по солидной площади.

Детали для работы над термометром с DS18B20 на основе Arduino

Чтобы собрать качественный аналоговый термометр, нужно подготовить:

  • электросхему типа Arduino (желательно новую);
  • температурный сенсор модели DS18B20;
  • аналоговый вольтметр;
  • 5 шнуров - два шнура понадобятся для создания цепи между платой Arduino и Вольтметром, 3 провода нужны для подключения к электросхеме температурного сенсора;
  • внешний аккумулятор.

Создание электрической цепи для термометра с DS18B20 на основе Arduino

Здесь алгоритм работы довольно простой, так что соединить все компоненты в единую цепь сможет даже новичок. Для начала на модуле DS18B20 необходимо найти отрицательный контакт (если смотреть на сенсор сверху, данный контакт будет слева). Отрицательный штырек надо соединить с нижней точкой заземления на плате Arduino (она будет обозначаться аббревиатурой GND). Штырь с положительным зарядом (правый) надо подключить к контакту питания на 5 В (тоже располагается внизу платы). Далее делается сигнальный вывод на цифровой контакт 2 (находится вверху платы), чтобы стало возможным измерение температуры (в этом случае используется центральный штырек сенсора).

Чтобы при работе обеспечивалось управление вольтметром, нужно соединить его положительный контакт с цифровым выводом под номером 9. Отрицательный контакт вольтметра подключается к верхней точке заземления платы (она также обозначается сокращением GND). Чтобы поменять цифровую шкалу вольтметра, необходимо просто распечатать заранее подготовленную картинку с градусами Цельсия. Эта картинка либо приклеивается поверх старой шкалы, либо вставляется вместо неё.

Описание широтно-импульсной модуляции

Если коротко, широтно-импульсная модуляция является методом получения аналоговых результатов (таких, как температура) при помощи цифровых средств. Она хороша тем, что даже очень высокие либо очень низкие значения передаются по каналам связи одним импульсом. Весь процесс широтно-импульсной модуляции проходит так: датчик отправляет процессору сигнальный импульс, а сам процессор уже проводит его обработку, после чего выдает значение на термометр. Чтобы иметь возможность получать информацию таким образом, необходимо задействовать специальные контактные штыри на плате Arduino. Распознать эти контакты предельно просто - рядом с ними есть вот такой значок «~». Кстати, данный значок присутствует и возле контакта под номером 9, с которым мы соединяем положительный штырь вольтметра. 9-й вывод был задействован только в качестве примера; при желании можно использовать любой другой контакт, рядом с которым стоит значок «~».

Прописывание кода для работы термометра с DS18B20 на основе Arduino

Прежде всего, в программу разработки надо добавить библиотеку под названием DallasTemperature. Стоит отдавать предпочтение именно ей, ведь она содержит самые высокие температурные значения (а это важно при использовании модуля DS18B20).

При создании кода нужно будет прописать три основные команды:

  1. Чтение температурных значений, поступающих от датчика.
  2. Преобразование температуры методом широтно-импульсной модуляции.
  3. Вывод значений на термометр.
Исходя из этого, в самом начале настраивается считывание температуры от датчика. После этого налаживается процесс широтно-импульсной модуляции. При наличии указанной библиотеки пользователь сможет получать значения в диапазоне от 0 до 255. Настройка широтно-импульсной модуляции осуществляется в программе разработки (для этого там предусмотрен пункт меню под названием «map»). При помощи кода устанавливается минимальная и максимальная температура, которую будет учитывать термометр. Чтобы обеспечить программную связь между вольтметром и платой Arduino, нужно прописать 9-й цифровой контакт в конкретной части кода (выше было указано, что именно к нему подключается сам вольтметр).

Следует учитывать, что минимальный и максимальный порог температуры может быть самым разным (здесь все зависит от предпочтений пользователя). Однако необходимо помнить одну деталь: чем больше разрыв между нижним и верхним пределом, тем меньше будут цифры на шкале.

Вот как выглядит весь код, необходимый для настройки работы термометра.

Сегодня мы рассмотрим проект на Arduino для студентов-инженеров. В этой статье расскажем вам, как сделать термометр на Arduino. Преимуществом строительства термометра на Arduino является простота конструкции. Мы уже и ее особенностями. Программирование Arduino намного проще, чем вы думаете.

Данный проект — цифровой термометр (цифровой датчик температуры Arduino), построенный на основе прецизионного интегрального датчика LM35.

Цифровые термометры широко используются во многих электронных устройствах, таких как кондиционеры, для информирования о температурном уровне и управления процессами системы охлаждения.

В данной схеме задействован датчик температуры LM35 для определения уровня температуры, который может измерять от -55 до 150°С. Измеренная температура отображается на ЖК-дисплее 16х2 с помощью Arduino.

Необходимые компоненты для проекта «Термометр на Arduino»

Цифровой термометр на Arduino использует легко доступные компоненты, которые каждый может приобрести в любом магазине электроники.

  • Arduino
  • Датчик температуры LM35
  • ЖК-дисплей 16х2
  • Потенциометр 1кОм

Работа термометра

Выходное напряжение датчика LM35 линейно пропорционально температуре (по Цельсию).

Выход LM35 имеет масштабный коэффициент 10 мВ/°C , что означает, что при каждом повышении температуры на 1°C произойдет соответствующее увеличение выходного напряжения на 10мВ, следовательно мы можем легко прочитать значение измеряемой температуры.

Arduino имеет аналоговый вывод (A0), способный считывать аналоговые сигналы от любого датчика. Как показано на принципиальной схеме, аналоговый вывод A0 Arduino подключается к выходу LM35.

Распиновка датчика температуры LM35

Arduino имеет 10-битный встроенный АЦП, поэтому он может считывать значение от 0 до 1023 , то есть для нулевого напряжения он считывает 0000, а для VCC (5 В) он считывает 1023.

Таким образом, мы масштабируем значения 0 — 1023 в новый диапазон 0 — 500, потому что LM35 выдает значения с шагом 10мВ на каждый градус, так что максимально возможный прирост составляет 500 (5В/0,01В).

Используя это сопоставление, мы можем принимать каждое приращение в значении АЦП как шаг повышения по шкале. Если значение АЦП равно 27, то значение измеряемо температуры составляет 27°C.

Скетч термометра

#include long A; int B; LiquidCrystal lcd(12, 11, 5, 4, 3, 2); void setup() { lcd.begin(16,2); lcd.print(«THERMO METER»); pinMode(A0,INPUT); } void loop() { A=analogRead(A0); B=map(A,0,1023,0,500); lcd.setCursor(0,0); lcd.print(«TEMPERARTURE: «); lcd.setCursor(0,1); lcd.print(B); lcd.print(«‘C «); }

Теперь перейдем к логике программы. Сначала нам необходимо объявить переменную long «A», чтобы сохранить значение, считанное с LM35, которое имеет диапазон от 0 до 1023. Затем объявляем другую целочисленную переменную «B» для хранения отображаемого (преобразованного) значения.

Значение температуры считывается из вывода A0 и хранится в переменной «A». Затем переменная «A» преобразуется в диапазон от 0 до 500 и сохраняется в переменной «B». Значение «B» выводиться непосредственно на ЖК-экране 16х2.