0
\$\begingroup\$

I'm working on a wireless sensor network in which I have one coordinator router (API mode 2) connected to a Raspberry Pi 2, 5 or more routers in API mode 2 as well. Each router is connected to an Arduino Uno. The Unos also have different sensors attached to them (temperature, humidity etc). I have to send data from the sensors to the coordinator and process it. I have successfully transferred data using one router and coordinator (just two XBee S2 modules). On the Arduini I'm using Andrew's library https://github.com/andrewrapp/xbee-arduino and on the Pi I'm using a Python-xbee library https://github.com/nioinnovation/python-xbee. For a single router and coordinator my codes are: Arduino Code (Router):

#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);
}

Raspberry Pi Code (Coordinator):

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
                })

I have a few questions that I can't find answers to. I have looked almost everywhere but still have some confusions.

1) In the Arduino code, there is a portion of code at the end where it checks for the status response (I did not write the code, found it on the internet). When I set it up, my errorLED connected to pin 12 blinks once and looking into the code it means that the "local XBee did not provide a timely TX Status Response". My question is, do I have to send a response myself from the coordinator in python or is it generated automatically? If I have to do it myself, how would I do it? Because right now, there is not response. My setup works fine as I'm getting correct values on my Pi.

2) When I have more than one router, how would I handle it in the code? Would I keep sending sensor values after every 2 seconds from the arduino and loop through the address on Pi or is there another way that it is done usually? I'm very confused about it.

3) Right now, if I add more routers, they will keep sending out frames with sensor values and the coordinator reads them in a loop. How can I setup the system such that the coordinator sends a signal to each router and asks for the data and then the router replies with the data? Is it possible?

Any help would be really appreciated. Thank you in advance :)

\$\endgroup\$
1
\$\begingroup\$
  1. I think the response is generated automatically
  2. You have to make sure the coordinator knows from which router the data is coming.
  3. I think the best way to deal with this is to do asynchronous read/write. This link might be helpful.
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.