XBee3の新機能を試す。(MicroPython:REPL編2)

〔マイコンのトップに戻る〕
[Xbeeの実験] [FileSystem] [REPL 1]   [PyCharm導入] [PyCharmの操作] [PyCharmで開発]


前回の続きで”MicroPython:REPL編”ですが、
このページではXBee32個使いそれぞれにルーター・コーディネーターとして動作させてみます。
ここの実験では、秋月電子のXBee USBインターフェースボードキットか、
スイッチサイエンスのXBee USB アダプターが 2個は必要です。
又、”USBシリアル変換モジュール”でも利用できます。

《コーディネータがメッセージを受信する》

XBee3の内臓温度センサー値をルーターから定期的にコーディネーターに送信してみます。

[ コーディネーター側 ]

コーディネータで、メッセージを受信するには、xbeeモジュールのreceive() 関数を使用します。
MicroPythonがデバイス上でアクティブな場合(APが4に設定されている)、全ての着信メッセージは
MicroPython内の受信キューに保存されます。
この受信キューのサイズは限られており、4メッセージ分のスペースしかありません。
データが失われない様にするには、受信キューを継続的に繰返して内部のパケットを処理する事が重要です
受信キューがいっぱいになり、別のメッセージがデバイスに送信された場合、パケットを確認応答せず、
送信側は0x24(アドレスが見つかりません)の失敗ステータスを生成します。
receive()関数結果は以下のフィールドを持つリスト出力です。
尚、メッセージがなし(受信キューが空)の場合は、Noneを返します。
 ・sender_nwk :送信ノードの16ビットネットワークアドレス
 ・sender_eui64:送信ノードの64ビットアドレス( "bytesオブジェクト"として)
 ・source_ep  :整数としてのソースエンドポイント
 ・dest_ep   :整数としての転送先エンドポイント
 ・cluster    :整数としてのクラスタID
 ・profile    :整数としてのプロファイルID
 ・broadcast   :フレームがブロードキャストならTrue、ユニキャストはFalse
 ・payload    :データ本体の「Bytesオブジェクト」
          データ本体にはバイナリデータを含める事ができる為、
          これは文字列ではなくバイトオブジェクトです。

次のコード例は、コーディネーターとしてZigbeeネットワークを形成し、リモートノードを見つける為に
ネットワーク検出を実行して、受信データを継続的に出力(受信していれば)します。

 1.親機(コーディネータ)を”パソコンと繋いでみる”の様に配線します、
   親機の設定はXBeeパート3の"親機の設定を行う"を参照下さい。
 2. MicroPython環境にアクセスします。
 3. 次のサンプルコードをコピーします。
   貼り付けモードの方法はこちらを参照ください。
--------------------------------------------------------------------------------
import xbee, time

# XBee3 受信したメッセージの操作を実行する為のユーティリティ関数
def format_eui64(addr):
    return ':'.join('%02x' % b for b in addr)

def format_packet(p):
    type = 'Broadcast' if p['broadcast'] else 'Unicast'
    print("%s message from EUI-64 %s (network 0x%04X)" %
          (type, format_eui64(p['sender_eui64']), p['sender_nwk']))
#    print("from EP 0x%02X to EP 0x%02X, Cluster 0x%04X, Profile 0x%04X:" %
#          (p['source_ep'], p['dest_ep'], p['cluster'], p['profile']))
    print(p['payload'],"\n")


print("Forming a new Zigbee network as a coordinator...")
xbee.atcmd("NI", "Coordinator")

network_settings = {"CE": 1, "ID": 0x777, "EE": 0, "NJ": 0xFF}
for command, value in network_settings.items():
    xbee.atcmd(command, value)
xbee.atcmd("AC")  # 変更を適用する
time.sleep(1)     # 1秒待つ

# ネットワーク接続が成功するまで待つ
while xbee.atcmd("AI") != 0:
     time.sleep(0.1)  # 0.1秒待つ
print("Network Established\n")

print("Waiting for a remote node to join...")
node_list = []
while len(node_list) == 0:
    # ルータが参加するまでネットワーク検出を実行する
    node_list = list(xbee.discover())
print("Remote node found, transmitting data")

for node in node_list:
    dest_addr    = node['sender_nwk']  # using 16 bit addressing
    dest_node_id = node['node_id']
    payload_data = "Hello, " + dest_node_id + "!"
    print("Sending \"{}\" to {}".format(payload_data, hex(dest_addr)))
    xbee.transmit(dest_addr, payload_data)  # 参加ルータにメッセージを送る

# 受信ループを開始する
print("Receiving data...")
print("Hit CTRL+C to cancel")
while True:
    p = xbee.receive()
    if p:
        # 何か受信したら表示を行う
        format_packet(p)
    else:
        time.sleep(0.25)  # 0.25秒待つ
--------------------------------------------------------------------------------
 4.[Ctrl + D]を押して起動させて置きます。
   下記の様に表示されリモートノードの接続待ちを行います。
   --------------------------------------------------------------------------------    Forming a new Zigbee network as a coordinator...    Network Established        Waiting for a remote node to join...    --------------------------------------------------------------------------------    リモートノードが起動(接続)状態であれば、リモートノードに"Hello, Router!"を送信し、    リモートノードからのデータ受信待ちにはいります。    "Router"文字はルータ側で設定されている"NI"ノード名になります。    --------------------------------------------------------------------------------    Forming a new Zigbee network as a coordinator...    Network Established        Waiting for a remote node to join...    Remote node found, transmitting data    Sending "Hello, Router!" to 0x375e    Receiving data...    Hit CTRL+C to cancel --------------------------------------------------------------------------------

[ ルーター側 ]

温度は、MicroPythonのatcmd()メソッドを使い、"ATコマンド"の”TP”コマンドから得ています。
そして、温度データはtransmit()関数で送信しています。
尚、"atcmd()"については前回の”MicroPythonを使用したATコマンド”を参照ください。
又、"transmit()"については”ネットワークコーディネータにメッセージを送信する”を参照ください。

次のコード例は、ルーターとしてZigbeeネットワークを形成し、コーディネーターに接続を行います。
ネットワークに参加出来たら約5秒毎に温度を送信し、約0.25秒毎にデータ受信の監視を行います。

 1.子機(ルーター)を”パソコンと繋いでみる”の様に配線します、
   (今回は、”USBシリアル変換モジュールで繋いでみる”の方法で子機側は配線しました)
   子機の設定はXBeeパート4の"子機の設定を行う"を参照下さい。
 2. MicroPython環境にアクセスします。
 3. 次のサンプルコードをコピーします。
   貼り付けモードの方法はこちらを参照ください。
--------------------------------------------------------------------------------
import xbee, time

# XBee3 受信したメッセージの操作を実行する為のユーティリティ関数
def format_eui64(addr):
    return ':'.join('%02x' % b for b in addr)

def format_packet(p):
    type = 'Broadcast' if p['broadcast'] else 'Unicast'
    print("%s message from EUI-64 %s (network 0x%04X)" %
          (type, format_eui64(p['sender_eui64']), p['sender_nwk']))
#    print("from EP 0x%02X to EP 0x%02X, Cluster 0x%04X, Profile 0x%04X:" %
#          (p['source_ep'], p['dest_ep'], p['cluster'], p['profile']))
    print(p['payload'],"\n")


print("Joining network as a router...")
xbee.atcmd("NI", "Router")

network_settings = {"CE": 0, "ID": 0x777, "EE": 0}
for command, value in network_settings.items():
    xbee.atcmd(command, value)
xbee.atcmd("AC")  # 変更を適用する
time.sleep(1)     # 1秒待つ

# ネットワーク接続成功を報告するまでAIに問い合わせる
while xbee.atcmd("AI") != 0:
    time.sleep(0.1)
print("Connected to Network\n")

last_sent = time.ticks_ms()
interval = 5000  # メッセージを送信する頻度

# 送受信ループを開始する
print("Sending temp data every {} seconds".format(interval/1000))
while True:
    p = xbee.receive()
    if p:
        # 何か受信したら表示を行う
        format_packet(p)
    else:
        # 準備ができたら温度を送信
        if time.ticks_diff(time.ticks_ms(), last_sent) > interval:
            temp = "Temperature: {}C".format(xbee.atcmd("TP"))
            print("\tsending " + temp)
            try:
                xbee.transmit(xbee.ADDR_COORDINATOR, temp)
            except Exception as err:
                print(err)
            last_sent = time.ticks_ms()
        time.sleep(0.25)  # 0.25秒待つ
--------------------------------------------------------------------------------
 4.[Ctrl + D]を押して起動させます。
   下記の様に表示されます。
   コーディネーターからのメッセージ"Hello, Router!"を受信し、
   5秒枚に温度データ"sending Temperature: 36Cを送信しています。"
   "Router"文字はルータ側で設定されている"NI"ノード名になります。
   --------------------------------------------------------------------------------
   Joining network as a router...
   Connected to Network
   
   Sending temp data every 5.0 seconds
   Unicast message from EUI-64 00:13:a2:00:41:93:f3:5e (network 0x0000)
   b'Hello, Router!' 
   
           sending Temperature: 36C
           sending Temperature: 36C
           sending Temperature: 36C
   Traceback (most recent call last):
     File "<stdin>", line 50, in <module>
   KeyboardInterrupt: 
   
   >>>
   --------------------------------------------------------------------------------
   コーディネーター側の表示は、
   --------------------------------------------------------------------------------
   Forming a new Zigbee network as a coordinator...
   Network Established
   
   Waiting for a remote node to join...
   Remote node found, transmitting data
   Sending "Hello, Router!" to 0x375e
   Receiving data...
   Hit CTRL+C to cancel
   Unicast message from EUI-64 00:13:a2:00:41:98:20:a7 (network 0x375E)
   b'Temperature: 36C' 
   
   Unicast message from EUI-64 00:13:a2:00:41:98:20:a7 (network 0x375E)
   b'Temperature: 36C' 
   
   Unicast message from EUI-64 00:13:a2:00:41:98:20:a7 (network 0x375E)
   b'Temperature: 36C' 
   
   Traceback (most recent call last):
     File "<stdin>", line 52, in <module>
   KeyboardInterrupt: 
   
   >>> 
   --------------------------------------------------------------------------------
※ XBee3の15番ピン(DIO5/ASSC)にLEDを配線すればネットワークに参加すると点滅するので
  解りやすいでしょう。




【きむ茶工房ガレージハウス】
Copyright (C) 2006-2019 Shigehiro Kimura All Rights Reserved.