nRF24L01+ArduinoでSLIPによるTCP/IP通信の実験

注)当記事で取り上げるnRF24L01ボードは技適を取得していないデバイスです。記事を参考にされる場合はご注意ください。

前回記事では、ラズパイ-Arduino間でnRF24L01を用いてTCP/IP通信が出来る事を確かめた。

ラズパイ-ラズパイ間であればnRF24L01経由のTCP/IP通信も出来るようだが、nRF24L01のドライバはラズパイ以外のLinuxシステムに未対応。但し、ArduinoとLinuxをシリアル通信で接続しSLIPを使ってArduino経由でTCP/IP通信は出来そう、という事で試してみた。

スポンサーリンク

nRF24L01を介して2台のLinux間でTCP/IP通信する

nRF24L01とTCP/IPプロトコルスタックを繋ぐ”RF24Ethernet”

nRF24L01を用いたTCP/IP通信は作者によってRF24Ethernetと呼ばれており、下記ページに情報がある。

RF24Ethernet - TCP/IP over RF24Network: RF24Ethernet library: TCP/IP over RF24Network

RF24Ethernetのネイティブ対応はラズパイのみ

上記RF24Ethernetのページを起点にあちこちリンクが飛んで情報が分散しており少々分かりづらいのだが、要は「ラズパイ同士ならnRF24L01を使ったEthernetもどきであるRF24Ethenetで通信出来る」という事らしい。逆に言うとラズパイ以外は非対応ということで、実際試しにArmbian(ハードはNano Pi Neo2、Armbianに関する詳細はこの記事参照)でトライしたところ、ビルドが通らず断念した。

ラズパイ以外のLinuxでRF24Ethernetを使うカラクリ

自分は一台しかラズパイの手持ちが無く詰んだと一瞬思ったものの、ArduinoにnRF24L01とIPパケットの相互変換を任せればラズパイ以外のLinuxでも行けそうと考え試したところ、無事ラズパイじゃないLinuxでもRF24Ethernetを使う事が出来た。Linux①をラズパイ、Linux②をラズパイ以外のLinuxとすると、Linux①②間でTCP/IP通信する様子はざっくり以下の図のようなイメージ。(コードをしっかり読んだわけではないので間違っているかもしれないが)

fig

Linux①②のマイコンの他に第3のマイコンArduinoを補助的に使う構成で、Linux①のインターネット接続を介してLinux②をインターネットに繋ぐための役割はそれぞれ以下のような感じ。

  • Linux①:インターネットへのルーティングと、IPパケット⇔nRF24L01無線パケットの相互変換
  • Arduino:IPパケット⇔nRF24L01無線パケットの相互変換と、IPパケットのSLIPインタフェース
  • Linux②:SLIPインタフェースを介してIPパケットを送受信することにより、TCP/IP通信する

ラズパイ/Arduino+nRF24L01のセットアップ

前回実験との違い

前回記事ではラズパイからnRF24L01ワイヤレス接続を介してArduinoにpingを打って返ってくる事だけを確認したのに対し、今回はArduinoのUART経由で外部のLinuxをTCP/IP接続させたいのでArduinoスケッチに少し変更が必要。

ハードの接続

ピン接続は以下の通りで、ハード的には前回記事と全く同じでOK。詳細は前回記事を参照。

NRF24L01Arduinoラズパイ
GND(1)GNDGND
VCC(2)3.3V LDO出力3V3
CE(3)digIO 7rpi-gpio22 (15)
CSN(4)digIO 8rpi-gpio8 (24)
SCK(5)digIO 13rpi-sckl (23)
MOSI(6)digIO 11rpi-mosi (19)
MISO(7)digIO 12rpi-miso (21)
IRQ(8)

Arduinoスケッチ

Arduinoのサンプルスケッチそのままでは目的を果たせないので、RF24EthernetのサンプルスケッチSLIP_Gatewayをベースに少し改造を加えた物を利用。変更箇所は、

  • 自分のIPアドレス(10.10.2.7)とラズパイGatewayのIPアドレス(10.10.2.1)を設定
  • SLIP経由で受け取ったパケットはMeshID 0(=Gateway)に全て投げる

変更したSLIP_Gateway.inoのダウンロードはここからどうぞ。
スケッチの主要部分を抜粋すると以下のような感じ。

#define MY_MESHID 7

void setup() {
  // Set up the speed of our serial link.
  Serial.begin(115200);
  printf_begin();
  Serial.println("start");

  mesh.setNodeID(MY_MESHID);
  mesh.begin();

  IPAddress myIP(10, 10, 2, MY_MESHID);
  Ethernet.begin(myIP);

  IPAddress gwIP(10, 10, 2, 1);
  Ethernet.set_gateway(gwIP);

  //Optional
  radio.printDetails();

  // Use the serial port as the SLIP device
  slipdev_init(Serial);
}

void loop() {
  //Ensure any incoming user payloads are read from the buffer
  while (network.available()) {
    RF24NetworkHeader header;
    network.read(header, 0, 0);
  }

  if (mesh.update() == EXTERNAL_DATA_TYPE) {
    networkToSLIP();
  }

  // Poll the SLIP device for incoming data
  uint16_t len;

  if ((len = slipdev_poll()) > 0) {
    if (len > MAX_PAYLOAD_SIZE) {
      return;
    }
    RF24NetworkHeader header(01, EXTERNAL_DATA_TYPE);
    header.to_node = 0;

    network.write(header, &slip_buf, len);
  }
}

Ubuntu22.04 Linux BoxのSLIP接続によるTCP/IP通信

前回実験とArduinoの周辺ハードは全く同じ状態で上記スケッチ書き込んだ後、ArduinoのUARTに接続されているUSBシリアルをそのままUbuntu22.04のLinuxに繋ぎ変えてテストを行った。

ラズパイ側の操作は前回記事と全く同一で、RF24Gateway_ncursesを実行しておけばOK。

写真

Ubuntu22.04側のSLIPとIPアドレスを設定

まずはSLIPインタフェースにシリアルポートをバインド。

sudo slattach -L -s 115200 -p slip /dev/ttyUSB0 &

IPアドレスの設定(Arduinoのスケッチで設定したのと同じアドレスを指定する)。

sudo ifconfig sl0 10.10.2.7/24

pingを実行

Ubuntu22.04側からラズパイ側(IPアドレス10.10.2.1)に向けてping実行。無事パケットが返ってきた。

$ ping 10.10.2.1
PING 10.10.2.1 (10.10.2.1) 56(84) bytes of data.
64 bytes from 10.10.2.1: icmp_seq=1 ttl=64 time=36.6 ms
64 bytes from 10.10.2.1: icmp_seq=2 ttl=64 time=36.7 ms
64 bytes from 10.10.2.1: icmp_seq=3 ttl=64 time=37.5 ms
64 bytes from 10.10.2.1: icmp_seq=4 ttl=64 time=36.5 ms

反対に、ラズパイ側からUbuntu22.04側に向けてping実行。こちらも問題なし。

$ ping 10.10.2.7
PING 10.10.2.7 (10.10.2.7) 56(84) bytes of data.
64 bytes from 10.10.2.7: icmp_seq=1 ttl=64 time=38.9 ms
64 bytes from 10.10.2.7: icmp_seq=2 ttl=64 time=37.8 ms
64 bytes from 10.10.2.7: icmp_seq=3 ttl=64 time=38.7 ms
64 bytes from 10.10.2.7: icmp_seq=4 ttl=64 time=40.0 ms

ping実行中にラズパイ側で実行中のRF24Gateway_ncursesの画面でRX PacketsとTX Packetがカウントアップされるのがを確認出来る。
TxRx

sshの実行

SSHを実行しラズパイへの接続を試みた…が、ログインプロンプトが表示されず。

ssh 10.10.2.1

ラズパイ側RF24Gateway_ncursesの画面でRX PacketsとTX Packetのカウントが増えていくので何らかパケットのやりとりはされている筈だが、残念ながら数分待ってもログインまで辿り着けなかった。

試しにSSHのポート番号22に向けてtelnetを実行してみると、ちゃんと応答が返って来るので通信自体は出来ていそうなのだが。

$ telnet 10.10.2.1 22
Trying 10.10.2.1...
Connected to 10.10.2.1.
Escape character is '^]'.
SSH-2.0-OpenSSH_8.4p1 Raspbian-5+deb11u1

HTTPサーバにtelnetで接続

どうも様子が変なので、ラズパイ側からUbuntu22.04で稼働しているHTTPサーバへtelnetで手動接続して応答が返ってくるか試してみた。

$ telnet 10.10.2.7 80
Trying 10.10.2.7...
Connected to 10.10.2.7.
Escape character is '^]'.
GET / HTTP/1.0

トップページ(/)のGETリクエストを手打ちで発行してもサーバからの応答が何も返って来ない。惜しい所まで来ている感じだが、TCP/IP通信が不完全で実用レベルには未だ達していないような印象。

まとめ

nRF24L01を用いたTCP/IP接続で2台のLinux間で通信が出来るか試してみた。双方のホストからpingの応答が得られたものの、HTTPやSSHの接続は何故か失敗するという結果となった。安価なnRF24L01はSBC用の通信インタフェースとして有望とちょっと期待したのだが、残念ながら実用レベルには達していないようだ。

コメント