2016-05-03 8 views
1

私は、コーディネータールーター(APIモード2)がAPIモード2のRaspberry Pi 2、5以上のルーターに接続されているワイヤレスセンサーネットワークに取り組んでいます。各ルータはArduino Unoに接続されています。ウノスにはさまざまなセンサー(温度、湿度など)が付いています。センサーからコーディネーターにデータを送信して処理する必要があります。私は1台のルータとコーディネータ(ただ2つのXBee S2モジュール)を使ってデータを正常に転送しました。 Arduiniで私はAndrewのライブラリhttps://github.com/andrewrapp/xbee-arduinoを使用していますが、私はPython-xbeeライブラリhttps://github.com/nioinnovation/python-xbeeを使っています。単一ルータとコーディネーターのために私のコードは次のとおりです。 Arduinoのコード(ルータ):XBee S2ワイヤレスセンサーネットワーク

#include <XBee.h> 
#include <math.h> 
// create the XBee object 
XBee xbee = XBee(); 

int sensor = A5; 
uint8_t payload[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 
// union to convert float to byte string 
union u_tag { 
    uint8_t b[4]; 
    float fval; 
} u; 


// SH + SL Address of receiving XBee 
XBeeAddress64 addr64 = XBeeAddress64(0x0013a200, 0x40DC7C90); 
ZBTxRequest zbTx = ZBTxRequest(addr64, payload, sizeof(payload)); 
ZBTxStatusResponse txStatus = ZBTxStatusResponse(); 

int statusLed = 13; 
int errorLed = 12; 

void flashLed(int pin, int times, int wait) { 

    for (int i = 0; i < times; i++) { 
    digitalWrite(pin, HIGH); 
    delay(wait); 
    digitalWrite(pin, LOW); 

    if (i + 1 < times) { 
     delay(wait); 
    } 
    } 
} 

double Thermistor(int RawADC) 
{ 
    double Temp; 
    Temp = log(10000.0 * ((1024.0/RawADC - 1))); 
    Temp = 1/(0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp)) * Temp); 
    Temp = Temp - 273.15;   // Convert Kelvin to Celcius 
    //Temp = (Temp * 9.0)/ 5.0 + 32.0; // Convert Celcius to Fahrenheit 
    return Temp; 
} 

void setup() { 
    pinMode(statusLed, OUTPUT); 
    pinMode(errorLed, OUTPUT); 
    Serial.begin(9600); 
} 

void loop() { 
    float rawADC = analogRead(sensor); 
    float t = Thermistor (rawADC); 

    // check if returns are valid, if they are NaN (not a number) then something went wrong! 
    if (!isnan(t)) { 

    // convert temperature into a byte array and copy it into the payload array 
    u.fval = t; 
    for (int i=0;i<4;i++){ 
     payload[i]=u.b[i]; 
    } 
    u.fval = 100.33; 
    for (int i=0;i<4;i++){ 
     payload[i+4]=u.b[i]; 
    } 

    xbee.send(zbTx); 
    flashLed(statusLed, 1, 100);  // flash TX indicator 


    // after sending a tx request, we expect a status response, wait up to half second for the status response 
    if (xbee.readPacket(500)) { 
     // got a response! 
     // should be a znet tx status    
     if (xbee.getResponse().getApiId() == ZB_TX_STATUS_RESPONSE) { 
     xbee.getResponse().getZBTxStatusResponse(txStatus); 

     // get the delivery status, the fifth byte 
     if (txStatus.getDeliveryStatus() == SUCCESS) { 
      // success. time to celebrate 
      flashLed(statusLed, 5, 50); 
     } else { 
      // the remote XBee did not receive our packet. is it powered on? 
      flashLed(errorLed, 3, 500); 
     } 
     } 
    } else if (xbee.getResponse().isError()) { 
     //nss.print("Error reading packet. Error code: "); 
     //nss.println(xbee.getResponse().getErrorCode()); 
    } else { 
     // local XBee did not provide a timely TX Status Response -- should not happen 
     flashLed(errorLed, 1, 50); 
    } 
    } 
    delay(2000); 
} 

ラズベリーパイコード(コーディネーター):

from xbee import ZigBee 
import serial 
import struct 
import datetime 

PORT = '/dev/ttyUSB0' 
BAUD_RATE = 9600 

def hex(bindata): 
    return ''.join('%02x' % ord(byte) for byte in bindata) 

# Open serial port 
ser = serial.Serial(PORT, BAUD_RATE) 

# Create API object 
xbee = ZigBee(ser,escaped=True) 

# Continuously read and print packets 
while True: 
    try: 
     response = xbee.wait_read_frame() 
     sa = hex(response['source_addr_long']) 
     rf = hex(response['rf_data']) 
     obj = createObject(response) 
     obj.createPacket() 
     print ("Temperature: %.2f" % obj.packet['temperature'], 
     "Humidity: %.2f" % obj.packet['humidity'], 
     "Source Address: 0x%s" % obj.packet['sourceAddressShort'], 
     "Timestamp: %s" % obj.packet['timestamp'].isoformat()) 
    except KeyboardInterrupt: 
     break 

ser.close() 

class createObject: 
    def __init__(self, response): 
     self.sourceAddrLong = hex(response['source_addr_long']) 
     self.rfData = hex(response['rf_data']) 
     self.sourceAddrShort = hex(response['source_addr_long'][4:]) 
     self.options = response.pop('options') 
     self.frameType = response['id'] 
     self.temperature = struct.unpack('f',response['rf_data'][0:4])[0] 
     self.humidity = struct.unpack('f',response['rf_data'][4:])[0] 
     self.dataLength = len(response['rf_data']) 
     self.packet={} 
     self.dateNow = datetime.datetime.utcnow() 
     self.packetJson=0 

    def createPacket(self): 
     self.packet.update({ 
       'timestamp' : self.dateNow, 
       'temperature' : self.temperature, 
       'humidity' : self.humidity, 
       'dataLength' : self.dataLength, 
       'sourceAddressLong' : self.sourceAddrLong, 
       'sourceAddressShort' : self.sourceAddrShort, 
       'options' : self.options, 
       'frameType' : self.frameType 
       }) 

私は答えを見つけることができないいくつかの質問を持っていますに。私はほとんどどこでも見えましたが、まだ混乱があります。 Arduinoのコードで

  1. 、それはステータス応答をチェック終了時のコードの一部は、(Iコードを書いていない、インターネット上で見られる)が存在します。私がセットアップすると、12番ピンに接続されたerrorLEDが一度点滅し、コードを調べると、「ローカルXBeeがタイムリーなTX Status Responseを提供していない」ことを意味します。私の質問は、Pythonでコーディネーターから自分自身で回答を送らなければならないのですか、それとも自動的に生成されますか?もし私がそれを自分でしなければならないなら、どうすればいいのですか?今のところ、応答がありません。私のパイに正しい値を得ているので、私の設定がうまくいきます。

  2. 私は複数のルータを持っていますが、どのように私はコードでそれを扱うでしょうか? arduinoから2秒ごとにセンサ値を送信し続け、Piのアドレスをループするか、それとも通常は別の方法でセンサを送信しますか?私はそれについて非常に混乱しています。

    現在、ルータを追加すると、センサ値を含むフレームが送信され続け、コーディネータがそれらをループで読み込みます。コーディネータが各ルータに信号を送信してデータを要求し、ルータがデータで応答するようにシステムを設定するにはどうすればよいですか?出来ますか?

答えて

0
  1. ローカルのXBeeがリモートのXBeeへの配信を確認したときに送信ステータス・フレームは自動的に行われます。それは低レベルの承認です。私の推測では、そのコードのロジックに問題があるということです。 500ms後に応答が戻ってくるかもしれない。最後に成功したTransmit Statusフレームが到着してからどれくらいの時間が経過したかを追跡するために、コードを再構成して、ローカルXBeeでフレームをポーリングし、センサステータスフレームを2秒ごとに送信し、また、Arduinoの既存のコードでは、必要なだけ頻繁にバイトを処理していないため(例えば、シリアルポートを読み取らずにアイドリングを2秒間行うなど)、ボーレートを上げることをお勧めします。

  2. "連続読み取りと印刷パケット"ループ内の複数のデバイスからのデータを処理するために、ラズベリーPiコードが既に設定されているようです。あなたのXBeeモジュールを115200bpsに設定し、新しい値でPythonコードを更新することをお勧めします。そうすれば、データレートは制限されません。

  3. 現在のデザインは管理が簡単です。ネットワーク上のルータは、常にセンサーの読み取り値を報告します。私は宛先アドレスとして00000000-00000000を使用するようにコードを更新することもできると思うし、ルータは常にコーディネータに送信されます。しかし、あなたはルータMACアドレス(ATNDノード発見によって発見された)のリストを保持し、必要に応じてそれらに要求を送るためにラズベリーPiコードを変更することができます。あなたは、着信フレームを監視するためにArduinoのコードを変更する必要があり、かつ要求が入ってきたときに送信フレームを生成する。

私は任意のコードを変更せず、セットアップに2つ目のルータを追加することをお勧めしたい、と思いますそれがどのように働くのか見ているだけです。私が知ることから、ラズベリーパイは、パケットが入ってくるときに異なる送信元アドレスでパケットを印刷するだけです。

+0

ありがとうございます。私はあなたが提案したことを試し、あなたに知らせるでしょう:) – Moeed

+0

最初の問題を修正しました。私は問題がどこにあるのかを知ろうとしていましたが、XCTUを使ってルータをリセットして、同じ設定で再度設定しました。赤いLED(エラーLED)が点灯しないので、すべてが良好です。私は上記とまったく同じコードを使用しています。私が他の部分に行くときあなたに知らせるでしょう:) – Moeed