XBeeとµIPを用いたTCP/IP通信のネットワーク性能評価


目次

1.はじめに

近年、IoT(Internet of Things)が注目されている。 特に、センシングされたデータなどを集めて解析を行い、新たな発見を目指す取り組みが盛んに行われている。 センサによって取得されたデータは、主に無線通信によってやり取りされる場合が多い。 特に、多数のセンサを用いてデータを収集できるようにした無線ネットワークをWSN(Wireless Sensor Network)と呼ぶ。 WSNで用いられる通信規格として、WSN構築を主目的とするIEEE802.15.4がある。

IEEE802.15.4はOSI参照モデルで物理層・MAC層に位置する規格である。 通信の速度をWSNに最適な速度に抑える調整により低消費電力を達成し、小型の電池や小型のバッテリで駆動できる。 IEEE802.15.4の上部にあたるネットワーク層の実装は様々ある。 ZigBee Alliance(現Connectivity Standards Alliance)が策定したZigBeeや、IPv6をWSNで用いられるように設計された6LowPANなどが存在する。

これら規格のうちZigBeeは、Digi社より規格に対応した製品としてXBeeと呼ばれる小型の無線送受信機が販売されている。 XBeeは専用のArduinoシールドを用いることにより、Arduinoへ容易に接続可能である。 そのため、低価格でWSNを構築する際によく用いられている。 しかし、ZigBee規格で策定されているのはOSI参照モデルのネットワーク層までであり、アプリケーションを利用する部分は実装によって様々である。

そこで、インターネット通信に用いられるネットワーク層・トランスポート層のTCP/IPをアプリケーションとして実装することで、単なる通信のみならず、既存のプロトコルに沿った多くの機能を提供できるのではないかと考えた。 また、TCP/IPスタックを利用することで、理論上は既存のファイル転送プロトコルを使用可能である。その結果、効率的なファイル転送手段を提供できる可能性があると考えられた。

本研究では、ArduinoとZigBee(XBee)を用い、TCP/IP通信の実装を行う。その後、帯域幅測定などを行い、どの程度の通信が可能であるかを明らかにする。

2.事前準備

2.1.Arduino Uno

Arduinoは、Microchip Technology社(合併前はAtmel社)のAVRマイコンを使用した開発キットの一種である。 AVRマイコンは、電子工作等に多く用いられる8bitアーキテクチャのRISCを用いており、比較的利用しやすい点が特徴である。 Arduinoはオープンソースハードウェアである。また、回路図が公開されているため、数多くの互換製品が存在する。

Arduinoの中で一般的なArduino Unoは、ATmega328PというAVRマイコンを使用したマイコンボードである。 プログラムメモリを32KB、RAMを2KB持ち、SPI・I2C・UARTなどの通信機能や16bit・8bitのタイマを持つ[1]。 電子工作等で基本的な制御を行う用途では十分な性能を持つ。

今回の研究では、Arduino UnoをATmega328Pとして使用している。 ArduinoにはArduino IDEと呼ばれる開発環境があり、Arduino言語と呼ばれるC++言語と同等の言語を用いてプログラミングを行う。 コンパイルから書き込みまでを一括で行えるため非常に便利なソフトウェアではあるが、レジスタを直接調整したり等の細かい部分の調整には不向きである。 よって、素のC言語を使用し、avr-gccによってコンパイルし、Avrdudeによって書き込む方法を取った。

2.2.シリアル通信

2.2.1.シリアル通信の仕組み[2]

マイコン間通信等に用いられるシリアル通信は、1本の伝送路を使用して1ビットずつデータを送受信する通信の方法である。RS-232やUSBはシリアル通信の規格の1つとなる。

Arduinoに搭載されるATmega328Pなどのマイコンには、UARTという周辺機能を持つ種類がある。 これは、プロセッサ内部で作成されたパラレルデータをシリアルデータに変換し、外部とやり取りを行うための機能を提供するものである。 UARTによって作成されたデータはArduinoボード上のTxピンから送信される。また、Rxピンを通して外部からシリアルデータを受信する。

図1 シリアルデータの構造

シリアル通信によって送受信されるデータの構造を図1に示す。8ビットのデータを送信するとき、前後のデータと区別をするため、スタートビットとストップビットと呼ばれる識別用データを付加する。また、パリティビットを追加してデータの誤りを検出可能な仕組みを持つ。 スタートビット、ストップビットやパリティを使用する場合、それぞれに1ビット必要となる。従って、8ビットのデータを送信する場合は、少なくとも10ビット以上のデータが送信される。

シリアル通信によってデータを送受信する際に、送信・受信側で決めた伝送速度を使用する。このとき、伝送速度の指標となる値がボーレートである。ボーレートは、デジタルデータを1秒間に変調可能な値を示す。例えば、ボーレートが9600[bps]であれば1秒あたりに9600回変調するので、シリアルデータ1ビットに対し約104[µs]程度掛かる計算になる。従って、8ビットデータとスタートビット・ストップビットの10ビットを送信する場合は1.04[ms]程度の時間が掛かる。

2.2.2.シリアル通信のフロー制御

シリアル通信ではTx、Rxの2つの伝送線によってデータの送受信を行う。 シリアル受信やシリアル送信後の処理はマイコンの性能に左右される。マイコンがデータを処理している間にもデータが到着する場合があり、それらのデータを一時的に保管するバッファを持つデバイスが多い。しかし、そのバッファの大きさを超えるようなデータが到着した時や、マイコンの処理が間に合わずにデータが溜まる場合がある。このような状態が続くとバッファがオーバーフローする。オーバーフローした場合は、送信側が送信したデータを正しく受信できない事態につながる。そこで、バッファがオーバーフローする前に送信側にデータの送信を待機してもらうなどのフロー制御が用いられる。シリアル通信で用いられるフロー制御のうち、ハードウェア的に行う方法がRTS/CTSフロー制御である。

図2 RTS/CTSフロー制御

データの送受信で用いるTx/Rx線の他にRTS/CTSの2線を用意することでフロー制御が可能となる。RTS(Request To Send)は出力であり、CTS(Clear To Send)は入力にあたる。また、RTS/CTSは負論理となっており、CTSにHighが入力されるとデータの送信が止まる。

入力側にあたるCTS(Clear To Send)がLowで入力されているとき、送信側はシリアルデータを送信可能である。ここで、受信側の受信バッファがオーバーフローする手前で受信側はRTS(Request To Send)をHighとする。すると、送信側のCTSがHighになり、送信側はデータの送信を止める。受信側のバッファに余裕が生まれると、送信側はRTSをLowに戻すので、再びデータの送信を再開する。このようにフロー制御を用いることで、データのロスが発生しないようにシリアル通信を行える。

2.3.OSI参照モデル

OSI参照モデルとは、異なるコンピュータ間での接続を行うために遵守されるべき階層型モデルのことである。OSI参照モデルを用いて各種プロトコルをレイヤ(層)ごとに管理することで、各レイヤごとのプロトコルを独立的に扱え、単純な仕組みや構造にできる。以下に、基本となる7層を表した図を示す。

図3 OSI参照モデル

図で示したように、OSI参照モデルではコンピュータ同士の通信を第1層の物理層から第7層のアプリケーション層に分類している。各レイヤではそれぞれのレイヤで定義・規定されたサービスを提供し、同階層同士であればプロトコルを用いて下位レイヤを気にせず通信が行える。また、上下の各層でサービスの呼び出しを行ったり応答を受け取るための機能をインターフェースという。

アプリケーション層やプレゼンテーション層といった上位レイヤで作成されたデータは、トランスポート層・インターネット層と順に下位レイヤへ送られる。その際に各レイヤで定義されたプロトコルに沿ったパケットになるように制御データが付けられる。そして物理層を通じて他のコンピュータへ送られる。

他のコンピュータは受け取ったデータを下位から順に処理し、制御データを取り外して上位レイヤへ渡す。この繰り返しで上位レイヤまでデータが送られるとアプリケーションが処理する。このような流れでコンピュータ間の通信を行う。

次節以降で述べるZigBeeやTCP/IPによる通信も、OSI参照モデルに則った階層型の構造を持っている。ただし、7層のうちいくつかの層がまとめられているなど、それぞれの特性に応じて最適化がされている場合がある。

2.4.ZigBee(XBee)[3],[4]

2.4.1.ZigBeeとは

ZigBeeは、WSNを主目的に策定されたIEEE802.15.4標準に基づく通信仕様標準の1つである。 低消費電力である代わりに転送速度が低速であったり、メッシュネットワークを構築可能である通信仕様がZigBeeプロトコルである。 このZigBeeプロトコルを用いて通信を行う無線通信端末がXBeeである。 XBeeはこれまでにいくつかの製品シリーズがリリースされており、S1(シリーズ1)からS2(シリーズ2)など、シリーズ番号が上がる際に若干の仕様変更がなされている。 S1とS2は仕様が異なり通信はできないが、S2、S2B、S2Cなどのリビジョン違いの製品は多少の差はあれど相互で使用できる。

図4 OSI参照モデルとZigBeeプロトコルの階層

OSI参照モデルとZigBeeプロトコルの階層構造は図4のように表される。 ZigBeeプロトコルは、物理層・データリンク層にあたる部分をIEEE802.15.4に則った実装としている。 そのため、無線通信に868MHz帯、815MHz帯、915MHz帯、2.4GHz帯を使用できる。 日本では2.4GHz帯のみ使用可能となっている。

ネットワーク層から上位レイヤに関してはZigBee独自の規格となっている。 ネットワーク層では、無線通信のデータパケットが複数のデバイスを経由して、正しく宛先にデータが送信できるようにルーティングを行う役割を持つ。

トランスポート層以上のレイヤはアプリケーションサポートサブレイヤ(APS)、アプリケーション層の2つに大別される。 アプリケーション層とネットワーク層以下を繋ぐインターフェースの役割を果たすのがAPSである。

ZigBeeには3つのデバイスタイプが存在する。 それぞれ、コーディネータ、ルータ、エンドデバイスである。コーディネータには、PAN(Personal Area Network)を構築する機能、チャネル管理などのネットワーク管理、ゲートウェイといった機能を持つ。 そのため、ZigBeeによって構成されるメッシュネットワークには必ず1台のコーディネータが必要である。 ルータは主に通信の中継をする機能を持ち、他デバイスからの通信を受け入れられる。 エンドデバイスはメッシュネットワークの最も端に位置するデバイスである。 スリープ機能を持っており、間欠動作で用いる際に用いる。 エンドデバイスがデータを送信するためには、ルータまたはコーディネータが必要である。 また、エンドデバイスは他デバイスから通信によってデータを受け入れる機能を持たないため、一方向のコミュニケーションをとるデバイスである。

図5 メッシュネットワーク構築例

ルータやコーディネータ、エンドデバイスを組み合わせることで、図5に示すようなメッシュネットワークを構築可能である。

2.4.2.ZigBeeの動作モード

ZigBeeでは、ATモードとAPIモードの2つの動作モードが用意されている。本実験ではATモードを用いて行う。以下に、それぞれの動作モードの特徴を示す。

2.4.3.XBee設定ソフトウェア XCTU

XCTUは、Digi社が提供するXBee用設定・テストツールである。XBeeはATモードではコマンド送信する形でXBee自体の設定を行うが、XCTUを用いることでGUIを用いて容易に設定を行なえる。以下に示す図がXCTUのパラメータ設定画面である。この他に、送受信したシリアルデータの確認やネットワークトポロジーの確認を行う機能も持つ。

図6 XCTUのパラメータ設定画面

2.5.TCP/IP

TCP/IPは様々なデバイスにおいて、インターネットによる通信を利用する際に用いられるプロトコルである。 TCP/IPはOSI参照モデルに対応するように実装されているが、効率化・最適化のために一部レイヤが統合されるなどされている。

図7 OSI参照モデルとTCP/IPプロトコルスタック

2.5.1.ネットワークインターフェース層

ネットワークインターフェース層は、OSI参照モデルでの物理層、データリンク層にあたる。 Ethernetや電波などを制御して通信を実現するための層である。

2.5.2.インターネット層

インターネット層は、OSI参照モデルでのネットワーク層にあたる。 このレイヤで用いられるプロトコルがIPである。IPはコネクションレス型の通信を提供し、インターネット上で接続されたデバイス同士でデータが含まれたパケットのやり取りに使われる。 ネットワーク上のデバイス識別のためにIPアドレスと呼ばれるアドレスを用いる。 IPによって作成されたパケットには送信先のIPアドレスが含まれており、このパケットはネットワーク上のルータを経由して目的の送信先デバイスに到達する。

IPはコネクションレス型である以上、実際に相手にパケットが届いたかどうかを保証しない。よって、信頼性が必要な通信の場合は、上位のレイヤの機能を用いて補う必要がある。

2.5.3.トランスポート層

トランスポート層は、OSI参照モデルでのトランスポート層と同等である。 このレイヤではTCPやUDPといったプロトコルが用いられる。 TCPはコネクション型の通信を提供するプロトコルである。 他のデバイスから受け取ったパケットにエラーや不足がないことを確認する機能を持つ。% typo 必要応じて => 必要に応じて また、必要に応じて再送を要求する機能を持つ。 IPのコネクションレス型を補完し、信頼性が必要な通信で用いられる。

一方UDPはコネクションレス型のプロトコルである。 効率的な通信を優先しているためTCPのような信頼性を保つための機能は持たない。 そのため、比較的単純なパケット構造や処理の仕組みとなっている。

2.5.4.アプリケーション層

アプリケーション層は、OSI参照モデルでのセッション層からアプリケーション層にあたる。 TCP/IPやUDPから受け取ったデータを実際に処理してサービスを提供する部分である。 HTTPやFTPなどはアプリケーション層で用いられるプロトコルである。

2.6.µIP

µIPは、8ビットマイコンにおいてTCP/IPを使用した通信を行うことを目的に開発された、軽量TCP/IPスタックである[5]。Swedish Institute of Computer ScienceのAdam Dankelsらが中心となり開発されたプロジェクトである。Adam Dankelsはマイコンで動作するOSのContiki OSにも関与しており、Contiki OSのTCP/IPスタックにもµIPが採用されている。ソースコードのすべてがC言語で記述されているため、各マイコン向けに用意されているコンパイラとも相性が良い。また、Arduino向けに調整されたライブラリがいくつか存在する。µIP の特徴として、次の点が挙げられる [6]

上記のように、8ビットマイコン上でTCP/IPによる通信を行うための機能は一通り揃えられている。ただし、実装サイズを抑えるために極僅かでしか用いられないような機能やインターフェースが省かれている。

2.7.SLIP (Serial Line Internet Protocol)[7]

SLIPは、従来のダイヤルアップ接続での通信において、シリアルラインでのTCP/IP接続ができるように開発されたプロトコルである。TCP/IPのパケットをシリアルラインで送受信するためにフレーム化するという機能のみを持つ。パケットがバイト列の中で区別できるよう、特殊な終端文字を追加してパケットの混雑を防いでいる。

SLIPによって、マイコンで用いられるUARTポートを用いたシリアル通信にTCP/IPのパケットを流せるようになる。これにより、シリアルデバイスをネットワークデバイスへ読み替える「slattach」コマンドなどが必要になるが、PC上のOSにあるターミナルなどを介して容易にTCP/IP通信が可能となる。

ただし、SLIPは1対1のシリアルラインでの通信を主目的としているため、動的な接続先の変更はできない。また、静的に接続するため互いが事前にアドレスなど必要な情報を知っている必要がある。これらの欠点を補うプロトコルが、後に開発されたPPP(Point to Point Protocol)である。

2.8.IPerf

IPerfは、複数台のPCを使用してネットワーク回線の負荷試験・スループット計測などを行うツールである。WindowsだけでなくLinux系OSなどでも使用でき、環境によらずに使用できるという利点がある[8]

IPerfのプログラムはクライアント側、サーバ側の2つに分かれている。予めサーバ側プログラムを起動してTCPの指定ポートで待機させ、そのポートにクライアント側プログラムで接続することでスループット計測を行う。

IPerfにはいくつかのバージョンがあり、2021年現在での最新はIPerf3である。今回はIPerf3でなく、Arduino上でIPerfサーバを試したWebページ(How to Measure Arduino Network Performance)に倣い、IPerf2を使用した。IPerf2を使用した理由は、バージョン2と3の間で互換性が無く、Webページで示された方法が使用できない事態を防ぐためである。

3.提案手法の説明

XBeeとµIPを用いたTCP/IP通信を実現するための基本的なアイデアは次の通りである。

3.1.ZigBeeレイヤとの関係

ZigBeeレイヤには、ユーザが記述した処理を行わせることのできるアプリケーション層がある。XBeeの中には、通信機能の他にプログラマブルなマイコンを搭載することにより、1ボード内で完結させることのできるデバイスもある。今回はXBeeを単なる通信用デバイスとして扱い、アプリケーション層にあたる処理はArduino(AVRマイコン)へのプログラミングで定義する。従って、AVRマイコンがZigBeeレイヤのアプリケーション層としての動作を果たし、TCP/IPの処理並びに更に上位レイヤであるアプリケーション層の処理を行うことになる。

図8 TCP/IP階層モデルとZigBeeレイヤの対応及び実装

各機能をTCP/IPの4階層モデルに照らし合わせた図が図8である。ZigBeeレイヤでの物理層からAPSまでが、TCP/IP階層モデルにおけるネットワークインターフェース層にあたる。この層はXBeeの通信機能をそのまま利用する形とする。 また、ZigBeeレイヤでのアプリケーション層が、TCP/IP階層モデルにおけるインターネット層からアプリケーション層にあたる。この部分がAVRマイコンによる実装となる。

このように、ZigBeeレイヤのアプリケーション層部分にTCP/IPの機能を載せることによってXBeeを使用したTCP/IP通信を実現していく。

3.2.ネットワークインターフェース層の実装

TCP/IPの4層モデルにおけるネットワークインターフェース層の部分は、XBee S2CによるZigBee通信を利用する形態とする。以下に、物理的な接続の概略図を示す。

図9 物理的な接続の概略図

以下、XBeeが有線接続されたPC側をデバイス1、XBeeがシールドによって接続されたマイコン側をデバイス2とする。

各XBee間の通信にはZigBeeでの無線通信を使用する。PC側のXBeeは、XBee単体ではPCと接続することはできない。従って、デバイス1側のXBeeは開発ボードに搭載し、USBポートを介したシリアル通信を行う。デバイス2側のXBeeはArduinoシールドに搭載し、マイコンとシリアル通信を行う。

ここで、デバイス間で通信するデータはSLIPを用いたデータ構造とし、生のシリアルデータを送受信する形とする。シリアルデバイスをネットワークデバイスとして変換・使用するSLIPを用いることで、PCにインストールされたOS上のターミナル等の既存アプリケーションを変更せずに使用できる利点がある。また、SLIPは生のシリアルデータに独自の終端文字を付与してパケット化し通信を行う。よって、XBeeの通信モードをATモードに限定することで実装を簡略化でき、SLIPを使用する恩恵を受けることができる。APIモードで実装する場合は、PC側で受け取ったZigBeeパケットを解釈するプログラムや複数のパケットのペイロードを1つにまとめる処理が必要になり、実装が複雑となる。

3.3.インターネット層・トランスポート層の実装

TCP/IPの4層モデルにおけるインターネット層、トランスポート層の部分は、AVRマイコンのプログラムとして実装する。本研究ではµIPによるTCP/IPスタックを利用する。

µIPでは、TCP/IPの処理を単一のメインプログラムとして実装して処理を行う。そのためには、各マイコンのアーキテクチャに対応したクロック設定や下位レイヤを利用するためのドライバ等を適切に実装する必要がある。

クロック設定

TCP/IPの処理を行う上でタイムアウト等の判定を行うには、正確な時間管理を行う必要がある。µIPでは、タイマーを用いて時間管理を容易にするタイマーライブラリが用意されている。このライブラリを有効にするため、使用するマイコンのタイマー割り込み等を用いて、タイマーライブラリに伝える処理を実装する。それがclock-arch.hとclock-arch.cのプログラムである。

#ifndef __CLOCK_ARCH_H__ #define __CLOCK_ARCH_H__ #include <stdint.h> typedef uint16_t clock_time_t; #define CLOCK_CONF_SECOND (clock_time_t)61 #include "clock.h" #endif

ソースコード1 clock-arch.h

#include "global-conf.h" #include <stdint.h> #include <stdlib.h> #include <stdio.h> #include <avr/interrupt.h> #include <avr/io.h> #include <avr/sfr_defs.h> #include "clock-arch.h" // カウンター clock_time_t clock_datetime = 0; ISR(TIMER0_OVF_vect) { clock_datetime += 1; TIFR0 |= (1 << TOV0); } /** * @brief * clockの初期化 */ void clock_init() { // timer0のオーバーフロー割り込みを有効化 TIMSK0 |= (1 << TOIE0); // プリスケーラを1024とする TCCR0B |= ((1 << CS12)|(1 << CS10)); // 割り込み許可 sei(); } /** * @brief * timeを返却 * @return clock_time_t */ clock_time_t clock_time() { clock_time_t time; cli(); time = clock_datetime; sei(); return time; }

ソースコード2 clock-arch.c

今回使用するマイコン(ATmega328P)はArduinoボード上に実装されている。そのため、AVRマイコンはボード上に実装されている水晶発振器により、16MHzのクロック周波数で動作する。ATmega328Pにはいくつかのタイマーが存在するが、8bitのTimer0を使用する。Timer0の設定は以下のようにした。

これらの設定より、1秒を計測するために必要なカウントの値を計算する。まず、分周比を1024と設定しているので、1024回に1回Timer0の値が1増えることになる。ここから、タイマー割り込み間隔が次の式によって求められる。

この式から、clock_time_tは約16[ms]毎に1カウントアップすることが分かる。したがって、clock_time_tによって1秒を計測するためには、上限を61とするとほぼ1秒を計測できる。ここから、ソースコード1のCLOCK\_CONF\_SECONDが61と定義される。 ソースコード2では、実際にTimer0を使用するための初期化処理や、現在のclock_time_tのカウント値を取得する処理が実装されている。これらのソースコードは、上位に存在するタイマーライブラリによって使用される。

ドライバ設定

µIPの処理系へ外部デバイスから受け取ったデータを渡すためにドライバが必要である。µIPバージョン1.0では、Ethernetを用いたデバイス用のドライバは用意されている。しかし、今回使用するSLIP(シリアル通信)用のドライバは含まれていない。従って、過去のµIPバージョンからSLIP用ドライバを移植し、AVRマイコンに対応するように改変することで対応する。

メイン制御ループの実装

µIPを用いたTCP/IP通信を使用するため、ドライバ側とTCP/IPスタック・アプリケーションをつなげる役目を果たすのがメイン制御ループである。メイン制御ループの実装を疑似プログラムとして下記に示す。

// メイン関数 // int main(void) { // 時間切れ(=タイムアウト)のタイマーを容易・初期化 struct timer periodic_timer; clock_init(); timer_set(&periodic_timer, CLOCK_SECOND / 4); // SLIPドライバの初期化 (m328のuart初期化を含む) slipdev_init(); // uIP初期化 uip_init(); // IPアドレスを設定 uip_ipaddr(ipaddr, 192, 168, 5, 3); uip_sethostaddr(ipaddr); // デフォルトゲートウェイを設定 uip_ipaddr(ipaddr, 192, 168, 5, 1); uip_setdraddr(ipaddr); // サブネットマスクを設定 uip_ipaddr(ipaddr, 255, 255, 255, 0); uip_setnetmask(ipaddr); // アプリケーションを開始する // // メイン制御ループ // while (1) { // SLIPでバッファにデータを読み取る // uip_len = slipdev_poll(); // データがあれば処理をする // if (uip_len > 0) { // データを処理系に入力 // 処理後に送信するデータがあれば // if (uip_len > 0) { // データをSLIPで送信する } } // タイムアウトした場合 // else if (timer_expired(&periodic_timer)) { // タイマーをリセット // タイムアウト時の処理をする } } }

ソースコード3 メイン制御ループの疑似プログラム

ソースコード3に示すような処理をメインプログラムとして実装することによって、µIPを使用したTCP/IP通信を使用することが可能となる。この際に、前述したタイマーライブラリやドライバが必要となる。メイン制御ループでは以下のような処理を行う。

  1. タイムアウトを計測するタイマーを定義・初期化
  2. ドライバの初期化
  3. µIP自身の初期化
  4. IPアドレス・デフォルトゲートウェイなどの設定
  5. 目的アプリケーションを起動
  6. メイン制御ループに入り、データの待機・タイムアウト時の処理を行う

アプリケーション層の構造・実装

アプリケーション層の部分は、µIPアプリケーションとして実装することになる。µIPでアプリケーションを作成する場合、アプリケーションがTCP/IPスタックと対話する仕組みが二通り用意されている。一つは"プロトソケット"と呼ばれるものであり、TCPを使用する際に非常に容易に対話ができるAPIとなっている。もう一つは"µIPRaw API"と呼ばれるものである。こちらはプロトソケットより低レベルであるが、メモリ使用量を抑えることが可能である。今回はRaw APIを用いたアプリケーション層の実装を行う。

// アプリケーションの初期化を行う // void example_myapp_init(void) { // ポート開放など } // もう一方のデバイス側でリセットされた際に行う処理 // static void aborted(void) {} // 接続がタイムアウトした際に行う処理 // static void timedout(void) {} // もう一方のデバイス側で接続が閉じられた際に行う処理 // static void closed(void){} // 接続が開始された際に行う処理 // static void connected(void) {} // 新しいデータが到着した際に行う処理 // static void newdata(void) {} // ackを受け取った際に行う処理 // static void acked(void) {} // データを送信する処理 // static void senddata(void) {} void example_myapp_appcall(void) { if (uip_aborted()) { aborted(); } if (uip_timedout()) { timedout(); } if (uip_closed()) { closed(); } if (uip_connected()) { connected(); } if (uip_acked()) { acked(); } if (uip_newdata()) { newdata(); } if (uip_rexmit() || uip_newdata() || uip_acked() || uip_connected() || uip_poll()) { senddata(); } }

ソースコード4 アプリケーションの基本構造

µIP Raw APIを使用したアプリケーションは上記のソースコードに従って定義される。このアプリケーションに目的のプロトコルを実装することにより、TCP/IPを用いる様々なアプリケーションを作成することが可能となる。今回の研究においてIPerfを用いた測定を行ったが、IPerfサーバを模倣するアプリケーションも上記のアプリケーション構造に従ったプログラムを作成した。

4.計測

4.1.IPerfを用いたTCP/IP通信のスループット計測

4.1.1.目的

本計測では、3章にて設計・実装したArduinoとµIP、XBeeを用いたTCP/IP通信の特性を調べる。XBeeでの伝送速度の指標となるボーレートを変化させた際に、どれだけのスループットを得られるかの計測を行った。また、RTS/CTSフロー制御を組み込んだ際に通信の特性が変化するかを調べた。

4.1.2.計測環境

本計測にて使用した機器は以下に示す通りである。

表1 計測に使用した機器一覧

使用機器名 型番等 個数
XBee S2C XBee ZigBee S2CTH 2
Arduino 用 XBee シールド DFR0015 1
XBee シールド (スイッチサイエンス製) 1
XBee 開発ボード XBee THT Grove Development Board 1
Arduino Uno Arduino Uno Rev.3 2
ロジックレベル変換モジュール FXMA108 1
ジャンパワイヤ 数本
ブレッドボード 1
USB ケーブル A オス-マイクロ B オス 1
USB ケーブル A オス-B オス 1
PC Optiplex3060 1

使用したPCの構成を以下に示す。

表2 計測に使用したPCの構成

PC Optiplex3060 SFF
ホストOS Windows 11 Pro (Version 10.0.22000.376)
CPU Intel Core i5-8500
ゲストOS1 Ubuntu 18.04 LTS (Windows Subsystem for Liunx 2)
ゲストOS2 Ubuntu 20.04 LTS (VirtualBox)

今回の計測では、プログラムのコンパイル・マイコンへの書き込み・マイコンとの通信をそれぞれ同じPC上の別環境で行った。それぞれの関係性を以下に図で示す。

図10 PC上の環境概略図

Windowsでは、XBeeの設定やAVRマイコンへのプログラム書き込みを主に行った。WSL2上のUbuntu 18.04ではAVRマイコン向けプログラムのコンパイルを行った。また、Virtual Box(仮想マシン)上のUbuntu 20.04は、実際にマイコンとTCP/IP通信を行う実験環境として使用した。

表3 計測に使用したソフトウェア等

ソフトウェア名 バージョン 使用した状況など
Oracle VM VirtualBox 6.1.28 r147628 Ubuntuを仮想マシン上で動作させるため
Windows Subsystem for Linux バージョン2 Ubuntuを軽量コンテナ上で動作させるため
XCTU Version: 6.5.6 XBeeの設定を行うため
Avrdude Version 6.3.1.1-windows AVRマイコンへ書き込みを行うため
avr-gcc 5.4.0 C言語プログラムをコンパイルするため
avr-objcopy 2.26.20160125 コンパイル後に使用する
slattach 2.10-alpha SLIPを使用するため
IPerf2 2.0.13 スループット計測のため

次に、XBeeやArduino等の接続図を以下に示す。

図11 接続図

また、実際に配線したときの画像を以下に示す。

図12 実際に接続した様子(ロジックレベル変換を含む)

TCP/IPを用いた通信を行うため、それぞれのデバイスへ次のようなアドレスを設定した。

表4 IPアドレス等の設定状況

PC側 マイコン側
IPアドレス 192.168.5.1 192.168.5.3
サブネットマスク 255.255.255.0 255.255.255.0
デフォルトゲートウェイ 192.168.5.1 192.168.5.1

最後に、今回の計測ではµIPの設定を以下のように行った。

表5 µIPの設定

設定 意味
UIP_CONF_MAX_CONNECTIONS 1 TCP接続可能な最大値
UIP_CONF_MAX_LISTENPORTS 1 待機できるTCPポートの最大値
UIP_CONF_BUFFER_SIZE 128 µIPバッファの大きさ
UIP_CONF_BYTE_ORDER LITTLE_ENDIAN AVRマイコンであればこの値
UIP_CONF_LOGGING 0 ログ機能は使用しない
UIP_CONF_UDP 0 UDPは使用しない
UIP_CONF_UDP_CHECKSUMS 0 UDPチェックサムは使用しない
UIP_CONF_STATISTICS 0 統計を使用しない
UIP_CONF_BROADCAST 0 ブロードキャストを使用しない
UIP_CONF_UDP_CONNS 0 UDP接続の最大値
UIP_REASSEMBLY 0 IPパケットを再構成しない
UIP_CONF_LLH_LEN 0 リンクレベルヘッダの長さ(SLIPなので0)

4.1.3.計測1:フロー制御を使用しない場合の手順

  1. 前節に示した接続図のように、XBee開発ボードやArduinoを接続する。
  2. XBeeの設定を行う。設定値は以下の通りとする。以下に記していない設定値は既定の値を使用する。

    表6 XBeeの設定値

    設定値 XBee1 XBee2 意味
    ID 2021 2021 PAN ID
    JV Enabled Disabled Channel Verification
    JN Disabled Disabled Join Notification
    CE Disabled Enabled Coordinator Enable
    DH 13A200 13A200 Destination Address High
    DL 41531D4A 41531EBF Destination Address Low
    NI ROUTER COORD Node Identifier
    BD 1200 1200 Baud Rate

    以下、XBee1をArduinoシールド側に接続したXBee、XBee2をPCに接続したXBeeとして扱う。

  3. AVRマイコンにIPerfサーバを模倣するµIPアプリケーション(付録2)を書き込む。この際、XBeeに設定したボーレートとAVRマイコンでのUARTボーレートを揃える。
  4. 全ての接続を確認後、仮想マシン上のUbuntuでslattachコマンドを使用してXBee2をネットワークデバイスに読み替える処理を行う。この際に使用したシェルスクリプトは付録3に記す。
  5. IPerfによるスループット計測を行う前に、接続確認のためpingをXBee1に向かって打つ。pingコマンドは以下に示す通りである。

    ping -c 10 192.168.5.3

  6. pingによる接続確認後、IPerf2を用いてスループット計測を行う。IPerfの設定を以下に示す。
    • Window Size : デフォルト 25KByte
    • 1秒毎に途中経過を表示
    • 30秒間計測を行う。

    これらを適用したIPerfのコマンドを以下に示す。

    iperf -c 192.168.5.3 -i 1 -t 30

  7. IPerfの計測は3回行い、最終的な結果(30秒間)の平均値を取る。
  8. 計測終了後、ボーレートを2400,4800,9600,19200,38400,57600,115200と変更し、同様の測定を行う。

4.1.4.計測2:フロー制御を使用する場合の手順

  1. 計測手順1と同様に、XBee開発ボードやArduinoを接続する。
  2. XBee1側のRTSポートをAVRマイコンに設けたRTSピンへ、CTSポートをCTSピンへ接続する。この際、直接接続するのではなく、ロジックレベル変換モジュールを介した接続とする。
  3. XBeeの設定を行う。計測手順1の設定値に示した値に加え、以下の項目を設定する。

    表7 XBeeの設定値

    設定値 XBee1 XBee2
    D6 nRTS flow control Disable
  4. AVRマイコンにIPerfサーバを模倣するµIPアプリケーション(付録2)を書き込む。この際、XBeeに設定したボーレートとAVRマイコンでのUARTボーレートを揃える。
  5. 全ての接続を確認後、仮想マシン上のUbuntuでslattachコマンドを使用してXBee2をネットワークデバイスに読み替える処理を行う。この際に使用したシェルスクリプトは付録3に記す。
  6. IPerfによるスループット計測を行う前に、接続確認のためpingをXBee1に向かって打つ。pingコマンドは以下に示す通りである。

    ping -c 10 192.168.5.3

  7. pingによる接続確認後、IPerf2を用いてスループット計測を行う。IPerfの設定を以下に示す。
    • Window Size : デフォルト 25KByte
    • 1秒毎に途中経過を表示
    • 30秒間計測を行う。

    これらを適用したIPerfのコマンドを以下に示す。

    iperf -c 192.168.5.3 -i 1 -t 30

  8. IPerfの計測は3回行い、最終的な結果(30秒間)の平均値を取る。
  9. 計測終了後、ボーレートを2400,4800,9600,19200,38400,57600,115200と変更し、同様の測定を行う。

4.1.5.計測1の結果

計測手順1において、フロー制御を使用していない場合のping結果は以下のようになった。なお、以下の結果が含まれるコンソールログ全文は付録に掲載した。

表8 ボーレートに対するping統計値

ボーレート[bps] パケット損失[%] RTT最小[ms] RTT平均[ms] RTT最大[ms]
1200 0 2895.047 2903.899 2911.118
2400 0 1462.325 1470.495 1481.756
4800 0 746.137 753.217 771.823
9600 0 388.704 394.371 400.673
19200 0 204.480 212.714 219.170
38400 0 116.488 124.927 134.118
57600 0 92.585 96.641 101.805
115200 100 - - -

図13 ボーレートに対する往復遅延時間の最小値・平均値・最大値の特性

フロー制御を使用しない場合、pingによるRTT(往復遅延時間)はボーレートが大きくなるにつれて減少する傾向が見られる。また、RTT最小・平均・最大の各値に大きな差がないと分かる。 なお、XBeeが使用できる標準最大ボーレートの115200[bps]では、パケット損失が100[%]となり、全く通信ができていないと確認された。

次に、計測手順1での、フロー制御を使用していない場合のIPerfによる帯域幅の結果を以下に示す。なお、以下の結果が含まれるコンソールログ全文は付録に掲載した。

表9 ボーレートに対するIPerfによる帯域幅

ボーレート[bps] 帯域幅[kbps]
1200 0.699
2400 0.951
4800 1.453
9600 2.376
19200 4.003
38400 6.52
57600 8.18
115200 -

図14 ボーレートに対する帯域幅の特性

上記のグラフは、表9の結果を両対数グラフで示したものである。このグラフから、ボーレートが倍々に増加する2400[bps]から38400[bps]の間で、帯域幅が直線的な増加をしている傾向が分かる。なお、pingによる計測にて使用できなかったボーレート115200[bps]は、IPerfによる帯域幅計測でも測定不能であった。

4.1.6.計測2の結果

計測手順2での、フロー制御を使用した場合のping結果は以下のようになった。なお、以下の結果が含まれるコンソールログ全文は付録に掲載した。

表10 ボーレートに対するping統計値

ボーレート[bps] パケット損失[%] RTT最小[ms] RTT平均[ms] RTT最大[ms]
1200 0 2779.340 2844.586 2926.622
2400 0 1390.903 1437.417 1476.864
4800 0 752.598 1085.977 1591.828
9600 0 391.921 1032.577 1313.606
19200 0 1131.868 1161.792 1188.682
38400 0 1069.943 1075.674 1084.303
57600 0 1049.754 1057.236 1060.496
115200 0 1035.020 1047.006 1082.609

図15 ボーレートに対する往復遅延時間の最小値・平均値・最大値の特性

フロー制御を使用した場合、ボーレートの115200[bps]にて通信ができると確認された。しかし、計測1のように単にRTTが減少していく結果では無かった。1200[bps]~2400[bps]の範囲では、単純にRTTは減少しているが、2400[bps]~19200[bps]の間ではRTT最小・最大に大きく差が見られる。また、19200[bps]以降では約1000[ms]付近でRTTが安定する傾向が見られる。

次に、計測手順2における、フロー制御を使用していない場合のIPerfによる帯域幅の結果を以下に示す。なお、以下の結果が含まれるコンソールログ全文は付録に掲載した。

表11 ボーレートに対するIPerfによる帯域幅

ボーレート[bps] 帯域幅[kbps]
1200 0.687
2400 0.966
4800 1.460
9600 2.383
19200 4.010
38400 6.583
57600 8.576
115200 10.96

図16 ボーレートに対する帯域幅の特性

上記のグラフは、表11の結果を両対数グラフに表したものである。フロー制御無しの場合と同様な結果となった。加えてボーレートが115200[bps]にて通信が行え、実際に帯域幅を測定できた。

4.2.比較・考察

計測の結果から、フロー制御の有無が計測値に影響を与える場合と、概ね影響が無い場合の2通りが見て取れた。

4.2.1.ping計測

フロー制御が影響を与えたと考えられる計測はpingである。フロー制御の有無の影響を比較するため、以下にpingによって測定できるRTT3値をグラフに表した図を示す。

図17 フロー制御の有無によるRTT最小値の比較

上記のグラフから見て取れるのは、ボーレートが19200[bps]以上であると、RTT最小値がフロー制御無しと比較して極端に悪化する傾向である。19200[bps]では約927[ms]、38400[bps]では約953[ms]、57600[bps]では約957[ms]と、1秒に近い悪化が見られる。この結果からして、ボーレートが19200[bps]以降ではシリアル通信の部分でフロー制御が発生していると考えるのが妥当である。RTS/CTSフロー制御では処理が間に合わない時にデータの送信を一時停止するため、今回見られた1秒近くの遅延は、マイコン側でのシリアル受信バッファが溢れた結果の遅延であると考えられる。

RTT最小値は、10回pingによる計測を行った中での最良値である。従って、ボーレート19200[bps]以降では、全てのpingの際にフロー制御が生じていたと考えるのが妥当である。

図18 フロー制御の有無によるRTT最大値の比較

上記のグラフは、RTT最大値の比較を行ったものである。RTT最小値を比較したグラフでは、フロー制御の有無による違いが見えたのはボーレートが19200[bps]以降であった。しかし、RTT最大値の比較では4800[bps]になった時点で差がある。フロー制御が無い場合は、ボーレートが上がるに従ってRTTは次第に減少するような曲線が見られる。フロー制御がある場合は、4800[bps]で一度悪化してから緩やかに減少していく形となっている。

RTT最大は、10回pingによる計測を行った中での最悪値であるので、ボーレート4800[bps]以降で、RTTが極端に悪化する事象が発生していると考えられる。2つの計測ではフロー制御の有無のみを変え、それ以外のパラメータやXBee間の物理的な距離は変更していないため、RTT悪化に関与した事象はフロー制御である可能性が高い。従って、ボーレート4800[bps]以降では少なくとも1回は、pingの際にフロー制御が掛かったと考えられる。

計測1・2やフロー制御の有無によるRTT最小・最大の比較結果から、次のように考えられる。

4.2.2.IPerf計測

pingによる計測では、フロー制御が結果に大きく影響したと考えられる。しかし、IPerfではフロー制御の有無は結果に影響が無いように見られる。以下に、フロー制御の有無によるIPerfでの帯域幅測定の比較を示す。

図19 フロー制御の有無による帯域幅の比較

上記に示したように、フロー制御をしていない状態ではボーレート57600[bps]までの計測しか実行できなかったという差はあるが、フロー制御の有無に関わらずほぼ同じ値を取ると分かる。このような結果を示した理由は以下の様に考えられる。

RTS/CTSフロー制御の発動条件とパケットサイズである。今回、AVRマイコンのシリアル通信を行うために外部のライブラリを使用した。今回使用したライブラリでは、シリアル受信バッファが設定値の-1バイト(今回は128バイト設定なので127バイト)になった際に、RTS出力をHighにする制御が行われている。その後、追加で2バイト分を受信できるようになっている。これは、RTSをHighにした時に相手に伝達するまでの時間差を考慮した実装である。

ここで、今回のIPerfによる測定ではµIPバッファを128バイトとしている関係で、互いにやり取りされるパケットの最大値サイズが128バイトである制限を考慮すると、以下のような処理となっていた可能性がある。

  1. マイコンはシリアル受信バッファにデータを貯めていく。
  2. 1パケットの127バイト目まで受信した時点でRTS出力をHighにしてフロー制御を掛けようとする。
  3. シールド上のXBeeはフロー制御により送信を止めるが、シリアル通信ライブラリの制御上128バイト目まで受信できる。
  4. µIPバッファにシリアル受信バッファをコピーする(この時点で受信バッファは空である)。
  5. シリアル受信バッファが空にであるため、フロー制御をやめるような処理が働く。

上記のような処理になっているのであれば、IPerf計測でのフロー制御は高ボーレートでの安定性を担保する程度の役割しか果たさず、57600[bps]までの結果がほぼ同一になったと考えられる。

フロー制御の有無がIPerfでの帯域幅測定に影響を及ぼさないと結果から見て取れるが、ボーレートに対して帯域幅が小さい結果が見られる。この理由を考察するため、パケットキャプチャを行った。パケットキャプチャを行うにあたって、計測2の手順に則り、ボーレートを57600[bps]に設定した。 ボーレート57600[bps]での1パケット毎の往復遅延時間を、WireSharkというネットワーク解析ソフトウェアにより解析した結果を以下に示す。

図20 1パケット毎の往復遅延時間(フロー制御あり・57600[bps])

グラフ上に示された点が1パケット毎のRTTを示している。上記のグラフを見る限り、多少の上下があるものの、おおむねRTTが80[ms]程度でパケットのやり取りが行われていると考えられる。そこで、RTTを80[ms]として計算を行う。

1パケットの送受信で約80[ms]かかるので、

となり、1秒間で概ね12パケット程度のやり取りが行われている計算になる。ここで、1パケットあたり128バイトであり、IP/TCPヘッダが40バイトであるので、ペイロード部分は88バイトである。したがって12パケットで

と求められるので、計測された値は適当であったと考えられる。

5.まとめ

本研究では、AVRマイコンとXBeeにおいて、効率的なファイル転送を行うための基礎として、µIPによるTCP/IP通信を用いる手法を提案した。実際のプロトコルを動作させるには至らなかったが、AVRマイコン上でTCP/IP通信をXBee(ZigBee)によるネットワーク上で行えたと考えられる。これにより、既存のTCP/IPを使用したアプリケーション層の資産を活かしつつ通信が可能となる。既存のIPerfというアプリケーションのサーバサイドの動作を実現できた結果から、IPerfに限らずとも、他のプロトコルを動作させ応用的な利用をし得ると考えられる。

また、IPerfによる計測より、シリアル通信フロー制御こそ必要であるが115200[bps]といった高いボーレートでは10[kbps]程度の帯域幅があると分かった。この計測上の数値によるが、10[kbps]は1.25[KB/s]程度となるため、2バイト文字換算で約500文字程度の送受信が行えると考えられる。

今後の課題は、これらTCP/IP通信の多デバイス対応と帯域幅向上・プロトコル処理の実現性が上げられる。本研究では、ZigBeeネットワークの動作モードとしてATモードを使用した。しかしながら、ATモードでは1対1での通信が主となってしまうため、センサネットワークを構築して利用するZigBeeの利点を生かし切れていない。他デバイス対応という観点ではAPIモードが理想的ではあるが、ZigBeeAPIパケットサイズが128バイトであるなど、Ethernet等の物理層と比較してリソース不足が否めない。センサネットワークとして利活用していくためには、この点を改善していくことが一つの課題となる。

帯域幅の向上については、長いパケットサイズに耐え得る性能を持つマイコンを使用するなどの工夫が必要である。特にプログラムメモリサイズ・RAM容量が重要である。今回実現するに至らなかったTFTP(Trivial File Transfer Protocol)は、512バイトのパケットサイズを基本にデータの送受信を行う。今回使用したATmega328Pは、プログラムメモリこそ潤沢ではあるがRAM容量が2[KB]と小さい。そこにµIPバッファ、シリアル送受信バッファをそれぞれ512バイト用意するだけでRAMの75%を使用してしまう。この点は、上位のマイコンを利用するなどして改善を図るべきである。 性能に余裕のあるマイコンを利用することは、センサネットワーク全体のコストが増加することにつながるが、それだけプロトコル処理の実現性向上につながるだろうと考えられる。

上記に示した課題を解決し、実際にセンサネットワーク上でプロトコルを用いたデータの転送を行えるように改善していきたい。

参考文献

  1. Microchip Technology, 「ATmega328P DataSheet」, https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf
  2. 東京電機大学 工学部 情報通信工学科, 「3EC 情報通信工学実験」, 東京電機大学出版局, pp.9-10, 2020年
  3. Digi International Inc. , 「XBee/XBee-PRO® S2C Zigbee® RF Module」, https://www.digi.com/resources/documentation/DigiDocs/90002002/Default.htm
  4. Digi International Inc. , 「XBee Zigbee Mesh Kit User Guide」, https://www.digi.com/resources/documentation/Digidocs/90001942-13
  5. Swedish Institute of Computer Science, 「The uIP embedded TCP/IP Stack (The uIP 1.0 Reference Manual)」, https://github.com/adamdunkels/uip
  6. 神奈川大学 工学部 電子情報フロンティア学科 上甲 薫:「µIPを用いたセンサネットワークの効率化」, 平成21年度
  7. 「TCP/IPネットワーク管理」, オライリー・ジャパン, pp.167-168, 2003年
  8. 「ネットワークトラブルシューティングツール」, オライリー・ジャパン, pp.98-105, 2002年

付録

付録1.µIPの構成図

図21 µIPを構成するプログラムの全体図

avr向けに調整されたµIPとUARTライブラリは以下のページにて公開されている。

https://github.com/avr-uip/avr-uip

今回の研究にあたり追加した部分は、

の主に3フォルダである。

付録2.µIPアプリケーションのプログラム

以下に、本研究にあたりµIPへ追加したプログラムを示す。

./projects/UIPTest-SLIP.m328p

./drivers/slipdev

他に「usart_config.h」、「usart.h」、「usart.c」というAVR向けシリアル通信ライブラリがこのフォルダに含まれる。これらは https://github.com/jnk0le/AVR-UART-libを利用したものである。

./apps/iperf-server

付録3.SLIP接続時のシェルスクリプト

次のように使用する

sudo sh SLIP_attach.sh -s 57600 -p /dev/ttyACM0

-sオプションでは使用したいボーレートを選択する。-pオプションでは接続されているポートを選択する。slattachコマンドの利用にsudoが必要となるので、シェルスクリプト実行時にsudoを付ける。

付録4.pingおよびIPerf計測結果のコンソールログ

以下に本研究において計測したping・IPerfの結果のコンソールログを示す。

計測手順1(フロー制御なし)の結果

計測手順2(フロー制御あり)の結果