Комнатная метеостанция с часами аппаратная платформа arduino. Метеостанция на Arduino с беспроводным датчиком температуры

За основу взят проект метеостанции из книги В. Петина "Проекты с использованием контроллера Arduino" 2-е издание (проект 5 приложения 2) . Использовалась среда Arduino IDE 1.8.5 в Windows 10.
При запуске скетча выдавалась ошибка

В интернете можно скачать библиотеки для Arduino, имеющие одинаковые названия, но разное содержимое. Скетч может не работать, если вы используете "не ту" библиотеку. Видимо, мне попались не те библиотеки. В проект добавил датчик BMP180 для измерения атмосферного давления и переработал скетч.

Схема соединений

Сканирование адресов

Сначала подключите к Arduino датчик BMP180 и индикатор LCD1602. Скомпилируйте скетч I2C scanner и запустите его, чтобы определить адреса устройств на шине I2C.

Каждые 5 секунд программа сканирует устройства и выдает адреса на COM порт. У меня найдены два устройства с адресами 0x3F и 0x77. BMP180 по умолчанию имеет адрес 0x77, значит LCD индикатор имеет адрес 0x3F.
В некоторых схемах книги перепутаны местами подключения сигналов SDA и SCL к плате Arduino. Должно быть: SDA — к A4, SCL — к A5. Если у модуля BMP180 пять выводов, то на вывод VIN подается +5 Вольт .

Монтажная схема

Теперь соберите схему полностью. Я использовал RGB светодиод с общим катодом, смонтированный на плате вместе с резисторами 150 Ом. Общий катод подключается к контакту GND, остальные выводы — по схеме. Вносить изменения в скетч не требуется, так как яркость светодиодов меняется по циклическому закону.
На схеме показано подключение RGB светодиода с общим анодом, как в книге .
Если на экране LCD1602 не видно символов, то покрутите регулятор яркости. Подсветка индикатора потребляет довольно большой ток, поэтому используйте блок питания на ток не менее 2 А. Я использовал USB хаб с внешним блоком питания на 2 А.
В схеме использовал пьезозвонок ЗП-22. Резистор, подключенный к звонку, на 100 Ом . Частоту звука можно изменить в программе. Выбрал частоту 1000 Гц. Если вам попался зуммер с фиксированной частотой звука, то включать и выключать его можно просто подачей и снятием напряжения, как обычный светодиод. При запуске скетча подается короткий звуковой сигнал. Можно включить периодическую подачу сигналов во время работы программы, раскомментировав строку //bzz(100); в скетче.
В проекте использовал датчик DHT11 в виде модуля с уже смонтированным резистором 4.7 кОм. Сопротивление может быть от 4.7 до 10 кОм.
Подключите контакт Vcc модуля часов DS1302 к шине +5 Вольт. Таким образом вы уменьшите разряд батареи, по сути она будет работать только тогда, когда отключится питание Arduino.

Программа (скетч)

Для обслуживания BMP180 использована библиотека bmp085. Значение давления зависит от высоты местности. Для корректного значения атмосферного давления надо подобрать высоту. Для этого отредактируйте строку dps.init(MODE_STANDARD, 10000, true); У меня высота равна 100 м (10000 см). Фрагмент расчета давления взят из примера BMP085_test2.ino библиотеки bmp085.

Скетч meteo_P

#include
#include
#include
#include "DHT.h"
#include
BMP085 dps = BMP085();
long Pressure = 0, Altitude = 0;
unsigned long time1 = 0;

#define DHTPIN 10
#define DHTTYPE 11 // 11 - DHT11, 22 - DHT22
DHT dht(DHTPIN, DHTTYPE);

int kCePin = 4; // RST DS1302
int kIoPin = 3; // Data DS1302
int kSclkPin = 2; // CLK DS1302
DS1302 rtc(kCePin, kIoPin, kSclkPin);

int REDpin = 9;
int GREENpin = 6;
int BLUEpin = 11;

LiquidCrystal_I2C lcd(0x3f, 16, 2); // укажите свой адрес 0x20...0xff address
unsigned long memTime;
int bzzPin = 8;

void HumTempRead() {
float hum = dht.readHumidity();
float temp = dht.readTemperature();
if (isnan(hum) || isnan(temp)) {
Serial.println("Failed to read from DHT sensor!");
lcd.setCursor(0, 1);
lcd.print("H=--% T=---");
lcd.setCursor(11, 1);
lcd.print((char)223);
lcd.setCursor(12, 1);
lcd.print("C ");
} else {
lcd.setCursor(0, 1);
lcd.print("H=");
lcd.setCursor(2, 1);
lcd.print(hum);
lcd.setCursor(4, 1);
lcd.print("% T=+");
lcd.setCursor(9, 1);
lcd.print(temp);
lcd.setCursor(11, 1);
lcd.print((char)223);
lcd.setCursor(12, 1);
lcd.print("C ") ;
}
}

void setup_bzz() {
pinMode (bzzPin, OUTPUT);
}

void bzz(int _bzzTime) {
tone(bzzPin, 1000 , _bzzTime); // частота 1000 Гц
}

void setup() {
Serial.begin(9600);
Wire.begin();
delay(1000);

dps.init(MODE_STANDARD, 10000, true); // 100 meters (высоту над уровнем моря в cм)

dht.begin();
setup_bzz();
bzz(100);

Lcd.init();
lcd.backlight();
lcd.home();
// lcd.setCursor(0, 0);

rtc.halt(false);
rtc.writeProtect(false);

//rtc.setDOW(FRIDAY); // Set Day-of-Week to FRIDAY установите день недели
//rtc.setTime(4, 58, 0); // Set the time to 12:00:00 (24hr format) установите время
//rtc.setDate(6, 8, 2010); // Set the date to August 6th, 2010 установите дату (число, месяц, год)
}

lcd.setCursor(8, 0);
lcd.print(rtc.getTimeStr());

if ((millis() - memTime > 2000) or (millis() < memTime)) { // DHT11/22 1 time each 2 seconds
HumTempRead();
memTime = millis ();
}
delay(100);

if (((millis() - time1) / 1000.0) >= 1.0) {
dps.calcTrueTemperature();
time1 = millis();
}
dps.getPressure(&Pressure);
Serial.print(" Pressure(Pa):");
Serial.println(Pressure);

long p2;
int pi;
p2 = (Pressure / 133.3224); // Па в мм рт.ст.
pi = trunc(p2); // отбрасывание дробной части числа

lcd.setCursor(0, 0);
lcd.print("P=");
lcd.setCursor(2, 0);
lcd.print(pi); // вывод атм. давл. на LCD
lcd.setCursor(5, 0);
lcd.print("mm");
// delay(3000);
//bzz(100); // раскомментируйте, если хотите слушать сигналы
{
for (int value = 0 ; value <= 255; value += 1) {
analogWrite(REDpin, value);
analogWrite(GREENpin, 255 - value);
analogWrite(BLUEpin, 255);
delay(5);
}

for (int value = 0; value <= 255; value += 1) {
analogWrite(REDpin, 255);
analogWrite(GREENpin, value);
analogWrite(BLUEpin, 255 - value);
delay(5);
}

for (int value = 0; value <= 255; value += 1) {
analogWrite(REDpin, 255 - value);
analogWrite(GREENpin, 255);
analogWrite(BLUEpin, value);
delay(5);
}
}
}

В Каталоге файлов вы можете скачать скетч и библиотеки, которые использовались в проекте.

Импортируйте в среду Arduino IDE библиотеки LiquidCrystal_I2C.zip, bmp085.zip, DS1302.zip и DHT.zip из скачанного архива. В меню пройдите Скетч Подключить библиотеку Добавить.ZIP библиотеку... и в окне выберите zip-архив библиотеки.
Загрузите скетч meteo_P. Замените в скетче адрес LCD1602 на значение, полученное при сканировании шины I2C. Скомпилируйте и запустите скетч.
Если скетч заработал, то откройте монитор порта и просмотрите выдаваемые сообщения. Подберите высоту в операторе dps.init(MODE_STANDARD, 10000 , true); , чтобы получить реальные значения давления.
Настройте часы. Раскомментируйте строку //rtc.setTime(4, 58, 0); и в скобках укажите текущее время (час, минуты и секунды через запятую) и перезагрузите скетч в контроллер. После того, как время установится, снова закомментируйте эту строку и опять перезапустите скетч.
Если вас раздражает иллюминация ночника, то вы можете ее настроить, изменив длительность задержки в циклах for в конце скетча. При delay(2); цикл длится 2-3 секунды, при delay(5); — от 4 до 5 секунд, при delay(30); — до 15-16 секунд. С таким же интервалом будет обновляться информация на индикаторе.
При автономном использовании метеостанции, т.е. без подключения к USB порту компьютера, закомментируйте в скетче строки со словами Serial ..., чтобы отключить вывод информации в монитор COM порта.

PS. В скетче книги и в примерах к библиотеке DHT указана строка определения #define DHTTYPE DHT 11 . Скетч запускается, но вылетает через несколько часов. Часы останавливаются, индикация не меняется. В мониторе порта появляется невнятное сообщение, в котором присутствует ссылка на dht.
В этой строке убрал буквы DHT, т.е. сделал #define DHTTYPE 11 . После этого скетч стал работать стабильно.

Статья обновлена 25.06.2018 г.

Использованные ресурсы
1. Петин В.А. Проекты с использованием контроллера Arduino (Электроника) 2-е издание, Спб. БХВ-Петербург, 2015 464 с.
2. Петин В. А., Биняковский А. А. Практическая энциклопедия Arduino. - М., ДМК Пресс, 2017. - 152 с.
3. http://arduinolearning.com/code/i2c-scanner.php
4. http://arduino.ru/forum/programmirovanie/ds1302lcd1602
5. http://роботехника18.рф/как-подключить-lcd-1602-к-arduino-по-i2c/
6. пример BMP085_test2.ino из библиотеки bmp085.zip
7. http://proginfo.ru/round/
8. http://homes-smart.ru/index.php?id=14&Itemid=149&option=com_content&view=article
9. http://iarduino.ru/lib/datasheet%20bmp180.pdf
10. http://it-donnet.ru/hd44780_dht11_arduino/



«Так, давайте сразу договоримся: вы не собираетесь снимать кино для Голливуда. Даже в Стране чудес утверждается не более пяти процентов от всех сценариев, и только один процент идет затем в производство… Таким образом, вместо всего этого вы собираетесь создать свой собственный Голливуд.»
Эд Гаскель «Снимаем цифровое кино, или Голливуд на дому»

Предисловие

Что, ещё одна погодная станция на Arduino?! Да, ещё одна и, что-то мне подсказывает, не последняя в интернете вещей.


Точно также, как каждый программист обязан написать программу «Hello World!», так и каждый ардуинщик обязан иметь за плечами опыт построения простой или не очень метеостанции.
Уже созданных проектов метеостанций в интернете описано немалое количество, читатель может выбрать любой из них для реализации. Не скрою, я внимательно изучил около десятка подобных проектов и ещё кучу смежных. Поэтому нельзя сказать, что я создал всё с нуля, конечно же я «стоял на плечах гигантов».


Сразу скажу, что в мои планы не входило использование сторонних сервисов для хранения и отображения данных. Хотелось лично пощупать и понять как всё это работает изнутри от начала до конца, от А до Я.


Так что тем, кто хочет быстро склепать нечто из ничего, эта серия статей скорее всего не подойдёт. Проще пойти и купить готовый конструктор с инструкцией по сборке. Профессионалам микроэлектроники тут совсем делать нечего, может быть поржать и вспомнить себя в начале пути.
А вот тем, кто действительно хочет разобраться, я думаю понравится. Возможно материал пригодится в качестве учебного пособия.



Этот проект был реализован в далеком уже 2016 году, но надеюсь еще актуален.

Набор технологий

Мы изучим и будем работать с простыми и сложными вещами:

  • датчиками температуры и влажности типа DHT22, DHT11
  • датчиком барометрического давления типа BMP180
  • WiFi модулем ESP8266
  • радиомодулем типа nRF24 2,4 Ггц
  • семейством Arduino Pro Mini, Arduino Mega
  • солнечной батареей и аккумуляторами
  • языком программирования C/C++
  • языком программирования PHP
  • системой управления базами данных MySQL
  • языком программирования Java и фреймворком Android (создание приложения для Adnroid для отображения погодных данных на смартфоне).

Некоторые темы из перечисленных и яйца выеденного не стоят, а некоторые можно изучать годами. Поэтому сложные вещи мы затронем только в части, непосредственно касающейся данного проекта, так чтобы вы поняли как это всё работает.


Но начнем мы с самого начала правильно. А именно с описания и проектирования будущего устройства «на бумаге» , чтобы в конце концов каждый кирпичик лёг на своё место.

Прототипирование

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


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


Каждый, кто клепает по вечерам свои поделки pet-project для «internet of things», должен отдавать себе отчёт в том, что он создаёт именно прототип, полуфабрикат. До уровня нормального промышленного изделия ему очень далеко. Поэтому не следует поручать нашим любительским поделкам какие-либо ответственные участки жизнеобеспечения и надеяться, что они нас не подведут.


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


Итак, вместо всей этой тягомотины, мы создадим свою собственную игрушку, но не простую. С элементами технического творчества, зачатками программирования и познания (в процессе создания) многих других смежных вещей.


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

Требования

Обычно этот этап пропускают. Решая сделать что-нибудь эдакое прямо сейчас, а потом выясняются мелкие детали, которые ставят весь проект в тупик или вовсе делают его неподъемным. Все наши хотелки необходимо записывать, я использую для этого гугл диск, он доступен с ПК и с мобильного устройства.


Итак, наша метеостанция должна:

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

Датчики используются самые простые и дешевые. Например, забегая наперед скажу, что температуру DHT22 измеряет достаточно точно, а вот с влажностью немного неточен. Но, опять таки повторюсь, это не имеет значения, поскольку перед нами - прототип, и разброс в 5% влажности ни на что важное в нашей жизни не повлияет.


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

Железо. Выбор компонентов

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


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


Замкнутый круг? Но замкнутые круги для того и существуют, чтобы их разрывать.


Выход есть. Можно просто взять и повторить чей-то проект. Я же изучил уже существующие проекты метеостанций и надеюсь сделал шаг вперед.


Итак. Архитектура погодной станции базируется на Arduino. Потому что Arduino имеет небольшой порог вхождения и я уже имел с этим дело. Дальше выбирать уже проще.


Сразу стало ясно, что в составе метеостанции будет удаленый, заоконный датчик и центральный модуль.


Центральный, основной блок будет расположен внутри помещения. Это важно определить на начальном этапе, от этого «пляшут» такие важные характеристики как температурный режим работы и питание.


Удаленный датчик (или датчики) будет без «мозгов», его задача - периодически проводить измерения и передавать данные на центральный домашний блок. Центральный блок принимает данные от всех датчиков, показывает их на экране и отправляет их же в интернет в базу данных. Ну, а там уже много проще, как только данные оказываются в базе с ними можно делать всё что захочешь, даже графики рисовать.


Для сношений с внешним миром интернет был однозначно выбран WiFi модуль ESP8266 практически без альтернативы (прим. возможно сейчас такие альтернативы появились). К Arduino выпускаются Ethernet платы расширения, но совсем не хотелось привязываться к кабелю.



Интересный вопрос состоял в том, чем обеспечивать связь между заоконным датчиком (или датчиками, про требование расширяемости системы помним?) и центром. Радиомаячки на 433 Мгц однозначно не подходят (они не подходят ни для чего вообще).


Воспользоваться опять ESP8266 ?


Минусы такого решения:

    необходим устойчивый WiFi за пределами дома

    дальность связи не будет большой

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

    большее энергопотребление.

    Энергопотребление ESP8266:

    при передаче 120-170 mA

    при приеме 50-56 mA

    в режиме Deep Sleep 10 µA (мкА)

    в выключенном состоянии 5 µA (мкА).

В конце концов для связи удаленных датчиков с основным домашним блоком был выбран чип nRF24L01+ с 2,4 Ггц передатчиком и приемником в одном флаконе, с дополнительной внешней антенной, чтоб уж наверняка «пробить» стены.



Энергопотребление nRF24L01+ 2,4 GHz:

  • при приеме 11 mA
  • при передаче на скорости 2Mbps - 13 mA
  • в режиме standby-I - 26 μA (мкА)
  • в выключенном состоянии 900 nA (нА).

Что у ESP8266, что у nRF24L01+ диапазон рабочих температур подходящий: от -40℃ до +80℃.


Купить nRF24L01+ можно примерно за $1, или сразу с внешней антенной за $3. Купить ESP8266-01 можно примерно за $4. Читайте внимательно описание товара! Иначе купите одну антенну.


Ядро системы вырисовалось. Переходим к самим датчикам.


На улице, как известно, температура может достигать отрицательных значений, поэтому датчик DHT11 не подходит, а вот DHT22 в самый раз.



Характеристики DHT22 / AM2302:

  • питание от 3,3 В до 5 В, рекомендуется 5 В
  • потребление 2.5mA максимум, в момент измерения и передачи данных
  • диапазон измерения влажности 0-100% с погрешностью 2-5%
  • диапазон измерения температуры от -40 до +125°C с погрешностью ±0.5°C
  • запрос на измерение не чаще 0,5 Гц - одного раза в 2 секунды.

Внутри дома, я надеюсь, отрицательных температур не будет, поэтому можно использовать DHT11, тем более, что он у меня уже был.


Характеристики DHT11:

  • питание от 3,3 В до 5 В
  • потребление 2,5 mA максимум, в момент измерения и передачи данных
  • диапазон измерения влажности 20-80% с погрешностью 5%
  • диапазон измерения температуры от 0 до +50°C с погрешностью ±2°C
  • запрос на измерение не чаще 1 Гц - одного раза в секунду.

Купить DHT22 можно примерно за $3. DHT11 стоит дешевле - $1, но он и менее точен.


Теперь возвращаемся опять к Arduino. Какую плату выбрать?


Я тестировал отдельные части системы на Arduino UNO. Т.е. подключал к уно ESP модуль и изучал его, отключал, затем подключал nRF24 и т.д. Для финальной реализации заоконного датчика выбрал Arduino Pro Mini как наиболее близкую к Uno из миниатюрных.



По энергопотреблению Arduino Pro Mini также выглядит неплохо:

  • нет преобразователя USB-TTL, который сам по себе «кушает» много,
  • светодиод подключен через 10к резистор.

Для продвинутого сбережения энергии планировалось:

  • удалить светодиод - индикатор питания на Arduino Pro Mini (я пожалел, не стал портить плату)
  • либо использовать «голую» сборку на микропроцессоре Atmel ATmega328 (не использовал)
  • использовать библиотеку Low Power Library или JeeLib .

Из библиотек выбрал Low Power Library , она проста и содержит только то, что нужно.


Для центрального блока, поскольку к нему планировалось подключить многочисленную периферию, была выбрана плата Arduino Mega. К тому же она полностью совместима с UNO и имеет больше памяти. Забегая наперед скажу, что этот выбор полностью оправдался.


Купить Arduino Mega можно примерно за $8.

Питание и энергопотребление

Теперь про питание и энергопотребление.


Arduino Pro Mini бывают двух видов:

  • на напряжение питания 5В и частоту 16МГц
  • на напряжение питания 3,3В и частоту 8МГц.

Поскольку радио-модуль nRF24L01+ требует для питания 3,3 В, а быстродействие здесь не важно, то покупайте Arduino Pro Mini на 8MHz и 3,3В.


При этом диапазон питающего напряжения Arduino Pro Mini составляет:

  • 3,35-12 В для модели 3,3 В
  • 5-12 В для модели 5 В.

У меня уже была Arduino Pro Mini на 5В, только поэтому я её и использовал. Купить Arduino Pro Mini можно примерно за $4.


Питание центрального блока будет от сети 220 В через небольшой блок питания, дающий на выходе 12В, 450mA, 5W. Типа такого за $5. Там еще есть отдельный вывод на 5В.



А ежели этого не хватит, то можно и помощнее поставить. Другими словами экономить электропитание для центрального блока нет особого смысла. А вот для удаленного беспроводного датчика энергосбережение является важнейшей частью. Но и функциональность не хотелось бы терять.


Поэтому Arduino Pro Mini и радиомодуль nRF24 будут запитываться от связки 4-х Ni-Mh аккумуляторов.


И помните, максимальная емкость современного аккумулятора примерно 2500-2700mAh, всё что больше это либо маркетинговые уловки (Ansmann 2850) либо обман (UltraFire 3500).


Li-Ion аккумуляторы я не использую по нескольким причинам:

  • очень дорогие
  • при снижении температуры окружающего воздуха ниже 0°C происходит снижение мощности литий-ионного аккумулятора до 40-50%
  • те которые дешёвые производятся без защиты и небезопасны (при КЗ или разряде могут взрываться и гореть, см. кучу роликов на ютюбе)
  • стареют, даже если не используются (впрочем это можно сказать обо всех химических элементах), через 2 года Li-Ion батарея теряет около 20% ёмкости.

Для прототипа вполне можно обойтись качественными Ni-MH AA или AAA аккумуляторами. Тем более, что нам не нужны большие токи. Единственный минус Ni-MH аккумуляторов - это их долгая зарядка.

Общая схема метеостанции

Подведем итоги. Вот общая схема как всё работает.



Продолжение следует.

Ноябрь - месяц непонятной погоды: ещё утром светило солнышко, а к обеду за окном всё уже белым бело от снега. Отслеживать всю эту погодную канитель поможет старая добрая погодная станция на Arduino. Вдохновляйтесь нашей подборкой самых крутых самодельных погодных станций, и собирайте себе свою, чтобы всегда быть готовым к сюрпризам природы и не сесть в лужу буквально.

Bluetooth погодная лампа

Управляющее устройство шарится в сети в поисках информации о погоде и отправляет по Bluetooth сигналы на сервомотор в лампе, которой меняет картинки в зависимости от прогноза. Простая и стильная погодная станция , способная украсить ваш интерьер.

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

Для тех, кто любит тучи побольше есть ещё вот такой вариант

Винтажная погодная станция

Любители винтажных вещиц и стимпанкеры со стажем смогут по достоинству оценить погодную станцию в виде старинных часов .

Погода в Twitter

Эта невзрачная на первый взгляд деревянная пирамидка на самом деле высокотехнологичная метеостанция, способная измерять температуру, влажность воздуха, давление, уровень освещённости, уровень CO и отправлять все данные вам в Twitter.

Tempescope

Tempescope - это такая штука, в которой можно принести домой дождь. Или туман. Или даже грозу. И они будут там жить. Теперь даже в окно смотреть не обязательно, чтобы знать, что приготовила вам на сегодня матушка природа.

Погода в кубе

Прогноз погоды можно не только увидеть, но и пощупать. Этот стальной кубик Cryoscope, руководствуясь данными из сети, нагревается или охлаждается до температуры за бортом. Прислоняете такой чуть пониже копчика, и сразу ясно - поддевать сегодня кальсончики или не нужно.

Как большинство работающих людей, занятие собственными проектами отнимает единственно оставшееся свободное время. Поэтому уже давно не творил и «чесались руки» что-либо сделать. Данная возможность появилась как ни странно в университете. За окном сентябрь, 4 курс и надвигающийся курсовой по схемотехнике. Нам сказали, что курсовые можно будет делать в двух вариациях: бумажном и «железе».

На протяжении 5 лет бумажный курсовой в нашем университете делался по принципу «возьми старые и собери их воедино». Такой подход меня не устраивал своей рутинностью, поэтому я сразу же выбрал курсовой в «железе». В качестве сердца курсовых был предложен микроконтроллер Arduino ввиду своей легкообучаемости. После определения с типом курсового оставался ещё один вопрос: а что именно бы сделать. Так как опыта в программировании микроконтроллеров не было, то сразу же открыл гугл и начал изучать существующие проекты. Проектов много, некоторые из них довольно простые, некоторые гениальны (3D сканер, например), но подавляющее большинство не имело практического применения. А мне хотелось именно того, что не валялось бы потом на полке и не собирало там пыль. После получасового экскурса в мир Arduino, меня заинтересовало тема домашних метеостанций, да и проекты показались не очень сложными в реализации (что в основном и подкупило новичка).

Вот так была выбрана тема для курсового и со временем проблем вроде как не намечалось.

Выбор компонентов

Просматривая разные проекты я понимал, что мне вполне достаточно будет Nano или даже Pro Mini, но всё-таки выбрал Arduino Uno в надежде, что программирование для Arduino мне понравится и в дальнейшем реализую ещё какие-нибудь проекты. Паяльник до этого в руках ни разу не держал, поэтому для более легкой разработки решил также приобрести Sensor Shield v4.

Подробнее

Плата способствует быстрому подключению датчиков, модулей, серво моторов, интерфейсов Serial и I2C, а также выводит все порты контроллера формфактора Duemilanova/Uno(также может быть подключена и в серию мега, но с ограничениями и вытекающими последствиями). Поддерживает другие шилды поверх себя.


В качестве источников для метеорологических данных выбрал следующие датчики:


С датчиками определился. Но что делать с данными, поступающими от датчиков. Решил выводить на дисплей. Картинку хотелось цветную, поэтому монохромные решения отбросил сразу. После нескольких минут поиска был выбран TFT дисплей ST7735 размером 1,8 дюймов.

Подробнее

Поскольку дисплей использует 4-проводной SPI протокод для связи и имеет свой собственный пикселе-адресуемый буфер кадра, он может использоваться с любыми видами микроконтроллеров. 1.8-дюймовый дисплей имеет 128x160 цветных пикселя. Также имеется слот для карты памяти microSD, следовательно, можно легко загружать полноцветные растровые изображения из FAT16 / FAT32 файловой системы microSD карты.

Характеристики:

  • Диагональ дисплея - 1.8 дюймов, разрешение 128x160 пикселей, 18-битный цвет (262 144 цвета)
  • Контроллер со встроенной пиксельной адресацией буфера видеопамяти
  • Встроенный слот для microSD - использует более 2 цифровых линий
  • Совместим с 3.3 и 5V
  • Габариты: 34 мм х 56 мм х 6,5 м


Программирование контроллера Arduino

После того, как определились с компонентами для метеостанции, начнём программирование контроллера. Для прошивки Arduino использовалась среда разработки Arduino IDE. Также использовал библиотеки от Adafruit.

Перед тем, как перейти к скетчу, рассмотрим функционал:

  • Показания снимаются с датчиков каждые 10 секунд и обновляются на экране только те показатели, которые были изменены по сравнению с прошлым измерением
  • Реализована передача данных по COM порту

Скетч

#include // library for communication with I2C devices #include // Core library for all sensors #include // library for BMP180 #include // Core graphics library #include // Hardware-specific library #include // library for communication with SPI devices #include "dht.h" // library for DHT #define DHT22_PIN 2 // connect data pin of DHT22 to 2 digital pin #define TFT_CS 10 // connect CS pin of TFT to 10 digital pin #define TFT_RST 9 // connect RST pin of TFT to 9 digital pin // you can also connect this to the Arduino reset // in which case, set this #define pin to 0! #define TFT_DC 8 // connect DC pin of TFT to 8 digital pin Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); //initialize TFT #define TFT_SCLK 13 // connect SCLK pin of TFT to 13 digital pin #define TFT_MOSI 11 // connect MOSI pin of TFT to 11 digital pin dht DHT; Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(10085); //initialize BMP180 int bmpFlag = 0; struct { uint32_t total; uint32_t ok; uint32_t crc_error; uint32_t time_out; uint32_t connect; uint32_t ack_l; uint32_t ack_h; uint32_t unknown; } stat = { 0,0,0,0,0,0,0,0}; // struct for dht status void setup(void) { Serial.begin(9600); Serial.println("Meteo Test"); Serial.println(""); if(!bmp.begin()) // check connection for BMP180 { Serial.print("Ooops, no BMP180 detected ... Check your wiring or I2C ADDR!"); bmpFlag = 1; } tft.initR(INITR_BLACKTAB); // Initialize TFT and fill with black color tft.fillScreen(ST7735_BLACK); tft.setRotation(tft.getRotation() + 1); tft.setTextSize(1.5); delay(500); // delay in order to ensure that TFT was initialized } // last measured data float oldTemperature = 0, oldAltitude = 0, oldPressure = 0, oldDHTHumidity = 0, oldDHTTemperature; bool wasUpdate = false; void loop(void) { if(Serial.available() > 0) // we have data is Serial port { Serial.read(); // read byte from serial port and send last measured data printValue("Pressure", oldPressure, " hPa", false); printValue("Temperature", oldTemperature, " C", false); printValue("Altitude", oldAltitude, " m", false); printValue("Humidity", oldDHTHumidity, "%", false); printValue("DHT_temperature", oldDHTTemperature, " C", false); Serial.println("END_TRANSMISSION"); } sensors_event_t event; float temperature, altitude; if(bmpFlag == 0){ bmp.getEvent(&event); // get data from BMP180 if (event.pressure) { bmp.getTemperature(&temperature); float seaLevelPressure = SENSORS_PRESSURE_SEALEVELHPA; altitude = bmp.pressureToAltitude(seaLevelPressure, event.pressure, temperature); } else { Serial.println("Sensor error"); } } uint32_t start = micros(); int chk = DHT.read22(DHT22_PIN);// get data from DHT22 uint32_t stop = micros(); stat.total++; switch (chk) // check status of DHT22 { case DHTLIB_OK: stat.ok++; break; case DHTLIB_ERROR_CHECKSUM: stat.crc_error++; Serial.print("Checksum error,\t"); break; case DHTLIB_ERROR_TIMEOUT: stat.time_out++; Serial.print("Time out error,\t"); break; case DHTLIB_ERROR_CONNECT: stat.connect++; Serial.print("Connect error,\t"); break; case DHTLIB_ERROR_ACK_L: stat.ack_l++; Serial.print("Ack Low error,\t"); break; case DHTLIB_ERROR_ACK_H: stat.ack_h++; Serial.print("Ack High error,\t"); break; default: stat.unknown++; Serial.print("Unknown error,\t"); break; } if(bmpFlag != 0 || !event.pressure) // update data { tft.fillRect(0, 30, 160, 6, ST7735_BLACK); tft.setCursor(0, 30); tft.setTextColor(ST7735_RED); printValue("ERROR BMP INITIALIZATION", 0, "", true); } else { if(event.pressure != oldPressure) { tft.fillRect(0, 30, 160, 7, ST7735_BLACK); tft.setCursor(0, 30); tft.setTextColor(ST7735_RED); printValue("Pressure", event.pressure, " hPa", true); oldPressure = event.pressure; wasUpdate = true; } if(temperature != oldTemperature) { tft.fillRect(0, 38, 160, 7, ST7735_BLACK); tft.setCursor(0, 38); tft.setTextColor(ST7735_WHITE); printValue("Temperature", temperature, " C", true); oldTemperature = temperature; wasUpdate = true; } if(altitude != oldAltitude) { tft.fillRect(0, 46, 160, 7, ST7735_BLACK); tft.setCursor(0, 46); tft.setTextColor(ST7735_BLUE); printValue("Altitude", altitude, " m", true); oldAltitude = altitude; wasUpdate = true; } } if(DHT.humidity != oldDHTHumidity) { tft.fillRect(0, 54, 160, 7, ST7735_BLACK); tft.setCursor(0, 54); tft.setTextColor(ST7735_GREEN); printValue("Humidity", DHT.humidity, "%", true); oldDHTHumidity = DHT.humidity; wasUpdate = true; } if(DHT.temperature != oldDHTTemperature) { tft.fillRect(0, 80, 160, 7, ST7735_BLACK); tft.setCursor(0, 80); tft.setTextColor(ST7735_YELLOW); printValue("DHT_temperature", DHT.temperature, " C", true); oldDHTTemperature = DHT.temperature; wasUpdate = true; } if(wasUpdate) { Serial.println("END_TRANSMISSION"); } wasUpdate = false; delay(10000); } void printValue(char* title, double value, char* measure, bool tftPrint) { if(tftPrint) // print data to TFT { tft.print(title); tft.print(": "); tft.print(value); tft.println(measure); } Serial.print(title); // send data to Serial port Serial.print(": "); Serial.print(value); Serial.println(measure); }

Самое время собрать корпус

Главным условием курсового было рабочий прототип в презентабельном виде. Поэтому пришлось купить корпус и, вооружившись напильником, любым способом засунуть метеостанцию в корпус.

В местном магазине радиоэлектроники был приобретён корпус.

Корпус

(На фото корпус немного не такой. У меня крышка прозрачная)



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

Корпус с отверстиями для датчиков и питания



Так как пришлось припаивать ножки к 2 датчикам и у одного из них я спалил дорожку, то решил не испытывать судьбу и не припаивать провода к датчикам (потренируюсь на чём-нибудь другом), а для того чтобы соединение было более-менее надёжным, решил перемотать изолентой.

Система перед "запихиванием" в корпус



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

Чудо-юда рыба-кит



Прикручиваем крышку, подключаем питание и ждём.

Законченная метеостанция в корпусе



После вывода результатов на экран, выявляем неприятную ошибку измерения влажности: DHT22 усердно выдаёт цифру 99,90% (крайне редко бывает 1,00%). Начинаем разбираться в чём проблема. Первое, что делаем - смотрим вывод значений в COM порт. Вроде всё нормально. После нексольких перезаливок, разборок и сборок корпуса в голову приходит мысль поискать ответ в гугле. Как и ожидалось русский гугл ничего дельного не сказал. Окей. Начинаем искать на английском и на одном из форумов натыкаемся на ребят с похожей проблемой. Первые четыре страницы обсуждения ничего дельного не дают, а на пятой странице находим ответ на наш вопрос:
Humidity sensors can easily be affected by the wrong gasses or very long exposure to high humidity IIRC. In the datasheet there is a procedure how to «reset» the sensor, you could give it a try.

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

Послесловие

Курсовой был сдан. Метеостанция отложена на неопределенное время до закрытия всех хвостов в университете. Однако, к метеостанции пришлось вернутся раньше, чем я думал. Так сложилось, что в середине ноября я поменял рабочее место и в новой команде я познакомился с людьми, которые интересуются платформой Arduino и им подобными. Поэтому мой интерес к данной платформе не успев остыть, разгорелся снова. Я достал свою метеостанцию, подключил к компьютеру и вспомнил, что я реализовывал передачу данных с Arduino по COM порту. И тут мне пришла в голову идея, написать программу, принимающую данные через COM порт от Arduino и передавать эти данные на народный мониторинг , но это уже совсем другая история.

Также хотелось бы иметь беспроводные датчики и всё-таки реализовать метеостанцию на Arduino Pro Mini. Поэтому мною были заказаны 4 Arduino Pro Mini с питанием 3,3В, 4 радиомодуля nRF24L01+ и ещё кое-какие дополнительные датчики, о чём я также постараюсь рассказать в следующий раз. А пока я жду посылки, в планах реализовать подключение часов реального времени для возможности сохранения времени обновления данных и самих данных на microSD карту при условии отсутствия соединения с клиентом по COM порту.

Вы можете помочь и перевести немного средств на развитие сайта



Загружать прошивку желательно до подключения компонентов, чтобы убедиться в том, что плата рабочая. После сборки можно прошить ещё раз, плата должна спокойно прошиться. В проектах с мощными потребителями в цепи питания платы 5V (адресная светодиодная лента, сервоприводы, моторы и проч.) необходимо подать на схему внешнее питание 5V перед подключением Arduino к компьютеру, потому что USB не обеспечит нужный ток, если например лента его потребует. Это может привести к выгоранию защитного диода на плате Arduino. Гайд по скачиванию и загрузке прошивки можно найти под спойлером на следующей строчке.

Содержимое папок в архиве

  • libraries – библиотеки проекта. Заменить имеющиеся версии
  • firmware – прошивки для Arduino
  • schemes – схемы подключения компонентов

Дополнительно

  • Как показал эксперимент, снаружи корпуса датчик температуры показывает на 0.5 градуса меньше, чем внутри! Нужно более удачно компоновать электронику, отводить и экранировать тепло от греющихся элементов…

  • Если дисплей показывает слишком тускло/на белом фоне
    На плате драйвера дисплея (к которой подключаются провода) есть крутилка контрастности, с её помощью можно подстроить контраст на нужный. Также контрастность зависит от угла взгляда на дисплей (это же LCD) и можно настроить дисплей на чёткое отображение даже под углом “дисплей на уровне пупка, смотрим сверху”. А ещё контрастность сильно зависит от питания: от 5V дисплей показывает максимально чётко и ярко, тогда как при питании от USB через Arduino напряжение будет около 4.5V (часть падает на защитном диоде по линии USB), и дисплей показывает уже не так ярко. Вывод настраивайте крутилкой при внешнем питании от 5V!

  • Если датчик CO2 работает некорректно (инфа от Евгения Иванова)
    Ну там в папке библиотеки сенсора в examples есть скетчи для калибровки. также ее можно запустить втупую замкнув на землю разъем “HD” на 7+ секунд.
    Само собой вот прямо на улице на морозе этим заниматься не обязательно… можно просто в бутылку набрать свежего воздуха с датчиком внутри и запечатать. калибровка проводится минимум 20 минут..
    По-умолчанию датчик поставляется с включенной автокалибровкой, которая происходит каждый день, и если датчик используется в невентелируемом помещении, то эта калибровка быстро уводит значения от нормы за горизонт, потому ее нужно обязательно отключать.
    Документация .

  • Автокалибровка датчика CO2 отключена в скетче!

  • Если у вас не работает датчик BME280 , скорее всего у него отличается адрес. В проекте используется библиотека Adafruit_BME280, у которой нет отдельной функции смены адреса, поэтому адрес задаётся вручную в файле библиотеки Adafruit_BME280.h почти в самом начале файла (лежит в папке Adafruit_BME280 в вашей папке библиотек, вы должны были её туда установить ), у моего модуля был адрес 0x76. Как узнать адрес своего модуля BME280? Есть специальный скетч, называется i2c scanner. Его можно нагуглить, можно . Прошиваете данный скетч, открываете порт и получаете список адресов подключенных к шине i2c устройств. Чтобы остальные модули вам не мешали – можно их отключить и оставить только BME280. Полученный адрес указываем в библиотеке, сохраняем файл и загружаем прошивку метео-часов. Всё!

  • Если отстают часы , проблема скорее всего в питании схемы. Если при смене блока питания на более качественный проблема не уходит, повесьте конденсатор по питанию RTC модуля (прям на плату на VCC и GND паять): обязательно керамический, 0.1-1 мкФ (маркировка 103 или 104, смотрите таблицу маркировок). Также можно поставить электролит (6.3V, 47-100 мкФ)

Настройки в прошивке

#define RESET_CLOCK 0 // сброс часов на время загрузки прошивки (для модуля с несъёмной батарейкой). Не забудь поставить 0 и прошить ещё раз! #define SENS_TIME 30000 // время обновления показаний сенсоров на экране, миллисекунд #define LED_MODE 0 // тип RGB светодиода: 0 - главный катод, 1 - главный анод #define LED_BRIGHT 255 // яркость светодиода СО2 (0 - 255) #define BLUE_YELLOW 1 // жёлтый цвет вместо синего (1 да, 0 нет) но из за особенностей подключения жёлтый не такой яркий #define DISP_MODE 1 // в правом верхнем углу отображать: 0 - год, 1 - день недели, 2 - секунды #define WEEK_LANG 1 // язык дня недели: 0 - английский, 1 - русский (транслит) #define DEBUG 0 // вывод на дисплей лог инициализации датчиков при запуске #define PRESSURE 1 // 0 - график давления, 1 - график прогноза дождя (вместо давления). Не забудь поправить пределы гроафика // пределы отображения для графиков #define TEMP_MIN 15 #define TEMP_MAX 35 #define HUM_MIN 0 #define HUM_MAX 100 #define PRESS_MIN -100 #define PRESS_MAX 100 #define CO2_MIN 300 #define CO2_MAX 2000