工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

Arduinoワイヤレスウェザーステーションプロジェクト

このチュートリアルでは、Arduinoベースのワイヤレス気象ステーションを作成する方法を学習します。次のビデオを見るか、以下のチュートリアルを読むことができます。

概要

屋外の温度と湿度はDHT22センサーを使用して測定され、このデータはNRF24L01トランシーバーモジュールを使用して屋内ユニットにワイヤレスで送信されます。室内ユニットには、室内の温度と湿度を測定するための別のDHT22センサーと、Arduinoの電源が切れた場合でも時間を追跡できるDS3231リアルタイムクロックモジュールもあります。これらのデータはすべて、0.96インチのOLEDディスプレイに印刷されています。

Arduinoワイヤレス気象ステーションの回路図

回路図とこのプロジェクトがどのように機能するかを見てみましょう。これらの各モジュールがどのように機能するかについての詳細なチュートリアルがすでにあることに注意してください。詳細については、NRF24L01チュートリアル、DHT22チュートリアル、DS3231チュートリアルを確認できます。

このプロジェクトに必要なコンポーネントは、以下のリンクから入手できます。

  • NRF24L01トランシーバモジュール………。
  • DHT22センサー……………。……………………
  • DS3231リアルタイムクロック…………………..Amazon / Banggood / AliExpress
  • ArduinoNano…………………………。……..

リアルタイムクロックモジュールとOLEDディスプレイはどちらもArduinoとの通信にI2Cプロトコルを使用するため、ArduinoNanoボードのI2Cピンまたはアナログピン番号4と5に接続されます。 NRF24L01トランシーバモジュールのすぐ隣には、電源をより安定させるためのコンデンサがあります。センサーが正しく機能するように、DHT22データピンにプルアップ抵抗が接続されています。

電源は室内機に12VのDC電源アダプターを使用し、反対側は室外機に電源を供給するために約7.5Vのリチウムイオン電池を2本使用しました。この構成では、データを定期的に送信し、その間に消費電力がわずか約7mAのスリープモードにするため、室外機はバッテリーが放電する前に約10日間稼働する可能性があります。

カスタムデザインPCB

電子部品を整理しておくために、回路図に従って、EasyEDAの無料オンライン回路設計ソフトウェアを使用してカスタムPCBを設計しました。屋内ユニットと屋外ユニットの両方に同じPCBを使用できることに注意してください。異なる方法でプログラムする必要があるのは、Arduinoボードのみです。

ここで設計が完了したら、PCBの製造に使用されるガーバーファイルをエクスポートするだけです。 Arduinoワイヤレス気象台のEasyEDAプロジェクトファイルはこちらで確認できます。

次に、実際にこのビデオのスポンサーであるJLCPCBにPCBを注文できます。

ここでは、ガーバーファイルをドラッグアンドドロップするだけで、アップロードしたら、ガーバービューアでPCBを確認できます。すべてが順調であれば、先に進み、PCBに必要なプロパティを選択してから、PCBをリーズナブルな価格で注文できます。 JLCPCBからの最初の注文の場合、わずか2ドルで最大10個のPCBを入手できることに注意してください。

それにもかかわらず、数日後、PCBが到着しました。 PCBの品質は素晴らしく、すべてが設計とまったく同じです。

私は、ピンヘッダーをPCBにはんだ付けすることにより、このプロジェクトの電子部品の組み立てを開始しました。このようにして、必要に応じてコンポーネントを簡単に接続および切断できます。

次に、コンデンサとプルアップ抵抗も挿入してはんだ付けしました。この手順が完了すると、コンポーネントをPCBのピンヘッダーに簡単に取り付けることができます。

次に、プロジェクトのケースを作成しました。そのために、8mmティックのMDFボードを使用し、丸鋸を使用して、すべてのピースをサイズに合わせてカットしました。

正確な温度と湿度を測定するには、ケースの側面から空気がケースに入ることができるようにする必要があります。そこで、ドリルとラスプを使用して、屋内ユニットと屋外ユニットの両方のサイドパネルにいくつかのスロットを作成しました。

また、フロントパネルにOLEDディスプレイ用のスロットを作成し、アルミニウムの小片をサイズにカットして、後でフロントパネルに装飾として取り付けます。

ケースの組み立てには、木工用ボンドといくつかのクランプ、およびいくつかのネジを使用しました。

ケースはスプレーペイントで塗装しました。室外機は白、室内機は黒を使用しました。塗料が乾いたら、PCBをケースに挿入するだけです。

室内機の裏側には電源ジャックと電源スイッチを挿入し、室外機では電源スイッチとしてシンプルなジャンパー線を使用しました。

これで、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ライブラリ、およびArduinoをスリープモードにするために使用されるLowPowerライブラリを含める必要があります。

インスタンス、モジュールが接続されているピン、およびいくつかの変数を定義した後、セットアップセクションで、ワイヤレス通信アドレスを初期化する必要があります。次に、ループセクションで、最初にDHT22センサーからデータを読み取ります。つまり、温度と湿度です。最初はこれらの値は整数で区切られているので、単一の文字列変数に変換して文字配列に入れ、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)

説明: 一方、室内ユニットまたはレシーバーには、さらに2つのライブラリを含める必要があります。1つはDS3231リアルタイムクロックモジュール用で、もう1つは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変数修飾子を使用してビットマップを定数として定義できます。これにより、ビットマップはArduinoボードのSRAMではなくフラッシュメモリに保存されます。

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モジュールを介して読み取ることができる着信データがあるかどうかを常にチェックします。 trueの場合、radio.read()関数を使用してそれを読み取り、最初の2文字を温度文字列変数に格納し、次の2文字を湿度文字列変数に格納します。

次に、millis()関数を使用して、3秒に設定したinterval変数で定義された間隔でさまざまなデータをディスプレイに表示します。このようにして残りのコードを繰り返し実行できるため、millis()関数を使用していますが、delay()関数を使用する場合、プログラムはその期間待機するため、受信データを見逃す可能性があります。室外機から。

次に、U8G2ライブラリのfirstPage()およびnextPage()関数を使用して、カスタム関数で定義された5つの異なる画面を印刷します。

drawDate()カスタム関数は、リアルタイムクロックモジュールから日付と時刻の情報を取得し、それをディスプレイに適切に出力します。 drawInTemperature()関数は、室内の温度を読み取り、それをディスプレイに適切に印刷します。実際、同じ方法がディスプレイ上のすべての画面の印刷に使用されます。

以上で、このArduinoプロジェクトを楽しんで、何か新しいことを学んだことを願っています。以下のコメントセクションでお気軽に質問してください。


製造プロセス

  1. ラズベリーパイをベースにした気象観測所
  2. Raspberry Pi2ウェザーステーション
  3. ラズベリーパイウェザーステーション
  4. Weather Station V 2.0
  5. 可聴周波数検出器
  6. ワイヤレスライトスイッチマニピュレーター
  7. Tech-TicTacToe
  8. Arduinoカウントダウンタイマー
  9. $ 10ポータブルArduinoウェザーステーション(AWS)
  10. eDOT-Arduinoベースの精密時計および気象観測所
  11. ThingSpeak Arduino Weather Station