Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Проект беспроводной метеостанции Arduino

<основной класс="главный сайт" id="главный">

В этом уроке мы узнаем, как сделать беспроводную метеостанцию ​​на базе Arduino. Вы можете посмотреть следующее видео или прочитать письменное руководство ниже.

Обзор

Наружная температура и влажность измеряются с помощью датчика DHT22, и эти данные передаются по беспроводной сети на внутренний блок с помощью приемопередающих модулей NRF24L01. Во внутреннем блоке также есть еще один датчик DHT22 для измерения температуры и влажности в помещении, а также модуль часов реального времени DS3231, который может отслеживать время, даже если Arduino теряет питание. Все эти данные печатаются на 0,96-дюймовом OLED-дисплее.

Схема беспроводной метеостанции Arduino

Давайте посмотрим на принципиальную схему и на то, как работает этот проект. Обратите внимание, что у меня уже есть подробные учебные пособия о том, как работает каждый из этих модулей, поэтому для получения более подробной информации вы можете просмотреть их:Учебное пособие по NRF24L01, Учебное пособие по DHT22, Учебное пособие по DS3231 .

Компоненты, необходимые для этого проекта, можно получить по ссылкам ниже:

Как модуль часов реального времени, так и OLED-дисплей используют протокол I2C для связи с Arduino, поэтому они подключены к контактам I2C или аналоговым контактам 4 и 5 на плате Arduino Nano. Рядом с модулем приемопередатчика NRF24L01 находится конденсатор, обеспечивающий более стабильное питание. Для правильной работы датчика к выводу данных DHT22 также подключен подтягивающий резистор.

Что касается источника питания, я использовал адаптер постоянного тока 12 В для внутреннего блока, а с другой стороны, для питания наружного блока я использовал две литий-ионные батареи, производящие около 7,5 В. При такой конфигурации наружный блок может работать около 10 дней до разряда батарей, потому что мы периодически передаем данные, а тем временем переводим Arduino в спящий режим, при котором потребляемая мощность составляет всего около 7 мА.

Плата индивидуального дизайна

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

Как только мы закончим проектирование здесь, мы можем просто экспортировать файл Gerber, который используется для изготовления печатной платы. Вы можете проверить файлы проекта EasyEDA беспроводной метеостанции Arduino здесь.

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

Здесь мы можем просто перетащить файл Gerber, и после загрузки мы можем просмотреть нашу плату в средстве просмотра Gerber. Если все в порядке, мы можем продолжить, выбрать свойства, которые мы хотим для нашей печатной платы, а затем мы можем заказать нашу печатную плату по разумной цене. Обратите внимание:если это ваш первый заказ в JLCPCB, вы можете получить до 10 печатных плат всего за 2 доллара США.

Тем не менее, через несколько дней печатные платы прибыли. Качество печатных плат отличное и все точно так же, как и в дизайне.

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

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

Затем я перешел к созданию кейсов для проекта. Для этой цели я использовал плиту МДФ толщиной 8 мм и с помощью циркулярной пилы вырезал все детали по размеру.

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

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

Для сборки корпусов я использовал столярный клей и струбцины, а также винты.

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

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

Вот и все, наша беспроводная метеостанция Arduino теперь работает, но в этом видео осталось посмотреть, как работает программа.

Код беспроводной метеостанции Arduino

Код наружного блока метеостанции Arduino:

/*
  Arduino Wireless Communication Tutorial
      Outdoor unit - Transmitter 
      
  by Dejan Nedelkovski, www.HowToMechatronics.com

Libraries:
NRF24L01 - TMRh20/RF24, https://github.com/tmrh20/RF24/
DHT22 - DHTlib, https://github.com/RobTillaart/Arduino/tree/master/libraries/DHTlib
LowPower - https://github.com/rocketscream/Low-Power 
*/
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <dht.h>
#include <LowPower.h>

#define dataPin 8 // DHT22 data pin
dht DHT; // Creates a DHT object

RF24 radio(10, 9); // CE, CSN
const byte address[6] = "00001";

char thChar[32] = "";
String thString = "";

void setup() {
  radio.begin();
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();

}
void loop() {
  int readData = DHT.read22(dataPin); // Reads the data from the sensor
  int t = DHT.temperature; // Gets the values of the temperature
  int h = DHT.humidity; // Gets the values of the humidity
  thString = String(t) + String(h);
  thString.toCharArray(thChar, 12);
  // Sent the data wirelessly to the indoor unit
  for (int i = 0; i <= 3; i++) {           // Send the data 3 times
    radio.write(&thChar, sizeof(thChar));
    delay(50);
  }
  // Sleep for 2 minutes, 15*8 = 120s
  for (int sleepCounter = 15; sleepCounter > 0; sleepCounter--)
  {
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
  }
}Code language: Arduino (arduino)

Описание: Наружный блок является передатчиком беспроводной связи, поэтому здесь сначала нам нужно включить библиотеку RF24, библиотеку DHT, а также библиотеку LowPower, которая используется для перевода Arduino в спящий режим.

После определения их экземпляров, контактов, к которым подключены модули, и некоторых переменных в разделе настройки нам нужно инициализировать адрес беспроводной связи. Потом в секции loop сначала считываем данные с датчика DHT22 или это температура и влажность. Изначально эти значения являются целыми и разделенными, поэтому я преобразовываю их в одну переменную типа String, помещаю их в массив символов и с помощью функции radio.write() отправляю эти данные на внутренний блок. С помощью цикла for мы отправляем данные 3 раза, чтобы быть уверенными, что получатель получит данные в случае, если контроллер занят в момент отправки.

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

Код внутреннего блока метеостанции Arduino:

/*
  Arduino Wireless Communication Tutorial
        Indoor unit  - Receiver

  by Dejan Nedelkovski, www.HowToMechatronics.com
 Libraries:
 DS3231 - http://www.rinkydinkelectronics.com/library.php?id=73
 U8G2 - https://github.com/olikraus/u8g2
*/
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <dht.h>
#include <DS3231.h>
#include <U8g2lib.h>
#include <Wire.h>

#define dataPin 8 // DHT22 sensor
dht DHT; // Creats a DHT object
DS3231  rtc(SDA, SCL);
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

RF24 radio(10, 9); // CE, CSN
const byte address[6] = "00001";

char text[6] = "";
int readDHT22, t, h;
String inTemp, inHum, outTemp, outHum;
String rtcTime, rtcDate;
int draw_state = 0;
unsigned long previousMillis = 0;
long interval = 3000;

#define Temperature_20Icon_width 27
#define Temperature_20Icon_height 47
static const unsigned char Temperature_20Icon_bits[] U8X8_PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x80, 0x7f, 0x00, 0x00,
  0xc0, 0xe1, 0x00, 0x00, 0xe0, 0xc0, 0x01, 0x00, 0x60, 0x80, 0xf9, 0x03,
  0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x79, 0x00,
  0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0xf9, 0x03,
  0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x00, 0x60, 0x8c, 0x79, 0x00,
  0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0xf9, 0x03,
  0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x79, 0x00,
  0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0xf9, 0x03,
  0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00,
  0x70, 0x9e, 0x03, 0x00, 0x38, 0x1e, 0x07, 0x00, 0x18, 0x3e, 0x0e, 0x00,
  0x1c, 0x3f, 0x0c, 0x00, 0x0c, 0x7f, 0x18, 0x00, 0x8c, 0xff, 0x18, 0x00,
  0x8e, 0xff, 0x38, 0x00, 0xc6, 0xff, 0x31, 0x00, 0xc6, 0xff, 0x31, 0x00,
  0xc6, 0xff, 0x31, 0x00, 0x8e, 0xff, 0x38, 0x00, 0x8c, 0xff, 0x18, 0x00,
  0x0c, 0x7f, 0x1c, 0x00, 0x3c, 0x1c, 0x0e, 0x00, 0x78, 0x00, 0x06, 0x00,
  0xe0, 0x80, 0x07, 0x00, 0xe0, 0xff, 0x03, 0x00, 0x80, 0xff, 0x00, 0x00,
  0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};


#define Humidity_20Icon_width 27
#define Humidity_20Icon_height 47
static const unsigned char Humidity_20Icon_bits[] U8X8_PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
  0x00, 0x70, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00,
  0x00, 0xdc, 0x01, 0x00, 0x00, 0x8e, 0x01, 0x00, 0x00, 0x86, 0x03, 0x00,
  0x00, 0x06, 0x03, 0x00, 0x00, 0x03, 0x07, 0x00, 0x80, 0x03, 0x06, 0x00,
  0x80, 0x01, 0x0c, 0x00, 0xc0, 0x01, 0x1c, 0x00, 0xc0, 0x00, 0x18, 0x00,
  0xe0, 0x00, 0x38, 0x00, 0x60, 0x00, 0x30, 0x00, 0x70, 0x00, 0x70, 0x00,
  0x30, 0x00, 0xe0, 0x00, 0x38, 0x00, 0xc0, 0x00, 0x18, 0x00, 0xc0, 0x01,
  0x1c, 0x00, 0x80, 0x01, 0x0c, 0x00, 0x80, 0x03, 0x0e, 0x00, 0x80, 0x03,
  0x06, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x07,
  0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06,
  0x63, 0x00, 0x00, 0x06, 0x63, 0x00, 0x00, 0x06, 0x63, 0x00, 0x00, 0x06,
  0xe3, 0x00, 0x00, 0x06, 0xc7, 0x00, 0x00, 0x06, 0xc6, 0x01, 0x00, 0x07,
  0x86, 0x03, 0x00, 0x03, 0x0e, 0x1f, 0x00, 0x03, 0x0e, 0x1e, 0x80, 0x01,
  0x1c, 0x00, 0xc0, 0x01, 0x38, 0x00, 0xe0, 0x00, 0x78, 0x00, 0x70, 0x00,
  0xf0, 0x00, 0x38, 0x00, 0xe0, 0x07, 0x1f, 0x00, 0x80, 0xff, 0x0f, 0x00,
  0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
};

void setup() {
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
  u8g2.begin();
  rtc.begin();
}
void loop() {
  if (radio.available()) {
    radio.read(&text, sizeof(text)); // Read incoming data
    outTemp = String(text[0]) + String(text[1]) + char(176) + "C"; // Outdoor Temperature
    outHum = String(text[2]) + String(text[3]) + "%"; // Outdoor Humidity
  }

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    u8g2.firstPage();
    do {
      switch (draw_state ) {
        case 0: drawDate(); break;
        case 1: drawInTemperature(); break;
        case 2: drawInHumidity(); break;
        case 3: drawOutTemperature(); break;
        case 4: drawOutHumidity(); break;
      }
    } while ( u8g2.nextPage() );
    draw_state++;
    if (draw_state > 4) {
      draw_state = 0;
    }
  }
}

void drawDate() {
  String dowa = rtc.getDOWStr();
  dowa.remove(3);
  rtcDate = dowa + " " + rtc.getDateStr();
  u8g2.setFont(u8g2_font_timB14_tr);
  u8g2.setCursor(0, 15);
  rtcTime = rtc.getTimeStr(); // DS3231 RTC time
  rtcTime.remove(5);
  u8g2.print(rtcDate);
  u8g2.setFont(u8g2_font_fub30_tf);
  u8g2.setCursor(8, 58);
  u8g2.print(rtcTime);
}

void drawInTemperature() {
  readDHT22 = DHT.read22(dataPin); // Reads the data from the sensor
  t = DHT.temperature; // Gets the values of the temperature
  inTemp = String(t) + char(176) + "C";
  u8g2.setFont(u8g2_font_helvR14_tr);
  u8g2.setCursor(24, 15);
  u8g2.print("INDOOR");
  u8g2.setFont(u8g2_font_fub30_tf);
  u8g2.setCursor(36, 58);
  u8g2.print(inTemp);
  u8g2.drawXBMP( 0, 17, Temperature_20Icon_width, Temperature_20Icon_height, Temperature_20Icon_bits);
}

void drawInHumidity() {
  h = DHT.humidity; // Gets the values of the humidity
  inHum = String(h) + "%";
  u8g2.setFont(u8g2_font_helvR14_tr);
  u8g2.setCursor(24, 15);
  u8g2.print("INDOOR");
  u8g2.setFont(u8g2_font_fub30_tf);
  u8g2.setCursor(36, 58);
  u8g2.print(inHum);
  u8g2.drawXBMP( 0, 17, Humidity_20Icon_width, Humidity_20Icon_height, Humidity_20Icon_bits);
}

void drawOutTemperature() {
  u8g2.setFont(u8g2_font_helvR14_tr);
  u8g2.setCursor(12, 15);
  u8g2.print("OUTDOOR");
  u8g2.setFont(u8g2_font_fub30_tf);
  u8g2.setCursor(36, 58);
  u8g2.print(outTemp);
  u8g2.drawXBMP( 0, 17, Temperature_20Icon_width, Temperature_20Icon_height, Temperature_20Icon_bits);
}
void drawOutHumidity() {
  u8g2.setFont(u8g2_font_helvR14_tr);
  u8g2.setCursor(12, 15);
  u8g2.print("OUTDOOR");
  u8g2.setFont(u8g2_font_fub30_tf);
  u8g2.setCursor(36, 58);
  u8g2.print(outHum);
  u8g2.drawXBMP( 0, 17, Humidity_20Icon_width, Humidity_20Icon_height, Humidity_20Icon_bits);
}Code language: Arduino (arduino)

Описание: С другой стороны, на внутреннем блоке или приемнике нам нужно включить еще две библиотеки, одну для модуля часов реального времени DS3231 и одну для OLED-дисплея, библиотеку U8G2. Так же, как и ранее, нам нужно определить экземпляры, выводы и некоторые переменные, необходимые для программы ниже. Также здесь нам нужно определить значки температуры и влажности в виде растровых изображений.

Растровое изображение значка температуры:

#define Temperature_20Icon_width 27
#define Temperature_20Icon_height 47
static const unsigned char Temperature_20Icon_bits[] U8X8_PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x80, 0x7f, 0x00, 0x00,
  0xc0, 0xe1, 0x00, 0x00, 0xe0, 0xc0, 0x01, 0x00, 0x60, 0x80, 0xf9, 0x03,
  0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x79, 0x00,
  0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0xf9, 0x03,
  0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x00, 0x60, 0x8c, 0x79, 0x00,
  0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0xf9, 0x03,
  0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x79, 0x00,
  0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0xf9, 0x03,
  0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00,
  0x70, 0x9e, 0x03, 0x00, 0x38, 0x1e, 0x07, 0x00, 0x18, 0x3e, 0x0e, 0x00,
  0x1c, 0x3f, 0x0c, 0x00, 0x0c, 0x7f, 0x18, 0x00, 0x8c, 0xff, 0x18, 0x00,
  0x8e, 0xff, 0x38, 0x00, 0xc6, 0xff, 0x31, 0x00, 0xc6, 0xff, 0x31, 0x00,
  0xc6, 0xff, 0x31, 0x00, 0x8e, 0xff, 0x38, 0x00, 0x8c, 0xff, 0x18, 0x00,
  0x0c, 0x7f, 0x1c, 0x00, 0x3c, 0x1c, 0x0e, 0x00, 0x78, 0x00, 0x06, 0x00,
  0xe0, 0x80, 0x07, 0x00, 0xe0, 0xff, 0x03, 0x00, 0x80, 0xff, 0x00, 0x00,
  0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};Code language: Arduino (arduino)

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

Затем мы можем открыть этот файл с помощью блокнота и оттуда скопировать растровое изображение в код Arduino.

Обратите внимание, что здесь мы можем определить растровое изображение как константу, используя модификатор переменной PROGMEM, и таким образом растровое изображение будет храниться во флэш-памяти, а не в SRAM платы Arduino.

static const unsigned char Temperature_20Icon_bits[] U8X8_PROGMEM // Save in the Flash memory 
static unsigned char Temperature_20Icon_bits[] // Save in the SRAM

В разделе настройки нам нужно инициализировать беспроводную связь, а также инициализировать OLED-дисплей и модуль часов реального времени.

Затем в секции цикла мы постоянно проверяем, есть ли входящие данные, доступные для чтения через модули NRF24L01. Если это правда, с помощью функции radio.read() мы читаем его и сохраняем первые два символа в строковой переменной температуры, а следующие два символа — в строковой переменной влажности.

Затем мы используем функцию millis() для отображения различных данных на дисплее с интервалами, определенными с помощью переменной interval, которую я установил на 3 секунды. Мы используем функцию millis(), потому что таким образом остальная часть кода может выполняться повторно, а в случае, если мы используем функцию delay(), программа ожидает этот период, поэтому таким образом мы, вероятно, пропустим входящие данные. от наружного блока.

Затем, используя функции firstPage() и nextPage() библиотеки U8G2, мы печатаем пять разных экранов, которые определены с помощью пользовательских функций.

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

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


Производственный процесс

  1. Метеостанция на основе Raspberry Pi
  2. Метеостанция Raspberry Pi 2
  3. Метеостанция Raspberry Pi
  4. Метеостанция V 2.0
  5. Детектор звуковой частоты
  6. Манипулятор беспроводного переключателя света
  7. Tech-TicTacToe
  8. Таймер обратного отсчета Arduino
  9. Портативная метеостанция Arduino (AWS) за 10 долларов
  10. eDOT - точные часы и метеостанция на базе Arduino