• Домашняя метеостанция на Arduino и отправка данных на "Народный мониторинг". Погодная станция на Arduino Начнем с базовой станции

    12.07.2023

    Как-то прогуливаясь по городу увидел новый открывшийся магазин радиоэлектроники. Зайдя в него обнаружил большое количество шилдов для Ардуины т.к. у меня дома была Arduino Uno и Arduino Nano сразу пришла мысль поиграться с передатчиками сигнала на расстоянии. Решил купить самый дешевый передатчик и приемник на 433 МГц:

    Передатчик сигнала.


    Приемник сигнала.

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

    Передатчик имеет следующие характеристики:
    1. Модель: MX -FS - 03V
    2. Радиус действия (зависит от наличия преграждающих предметов): 20-200 метров
    3. Рабочее напряжение: 3.5 -12В
    4. Размеры модуля: 19 * 19 мм
    5. Модуляция сигнала: AM
    6. Мощность передатчика: 10 мВт
    7. Частота: 433 МГц
    8. Необходимая длина внешней антенны: 25см
    9. Простота подключения (всего три провода): DATA ; VCC ; земля.

    Характеристики приемного модуля:
    1. Рабочее напряжение: DC 5В
    2. Ток: 4мA
    3. Рабочая частота: 433,92 МГц
    4. Чувствительность: - 105дБ
    5. Размеры модуля: 30 * 14 * 7 мм
    6. Небходима внешняя антенна: 32 см.

    В просторах интернета сказано, что дальность передачи информации на 2Кб/сек может доходить до 150м. Сам не проверял, но в двухкомнатной квартире принимает везде.

    Аппаратная часть домашней метеостанции

    После нескольких экспериментов решил подключить к Arduino Nano датчик температуры, влажности и передатчик.


    Датчик температуры DS18D20 подключается к ардуино следующим образом:

    1) GND к минусу микроконтроллера.
    2) DQ через подтягивающий резистор к земле и к выводу D2 Ардуины
    3) Vdd к +5В.

    Модуль передатчика MX -FS - 03V питается от 5 Вольт, вывод данных (ADATA) подключен к выводу D13.

    К Ардуино Уно подключил LCD дисплей и барометр BMP085.


    Схема подключение к ардуино уно

    Приемник сигнала подключен к выводу D10.

    Модуль BMP085 - цифровой датчик атмосферного давления. Датчик позволяет измерять температуру,давление и высоту над уровнем моря. Интерфейс подключения: I2C. Напряжение питания датчика 1.8-3.6 В

    Подключается модуль к Arduino также, как и другие I2C устройства:

    • VCC - VCC (3,3 В);
    • GND - GND;
    • SCL - к аналоговому выводу 5;
    • SDA - к аналоговому выводу 4.
    • Очень низкая стоимость
    • Питание и I/O 3-5 В
    • Определение влажности 20-80% с 5% точностью
    • Определение температуры 0-50 град. с 2% точностью
    • Частота опроса не более 1 Гц (не более раза в 1 сек.)
    • Размеры 15.5мм x 12мм x 5.5мм
    • 4 вывода с расстоянием между ножками 0.1"

    DHT имеет 4 вывода:

    1. Vcc (3-5V питание)
    2. Data out - Вывод данных
    3. Не используется
    4. Общий

    Подключается к D8 Ардуины.

    Программная часть домашней метеостанции

    Передающий модуль измеряет и передает температуру раз в 10 минут.

    Ниже привожу программу:

    /* Версия скетча 1.0 Отсылаем температуру каждые 10мин. */ #include #include #include #define ONE_WIRE_BUS 2 //Пин подключения датчика Даллас OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); DeviceAddress insideThermometer; void setup(void) { //Serial.begin(9600); vw_set_ptt_inverted(true); // Необходимо для DR3100 vw_setup(2000); // Устанавливаем скорость передачи (бит/с) sensors.begin(); if (!sensors.getAddress(insideThermometer, 0)); printAddress(insideThermometer); sensors.setResolution(insideThermometer, 9); } void printTemperature(DeviceAddress deviceAddress) { float tempC = sensors.getTempC(deviceAddress); //Serial.print("Temp C: "); //Serial.println(tempC); //Формирование данных для для отправки int number = tempC; char symbol = "c"; //Служебный символ определения что это датчик String strMsg = "z "; strMsg += symbol; strMsg += " "; strMsg += number; strMsg += " "; char msg; strMsg.toCharArray(msg, 255); vw_send((uint8_t *)msg, strlen(msg)); vw_wait_tx(); // Ждем пока передача будет окончена delay(200); } void loop(void) { for (int j=0; j <= 6; j++) { sensors.requestTemperatures(); printTemperature(insideThermometer); delay(600000); } } //Определение адреса void printAddress(DeviceAddress deviceAddress) { for (uint8_t i = 0; i < 8; i++) { if (deviceAddress[i] < 16); //Serial.print("0"); //Serial.print(deviceAddress[i], HEX); } }

    Приемное устройство принимает данные, измеряет давление и температуру в помещении и передает на дисплей.

    #include #include LiquidCrystal lcd(12, 10, 5, 4, 3, 2); #include dht11 sensor; #define DHT11PIN 8 #include #include BMP085 dps = BMP085(); long Temperature = 0, Pressure = 0, Altitude = 0; void setup() { Serial.begin(9600); vw_set_ptt_inverted(true); // Необходимо для DR3100 vw_setup(2000); // Задаем скорость приема vw_rx_start(); // Начинаем мониторинг эфира lcd.begin(16, 2); Wire.begin(); delay(1000); dps.init(); //lcd.setCursor(14,0); //lcd.write(byte(0)); //lcd.home(); } void loop() { uint8_t buf; // Буфер для сообщения uint8_t buflen = VW_MAX_MESSAGE_LEN; // Длина буфера if (vw_get_message(buf, &buflen)) // Если принято сообщение { // Начинаем разбор int i; // Если сообщение адресовано не нам, выходим if (buf != "z") { return; } char command = buf; // Команда находится на индексе 2 // Числовой параметр начинается с индекса 4 i = 4; int number = 0; // Поскольку передача идет посимвольно, то нужно преобразовать набор символов в число while (buf[i] != " ") { number *= 10; number += buf[i] - "0"; i++; } dps.getPressure(&Pressure); dps.getAltitude(&Altitude); dps.getTemperature(&Temperature); //Serial.print(command); Serial.print(" "); Serial.println(number); lcd.print("T="); lcd.setCursor(2,0); lcd.print(number); lcd.setCursor(5,0); lcd.print("P="); lcd.print(Pressure/133.3); lcd.print("mmH"); lcd.setCursor(0,1); lcd.print("T="); lcd.print(Temperature*0.1); lcd.print(" H="); lcd.print(sensor.humidity); lcd.home(); //delay(2000); int chk = sensor.read(DHT11PIN); switch (chk) { case DHTLIB_OK: //Serial.println("OK"); break; case DHTLIB_ERROR_CHECKSUM: //Serial.println("Checksum error"); break; case DHTLIB_ERROR_TIMEOUT: //Serial.println("Time out error"); break; default: //Serial.println("Unknown error"); break; } } }

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

    Ниже прилагаю фото того что получилось:

    Список радиоэлементов

    Обозначение Тип Номинал Количество Примечание Магазин Мой блокнот
    Передающая часть.
    Плата Arduino

    Arduino Nano 3.0

    1 В блокнот
    Датчик температуры

    DS18B20

    1 В блокнот
    Резистор

    220 Ом

    1 В блокнот
    Модуль передатчика MX-FS-03V (433 МГц) 1 В блокнот
    Радиоприемная часть.
    Плата Arduino

    Arduino Uno

    1 В блокнот
    Подстроечный резистор 1 В блокнот
    Резистор

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



    Так как погодные условия здесь достаточно переменчивы, а температура колеблется в диапазоне 30-40°С, я решил сделать домашнюю метеостанцию.

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

    Обычно это следующие датчики:

    • ветра
    • влажности
    • дождя
    • температуры
    • давления
    • высоты

    Моя цель – сделать портативную настольную метеостанцию своими руками.

    Она должна уметь определять следующие параметры:

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

    Шаг 1: Покупаем нужные компоненты







    • DHT22 , датчик температуры и влажности.
    • BMP180 , датчик давления.
    • Припой
    • Однорядный разъем на 40 выходов

    Из оборудования вам понадобятся:

    • Паяльник
    • Плоскогубцы для носоупоров
    • Провода

    Шаг 2: Датчик температуры и влажности DHT22







    Для измерения температуры используются разные датчики. Популярностью пользуются DHT22, DHT11, SHT1x

    Я объясню, чем они отличаются друг от друга, и почему я использовал именно DHT22.

    Датчик AM2302 использует цифровой сигнал. Этот датчик работает на уникальной системе кодировки и сенсорной технологии, поэтому его данные надежны. Его сенсорный элемент соединен с 8-битным однокристальным компьютером.

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

    Маленький размер, низкое потребление энергии, большое расстояние передачи (100 м) позволяют AM2302 подходить почти ко всем приложениям, а 4 выхода в один ряд делают монтаж очень простым.

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

    DHT11

    Плюсы: не требует пайки, самый дешевый из трех моделей, быстрый стабильный сигнал, дальность свыше 20 м, сильная интерференция.
    Минусы: Библиотека! Нет вариантов разрешения, погрешность измерений температуры +/- 2°С, погрешность измерений уровня относительной влажности +/- 5%, неадекватный диапазон измеряемых температур (0-50°С).
    Области применения: садоводство, сельское хозяйство.

    DHT22

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

    SHT1x

    Плюсы: не требует пайки, сглаженные кривые, малые погрешности измерений, быстрое срабатывание, низкое потребление энергии, автоматический режим сна, высокая стабильность и согласованность данных.
    Минусы: два цифровых интерфейса, погрешность в измерении уровня влажности, диапазон измеряемых температур 0-50°С, нужна библиотека.
    Области применения: эксплуатация в суровых условиях и в долгосрочных установках. Все три датчика относительно недорогие.

    Соединение

    • Vcc – 5В или 3,3В
    • Gnd – с Gnd
    • Data – на второй вывод Arduino

    Шаг 3: Датчик давления BMP180



    BMP180 – барометрический датчик атмосферного давления с I2C-интерфейсом.
    Барометрические датчики атмосферного давления измеряют абсолютное значение окружающего воздуха. Этот показатель зависит от конкретных погодных условий и от высоты над уровнем моря.

    У модуля BMP180 имелся 3,3В стабилизатор на 662кОм, который я, по собственной глупости, случайно взорвал. Пришлось делать обводку питания напрямую к чипу.

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

    Схема соединения датчика и шины I2C с Arduino (nano или uno)

    • SDA — A4
    • SCL — A5
    • VCC — 3.3V
    • GND – GND

    Давайте немного поговорим о давлении, и его связи с температурой и высотой.

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

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

    Атмосферное давление также изменяется с высотой. Абсолютное давление в базовом лагере на Эвересте (5400 м над уровнем моря) ниже, чем абсолютное давление в Дели (216 м над уровнем моря).

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

    Измерение высоты

    Среднее давление на уровне моря 1013,25 ГПа (или миллибар). Если подняться над атмосферой, это значение упадет до нуля. Кривая этого падения вполне понятна, поэтому вы можете сами вычислить высоту над уровнем моря, используя следующее уравнение: alti=44330*

    Если вы примите давление на уровне моря 1013,25 Гпа как р0, решением уравнения будет ваша текущая высота над уровнем моря.

    Меры предосторожности

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

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

    Защитите от влаги. Датчик BMP180 чувствителен к уровню влажности, постарайтесь предотвратить возможное попадание воды на датчик.

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

    Шаг 4: Собираем прибор







    Устанавливаем однорядные разъемы для Arduino Nano. Вообще, мы обрезали их до нужного размера и немного зашкурили, так что они смотрятся, словно такими и были. Потом припаиваем их. После, устанавливаем однорядные разъемы для датчика DHT22.

    Устанавливаем 10кОМ резистор от вывода данных к земле (Gnd). Все паяем.
    Потом точно также устанавливаем однорядный разъем для датчика BMP180, питание делаем 3,3В. Соединяем все с шиной I2C.

    В последнюю очередь подключаем LCD-дисплей, на ту же I2C шину, что и датчик BMP180.
    (в четвертый разъем я планирую позже подключить RTC-модуль (часы реального времени), чтобы прибор еще и время показывал).

    Шаг 5: Кодирование




    Загрузите библиотеки

    Чтобы установить библиотеки на Arduino, перейдите по ссылке

    #include
    #include #include #include "DHT.h" #include

    SFE_BMP180 pressure;

    #define ALTITUDE 20.56 #define I2C_ADDR 0x27 // <<- Add your address here. #define Rs_pin 0 #define Rw_pin 1 #define En_pin 2 #define BACKLIGHT_PIN 3 #define D4_pin 4 #define D5_pin 5 #define D6_pin 6 #define D7_pin 7

    #define DHTPIN 2 // what digital pin we"re connected to

    // Uncomment whatever type you"re using! //#define DHTTYPE DHT11 // DHT 11 #define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 DHT dht(DHTPIN, DHTTYPE); LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin); float t1,t2;

    void setup() { Serial.begin(9600); lcd.begin (16,2); // <<-- our LCD is a 20x4, change for your LCD if needed // LCD Backlight ON lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE); lcd.setBacklight(HIGH); lcd.home (); // go home on LCD lcd.print("Weather Station"); delay(5000); dht.begin(); pressure.begin(); } void loop() { char status; double T,P,p0,a; status = pressure.startTemperature(); if (status != 0) { delay(status);

    status = pressure.getTemperature(T); if (status != 0) { Serial.print("1"); lcd.clear(); lcd.setCursor(0,0); lcd.print("Baro Temperature: "); lcd.setCursor(0,1); lcd.print(T,2); lcd.print(" deg C "); t1=T; delay(3000);

    status = pressure.startPressure(3); if (status != 0) { // Wait for the measurement to complete: delay(status);

    status = pressure.getPressure(P,T); if (status != 0) {lcd.clear(); lcd.setCursor(0,0); lcd.print("abslt pressure: "); lcd.setCursor(0,1); lcd.print(P,2); lcd.print(" mb "); delay(3000);

    p0 = pressure.sealevel(P,ALTITUDE); // we"re at 1655 meters (Boulder, CO)

    a = pressure.altitude(P,p0); lcd.clear(); lcd.setCursor(0,0); lcd.print("Altitude: "); lcd.setCursor(0,1); lcd.print(a,0); lcd.print(" meters"); delay(3000); } } } } float h = dht.readHumidity(); // Read temperature as Celsius (the default) float t = dht.readTemperature(); t2=t; lcd.clear(); lcd.setCursor (0,0); // go to start of 2nd line lcd.print("Humidity: "); lcd.setCursor(0,1);lcd.print(h); lcd.print(" %"); delay(3000); lcd.clear(); lcd.setCursor (0,0); // go to start of 2nd line lcd.print("DHT Tempurature: "); lcd.setCursor(0,1); lcd.print(t); lcd.print(" deg C "); delay(3000); lcd.clear(); lcd.setCursor (0,0); // go to start of 2nd line lcd.print("Mean Tempurature: "); lcd.setCursor(0,1); lcd.print((t1+t2)/2); lcd.print(" deg C "); delay(3000); }

    Я использовал версию Arduino 1.6.5, код точно к ней подходит, к более поздним так же может подойти. Если код по каким-либо причинам не подходит, используйте версию 1.6.5 как базовую.

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

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

    

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

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

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

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

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

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

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

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

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

    Погода в Twitter

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

    Tempescope

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

    Погода в кубе

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

    Похожие статьи