Star configuration with xbee and arduino

Hello newbie here. So I am building a project called "Flood monitoring" consisting of xbee, ultrasonic sensors and arduino. I had this wired in a star configuration since each sensor nodes will be capable to send data to the coordinator node or center node. I had my xbee configured in API mode since as browsed the internet it said that when dealing with multiple xbees it has to be in API mode. However when I tried doing it with the arduino I get this weird looking characters in my serial monitor in my transmitter side and I dont receive these characters in my receiver side.
I need help plss I am losing my mind huhu.

Here is the code for my transmitter side.

#include <XBee.h>
#define echoPin 2 // attach pin D2 Arduino to pin Echo of HC-SR04
#define trigPin 3 //attach pin D3 Arduino to pin Trig of HC-SR04
long duration; // variable for the duration of sound wave travel
int distance; // variable for the distance measurement

// create the XBee object
XBee xbee = XBee();

uint8_t payload[] = { 0 };

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


void setup() {
  Serial.begin(9600);
  xbee.setSerial(Serial);
  pinMode(trigPin, OUTPUT); // Sets the trigPin as an OUTPUT
  pinMode(echoPin, INPUT);
}

void loop() {   
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  // Sets the trigPin HIGH (ACTIVE) for 10 microseconds
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  // Reads the echoPin, returns the sound wave travel time in microseconds
  duration = pulseIn(echoPin, HIGH);
  // Calculating the distance
  distance = duration * 0.034 / 2; // Speed of sound wave divided by 2 (go and back)
  // Displays the distance on the Serial Monitor
   payload[0]= distance;
   xbee.send(zbTx);
   delay(3000);

}

And here is the code for my receiver side:

#include <XBee.h>

XBee xbee = XBee();
XBeeResponse response = XBeeResponse();
// create reusable response objects for responses we expect to handle 
ZBRxResponse rx = ZBRxResponse();



void setup() {
  // start serial
  Serial.begin(9600);
  xbee.begin(Serial);
  
}

// continuously reads packets, looking for ZB Receive or Modem Status
void loop() {
    
    xbee.readPacket();
    
    if (xbee.getResponse().isAvailable()) {
      // got something
      
      if (xbee.getResponse().getApiId() == ZB_RX_RESPONSE) {
        // got a zb rx packet
        
        // now fill our zb rx class
        xbee.getResponse().getZBRxResponse(rx);
      }
    }         
}  

Note that is only communication between two xbees. I dont have any clue how to do this when dealing with multiple xbees and arduinos. Any suggestion would help :).

looks like you have the incorrect serial baudrate which is therefore giving garbage
try different baudrates 19200 38400 57600 115200
edit: one of my Zigbee documents mentions 115200baud

upload a schematic of the wiring?

1 Like

Thank you for the reply horace! I was able to successfully communicate between two xbees using arduino printing hello world and receiving it on the other arduino. However I do have another problem. There seems to be no problem when transferring a string, but when i tried transferring numerical data I cant. I do need help with this, I think there seems to be a problem in my code when transferring numerical data.

Here is my code Tx code when transmitting a String "Hello World".

#include <XBee.h>
#include <SoftwareSerial.h>
XBee xbee = XBee();
// This is the XBee broadcast address.  You can use the address
// of any device you have also.
XBeeAddress64 Broadcast = XBeeAddress64(0x00000000, 0x0000ffff);

char Hello[] = "Hello World\r";
char Buffer[128];  // this needs to be longer than your longest packet.
#define ssRX 2
#define ssTX 3
SoftwareSerial nss(ssRX, ssTX);

void setup() {
  // start serial
  Serial.begin(9600);
  // and the software serial port
  // now that they are started, hook the XBee into
  // Software Serial
  nss.begin(9600);
  xbee.setSerial(nss);
  Serial.println("Initialization all done!");
}

void loop() {
  ZBTxRequest zbtx = ZBTxRequest(Broadcast, (uint8_t *)Hello, strlen(Hello));
  xbee.send(zbtx);
  delay(30000);
  strcpy(Buffer,"Hello Coordinator.\r");
  zbtx = ZBTxRequest(Broadcast, (uint8_t *)Buffer, strlen(Buffer));
  xbee.send(zbtx);
  delay(30000);
}

And here is my attempt updated code where I want to transmit numerical data

#include <XBee.h>
#include <SoftwareSerial.h>
#define echoPin 4 // attach pin D2 Arduino to pin Echo of HC-SR04
#define trigPin 5 //attach pin D3 Arduino to pin Trig of HC-SR04


XBee xbee = XBee();
// This is the XBee broadcast address.  You can use the address
// of any device you have also.
XBeeAddress64 Broadcast = XBeeAddress64(0x00000000, 0x0000ffff);

long duration; // variable for the duration of sound wave travel
int distance; // variable for the distance measurement
char Hello[] = {distance};
char Buffer[128];  // this needs to be longer than your longest packet.
// defines variables

#define ssRX 2
#define ssTX 3
SoftwareSerial nss(ssRX, ssTX);

void setup() {
  // start serial
  Serial.begin(9600);
  // and the software serial port
  // now that they are started, hook the XBee into
  // Software Serial
  pinMode(trigPin, OUTPUT); // Sets the trigPin as an OUTPUT
  pinMode(echoPin, INPUT);
  // Sets the echoPin as an INPUT
  nss.begin(9600);
  xbee.setSerial(nss);
  Serial.println("Initialization all done!");
}

void loop() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  // Sets the trigPin HIGH (ACTIVE) for 10 microseconds
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  // Reads the echoPin, returns the sound wave travel time in microseconds
  duration = pulseIn(echoPin, HIGH);
  // Calculating the distance
  distance = duration * 0.034 / 2; // Speed of sound wave divided by 2 (go and back)
  // Displays the distance on the Serial Monitor
  ZBTxRequest zbtx = ZBTxRequest(Broadcast, (uint8_t *)Hello, strlen(Hello));
  xbee.send(zbtx);
  delay(30000);
  strcpy(Buffer,"Hello coordinator.\r");
  zbtx = ZBTxRequest(Broadcast, (uint8_t *)Buffer, strlen(Buffer));
  xbee.send(zbtx);
  delay(30000);
}

ohh I think I got it! I just used the sprintf() function! Yay!

good to hear you got it working
however, I noticed a problem if you may have when using sprintf()
I assume you implemented code such as

  distance = duration * 0.034 / 2; // Speed of sound wave divided by 2 (go and back)
  // Displays the distance on the Serial Monitor
  sprintf(Hello,"%d",distance);
  ZBTxRequest zbtx = ZBTxRequest(Broadcast, (uint8_t *)Hello, strlen(Hello));

if I compile the code I get warnings

C:\Users\bb\Documents\Arduino\sketch_nov21b\sketch_nov21b.ino:14:17: warning: narrowing conversion of 'distance' from 'int' to 'char' [-Wnarrowing]
   14 | char Hello[] = {distance};
      |                 ^~~~~~~~
C:\Users\bb\Documents\Arduino\sketch_nov21b\sketch_nov21b.ino: In function 'void loop()':
C:\Users\bb\Documents\Arduino\sketch_nov21b\sketch_nov21b.ino:48:17: warning: 'sprintf' writing a terminating nul past the end of the destination [-Wformat-overflow=]
   48 |   sprintf(Hello,"%d",distance);
      |                 ^~~~
C:\Users\bb\Documents\Arduino\sketch_nov21b\sketch_nov21b.ino:48:10: note: 'sprintf' output between 2 and 12 bytes into a destination of size 1
   48 |   sprintf(Hello,"%d",distance);
      |   ~~~~~~~^~~~~~~~~~~~~~~~~~~~~

the problem is the definition of Hello[]

int distance; // variable for the distance measurement
char Hello[] = {distance};

in effect size of the array is defined as 1 with an initial value of 0, e.g.

char Hello[1]={0} ;

make sure when you define an array you allocate sufficent storage for your target data, e.g. allocate 25 bytes initialised to 0

char Hello[25]={0} ;
1 Like

Hello again horace, so I am having again a problem in my coordinator node. I did get the values of the data correctly without the GSM module, However in my coordinator node when I tried to hook up the GSM module with the xbee and arduino I wont anymore receive any data. Need help plss ASAP

Here is my Receiver code/Coordinator node:

#include <XBee.h>
#include <SoftwareSerial.h>

XBee xbee = XBee();
XBeeResponse response = XBeeResponse();
// create reusable response objects for responses we expect to handle
ZBRxResponse rx = ZBRxResponse();

// Define NewSoftSerial TX/RX pins
// Connect Arduino pin 2 to Tx and 3 to Rx of the XBee
// I know this sounds backwards, but remember that output
// from the Arduino is input to the Xbee
#define ssRX 2
#define ssTX 3
SoftwareSerial nss(ssRX, ssTX);
SoftwareSerial gsmSerial(9, 5); //RX, TX
char Buffer[128];


void setup() {
  // start serial
  Serial.begin(9600);
  // and the software serial port
  // now that they are started, hook the XBee into
  nss.begin(9600);
  gsmSerial.begin(115200);
  xbee.setSerial(nss);
  // Software Serial
  // I think this is the only line actually left over
  // from Andrew's original example
  Serial.println("Starting up!");
}

void loop() {
    // doing the read without a timer makes it non-blocking, so
    // you can do other stuff in loop() as well.
    xbee.readPacket();
    // so the read above will set the available up to
    // work when you check it.
    
    if (xbee.getResponse().isAvailable()) {
      // got something
      Serial.println();
      Serial.print("Frame Type is ");
      // Andrew call the frame type ApiId, it's the first byte
      // of the frame specific data in the packet.
      Serial.println(xbee.getResponse().getApiId(), HEX);
   
      if (xbee.getResponse().getApiId() == ZB_RX_RESPONSE) {
        // got a zb rx packet, the kind this code is looking for
     
        // now that you know it's a receive packet
        // fill in the values
        
        xbee.getResponse().getZBRxResponse(rx);
     
        // this is how you get the 64 bit address out of
        // the incoming packet so you know which device
        // it came from
        Serial.print("Got an rx packet from: ");
        XBeeAddress64 senderLongAddress = rx.getRemoteAddress64();
        print32Bits(senderLongAddress.getMsb());
        Serial.print(" ");
        print32Bits(senderLongAddress.getLsb());
     
        // this is how to get the sender's
        // 16 bit address and show it
        uint16_t senderShortAddress = rx.getRemoteAddress16();
        Serial.print(" (");
        print16Bits(senderShortAddress);
        Serial.println(")");
     
        // The option byte is a bit field
        if (rx.getOption() & ZB_PACKET_ACKNOWLEDGED)
            // the sender got an ACK
          Serial.println("packet acknowledged");
        if (rx.getOption() & ZB_BROADCAST_PACKET)
          // This was a broadcast packet
          Serial.println("broadcast Packet");
       
        Serial.print("checksum is ");
        Serial.println(rx.getChecksum(), HEX);
     
        // this is the packet length
        Serial.print("packet length is ");
        Serial.print(rx.getPacketLength(), DEC);
     
        // this is the payload length, probably
        // what you actually want to use
        Serial.print(", data payload length is ");
        Serial.println(rx.getDataLength(),DEC);
     
        // this is the actual data you sent
        Serial.println("Received Data: ");
        for (int i = 0; i < rx.getDataLength(); i++) {
          print8Bits(rx.getData()[i]);
          Serial.print(' ');
        }
     
        // and an ascii representation for those of us
        // that send text through the XBee
        Serial.println();
        for (int i= 0; i < rx.getDataLength(); i++){
          Serial.write(' ');
          if (iscntrl(rx.getData()[i]))
            Serial.write(' ');
          else
            Serial.write(rx.getData()[i]);
          Serial.write(' ');
        }
        SendMessage();
        Serial.println();
     
        // So, for example, you could do something like this:
        handleXbeeRxMessage(rx.getData(), rx.getDataLength());
/*
        // I commented out the printing of the entire frame, but
        // left the code in place in case you want to see it for
        // debugging or something
        Serial.println("frame data:");
        for (int i = 0; i < xbee.getResponse().getFrameDataLength(); i++) {
          print8Bits(xbee.getResponse().getFrameData()[i]);
          Serial.print(' ');
        }
        Serial.println();
        for (int i= 0; i < xbee.getResponse().getFrameDataLength(); i++){
          Serial.write(' ');
          if (iscntrl(xbee.getResponse().getFrameData()[i]))
            Serial.write(' ');
          else
            Serial.write(xbee.getResponse().getFrameData()[i]);
          Serial.write(' ');
        }
        Serial.println();
*/
      }
    }
    else if (xbee.getResponse().isError()) {
      // some kind of error happened, I put the stars in so
      // it could easily be found
      Serial.print("************************************* error code:");
      Serial.println(xbee.getResponse().getErrorCode(),DEC);
    }
    else {
      // I hate else statements that don't have some kind
      // ending.  This is where you handle other things
    }
}

void handleXbeeRxMessage(uint8_t *data, uint8_t length){
  // this is just a stub to show how to get the data,
  // and is where you put your code to do something with
  // it.
  for (int i = 0; i < length; i++){
//    Serial.print(data[i]);
  }
//  Serial.println();
}

// these routines are just to print the data with
// leading zeros and allow formatting such that it
// will be easy to read.
void print32Bits(uint32_t dw){
  print16Bits(dw >> 16);
  print16Bits(dw & 0xFFFF);
}

void print16Bits(uint16_t w){
  print8Bits(w >> 8);
  print8Bits(w & 0x00FF);
}

void print8Bits(byte c){
  uint8_t nibble = (c >> 4);
  if (nibble <= 9)
    Serial.write(nibble + 0x30);
  else
    Serial.write(nibble + 0x37);
     
  nibble = (uint8_t) (c & 0x0F);
  if (nibble <= 9)
    Serial.write(nibble + 0x30);
  else
    Serial.write(nibble + 0x37);
}
void SendMessage()
{
   Serial.println("Setting the GSM in text mode");
   gsmSerial.println("AT+CMGF=1\r");
   delay(2000);
   Serial.println("Sending SMS to the desired phone number!");
   gsmSerial.println("AT+CMGS=\"+639484443674\"\r");
   // Replace x with mobile number
   delay(2000);
   for (int i = 0; i < rx.getDataLength(); i++) {
          print8Bits(rx.getData()[i]);
   
    
   sprintf(Buffer,"Critical! Node 1: %d", print8Bits);
   gsmSerial.println(Buffer);    // SMS Text
   delay(200);
}

and here is my transmitter code:

#include <XBee.h>
#include <SoftwareSerial.h>
#include <Adafruit_Sensor.h> // Including Adafruit sensor library:
#include <DHT.h> //including DHT-sensor-library
#define echoPin 4 // attach pin D2 Arduino to pin Echo of HC-SR04
#define trigPin 5 //attach pin D3 Arduino to pin Trig of HC-SR04
#define DHTPin 12       //defining the sensor pin (pin no-04)
#define DHTType DHT11
#define ssRX 2
#define ssTX 3


XBee xbee = XBee();
// This is the XBee broadcast address.  You can use the address
// of any device you have also.
XBeeAddress64 Broadcast = XBeeAddress64(0x00000000, 0x0000ffff);

long duration; // variable for the duration of sound wave travel
int distance; // variable for the distance measurement
float speedofsound; 
char Hello[] = "Hello Coordinator.\r";
char Buffer[128];  // this needs to be longer than your longest packet.
// defines variables


DHT dht = DHT(DHTPin,DHTType);// Create a DHT sensor object i.e. dht
SoftwareSerial nss(ssRX, ssTX);

void setup() {
  // start serial
  Serial.begin(9600);
  // and the software serial port
  // now that they are started, hook the XBee into
  // Software Serial
  pinMode(trigPin, OUTPUT); // Sets the trigPin as an OUTPUT
  pinMode(echoPin, INPUT);
  // Sets the echoPin as an INPUT
  nss.begin(9600);
  dht.begin(); // Begins the Serial communication so that the Arduino can send out commands through USB connection
  xbee.setSerial(nss);
  Serial.println("Initialization all done!");
}

void loop() {
  digitalWrite(trigPin, LOW);//setting trigger pin in LOW state
  delayMicroseconds(5);      //for 5 microseconds
 
  digitalWrite(trigPin, HIGH);  //setting trigger pin in HIGH state
  delayMicroseconds(10);       //for 10 microsecond and emits 8pulses from the transmitter and bounces back onces hit by an object
  digitalWrite(trigPin, LOW);  //after recieving the signal,setting the trigger pin to LOW state
 
  duration = pulseIn(echoPin, HIGH); //duration is a variable that starts timing once echo pin is high by using  arduino  function pulseIn()
 
  float temperature = dht.readTemperature();// temperature is the variable use to store the value of current temperature which sensors detects
 
   speedofsound = 331.3+(0.606*temperature);// Calculate speed of sound by using the given formula in m/s:
   distance = duration*(speedofsound/10000)/2; // Calculate the distance by using the given formula in cm:
   delay(33000);
   if (distance < 30){
    sprintf(Buffer,"Critical! Node 4: %d", distance);
    ZBTxRequest zbtx = ZBTxRequest(Broadcast, (uint8_t *)Buffer, strlen(Buffer));
    xbee.send(zbtx);
   }
   if (60 > distance > 30){
    sprintf(Buffer,"Warning! Node 4: %d", distance);
    ZBTxRequest zbtx = ZBTxRequest(Broadcast, (uint8_t *)Buffer, strlen(Buffer));
    xbee.send(zbtx);
   }
  delay(26000);
}
type or paste code here

does the GSM module work OK by itself
if you comment out the SendMessage(); call in loop() does it work?
upload serial monitor output so we can see flow of code?
upload a schematic of the wiring

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.