Беспроводная метеостанция. BMP085 Barometric Pressure Sensor Module for arduino (или как сделать метеостанцию своими руками) Комнатная метеостанция на arduino pro mini


За основу взят проект метеостанции из книги В. Петина "Проекты с использованием контроллера 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. Вдохновляйтесь нашей подборкой самых крутых самодельных погодных станций, и собирайте себе свою, чтобы всегда быть готовым к сюрпризам природы и не сесть в лужу буквально.

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

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

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

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

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

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

Погода в Twitter

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

Tempescope

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

Погода в кубе

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

Наблюдение за погодой - весьма увлекательное занятие. Я решил построить свою погодную станцию на базе популярного .

Прототип метеостанции выглядит так:

Функции моей метеостанции:

  • измерение и отображение комнатной и наружной температур;
  • отображение текущего времени (часы и минуты);
  • отображение текущих фазы Луны и лунного дня;
  • передача результатов измерений на компьютер через последовательное соединение;
  • передача результатов измерений по протоколу MQTT с помощью приложения на компьютере.


Hex
-файл
прошивки для (версия от 9 мая 2018 года) - .
Как прошить hex -файл в плату Arduino , я описал .

Микроконтроллер Arduino Nano 3.0

"Сердцем" моей метеостанции является микроконтроллер eBay ):

Для управления индикацией и опросом датчиков я использую таймер 1 Arduino , вызывающий прерывания с частотой 200 Гц (период - 5 мс).

Индикатор

Для отображения измеряемых показаний датчиков и текущего времени я подключил к Arduino четырехразрядный светодиодный индикатор Foryard FYQ-5643BH с общими анодами (аноды одинаковых сегментов всех разрядов объединены).
Индикатор содежит четыре семисегментных разряда и две разделительные (часовые) точки:

Аноды индикатора подключены через токограничивающие резисторы к выводам Arduino :

разряд 1 2 3 4
вывод A3 A2 D3 D9

Катоды сегментов подключены к выводам Arduino :

сегмент a b c d e f g p
вывод D7 D12 D4 D5 D6 D11 D8 D13

Сегмент индикатора светится, если на аноде соответствующего разряда высокий потенциал (1), а на катоде - низкий (0).

Я использую динамическую индикацию для отображения информации на индикаторе - в каждый момент времени активен только один разряд. Активные разряды чередуются с частотой 200 Гц (период отображения 5 мс). При этом для глаз мерцание сегментов незаметно.

Датчик температуры DS18x20

Для возможности удаленного измерения температуры я подключил датчик , который обеспечивает измерение наружной температуры в широких пределах. Датчик подключается к шине 1-Wire и имеет три вывода - питание (VCC ), данные (DAT ), земля (GND ):

вывод датчика VCC DAT GND
вывод Arduino 5V A1 GND

Между выводами VCC и DAT я включил подтягивающий резистор сопротивлением 4,7 кОм.

Для перевода между градусами Цельсия и Фаренгейта можно использовать такую табличку:

Я разместил датчик за окном дома в пластиковом корпусе от шариковой ручки:

\

В профессиональных метеостанциях для защиты термометра от прямых солнечных лучей и обеспечения циркуляции воздуха используется экран Стивенсона (англ. Stevenson screen ):

Датчик давления и температуры BMP280

Для измерения атмосферного давления традиционно используют ртутные барометры и барометры-анероиды.

В ртутном барометре атмосферное давление уравновешивается весом столба ртути, высота которого и ипользуется для измерения давления:

В барометре-анероиде используется сжатие и растяжение коробки под действием атмосферного давления:

Для измерения атмосферного давления и комнатной температуры в своей домашней метеостанции я использую датчик - маленький SMD -датчик размером 2 x 2,5 мм, основанный на пьезорезистивной технологии:

Платка с датчиком приобретена на торговой площадке eBay :

Датчик подключается к шине I2C (контакт данных - SDA/SDI , контакт синхронизации - SCL/SCK ):

вывод датчика VCC GND SDI SCK
вывод Arduino 3V3 GND A4 A5

Adafruit - файлы Adafruit_Sensor.h , Adafruit_BMP280.h , Adafruit_BMP280.cpp .

Единицы измерения атмосферного давления

Датчик через функцию readPressure выдает значение атмосферного давления в паскалях. Основной единицей измерения атмосферного давления служит гектопаскаль (гПа) (1 гПа = 100 Па), аналогом которого является внесистемная единица "миллибар " (мбар) (1 мбар = 100Па = 1гПа). Для перевода между часто используемой внесистемной единицей измерения давления "миллиметр ртутного столба " (мм рт. ст.) и гектопаскалями используются соотношения:
1гПа = 0,75006 мм рт. ст. ≈ 3/4 мм рт.ст.; 1 мм рт.ст. =1,3332 гПа ≈ 4/3 гПа.

Зависимость атмосферного давления от высоты над уровнем моря

Атмосферное давление может быть представлено как в абсолютной, так и в относительной форме.
Абсолютное давление QFE (англ. absolute pressure ) – это актуальное атмосферное давление, не учитывающее поправку над уровнем моря.
Атмосферное давление уменьшается примерно на 1 гПа при повышении высоты на 1 м:

Барометрическая формула позволяет определить коррекцию показаний барометра для получения относительного давления (в мм рт. ст.):
$\Delta P = 760 \cdot (1 - {1 \over {10^ { {0,0081350 \cdot H} \over {T + 0,00178308 \cdot H} }}})$ ,
где $T$ - средняя температура воздуха по шкале Ранкина, °Ra , $H$ - высота над уровнем моря, футы.
Перевод градусов Цельсия в градусы Ранкина:
$^{\circ}Ra = {^{\circ}C \cdot 1,8} + 491,67$
Барометрическая формула используется при барометрическом нивелировании - определении высот (с погрешностью 0,1 - 0,5 %). В формуле не учитывается влажность воздуха и изменение ускорения свободного падения с высотой. Для небольших перепадов высоты эту экспоненциальную зависимость можно с достаточной точностью аппроксимировать линейной зависимостью.
Относительное давление QNH (англ. relative pressure , Q-code Nautical Height ) – это атмосферное давление, учитывающее поправку к среднему уровню моря (англ. Mean Sea Level, MSL ) (для ISA и температуры 15 градусов Цельсия), и первоначально выставляется с учётом высоты, на которой находится метеостанция. Его можно узнать из данных метеослужбы, показаний откалиброванных приборов в публичных местах, аэропорту (из сводок METAR ), из Интернета.
Например, для расположенного рядом аэропорта Гомель (UMGG ) я могу посмотреть сводку фактической погоды METAR на ru.allmetsat.com/metar-taf/russia.php?icao=UMGG :
UMGG 191800Z 16003MPS CAVOK M06/M15 Q1014 R28/CLRD// NOSIG ,
где Q1014 - давление QNH на аэродроме равно 1014 гПа.
Историю сводок METAR можно получить на aviationwxchartsarchive.com/product/metar .
За нормальное относительное давление воздуха QNH принимается давление 760 мм рт. ст. или 1013,25 гПа (при температуре 0ºС, под широтой 45º Северного или Южного полушария).
Я выставил для барометра-анероида давление QNH с помощью винта настройки чуткости:

Прогноз погоды

Анализ изменения давления позволяет строить прогноз погоды, причем его точность тем выше, чем более резко меняется давление. Например, старое эмпирическое правило мореплавателей гласит - падение давления на 10 гПа (7,5 мм рт. ст.) за период 8 часов говорит о приближении сильного ветра.

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

За направление ветра в метеорологии принимается направление, откуда дует ветер:

Это направление сводится к восьми румбам.

Для предсказания погоды на основе атмосферного давления и направления ветра часто используется алгоритм Zambretti .

Датчик влажности

Для определения относительной влажности воздуха я использую модуль DHT11 (приобретен на торговой площадке eBay ):

Датчик влажности DHT11 имеет три вывода - питание (+ ), данные (out ), земля (- ):

вывод датчика + out -
вывод Arduino 5V D10 GND

Для работы с датчиком я использую библиотеку от Adafruit - файлы DHT.h , DHT.cpp .

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

Для человека оптимальный интервал влажности воздуха - 40 ... 60 %.

Часы реального времени

В качестве часов реального времени я применил модуль RTC DS1302 (платка с часиками приобретена на торговой площадке eBay ):

Модуль DS1302 подключается к шине 3-Wire . Для использования этого модуля совместно с Arduino разработана библиотека iarduino_RTC (от iarduino.ru ).

Плата с модулем DS1302 имеет пять выводов, которые я соединил с выводами платы Arduino Nano :

вывод RTC VCC GND RST CLK DAT
вывод Arduino 5V GND D2 D1 D0

Для сохранения верных показаний часов при отключенном питании в гнездо на плате я вставил батарейку CR2032 .

Точность моего часового модуля оказалась не слишком высокой - часы спешат примерно на одну минуту за четверо суток. Поэтому я сделал сброс минут на "ноль" и часа на ближайший при удержании кнопки, подключенной к выводу A0 Arduino, после включения питания метеостанции. После инициализации вывод A0 используется для передачи данных через последовательное соединение.

Передача данных на компьютер и работа по протоколу MQTT

Для передачи данных через последовательное соединение к Arduino подключается USB -UART преобразователь:

Вывод Arduino используется для передачи данных в формате 8N1 (8 бит данных, без бита четности, 1 стоп-бит) со скоростью 9600 бит/с. Данные передаются пакетами, причем длина пакета - 4 символа. Передача данных осуществляется в "bit-bang " режиме, без использования аппаратного последовательного порта Arduino .

Формат передаваемых данных:

Параметр 1-й байт 2-й байт 3-й байт 4-й байт
наружная температура o пробел либо минус десятки градусов либо пробел единицы градусов
комнатная температура i пробел либо минус десятки градусов либо пробел единицы градусов
атмосферное давление p сотни мм р. ст. десятки мм рт.ст. единицы мм рт. с.
относительная влажность h пробел десятки процентов либо пробел единицы процентов
текущее время десятки часов единицы часов десятки минут единицы минут

MQTT

Golang приложение - клиент протокола MQTT , отправляющую принятую от метеостанции информации на сервер (MQTT -брокер) :

Сервис позволяет создать акаунт с бесплатным тарифным планом "" (ограничения: 10 соединений, 10 Кб/с):

Для мониторинга показаний метеостанции при этом можно использовать Android -приложение :

Питание

Для питания метеостанции я использую зарядное устройство от старого мобильного телефона Motorola , выдающее напряжение 5 В с током до 0,55 А и подключаемое к контактам 5V (+) и GND (-):

Также можно использовать для питания батарейку напряжением 9 В, подключаемую к контактам VIN (+) и GND (-).

Эксплуатация метеостанции

При запуске происходит инициализация и проверка датчиков.

При отсутствии датчика DS18x20 выдается ошибка "E1", при отсутствии датчика - ошибка "E3".

Затем запускается рабочий цикл метеостанции:

  • измерение и отображение наружной температуры;
  • измерение и отображение комнатной температуры;
  • измерение и отображение атмосферного давления и тренда его изменения;
  • измерение и отображение относительной влажности воздуха;
  • отображение текущего времени;
  • отображение фазы Луны и лунного дня.


Видео работы моей метеостанции доступно на моем -канале: https://youtu.be/vVLbirO-FVU

Отображение температуры

При измерении температуры индицируется две цифры температуры и для отрицательной температуры знак "минус" (с символом градуса в крайнем правом разряде);
для наружной температуры знак градуса отображается вверху:


для комнатной температуры - внизу:

Отображение давления

При измерении давления индицируются три цифры давления в мм ртутного столба (с символом "P " в крайнем правом разряде):

Если давление резко упало, то вместо символа "P " в крайнем правом разряде отображается символ "L ", если резко выросло - то "H ". Критерий резкости изменения - 8 мм рт. ст. за 8 часов:

Так как моя метеостанция отображает абсолютное давление (QFE ), то показания оказываются несколько заниженными по сравнению со сведениями в сводке METAR (в которой приводится QNH ) (14 UTC 28 марта 2018 года):

Отношение давлений (по сведениями ATIS ) составило ${1015 \over 998} = 1,017$. Возвышение аэропорта Гомель (код ИКАО UMGG ) над уровнем моря составляет 143,6 м. Температура по данным ATIS составляла 1 °C .

Показания моей метеостанции практически совпали с абсолютным давлением QFE по сведениями ATIS !

Максимальное/минимальное давления (QFE ), зарегистрированные моей метеостанцией за все время наблюдений:

Отображение относительной влажности воздуха

Относительная влажность воздуха отображается в процентах (в двух правых разрядах отображается символ процента):

Отображение текущего времени

Текущее время отображается на индикаторе в формате "ЧЧ:ММ", причем разделительное двоеточие мигает раз в секунду:

Отображение фаз Луны и лунного дня

Первые два разряда индикатора отображают текущую лунную фазу, а следующие два - текущий лунный день:

У Луны выделяются восемь фаз (приведены английские и русские (синим цветом - неточные) названия):

На индикаторе фазы отображаются пиктограммами:

фаза пиктограмма
растущий серп (полумесяц)
убывающий серп (полумесяц)

Передача данных на компьютер

Если соединить метеостанцию с USB -UART преобразователем (например, на базе микросхемы CP2102 ), подключенным к USB -порту компьютера, то можно с помощью терминальной программы наблюдать передаваемые метеостанцией данные:

Я разработал на языке программирования golang программу, ведущую журнал метеонаблюдений и отправляющую данные в сервис , и их можно просматривать на Android -смартфоне с помощью приложения :

По данным журнала метеонаблюдений можно, например, строить график изменения атмосферного давления:
пример графика с заметным минимумом давления


пример графика с незначительным ростом давления

Планируемые доработки:

  • добавление датчиков направления и скорости ветра

В метеостанциях для измерения скорости ветра используется трехчашечный анемометр (1), а для определения направления ветра - флюгер (2):

Также для измерения скорости ветра используются термоанемометры с нитью накала (англ. hot wire anemometer ). В качестве нагреваемой проволоки можно использовать вольфрамовую нить накала от лампочки с разбитым стеклом. В промышленно выпускаемых термоанемометрах датчик обычно располагается на телескопической трубке:

Принцип действия этого прибора заключается в том, что тепло отводится от нагревательного элемента вследствие конвекции воздушным потоком - ветром. При этом сопротивление нити накала определяется температурой нити. Закон изменения сопротивления нити накала $R_T$ от температуры $T$ имеет вид:
$R_T = R_0 \cdot (1 + {\alpha \cdot (T - T_0)})$ ,
где $R_0$ - сопротивление нити при температуре $T_0$, $\alpha$ - температурный коэффициент сопротивления (для вольфрама $\alpha = 4,5\cdot{10^{-3} {^{\circ}{C^{-1}}}}$).

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

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

В свободное время, и на этот раз написал инструкцию по изготовления небольшой метеостанции. Она будет выполнять функцию часов с датой и показывать температуры внутри и снаружи помещения. Как основной контролер будем использовать Arduino UNO, но подойдет и другая плата с Atmega328p на борту. Для отображения используем графический экран WG12864B. Также подключим два датчика температуры ds18b20. Один внутри помещения, второй вынесем наружу. Начнем.

В процессе изготовления самоделки нам понадобится:

Arduino UNO (Или любая другая Arduino совместимая плата)
- WG12864B графический экран
- ds18b20 датчик температуры, 2шт
- Блок питания 6 – 12 В
- Резисторы 4.7 Ком 0.25 Вт, 2 шт.
- Резисторы 100 ом 0.25 Вт
- Батарейный отсек для 4 батареек типа ААА «мизинчиковых»
- Коробка от картриджа приставки SEGA
- Изолента
- Соединительные провода
- Монтажная плата
- Кнопки
- Канцелярский нож
- Паяльник
- Припой, канифоль
- Двусторонний скотч

Шаг 1 Подготовка WG12864B3.
Тех, кто не работал до этого с экранами, может напугать большое количество модификаций, с виду одинаковых, экранов. Немного поясню. Большинство экранов такого типа работают на микросхемах ks0107/ks0108. Все экраны можно раздлить на 4 типа:

Вариант A: HDM64GS12L-4, Crystalfontz CFAG12864B, Sparkfun LCD-00710CM, NKC Electronics LCD-0022, WinStar WG12864B-TML-T

Вариант B: HDM64GS12L-5, Lumex LCM-S12864GSF, Futurlec BLUE128X64LCD, AZ Displays AGM1264F, Displaytech 64128A BC, Adafruit GLCD, DataVision DG12864-88, Topway LM12864LDW, Digitron SG12864J4, QY-12864F, TM12864L-2, 12864J-1

Вариант C: Shenzhen Jinghua Displays Co Ltd. JM12864

Вариант D: Wintek- Cascades WD-G1906G, Wintek - GEN/WD-G1906G/KS0108B, Wintek/WD-G1906G/S6B0108A, TECDIS/Y19061/HD61202, Varitronix/MGLS19264/HD61202

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

Вкратце характеристики:

В интернете много разных схем подключения, и все вроде как рабочие. Все дело в том, что существуют не только разные экраны, но и два способа их подключения: последовательный и параллельный. При использовании подключения по последовательному порту – нам понадобится всего 3 выхода микроконтроллера. При параллельном минимум 13. Выбор в данном случаем очевиден, у Arduino и так не много выводов. Для параллельного соединения схема подключения следующая:

Для последовательного подключения, которое будем использовать мы, схема следующая:

WG12864B – Arduino UNO 1 (GND) - GND 2 (VCC) - +5V 4 (RS) – 10 5 (R/W) – 11 6 (E) – 13 15 (PSB) – GND 19 (BLA) – через резистор 100 Ом - +5V 20 (BLK) – GND

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

Резистор в 100 Ом нужен, чтобы напряжением в 5 вольт, случайно не сжечь диоды подсветки.

Шаг 2 Изготовление корпуса.
Для корпуса возьмем коробку от картриджа приставки Sega. Если не найдете под руками эту коробку, можно использовать и другой корпус. Главное, чтобы в него поместился экран и Arduino.

Срезаем прозрачную пленку, сверху коробки, так чтобы не оставалось кусков:

Затем, используя канцелярский нож, вырезаем окошко размером 37х69, для экрана.

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

Снимаем защитную бумажку со скотча, и приклеиваем на него наш экран:

С внешней стороны должно выглядеть так:

Ниже экран, также на двусторонний скотч, крепим Arduino, сделав предварительно вырезы под USB- порт и гнездо питания:

Вырезы под гнезда Arduino надо делать с двух сторон коробки, так чтобы она могла свободно закрываться:

Шаг 3 Датчики температуры.
Мы будем использовать цифровые датчики температуры DS18B20. Используя их мы получаем большую точность измерения, погрешность не более 0,5 °C, в большом диапазоне температур -55 … + 125 °C. Кроме этого, датчик цифровой и все вычисления выполняет сам, а Arduino просто получает готовые показания. При подключении этого датчика не забывайте о подтягивающем резисторе, номиналом 4.7 КОм, между контактами DQ и VDD. Также возможно несколько вариантов подключения. С внешним питание, на мой взгляд лучший вариант, его и будем использовать:

При любом варианте питания, датчики подключаются параллельно:

Датчик замера температуры внутри помещения разместим на маленькой плате вместе с двумя кнопками, которые мы будем использовать для установки времени и даты часов:

Общий провод от обоих кнопок подключаем к GND, провод от первой кнопки подключаем к A0, от второй к A1.
Крепим на двусторонний скотч рядом с Arduino:

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

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

Провод от шины данных DQ обоих датчиков подключаем к pin 5 Arduino.
Vdd - +5 Arduino.
GND – GND Arduino.

Шаг 4 Питание.
Для питания можно использовать блок питания напряжением от 6 до 12 вольт. На конце провода блика питания следует напаять штекер, подходящий к гнезду питания Arduino:

Или можете поместить в корпус батарейный отсек для четырех батареек типа «ААА», «мизинчиковые». И подключить плюсовой провод от отсека к Vin Arduino, а минус к GND.

Шаг 5 Подготовка среды программировании.
Для начала необходимо скачать и установить Arduino IDE с официального сайта

А также добавить в две библиотеки, необходимые для скетча. OneWire – необходима для связи с датчиками ds18b20:

U8glib – используется для вывода информации на экран:

Скачиваем библиотеки. Затем распаковываем архивы, и перемещаем содержимое архивов в папку «libraries», находящуюся в папке с установленной Arduino IDE. Также можно добавить библиотеки через Arduino IDE. Для этого, не распаковывая архивы, запускаем Arduino IDE, выбираем в меню Скетч – Подключить библиотеку. В самом верху выпадающего списка выбираем пункт «Добавить.Zip библиотеку». Указываем место нахождения скачанных архивов. После всех действий, необходимо перезагрузить Arduino IDE.

Шаг 6 Редактирование скетча.
Датчики температуры работают по протоколу One Wire и имеют уникальный адрес для каждого устройства - 64-разрядный код. Добавлять команды поиска датчиков в скетч не целесообразно. Незачем нагружать Arduino каждый раз икать датчики. Поэтому вначале, собрав все вместе, заливаем в Arduino скетч, находящийся в меню Файл – Примеры – Dallas Temperature – OneWireSearch. Затем запускаем Инструменты - Монитор порта. Arduino должна найти наши датчики, написать адреса и показания температуры. Эти адреса необходимо записать или просто скопировать куда-нибудь. Теперь открываем скетч Ard_Tic_Tak_WG12864B_2_x_Term_Serial, и ищем строки:

Byte addr1={0x28, 0xFF, 0x75, 0x4E, 0x87, 0x16, 0x5, 0x63};//адрес внутреннего byte addr2={0x28, 0xFF, 0xDD, 0x14, 0xB4, 0x16, 0x5, 0x97};//адрес внешнего датчика

Заменяем адреса соответствующих местонахождению датчиков, на свои адреса.
У нас часы не используют модуль RTC (часы реального времени), поэтому необходимо откорректировать ход часов. Для удобства раскомментируйте строку (на экране появятся секунды):

//u8g.setPrintPos(44, 50); u8g.print(sek); // Выводим секунды для контроля правильности хода

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

Если часы спешат, меняем значение на большее, рекомендую экспериментировать с шагом в 100 единиц. Если отстаю следует уменьшить значение в строке:

If (micros() - prevmicros >494000) { // поменять на другое для корректировки было 500000

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

Как большинство работающих людей, занятие собственными проектами отнимает единственно оставшееся свободное время. Поэтому уже давно не творил и «чесались руки» что-либо сделать. Данная возможность появилась как ни странно в университете. За окном сентябрь, 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 порту.

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








2024 © kubanteplo.ru.