Создаем беспроводной термометр на Arduino
Узнайте, как использовать RF модуль 433 МГц совместно с ATMega328P-PU. В данной статье мы соберем схему из датчика DHT11 и радиочастотного передатчика. А также соберем приемное устройство с радиоприемником 433 МГц и LCD дисплеем.
Что нам потребуется
- компьютер с установленной Arduino IDE (я использую версию 1.6.5);
- библиотека VirtualWire (ссылка ниже);
- Arduino Mega;
- ATMega328P;
- программатор AVR MKII ISP;
- LCD дисплей;
- датчик температуры и относительной влажности воздуха DHT11;
- радиочастотные модули 433 МГц;
- перемычки;
- макетная плата;
- компоненты из перечня элементов, приведенного ниже.
Введение
В данной статье я покажу вам, как собрать устройство, которое измеряет температуру и относительную влажность воздуха и посылает измеренные значения с помощью стандартного радиочастотного модуля 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.
Принципиальные схемы
Передатчик
В данном примере я не буду выводить неиспользуемые выводы микроконтроллера на внешние контакты термометра, после чего их можно было бы использовать для дальнейшего усовершенствования устройства. Здесь мы рассматриваем лишь идею для устройства и соберем его только на макетной плате.
Приемник
Пожалуйста, обратите внимание, что приемник построен на базе платы Arduino Mega, которая не изображена на схеме. Для подключения платы Arduino Mega соедините с ней радиочастотный модуль и LCD дисплей согласно метка на схеме.
Перечень элементов
Передатчик
Приемник
Программа
Программа передатчика
Сперва рассмотрим программу передающей части:
// Подключаем необходимые библиотеки
#include <VirtualWire.h>
#include <DHT.h>
// Определение
#define dhtPin 4
#define dhtType DHT11
#define txPowerPin 8
// Использование библиотеки DHT
DHT dht(dhtPin, dhtType);
// Переменные
char msg0[3];
char msg1[3];
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 <VirtualWire.h>
#include <LiquidCrystal.h>
// Определение подключение 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[8] = {
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[VW_MAX_MESSAGE_LEN]; // Переменная для хранения принятых данных
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 – выключен).
В функции setup()
вы создаете его с помощью createChar
. createChar
принимает два аргумента: номер позиции для хранения символа и массив байт, в котором определено, какие пиксели будут отображаться. В нашем случае это lcd.createChar(1, degreesymbol)
. Затем символ выводится на LCD с помощью функции lcd.write
.
Заключение
В данной статье я использовал датчик температуры и влажности DHT11. Температура и влажность были преобразованы в массив символов, а затем переданы с помощью передатчика 433 МГц. На приемной стороне массив символов был разделен на пары и выведен на LCD. Для получения символа градусов я использовал функцию createChar
библиотеки LiquidCrystal.
Загрузки
- Библиотека VirtualWire версия 1.6 (библиотека для Arduino для организации связи через радиомодули с использованием амплитудной манипуляции).
- Описание библиотеки VirtualWire.