XBeeのフレームをArduinoで表示する

はじめに

前回はXBee同士でのAPIモードを使った温度受信を試してみたので、今回はコーディネータが受信した値をArduinoからシリアルモニタに出力してみる。

kyonta1022.hatenablog.com

XBee親機(コーディネータ)の設定

コーディネータと接続するArduinoへのスケッチ書込みと、XBeeと接続する。

Arduinoへスケッチ書込み

コーディネータが受信したフレームをコンソールに出力するようにする。
XBeeとの送受信はシリアルポート経由で行う。

- ツール > シリアルポート > Arduino /Genuino Uno
- マイコンボードに書き込む

Arduinoへ書き込む時にシリアルポートがXBeeと繋がった状態だとエラーが起きるので、書き込む時だけは配線しないようにする。

#include <stdlib.h>

#define XBEE_FRAME 0x7E
#define CHECK_SUM_LENGTH 1

// API frame structure
// https://www.digi.com/resources/documentation/Digidocs/90001942-13/concepts/c_api_frame_structure.htm?tocpath=XBee%20API%20mode%7C_____2
struct api_frame {
  int type;
  int address_64[8];
  int address_16[2];
  int receive_options;
  int number_of_samples;
  int digital_channel_mask[2];
  int analog_channel_mask;
};

void setup() {
  Serial.begin(9600);
}

void loop() {
  if (Serial.available() > 0) {
    long delimiter = Serial.read();
    if (delimiter == XBEE_FRAME) {
      delay(50);
      long len_msb = Serial.read();
      long len_lsb = Serial.read();
      long frame_data_length = len_msb + len_lsb;
      long rf_data_length = frame_data_length - (sizeof(struct api_frame) / sizeof(int));

      // Read
      int received_data[frame_data_length];
      for (int i = 0; i < (frame_data_length); i++) {
        received_data[i] = Serial.read();
      }
      
      // Drop the checksum.
      Serial.read();

      // Show data
      Serial.print("Receive data from xbee [ " + String(delimiter, HEX) + " " + String(len_msb, HEX) + " " + String(len_lsb, HEX) + " ");
      for (int i = 0; i < sizeof(received_data) / sizeof(int); i++) {
        Serial.print(String(received_data[i], HEX) + " ");
      }
      Serial.println("]");

      // Include in the structure
      struct api_frame *frame = (struct api_frame*)received_data;
      int *rf_data = (received_data + (sizeof(struct api_frame) / sizeof(int)));
      Serial.println("delimiter            :" + String(delimiter, HEX));
      Serial.println("len_msb              :" + String(len_msb, HEX));
      Serial.println("len_lsb              :" + String(len_lsb, HEX));
      Serial.println("type                 :" + String(frame->type, HEX));
      Serial.println("address_64           :" + String(frame->address_64[0], HEX) + String(frame->address_64[1], HEX) + String(frame->address_64[2], HEX) + String(frame->address_64[3], HEX) + String(frame->address_64[4], HEX) + String(frame->address_64[5], HEX) + String(frame->address_64[6], HEX) + String(frame->address_64[7], HEX));
      Serial.println("address_16           :" + String(frame->address_16[0], HEX) + String(frame->address_16[1], HEX));
      Serial.println("receive_options      :" + String(frame->receive_options, HEX));
      Serial.println("number_of_samples    :" + String(frame->number_of_samples, HEX));
      Serial.println("digital_channel_mask :" + String(frame->digital_channel_mask[0], HEX) + String(frame->digital_channel_mask[1], HEX));
      Serial.println("analog_channel_mask  :" + String(frame->analog_channel_mask, HEX));
      Serial.print("rf_data              :");
      for (int i = 0; i < rf_data_length; i++) {
        Serial.print(String(rf_data[i], HEX));
      }
      Serial.println("");
    }
  }
}

回路図

こんな感じで、電源供給はArduinoから行い、シリアルポートを繋ぐだけ。 f:id:kyonta1022:20191019002821p:plain

XBee子機(ルータ)の設定

前回の設定と回路のままで子機を動かす。

実行

ArduinoIDEのシリアルモニタを開くと、子機から受信したフレームが表示されているのを確認できる。

Receive data from xbee [ 7e 0 12 92 0 13 a2 0 41 7d 50 31 24 a4 1 1 0 0 2 2 c ]
delimiter            :7e
len_msb              :0
len_lsb              :12
type                 :92
address_64           :013a20417d5031
address_16           :24a4
receive_options      :1
number_of_samples    :1
digital_channel_mask :00
analog_channel_mask  :2
rf_data              :2c

完成

f:id:kyonta1022:20191019003612j:plain