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

HC-12モジュールで信頼性の高い長距離Arduinoネットワークを構築する

概要

このArduinoチュートリアルでは、複数のArduinoボード間で最大1.8kmの長距離無線通信を実現できるHC-12ワイヤレスシリアル通信モジュールの使い方を学びます。詳細については、以下のビデオまたは文章チュートリアルをご覧ください。

HC-12ワイヤレス通信モジュール

まず、HC-12ワイヤレスシリアルポート通信モジュールを詳しく見ていきましょう。主な仕様は以下の通りです。

  • ワイヤレス動作周波数帯: 433.4MHz〜473.0MHz
  • チャンネル数: 100チャンネル(チャンネル間隔400kHz)
  • 送信電力: -1dBm(0.79mW)〜20dBm(100mW)
  • 受信感度: -117dBm(0.019pW)〜-100dBm(10pW)

これらの値は、選択したシリアルおよびオーバーザエアボーレートによって変わります(下表参照)。

HC-12モジュールで信頼性の高い長距離Arduinoネットワークを構築する

HC-12モジュールにはマイクロコントローラが搭載されていますが、ユーザーがプログラミングする必要はありません。モジュールの設定にはATコマンドを使用し、Arduino、PC、またはその他のマイクロコントローラからシリアルポート経由で送信できます。ATコマンドモードに入るには、モジュールの「Set」ピンをローレベル(Low)に設定するだけです。

ArduinoとHC-12の接続

HC-12モジュールをArduinoに接続し、最初の例を作成します。回路図は以下の通りです。モジュールの動作電圧は3.2V〜5.5Vで、より安定した動作のためにデカップリングコンデンサと外部電源の使用が推奨されます。ただし、このチュートリアルの3つの例ではすべてPCのUSB電源を使用しましたが、問題は発生しませんでした。

HC-12モジュールで信頼性の高い長距離Arduinoネットワークを構築する

最初のモジュールをArduino UNOに、2つ目のモジュールをArduino MEGAに接続しましたが、もちろん任意のボードを使用できます。

必要なコンポーネント

  • HC-12ワイヤレス通信モジュール
  • Arduinoボード
  • ブレッドボードとジャンパワイヤ

例1:基本通信のArduinoコード


最初の例として、2つのモジュール間でシリアルモニタを使用した基本通信を行うArduinoコードを示します。同じコードを両方のArduinoにアップロードします。

/* Arduino Long Range Wireless Communication using HC-12 Example 01
   by Dejan Nedelkovski, www.HowToMechatronics.com */
#include <SoftwareSerial.h>
SoftwareSerial HC12(10, 11); // HC-12 TX Pin, HC-12 RX Pin

void setup() {
  Serial.begin(9600);  // PCとのシリアル通信
  HC12.begin(9600);    // HC-12とのシリアル通信
}

void loop() {
  while (HC12.available()) {        // HC-12からデータを受信
    Serial.write(HC12.read());      // シリアルモニタに出力
  }
  while (Serial.available()) {      // シリアルモニタからデータを受信
    HC12.write(Serial.read());      // HC-12に送信
  }
}

2台のArduinoを別々のPCに接続しても、1台のPCで2つのArduino IDEを起動してそれぞれ別のCOMポートを選択しても動作します。シリアルモニタで文字を入力して送信すると、一方から他方へ無線でデータが転送されます。

HC-12モジュールで信頼性の高い長距離Arduinoネットワークを構築する

コードの動作原理

シリアルモニタで文字を入力して送信ボタンを押すと、最初のArduinoでSerial.available()がtrueになり、HC12.write()でデータがHC-12モジュールに送られます。このモジュールが無線でデータを転送し、2つ目のArduinoではHC12.available()がtrueになり、Serial.write()でシリアルモニタにデータが表示されます。

この同じコードでATコマンドを送信し、モジュールのパラメータを設定することもできます。モジュールの「Set」ピンをGNDまたはArduinoのデジタルピンに接続し、ローレベルに設定するだけです。

HC-12モジュールで信頼性の高い長距離Arduinoネットワークを構築する

ATコマンドモードに正しく入れたかテストするには、シリアルモニタで「AT」と入力し、「OK」という応答が返ってくるか確認します。全12種類のATコマンドがあり、ボーレート、チャンネル、送信電力などのパラメータを変更できます。例えば「AT+B38400」と送信すると、ボーレートが38400に設定されます。

主なATコマンド

  1. AT - テストコマンド。応答:「OK」
  2. AT+Bxxxx - シリアルポートのボーレート変更
    • 利用可能: 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200 bps(デフォルト: 9600)
    • 例: 「AT+B38400」→ 応答「OK+B19200」
  3. AT+Cxxxx - ワイヤレス通信チャンネル変更(001〜100)
    • デフォルト: チャンネル001(433.4MHz)。各チャンネルは400kHz刻み
    • 例: 「AT+C006」→ チャンネル006(435.4MHz)に設定、応答「OK+C006」

例2:プッシュボタンでチャンネル切り替え


2つのプッシュボタンを使って通信チャンネルを切り替え、着信データを文字列変数に格納する別の方法を紹介します。

HC-12モジュールで信頼性の高い長距離Arduinoネットワークを構築する

注意: 両HC-12モジュールの「Set」ピンはそれぞれのArduinoのピン6に接続。最初のArduinoの2つのボタンはピン4と3に接続。

最初のArduinoコード(ボタン側)

/* Arduino Long Range Wireless Communication using HC-12 Example 02
   Changing channels using push buttons - Buttons side
   by Dejan Nedelkovski, www.HowToMechatronics.com */
#include <SoftwareSerial.h>
#define setPin 6
#define button1 4
#define button2 3
SoftwareSerial HC12(10, 11);
byte incomingByte;
String readBuffer = "";
int button1State = 0, button1Pressed = 0;
int button2State = 0, button2Pressed = 0;

void setup() {
  Serial.begin(9600);
  HC12.begin(9600);
  pinMode(setPin, OUTPUT);
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);
  digitalWrite(setPin, HIGH); // 通常モード
}

void loop() {
  // 着信データをString変数に格納
  while (HC12.available()) {
    incomingByte = HC12.read();
    readBuffer += char(incomingByte);
  }
  delay(100);

  // シリアルモニタからのデータを他方のHC-12へ転送
  while (Serial.available()) {
    HC12.write(Serial.read());
  }

  // ボタン1押下でチャンネル01に設定
  button1State = digitalRead(button1);
  if (button1State == HIGH && button1Pressed == LOW) {
    button1Pressed = HIGH;
    delay(20);
  }
  if (button1Pressed == HIGH) {
    HC12.print("AT+C001"); // 他方のモジュールへATコマンド送信
    delay(100);
    digitalWrite(setPin, LOW);  // ATコマンドモードへ
    delay(100);
    HC12.print("AT+C001"); // 自身のHC-12へATコマンド送信
    delay(200);
    while (HC12.available()) {
      Serial.write(HC12.read()); // 応答をシリアルモニタに表示
    }
    Serial.println("Channel successfully changed");
    digitalWrite(setPin, HIGH); // 通常モードに戻る
    button1Pressed = LOW;
  }

  // ボタン2押下でチャンネル02に設定(同様の処理)
  button2State = digitalRead(button2);
  if (button2State == HIGH && button2Pressed == LOW) {
    button2Pressed = HIGH;
    delay(100);
  }
  if (button2Pressed == HIGH) {
    HC12.print("AT+C002");
    delay(100);
    digitalWrite(setPin, LOW);
    delay(100);
    HC12.print("AT+C002");
    delay(200);
    while (HC12.available()) {
      Serial.write(HC12.read());
    }
    Serial.println("Channel successfully changed");
    digitalWrite(setPin, HIGH);
    button2Pressed = LOW;
  }

  checkATCommand();
  readBuffer = "";
}

// シリアルモニタ経由でATコマンドを受信したかチェック
void checkATCommand() {
  if (readBuffer.startsWith("AT")) {
    digitalWrite(setPin, LOW);
    delay(200);
    HC12.print(readBuffer);
    delay(200);
    while (HC12.available()) {
      Serial.write(HC12.read());
    }
    digitalWrite(setPin, HIGH);
  }
}

2つ目のArduinoコード(受信側)

/* Arduino Long Range Wireless Communication using HC-12 Example 02
   Changing channels using push buttons
   by Dejan Nedelkovski, www.HowToMechatronics.com */
#include <SoftwareSerial.h>
#define setPin 6
SoftwareSerial HC12(10, 11);
byte incomingByte;
String readBuffer = "";

void setup() {
  Serial.begin(9600);
  HC12.begin(9600);
  pinMode(setPin, OUTPUT);
  digitalWrite(setPin, HIGH);
}

void loop() {
  while (HC12.available()) {
    incomingByte = HC12.read();
    readBuffer += char(incomingByte);
  }
  delay(100);

  while (Serial.available()) {
    HC12.write(Serial.read());
  }

  // チャンネル01設定コマンド受信時
  if (readBuffer == "AT+C001") {
    digitalWrite(setPin, LOW);
    delay(100);
    HC12.print(readBuffer);
    delay(200);
    while (HC12.available()) {
      Serial.write(HC12.read());
    }
    Serial.println("Channel successfully changed");
    digitalWrite(setPin, HIGH);
    readBuffer = "";
  }

  // チャンネル02設定コマンド受信時
  if (readBuffer == "AT+C002") {
    digitalWrite(setPin, LOW);
    delay(100);
    HC12.print(readBuffer);
    delay(200);
    while (HC12.available()) {
      Serial.write(HC12.read());
    }
    Serial.println("Channel successfully changed");
    digitalWrite(setPin, HIGH);
    readBuffer = "";
  }

  checkATCommand();
  readBuffer = "";
}

void checkATCommand() {
  if (readBuffer.startsWith("AT")) {
    digitalWrite(setPin, LOW);
    delay(100);
    HC12.print(readBuffer);
    delay(200);
    while (HC12.available()) {
      Serial.write(HC12.read());
    }
    digitalWrite(setPin, HIGH);
  }
}

コードの説明

まずピンを定義し、「Set」ピンをHighにして通常(透過)モードで動作させます。最初のwhileループで着信データを1バイトずつ読み取り、String変数readBufferに結合します。これにより「Test123」のような文字列を7回のイテレーションで完全に受信できます。

HC-12モジュールで信頼性の高い長距離Arduinoネットワークを構築する

ボタン1が押されると「AT+C001」を送信し、相手側でもATコマンドモードに入って同じコマンドを実行することで、両モジュールのチャンネルを同時に切り替えます。ボタン2でも同様にチャンネル02に切り替え可能です。最後にcheckATCommand()関数で、受信文字列が「AT」で始まるATコマンドかどうかを判定し、該当する場合は実行します。

例3:加速度センサでステッピングモータを制御


3つ目の例では、最初のArduinoに接続した加速度センサ(ADXL345)の傾きに応じて、2つ目のArduinoのステッピングモータ位置を無線制御します。

HC-12モジュールで信頼性の高い長距離Arduinoネットワークを構築する

回路にはステッピングモータの原点(0度)を検出するマイクロスイッチも含まれます。

HC-12モジュールで信頼性の高い長距離Arduinoネットワークを構築する

必要なコンポーネント

  • HC-12ワイヤレス通信モジュール
  • A4988ステッピングモータドライバ
  • NEMA 17ステッピングモータ
  • Arduinoボード
  • ブレッドボードとジャンパワイヤ
  • ADXL345搭載GY-80ボード

加速度センサとステッピングモータの詳細な接続・使用方法は別チュートリアルを参照してください。ここではHC-12関連のコード部分のみ解説します。

最初のArduino(送信側・加速度センサ)コード

/* Arduino Long Range Wireless Communication using HC-12 Example 03
   Stepper Motor Control using Accelerometer - Transmitter
   by Dejan Nedelkovski, www.HowToMechatronics.com */
#include <SoftwareSerial.h>
#include <Wire.h>
SoftwareSerial HC12(10, 11);
float angle;
int lastAngle = 0, count = 0, angleSum = 0;

// ADXL345レジスタアドレス
#define Power_Register 0x2D
#define X_Axis_Register_DATAX0 0x32
#define X_Axis_Register_DATAX1 0x33
#define Y_Axis_Register_DATAY0 0x34
#define Y_Axis_Register_DATAY1 0x35
#define Z_Axis_Register_DATAZ0 0x36
#define Z_Axis_Register_DATAZ1 0x37

int ADXAddress = 0x53;
int X0, X1, X_out, Y0, Y1, Y_out, Z1, Z0, Z_out;
float Xa, Ya, Za;

void setup() {
  HC12.begin(9600);
  Wire.begin();
  Serial.begin(9600);
  delay(100);
  Wire.beginTransmission(ADXAddress);
  Wire.write(Power_Register);
  Wire.write(8); // 測定モード有効
  Wire.endTransmission();
}

void loop() {
  // X軸読み取り
  Wire.beginTransmission(ADXAddress);
  Wire.write(X_Axis_Register_DATAX0);
  Wire.write(X_Axis_Register_DATAX1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress, 2);
  if (Wire.available() <= 2) {
    X0 = Wire.read();
    X1 = Wire.read();
    X1 = X1 << 8;
    X_out = X0 + X1;
    Xa = X_out / 256.0;
  }

  // Y軸読み取り
  Wire.beginTransmission(ADXAddress);
  Wire.write(Y_Axis_Register_DATAY0);
  Wire.write(Y_Axis_Register_DATAY1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress, 2);
  if (Wire.available() <= 2) {
    Y0 = Wire.read();
    Y1 = Wire.read();
    Y1 = Y1 << 8;
    Y_out = Y0 + Y1;
    Ya = Y_out / 256.0;
  }

  // X, Yから0-180度の角度を算出
  if (Y_out > 0) angle = map(Y_out, 0, 256, 90, 0);
  else if (Y_out < 0) { angle = map(Y_out, 256, 0, 90, 0); angle = 90 - angle; }
  if (X_out < 0 && Y_out < 0) angle = 180;
  if (X_out < 0 && Y_out > 0) angle = 0;

  int angleInt = int(angle);
  // 100回読み取り平均でスムージング
  angleSum += angleInt;
  count++;
  if (count >= 100) {
    angleInt = angleSum / 100;
    angleSum = 0; count = 0;
    // 前回から±2度以上変化した場合のみ送信
    if (angleInt > lastAngle + 2 || angleInt < lastAngle - 2) {
      Serial.println(angleInt);
      String angleString = String(angleInt);
      // 開始マーカー's'と終了マーカー'e'を付加
      HC12.print("s" + angleString + "e");
      delay(10);
      lastAngle = angleInt;
    }
  }
}

2つ目のArduino(受信側・ステッピングモータ)コード

/* Arduino Long Range Wireless Communication using HC-12 Example 03
   Stepper Motor Control using Accelerometer - Receiver
   by Dejan Nedelkovski, www.HowToMechatronics.com */
#include <SoftwareSerial.h>
SoftwareSerial HC12(10, 11);
char incomingByte;
String readBuffer = "";
const int dirPin = 4, stepPin = 3, button = 2;
int currentAngle = 0, lastAngle = 0, rotate = 0;

void setup() {
  Serial.begin(9600);
  HC12.begin(9600);
  pinMode(dirPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  pinMode(button, INPUT_PULLUP); // マイクロスイッチ
  delay(10);
  digitalWrite(dirPin, HIGH);
  // 原点復帰
  boolean startingPosition = true;
  while (startingPosition) {
    digitalWrite(stepPin, HIGH); delayMicroseconds(200);
    digitalWrite(stepPin, LOW); delayMicroseconds(200);
    if (digitalRead(button) == LOW) startingPosition = false;
  }
  delay(100);
}

void loop() {
  readBuffer = "";
  boolean start = false;

  // 's'と'e'の間のデータを読み取り
  while (HC12.available()) {
    incomingByte = HC12.read();
    delay(5);
    if (start) {
      if (incomingByte != 'e') readBuffer += char(incomingByte);
      else start = false;
    } else if (incomingByte == 's') {
      start = true;
    }
  }

  currentAngle = readBuffer.toInt();
  if (currentAngle > 0 && currentAngle < 180) {
    // 角度をステップ数に変換(16分割ステップ: 180度 = 1600ステップ)
    currentAngle = map(currentAngle, 0, 180, 0, 1600);
    digitalWrite(dirPin, LOW);
    if (currentAngle != lastAngle) {
      if (currentAngle > lastAngle) {
        rotate = currentAngle - lastAngle;
        for (int x = 0; x < rotate; x++) {
          digitalWrite(stepPin, HIGH); delayMicroseconds(400);
          digitalWrite(stepPin, LOW); delayMicroseconds(400);
        }
      } else {
        rotate = lastAngle - currentAngle;
        digitalWrite(dirPin, HIGH); // 逆回転
        for (int x = 0; x < rotate; x++) {
          digitalWrite(stepPin, HIGH); delayMicroseconds(400);
          digitalWrite(stepPin, LOW); delayMicroseconds(400);
        }
      }
    }
    lastAngle = currentAngle;
  }
}

コードのポイント

送信側では加速度センサのX/Y軸値から0〜180度の角度を算出し、100回測定の平均を取ってスムージング。さらに前回値から±2度以上変化した場合のみ、開始マーカー「s」と終了マーカー「e」を付けて送信します。受信側では「s」を検出してから「e」が来るまでデータを蓄積し、整数に変換してステッピングモータを目標位置まで回転させます。A4988ドライバの16分割ステップ設定に合わせ、0〜180度を0〜1600ステップにマッピングしています。

以上でこのArduinoチュートリアルは終了です。ご質問はコメント欄でお気軽にどうぞ。

製造プロセス

  1. Arduino UNOで作るLCDアニメーション&ゲーム入門
  2. JX Wave Generator – Arduino互換DDS発振器(OLEDディスプレイ搭載)
  3. u-blox LEA-6H 02 GPSモジュール: Arduino & Python 統合ガイド
  4. ワイヤレス非接触温度スキャナー:Arduino Nano+Bluetooth+MLX90614
  5. Python 3からArduino UNOを制御 – シリアル通信でLED点滅デモ
  6. Arduino NanoとRDA5807Mで作るコンパクトFMラジオ
  7. Arduino + Windows IoT + Azure クラウドによる高度な転倒検知システム
  8. ArduRadio:Arduino自作FMラジオ付き目覚まし時計
  9. Arduino超音波距離センサー:HC-SR04で測定システム構築
  10. ワイヤレス通信距離をマスターする:電力、データレート、干渉が接続性をどう形作るか
  11. 電池駆動の長距離ワイヤレスが接続性をどう変えるか