Содержание
Скетч
Прошейте контроллер скетчем через Arduino IDE.
- weather-station-display.ino
-
// библиотека для работы I²C #include <Wire.h> // библиотека для работы с метеосенсором #include <TroykaMeteoSensor.h> // Подключаем библиотеку для работы с дисплеем #include <QuadDisplay2.h> // создаём объект для работы с метеосенсором TroykaMeteoSensor meteoSensor; // создаём объект класса QuadDisplay и передаём номер пина CS QuadDisplay qd(10); // создаем объект класса long для хранения счетчиков unsigned long respite_Time = ; unsigned long respite_Meteo = ; // создаем объект для регулировки времени показа значений на экране int slowdown_qd = 1000; void setup() { // инициализация дисплея qd.begin(); // инициализируем метеосенсор meteoSensor.begin(); } void loop() { // запускаем бесконечный счетчик. Его содержимое будет обрабатываться каждые 1000 миллисекунд if (millis() - respite_Time > slowdown_qd) { // запускаем функции вывода температуры и влажности по очереди if (millis() - respite_Meteo < 2 * slowdown_qd) { showTemperatureC(); } else if (millis() - respite_Meteo < 3 * slowdown_qd ) { showHumidity(); } // гасим экран и обнуляем цикл else if (millis() - respite_Meteo < 4 * slowdown_qd ) { qd.displayDigits(QD_NONE, QD_NONE, QD_NONE, QD_NONE); respite_Meteo = millis(); } respite_Time = millis(); } } // функция работы датчика температуры void showTemperatureC() { // считываем данные с датчика int stateSensor = meteoSensor.read(); // проверяем состояние данных switch (stateSensor) { // выводим показания температуры на дисплей case SHT_OK qd.displayTemperatureC(meteoSensor.getTemperatureC()); break; // выводим сообщение "Errd", если ошибка данных или сенсор не подключён case SHT_ERROR_DATA qd.displayDigits(QD_E, QD_r, QD_r, QD_d); // выводим сообщение "ErrC", если ошибка контрольной суммы case SHT_ERROR_CHECKSUM qd.displayDigits(QD_E, QD_r, QD_r, QD_C); break; } } // функция работы датчика влажности void showHumidity() { // считываем данные с датчика int stateSensor = meteoSensor.read(); // проверяем состояние данных switch (stateSensor) { // выводим показания влажности на дисплей case SHT_OK qd.displayHumidity(meteoSensor.getHumidity()); break; // выводим сообщение "Errd", если ошибка данных или сенсор не подключён case SHT_ERROR_DATA qd.displayDigits(QD_E, QD_r, QD_r, QD_d); // выводим сообщение "ErrC", если ошибка контрольной суммы case SHT_ERROR_CHECKSUM qd.displayDigits(QD_E, QD_r, QD_r, QD_C); break; } }
Часто задаваемые вопросы
Как установить библиотеку
У вас предыдущая версия модуля. Она снята с производства пару лет назад. С этим скетчем, библиотекой и схемой сборки модуль работать не будет.
Дисплей 16×4 LCD1604
Подробнее о дисплее и работе с ним погуглите «Работа с символьными ЖКИ на базе HD44780». Отметим, что нужно внимательно отнестись к полярности подключения питания к ЖК-индикатору и чтобы напряжение питания было в диапазоне +4,5…5,5 В. Невнимательное отношение к этому может привести к выходу индикатора из строя!
Пин LCD 1604 | Arduino MEGA | Arduino UNO | Описание |
---|---|---|---|
VSS | GND | GND | GND |
VDD | 5 V | 5 V | 4,7 — 5,3V |
RS | 22 | 4 | Высокий уровень означает, что сигнал на выходах DB0—DB7 является данными, низкий — командой |
RW | GND | GND | Определяет направление данных (чтение/запись). Так как операция чтения данных из индикатора обычно бывает невостребованной, то можно установить постоянно на этом входе низкий уровень |
E | 23 | 5 | Импульс длительностью не менее 500 мс на этом выводе определяет сигнал для чтения/записи данных с выводов DB0-DB7, RS и WR |
DB4 | 24 | 8 | Входящие/исходящие данные |
DB5 | 25 | 9 | |
DB6 | 26 | 10 | |
DB7 | 27 | 11 | |
LED A+ | +5V или резистор 220 Ом → +5VLED-A | ||
LED B- | GND | ||
V0 | GND или подстроечник на 10кОм |
Программная инициализация будет выглядеть так:
Температура, влажность DHT11
Подключение датчика температуры и влажности DHT11 (SainSmart). Датчик расположите лицевой стороной вверх, выводы будут описаны слева направо.
DHT11 | Arduino Mega |
---|---|
DATA | Digital pin 2 (PWM) (см. ниже DHTPIN) |
VCC | 3,3—5 В (рекомендуется 5 В, лучше внешнее питание) |
GND | GND |
Программная инициализация
Барометр BMP180
Подключение датчика атмосферного давления BMP180 (барометр) + температура по интерфейсу I2C/TWI.
BMP180 | Arduino Mega |
---|---|
VCC | не подключен |
GND | GND |
SCL | 21 (SCL) |
SDA | 20 (SDA) |
3,3 | 3,3 В |
Для UNO: A4 (SDA), A5 (SCL).
nRF24L01+
Краткие характеристики:
- Диапазон частот 2,401 — 2,4835 Ггц
- 126 каналов. Нулевой канал начинается с 2400 Мгц и далее с шагом 1 Мгц, например 70 канал находится соответственно на 2470 Мгц. При установке скорости передачи 2Mbps занимается ширина канала в 2 Мгц
- Питание 1,9 — 3,6 В (рекомендуется 3,3 В)
Вот распиновка модуля.
Некоторые советуют сразу же припаять керамический конденсатор 100nF (можно 1µF, 10µF) на выводы питания RF для избежания электрических помех.
Распиновка nRF24L01+ (смотреть сверху платы там где чип, пины должны быть внизу) :
пин 2 3,3V | пин 4 CSN | пин 6 MOSI | пин 8 IRQ |
пин 1 GND | пин 3 CE | пин 5 SCK | пин 7 MISO |
Подключение для метеостанции:
Arduino Mega | nRF24L01+ |
---|---|
3,3 В | VCC пин 2 (лучше внешнее питание) |
пин D8 | CE пин 3 (chip enable in) |
SS пин D53 | CSN пин 4 (chip select in) |
SCK пин D52 | SCK пин 5 (SPI clock in) |
MOSI пин D51 | SDI пин 6 (SPI Data in) |
MISO пин D50 | SDO пин 7 (SPI data out) |
IRQ пин 8 (Interrupt output) не подсоединен | |
GND | GND пин 1 (ground in) |
Программирование радиомодуля будет подробно описано в программной части.
ESP8266
Распиновка ESP8266 (смотреть сверху платы там где чипы, пины должны быть внизу):
GND | GPIO2 | GPIO0 | RX |
TX | CH_PD | RESET | VCC |
Подключение ESP8266 для метеостанции:
ESP8266 | Arduino Mega |
---|---|
TX | 10 пин (SoftwareSerial RX) |
RX | 11 пин (SoftwareSerial TX) |
VCC | 3,3 В |
GND | GND |
CH_PD | Через резистор 10К к 3,3 В Arduino |
GPI0 | Необязательно. Через резистор 10К к 3,3 В Arduino |
GPI2 | Необязательно. Через резистор 10К к 3,3 В Arduino |
КДПВ
Центральный блок в сборе. «Материнскую плату» вырезал из картонной коробки из-под обуви и к ней винтиками на 3 прикрутил всё остальное.
Как видим в этом месте всё питание осуществляется от пинов Ардуино, т.е. к блоку питания напрямую ничего не идёт, и пока мощи хватает.
Вроде всё. Ничего не забыл.
Паяйте, соединяйте. В следующей части будет приведен рабочий скетч для центрального блока и наша метеостанция уже что-то покажет.
Android
Теперь напишем простое приложение для Андроид, которое запрашивает, получает, декодирует JSON-данные и отображает информацию на экране.
Наше Android-приложение будет простым насколько это возможно, только сама суть технологии. Далее вокруг этого «скелета» уже можно будет наворачивать различные «красивости».
Вот скриншот того, что должно получиться в итоге
Как видим UI просто спартанский, основан на LinearLayout, ничего лишнего.
В верхней части TextView показывает ID датчиков и их метео-данные. Кнопка «Обновить» инициирует повторный запрос к веб-серверу. Далее в EditText расположена единственная настройка программы — это URL запроса в виде
Что необходимо отметить?
В манифест добавьте строки разрешающие интернет и проверку состояния сетевого соединения :
Работа с сетью и получение данных с веб-сайта происходит следующим образом.
Используем AsyncTask, чтобы создать фоновую задачу отдельно от главного потока пользовательского интерфейса. Эта фоновая задача берет URL запроса и использует его для создания .
После того, как соединение установлено, AsyncTask загружает содержимое веб-страницы (JSON) как InputStream. Далее InputStream преобразуется в строку, которая декодируется с помощью JSONObject и отображается в пользовательском интерфейсе методом .
В MainActivity.java измените URL на ваш :
он будет использоваться по умолчанию при первом запуске Android приложения.
Исходный код
Код автономной части
- meteo_sensor.ino
-
#include <Arduino.h> #include <SHT1x.h> #include <LowPower_Teensy3.h> #include <ampline.h> // Таймаут между посылками (не более 65535) #define TIMEOUT 60000 // Количество попыток отправки посылки #define ATTEMPTS 3 // Информационный пин передатчика #define RF_PIN 5 // Пины датчика температуры и влажности #define GND1_PIN 10 #define VCC1_PIN 11 #define GND2_PIN 7 #define VCC2_PIN 8 #define DATA_PIN 12 #define CLK_PIN 9 AmperkaLine rf(RF_PIN); SHT1x sht1x(CLK_PIN, DATA_PIN); void loop(void); // Функция усыпления платы. Каждые TIMEOUT секунд // будет вызываться функция loop_func. TEENSY3_LP LP = TEENSY3_LP(); sleep_block_t* LP_config; void sleep_mode(void) { LP_config = (sleep_block_t*)calloc(1,sizeof(sleep_block_t)); // Просыпаться будем по таймеру LP_config->modules = (LPTMR_WAKE); // Задаём таймаут для таймера LP_config->lptmr_timeout = TIMEOUT; // По истечении таймаута будет вызываться функция loop LP_config->callback = loop; LP.Hibernate(LP_config); } // Функция включения периферии void periferial_start(void) { // Включаем линию передачи данных pinMode(RF_PIN, OUTPUT); // Включаем питания и земли датчиков температуры и влажности pinMode(GND1_PIN, OUTPUT); pinMode(GND2_PIN, OUTPUT); pinMode(VCC1_PIN, OUTPUT); pinMode(VCC2_PIN, OUTPUT); digitalWrite(GND1_PIN, LOW); digitalWrite(GND2_PIN, LOW); digitalWrite(VCC1_PIN, HIGH); digitalWrite(VCC2_PIN, HIGH); // Включаем светодиод для индикации передачи pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH); // Выбираем в качестве опорного напряжения внутренний // источник (=1.2 В) analogReference(INTERNAL); } // Функция выключения периферии void periferial_stop(void) { // Выключаем линию передачи данных pinMode(RF_PIN, INPUT); // Выключаем датчик температуры и влажности pinMode(GND1_PIN, INPUT); pinMode(GND2_PIN, INPUT); pinMode(VCC1_PIN, INPUT); pinMode(VCC2_PIN, INPUT); pinMode(18, INPUT_PULLUP); pinMode(19, INPUT_PULLUP); // Выключаем светодиод digitalWrite(LED_BUILTIN, LOW); } void setup(void) { // Ничего не инициализируем, сразу засыпаем sleep_mode(); } // Эта функция выполняется раз в TIMEOUT секунд void loop(void) { unsigned long msg; byte temp, humidity, voltage; // Включаем периферию periferial_start(); // Подождём, пока включится датчик температуры и влажности delay(30); // Получаем входные данные с сенсоров temp = (byte)(sht1x.readTemperatureC() + 40.)*2; humidity = (byte)sht1x.readHumidity(); voltage = analogRead(A0)4; // Составляем из данных посылку msg = ; msg |= voltage; msg <<= 8; msg |= humidity; msg <<= 8; msg |= temp; // Отправляем несколько раз посылку for(int i = ; i < ATTEMPTS; i++) rf.send(msg); // Выключаем периферию periferial_stop(); // После выхода из функции плата снова уснёт }
Код платы, работающей в помещении
- receiver.ino
-
#include <Arduino.h> #include <SPI.h> #include <Ethernet.h> #include <ampline.h> byte mac = { 0x90, 0xA7, 0xDA, 0x0F, 0xBC, 0x75 }; char server = "narodmon.ru"; EthernetClient client; const int rfpin = 7; AmperkaLine rf(rfpin); void setup(void) { pinMode(rfpin, INPUT); pinMode(6, OUTPUT); Serial.begin(9600); Serial.println("Started."); } void loop(void) { static unsigned long pushtimeout = ; static float temp, humidity, voltage; unsigned long msg; int res; if((res = rf.receive(&msg)) == ) { temp = ((float)(msg&0xFF))2. - 40.; msg >>= 8; humidity = (float)(msg&0xFF); msg >>= 8; voltage = (float)(msg&0xFF) 256. * 1.2 * 10 * 1.1; digitalWrite(6, HIGH); Serial.print("Temp: "); Serial.print(temp); Serial.print(", humidity: "); Serial.print(humidity); Serial.print(", voltage: "); Serial.println(voltage); digitalWrite(6, LOW); } else Serial.println('E'); if(millis() - pushtimeout > 60000*5) { pushtimeout = millis(); Serial.println("Starting Ethernet..."); if (Ethernet.begin(mac) == ) { Serial.println("Failed to configure Ethernet using DHCP"); while(1) { } } delay(1000); Serial.println("connecting..."); if (client.connect(server, 8283)) { Serial.println("connected"); client.println("#90-A7-DA-0F-BC-75#Sensor#55.751775#37.616856#0.0"); client.print("#90A7DA0FBC7501#"); client.print(temp, DEC); client.println("#In"); client.print("#90A7DA0FBC7502#"); client.print(humidity, DEC); client.println("#Humidity"); client.print("#90A7DA0FBC7503#"); client.print(voltage, DEC); client.println("#Voltage"); client.println("##"); } else Serial.println("connection failed"); { unsigned long tm = millis(); while(millis() - tm < 5000) { if (client.available()) { char c = client.read(); Serial.print(c); } } } client.stop(); } }
Датчик на Arduino Uno и плате расширения Troyka Shield
Рассмотрим еще одну погодную станцию. Ее особенности:
- использование цифрового метеосенсора troyka;
- термометр DS18B20;
- барометр Troyka V2.
- хранение данных на карточке MicroSD — для удобства их последующего анализа на любом устройстве.
Компоненты
Для проекта требуются:
- контроллер Arduino Uno;
- плата расширения Troyka Shield;
- метеодатчик;
- четырехразрядный цифровой дисплей-индикатор;
- барометр с troyka-блоком подтяжки;
- картридер и карточка micro-SD.
Порядок сборки
Система собирается по шагам.
- Установить плату расширения на Ардуино.
- Подключить к пинам шины I2C метеодатчик.
- Подсоединить дисплей в разъемы e-f на схеме. Пин CS идет на пин 10 микрокомпьютера Ардуино.
- Барометр вставляется в слот B, пины шины I2C.
- Термометр подключается в слот C, пин 4. Для его работы потребуется дополнительный модуль подтяжки.
- И, наконец, к слоту D и на пин 8 подключается картридер.
Общий принцип работы
Измеряющая данные окружающей среды метеостанция на Ардуино состоит из нескольких основных компонентов:
- собственно плата управления Arduino (например, Uno). На нее поступает информация со внешних датчиков, контроллер выполняет вычисления и выводит информацию на экран;
- электронный дисплей — служит для отображения поступивших с контроллера данных в понятной человекочитаемой форме;
- сенсор влажности температуры. В подобных схемах популярны датчики DHT11 и DHT22. Они регистрируют данные среды и отдают их контроллеру;
- макетная плата — основа для сборки всех компонентов. На ней фиксируются все элементы метеостанции, по ней же прокладываются электрические соединения;
- соединительные провода — с «оголенными» концами под пайку или оснащенные штекерами.
Кроме того, в плату понадобится залить соответствующее программное обеспечение — скетч. Его содержимое зависит от набора элементов и выполняемых задач, примеры скетчей мы также рассмотрим ниже.
Создание метеостанции на базе Arduino и датчика температуры и влажности DHT22
Для создания метеостанции нам необходимо:
- Arduino
- Датчик температуры и влажности DHT22 (существуют модификации DHT11 или DHT21, но они имеют меньшую точность измерений)
Минимальный набор готов, но если вам не хочется использовать свой компьютер как экран для вывода показаний с датчика, то понадобится еще и устройство вывода данных, идеальным решением для этого может стать:
Двухстрочный дисплей LCD 1602А
Его подключение вы можете найти в предыдущей статье.
Начнем, пожалуй, с подключения нашего датчика температуры и влажности к Arduino. Две крайние ножки датчика это питание: крайняя левая +5V, крайняя правая — GND (земля). Ножка, отмеченная на схеме голубым проводом – сигнал (S), ее мы подключаем к порту на плате и обязательно подтягиваем резистором к питанию (10 кОм). Именно его в дальнейшем и пропишем в программе как пин, с которого мы будем считывать данные. Отлично, теперь датчик подключен, перейдем к программированию.
Так как DHT22 является конденсационным, да и в своем устройстве он не так уж прост, для работы будем использовать готовую библиотеку, с помощью которой работа с датчиками сводится к использованию готовых функций.Итак, подключаем библиотеку DHT-master.
В директивах (параметрах, определяемых до начала основных блоков программы) описываем пин, к которому подключили сигнал (S), тип датчика и создаем класс, в котором соединим эти два параметра, для дальнейшей возможности обращения этим параметрам в программе.
В функции voidsetup() подключаем монитор порта (его мы будем использовать только для тестирования, потом выведем показания на дисплей) и инициализируем начало работы с датчиком температуры и влажности
В основном блоке программы (void loop()) ставим задержку между двумя последовательными измерениями и описываем считывание данных с датчика с помощью библиотечных функций
Проверяем, получаем ли мы данные и, если все идет по плану, то выводим эти показания в монитор порта.
Загружаем программу в плату и, чтобы увидеть показания, которые нам присылает DHT22, открываем монитор порта (Ctrl+Shift+M или Инструменты — Монитор порта) следим за изменениями температуры и влажности в комнате.Итак, LevelUP: теперь давайте освоим вывод показаний на двухстрочный дисплей.Для того, чтобы компьютер (ноутбук) не использовался исключительно как монитор для вывода показаний с датчика, мы будем использовать двухстрочный дисплей LCD 1602А, как устройство внешнего вывода.Для этого обратимся к статье подключение двухстрочного дисплея.Добавим пару элементов в программе, которые позволят нам использовать для вывода именно дисплей: подключим библиотеку для работы с дисплеем, и также, как и DHT22, создадим класс LiquidCrystal, в котором в качестве параметров указаны пины, используемые, как сигнальные для дисплея.
Далее в теле функции void setup() инициализируем дисплей: lcd.begin(16, 2) т.е. определяем максимальное количество символов в строке и количество строк и выводим название нашего мини-проекта.
А теперь приступим к основному блоку программы. В функции void loop() опишем считывание показания с датчика температуры и влажности и опишем его вывод на дисплей.
Собираем наше устройство, загружаем программу и наша портативная метеостанция готова к работе. Чтобы она работала постоянно, можно использовать питание не от USB, а от батарейки, разъем для которой есть на плате.
Arduino
- 80
А как же камера?
Пока никак. Сделанные фото можно передавать на WeatherUnderground. Это сделать несложно через ftp
Однако, даже просто вручную передать данные на WU у меня не получилось ни разу. Судя по форумам техподдержки, данная фича работает плохо и сбоит.
Альтернативной является передача изображения на narodmon.ru,
Собственно, время от времени (раз в полчаса) дёргаем ручку /api/v1/capture_photo (которая зовёт take_photo). Например, будем звать через cron этот bash-скрипт:
На сервисе сразу появится снимок:
Плюс, не забываем время от времени (например раз в семь дней) чистить старые изображения:
HTTP GET и JSON
Вопрос, который нужно решить в первую очередь — это каким образом будет происходить передача данных от веб-сервера к Андроид-приложению.
Придумывать тут ничего не нужно, всё уже придумано за нас — это HTTP GET и JSON.
В нашем случае простой GET запрос к веб-серверу можно составить и отладить вручную, пока Андроид приложение ещё не готово.
В Java и в Android есть готовые библиотеки для обработки данных в формате JSON. JSON текстовый формат, читается человеком, что полезно для отладки.
Для того, чтобы сформировать текущие данные от датчиков метеостанции создадим на веб-сервере новый PHP скрипт last-data-to-json.php.
Вызов скрипта :
где , как мы помним, это секретный ключ доступа к БД.
Пример ответа в формате JSON :
Необходимо напомнить, что у нас 3 датчика. Их ID и тип (DHT или BMP) жёстко закодированы по всему коду метеостанции. Такой способ хардкордного кодирования идеологически неверен, но для наколенного прототипа (где необходимо быстрое и простое решение) это разумный компромисс.
Скрипт берет из БД самые последние данные от этих разнотипных датчиков и упаковывает в формат JSON. Выборка данных из БД «с конца» просходит таким способом :
Метеостанция на Arduino от А до Я. Часть 5 +9
- 12.10.18 05:28
•
tim4dev
•
#426019
•
Хабрахабр
•
•
2400
Разработка под Arduino, DIY или Сделай сам
Окончание. Предыдущая часть.
- Часть 1. Требования. Выбор железа. Общая схема
- Часть 2. Софт. Центральный блок, железо
- Часть 3. Центральный блок, софт
- Часть 4. Заоконный датчик
- Часть 5. MySQL, PHP, WWW, Android
Заоконный датчик. Программное обеспечение
Поговорим о программном обеспечении заоконного датчика. После этого у вас получится законченная система с которой уже можно экспериментировать.
Напомню, что сервер — это центральный, домашний блок, который может общаться с интернет через WiFi, а клиент — это удалённый, заоконный датчик, который передаёт данные на сервер по радиоканалу.
Исходный код как для сервера, так и для клиента находится здесь.
Исходные тексты снабжены подробными комментариями.
На клиенте почти ничего настраивать не надо.
Радиопередатчик nRF24L01+, точнее библиотека RadioHead, требует указания адресов сервера и клиента. Адреса предусмотрены на тот случай, если у вас будет серверов и клиентов больше чем один. Адрес — это просто любое целое число. Когда клиент посылает пакет с данными на сервер, то он указывает для какого сервера предназначен этот пакет. Сервер зная свой собственный адрес, в свою очередь, определяет для него ли предназначен этот пакет.
Поэтому на сервере и на клиенте должен совпадать, а вот для разных клиентов должен отличаться. Другими словами, если к нашей системе вы в будущем подключите еще один новый датчик, то для него нужно будет изменить.
Номер радиоканала должен быть одинаковым у всех. По умолчанию он равен 2. Я изменил номер по умолчанию, вы можете выбрать любой другой.
Настройки вольтметра для измерения питающего напряжения батареи необходимо изменить:
Для экономии энергии используется библиотека Lightweight low power library for Arduino.
Вот мои замеры фактического потребления для Arduino Pro Mini с этой либой :
- обычно 25mA
- при работе с DHT то же самое
- при радио передаче 38 mA
- при LowPower.idle 15 mA
- при LowPower.powerDown 7.5 mA
Клиент делает замеры температуры, влажности и напряжения питания, упаковывает всё это в структуру данных, отсылает данные на сервер и «засыпает». Если при передаче произошли ошибки, то передача тут же повторяется.
Сервер (центральный, домашний блок) в свою очередь данные принимает, подтверждает прием и обрабатывает их.
База данных, MySQL, PHP, WWW-сервер
После проделанной работы у нас есть вполне работоспособная конструкция метеостанции. Но сейчас таких метеостанций пруд пруди, локальные поделки это уже не модно. У нас ведь интернет вещей.
Поэтому поговорим о том, как осуществляется выход в эти ваши интернеты, приделаем к нашей метеостанции базу данных и веб-морду к ней.
Постановка задачи для «вебки» :
- принимать и хранить данные метеостанции: температура, влажность, атмосферное давление, напряжение питания
- отображать эти данные
- строить графики.
При этом нам понадобится хостинг с поддержкой Apache, PHP и MySQL с модулем mysqli. И этим условиям удовлетворяет практически любой хостинг на планете Земля. Либо вместо хостинга будет ваш компьютер играющий роль сервера, подключённый к домашнему сетевому маршрутизатору и имеющий выход в Интернет.
Как сделать метеостанцию на LM35
В следующем скетче для определения температуры был использован датчик LM35, подключенный к аналоговому порту. Для точности измерений температуры необходимо будет откалибровать датчик. В этом примере измеряется только температура, при этом данные отправляются на смартфон только в том случае, если произошло изменение температуры или нажата кнопка «Обновить» в приложении.
Скетч для метеостанции на Ардуино с LM35
#include <SoftwareSerial.h> // подключение библиотеки SoftwareSerial.h SoftwareSerial mySerial(2, 3); // указываем пины rx и tx соответственно int temp1; // освобождаем память для переменной "temp1" int temp2; // освобождаем память для переменной "temp2" int temp3; // освобождаем память для переменной "temp3" float temp; // освобождаем память для переменной "temp" byte val; // освобождаем память для переменной "val" String stringT = String("*"); void setup() { pinMode(A0, INPUT); // сенсор LM35 подключим к аналоговому входу A0 Serial.begin(9600); // запуск аппаратного последовательного порта mySerial.begin(9600); // запуск программного последовательного порта } void loop() { temp1 = analogRead(A0); // считываем значение с датчика delay(60000); temp2 = analogRead(A0); // повторно считываем значение с датчика temp3 = temp1 - temp2; // определяем, изменилась ли температура // отправляем сообщение только, когда изменилась температура if (temp3 != 0) { temp = ( temp2/1023.0 )*5.0*1000/10; // вычисляем значение температуры mySerial.println(temp + stringT); // отправляем температуру на телефон Serial.println(temp + stringT); // отправляем температуру на монитор Serial.println(""); } // отправляем сообщение, когда нажата кнопка "обновить" в приложении if (Serial.available()) // проверяем, поступают ли какие-то команды { val = Serial.read(); // переменная val равна полученной команде if (val == '1') { temp = ( temp2/1023.0 )*5.0*1000/10; // вычисляем значение температуры mySerial.println(temp + stringT); // отправляем температуру на телефон Serial.println(temp + stringT); // отправляем температуру на монитор Serial.println(""); } } }
Шаг первый. Подключаем термистор
У меня самый простой термистор: если его нагреть, сопротивление уменьшится, если охладить — вырастет. Такие элементы называют термисторами с отрицательным температурным коэффициентом или NТС (от английских слов Negative Temperature Coefficent).
К сожалению, на Ардуино нет встроенных инструментов для измерения сопротивления, поэтому будем выкручиваться. В эксперименте с батарейками мы использовали делитель напряжения: пара сопротивлений помогла снизить напряжение вдвое. Использую ту же схему, только одно сопротивление заменю термистором.
При комнатной температуре, 25 по Цельсию, его сопротивление равно 10 килоомам — столько же, сколько и у постоянного резистора. Теперь выходное напряжение цепи зависит только от сопротивления термистора. Измерю напряжение, подключив цепь к контакту А5.
Теперь я знаю всё, что нужно для определения сопротивления термистора. Воспользуюсь общей формулой делителя напряжения, чтобы найти сопротивление моего термистора.
Чтобы не возиться с подключением экрана раньше времени — вдруг мой сенсор не заработает — выведу показания с платы на экран компьютера. Передам данные по USB, с помощью интерфейса последовательного порта. Запищу передачу командой Serial.begin. Текст сообщений буду составлять с помощью функций Serial.print и Serial.println. Первая просто добавляет данные к текущей строке, вторая — сначала добавляет данные, затем заканчивает строку. Загружу в Ардуинку первую программу.
Программа загрузилась, но ничего не происходит. Чтобы увидеть данные, нужно запустить монитор последовательного порта.
Это можно сделать в верхнем меню редактора кода (монитор порта находится во вкладке инструменты) или с помощью комбинации клавиш Ctrl+Shift+M.
При комнатной температуре у меня получилось, что напряжение срезалось вдвое. Это подтверждает, что мой термистор сейчас имеет сопротивление 10 кОм.
Код:
Копируем этот код и вставляем в IDE
#include <LCD_1602_RUS.h> // подключаем библиотеку для датчика
LCD_1602_RUS lcd(0x27, 20, 4); // определяем адрес дисплея и его размер
#include <DHT.h> // подключаем библиотеку для датчика
DHT dht(2, DHT11); // сообщаем на каком порту будет датчик
void setup()
{
lcd.init(); // Инициализация дисплея
lcd.backlight(); // Подключение подсветки
lcd.clear(); // Чистим дисплей
dht.begin(); // запускаем датчик DHT11
}
void loop()
{
float h = dht.readHumidity(); // считываем температуру (t)
float t = dht.readTemperature(); // и влажность (h)
lcd.setCursor(0, 0); // Устанавливаем курср на нулевую символ и нулевой строки
lcd.print(«Влажн. :»); // выводим надпись «Влажн.:»
lcd.print(h,1); // выводим значение влажности с одним символом после запятой
lcd.print(» %»); // выволим знак процента
lcd.setCursor(0, 1); // Устанавливаем курср на нулевой символ первой строки
lcd.print(«Темпер.:»); // выводим надпись «Темпер.:»
lcd.print(t,1); // выводим значение влажности с одним символом после запятой
lcd.print(«\337C»); // выволим знак градуса (337 символ в талице) и «С»
delay(2000); // ждём 2000 микросикенд (2 секунды)
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#include <LCD_1602_RUS.h> // подключаем библиотеку для датчика LCD_1602_RUS lcd(0x27,20,4);// определяем адрес дисплея и его размер #include <DHT.h> // подключаем библиотеку для датчика DHT dht(2,DHT11);// сообщаем на каком порту будет датчик voidsetup() { lcd.init();// Инициализация дисплея lcd.backlight();// Подключение подсветки lcd.clear();// Чистим дисплей dht.begin();// запускаем датчик DHT11 } voidloop() { floath=dht.readHumidity();// считываем температуру (t) floatt=dht.readTemperature();// и влажность (h) lcd.setCursor(,);// Устанавливаем курср на нулевую символ и нулевой строки lcd.print(«Влажн. :»);// выводим надпись «Влажн.:» lcd.print(h,1);// выводим значение влажности с одним символом после запятой lcd.print(» %»);// выволим знак процента lcd.setCursor(,1);// Устанавливаем курср на нулевой символ первой строки lcd.print(«Темпер.:»);// выводим надпись «Темпер.:» lcd.print(t,1);// выводим значение влажности с одним символом после запятой lcd.print(«\337C»);// выволим знак градуса (337 символ в талице) и «С» delay(2000);// ждём 2000 микросикенд (2 секунды) } |
Копируем его в поле для кода IDE:
и жмём загрузить:
Кнопка «загрузить»
Загрузка завершена
Ждём несколько секунд и наша метеостанция работает:
Метеостанция работает
Настройка ThingSpeak
Структурная схема работы нашего проекта представлена на следующем рисунке и она содержит 4 секции. Вначале с помощью датчика температуры и влажности DHT11 измеряются эти параметры атмосферы. Затем плата Arduino Uno считывает эти данные с DHT11 и преобразует их в нужную для нас форму, а затем она передает их на Wi-Fi модуль. После этого Wi-Fi модуль ESP8266 передает эти данные на сервер ThingSpeak. Затем сервис ThingSpeak анализирует эти данные и показывает их в удобной графической форме. Также дополнительно значения температуры и влажности показываются на экране ЖК дисплея.
1. Вначале нам необходимо создать аккаунт на ThingSpeak.com, заходим туда, жмем Sign In, а потом Get Started.
2. Затем идем в пункт меню ‘Channels’ (каналы) и создаем новый канал с помощью кнопки New Channel.
3. После этого увидите форму для создания нового канала, заполните там поля Name (имя) и Description (описание) по своему усмотрению. Затем напишите ‘Humidity’ (влажность) и ‘Temperature’ (температура) в Field 1 (поле 1) и Field 2 (поле 2) и поставьте галочки в чек-боксах напротив этих полей. Также поставьте галочку в чек-боксе ‘Make Public’ (сделать общедоступным) в форме ниже и сохраните канал (Save the Channel). Теперь новый канал для вас создан.
4. Теперь откройте вкладку ‘API keys’ чтобы записать свои ключи с этой вкладки. Нам будет нужен только ключ для записи (Write key). Скопируйте этот ключ в переменную char *api_key в тексте программы (приведен в конце статьи).
5. После этого кликните на ‘Data Import/Export’ и скопируйте Update Channel Feed GET Request URL, который будет примерно вида https://api.thingspeak.com/update?api_key=SIWOYBX26OXQ1WMS&field1=0.
6. Теперь необходимо открыть api.thingspeak.com используя функцию httpGet с postUrl в виде “update?api_key=SIWOYBX26OXQ1WMS&field1=0” и затем передать данные используя адрес обновления запроса.
Перед передачей данных необходимо отредактировать строку запроса или postUrl с полями данных температуры и влажности как показано в программном коде ниже. Здесь мы добавили в строку оба параметра, которые нам необходимо передать используя GET запрос к серверу, после этого необходимо использовать httpGet чтобы передать данные на сервер. Более подробно все эти процессы представлены в полном тексте программы, представленном в конце статьи.
В рассматриваемом проекте плата Arduino передает сигнал старта (после которого начинаются измерения) на датчик DHT, а в ответ датчик DHT передает Arduino сигнал, содержащий необходимые данные измерений. Плата Arduino собирает и извлекает эти данные в два приема: сначала извлекается влажность, а потом извлекается температура. Далее эти данные обрабатываются и передаются на ЖК дисплей 16×2 и сервер ThingSpeak. Сервис ThingSpeak отображает данные температуры и влажности в виде графиков, пример которых показан на следующем рисунке.
Прошивка
Устройство готово. Осталось его прошить и смонтировать. Начнем с прошивки. Как я уже говорил выше, то желания изобретать велосипед у меня не было. И смыла изобретать его тоже не было.
Я уже довольно давно работаю с альтернативной прошивкой для датчиков Sonoff, которая называется Tasmota. Я устанавливаю эту прошивку на модули умного дома Sonoff. Эта прошивка прекрасно работает по MQTT с моим сервером умного дома. Задача по мониторингу температуры и влажности для этой прошивки более чем тривиальная. При этом не нужно собирать какой-то кастомный билд прошивки. Берем готовую прошивку и заливаем. Хочешь из hex файла, хочешь, компилируешь в среде arduino ide и заливаешь.
Для тех кому не нравится Tasmota, можете использовать проект espeasy. С этой прошивкой тоже все будет работать, но опыта ее использования у меня практически нет.
Проще говоря, положительный опят использования прошивки Tasmota, а так же нежелание разводить зоопарк из рахных прошивок заставили меня выбрать именно Tasmota. Просто потому что остальные девайсы уже на ней прекрасно работают. И модули управления светом и модули открывания/закрывания ворот.
Не вижу большого смысла описывать все нюансы прошивки, которая используется в готовом виде. Просто прикладываю скрины со своими настройками:
Вот такие вот параметры были выставлены у меня. После полной сборки проекта необходимо было переходить к монтажу.
Android
Теперь напишем простое приложение для Андроид, которое запрашивает, получает, декодирует JSON-данные и отображает информацию на экране.
Наше Android-приложение будет простым насколько это возможно, только сама суть технологии. Далее вокруг этого «скелета» уже можно будет наворачивать различные «красивости».
Вот скриншот того, что должно получиться в итоге
Как видим UI просто спартанский, основан на LinearLayout, ничего лишнего.
В верхней части TextView показывает ID датчиков и их метео-данные. Кнопка «Обновить» инициирует повторный запрос к веб-серверу. Далее в EditText расположена единственная настройка программы — это URL запроса в виде
Что необходимо отметить?
В манифест добавьте строки разрешающие интернет и проверку состояния сетевого соединения :
Работа с сетью и получение данных с веб-сайта происходит следующим образом.
Используем AsyncTask, чтобы создать фоновую задачу отдельно от главного потока пользовательского интерфейса. Эта фоновая задача берет URL запроса и использует его для создания .
После того, как соединение установлено, AsyncTask загружает содержимое веб-страницы (JSON) как InputStream. Далее InputStream преобразуется в строку, которая декодируется с помощью JSONObject и отображается в пользовательском интерфейсе методом .
В MainActivity.java измените URL на ваш :
он будет использоваться по умолчанию при первом запуске Android приложения.