Send Zigbee API frame from PC to XBEE through Arduino

Hi,

I’m trying to send API frame (hexadecimal) from a PC to a Zigbee S2C, attached to an Arduino.
Arduino is connected to the PC (Serial, pin 0/1) and Zigbee S2C (software serial pin 2/3 ; XBserial).

It works fine if the Arduino send itself the API frame, with the following code :

byte XBdata;
byte PCdata;

void setup () 
{
    Serial.begin(38400);
    XBserial.begin(38400);

    // send one time the API frame (OK)
    PCdata = {0x7E, 0x00, 0x04, 0x08, 0x01, 0x4E, 0x44, 0x64); // AT command (ND)
    XBSerial.write(PCdata, 8);
}

void loop()
{
	// print on PC serial console the result (OK)
        if (XBserial.available())
        {
		XBdata = XBserial.read();
		Serial.print(XBdata, HEX);
        }
}

But, I would like to send API frame from the PC instead from Arduino.
So in a nutshell :
1 - read the data (API frame) from the PC (serial)
2 - write / send the data on Zigbee S2C (software serial)
3 - read (software serial) and print (serial) the answer to PC

I’ve tried this way, but no result (following data send from PC : “7E 00 04 08 01 4E 44 64 \r”, via the Arduino IDE serial monitor)

byte XBdata;
String PCdata;

void setup () 
{
   Serial.begin(38400);
   XBserial.begin(38400);
}

void loop()
{
	// print on PC serial console the result from XBEE
        if (XBserial.available())
        {
		XBdata = XBserial.read();
		Serial.print(XBdata, HEX);
        }

	// send to XBEE API frame received form PC
        if (Serial.available())
        {
		PCdata = Serial.readStringUntil(‘\r‘);
		XBserial.print(PCdata);
        }
}

Self-analysis : readStringUntil give a String and not a byte array, so I can’t use XBserial.write.

Do you have an idea about what’s wrong ? is there an good way to achieve that ?

Many thanks and best regards,

Self-analysis : readStringUntil give a String and not a byte array, so I can't use XBserial.write.

That is only part of the problem. "7E" is NOT the same as 0x7E. When the XBee sends the packet, the first byte is 0x7E. When you try to send a String, the first byte is '7'. Not the same thing AT ALL.

You have two choices. First, you could write a PC app that will take the "bytes" of the packet, and turn them into real bytes, and send them to the Arduino.

Second, you could send the string starting with "7E ..." and have the Arduino collect and parse the data, and convert the "bytes" to bytes, and send the bytes.

Hi PaulS, thanks for you (quick and detailed) answer !
I have an explaination about the root cause of my issue, and it's clear for me.

As the first choice is not doable according to my context, I switch to the second one : "you could send the string starting with "7E ..." and have the Arduino collect and parse the data, and convert the "bytes" to bytes, and send the bytes."

... but no idea about how to perform that (mainly to convert "bytes" to bytes).

1/ collect and parse :

  • I can use Serial.readStringUntil(' ') > to get each "bytes" per "bytes" ("7E").

2/ convert "bytes" to bytes :

  • use String.getBytes > but it will give me the bytes of my bytes ... no ? (I can't test it now)
  • in fact I juste need to "cast" a String ("7E") in a bytes (0x7E) .. no ? how ? I've tried many things but never get a good result :sob:

3/ send the bytes

  • XBserial.write("byte" string transformed as a byte)

thanks.

EDIT : I think I may need to look around "strtoul" :slight_smile: to convert my "bytes" string to bytes (?)

1 Like

1/ collect and parse :

  • I can use Serial.readStringUntil(' ') > to get each "bytes" per "bytes" ("7E").

Then, you can extract the string from the String, and pass the string to strtoul(), to get the numeric byte value.

But, you are pissing away resources using the String class. You need a very small array (3 characters, max) and a byte-sized index.

Set the index value to 0. Each time there is a character to read, read the character. If the character is not a space, store the character in the array, in the position defined by index, then increment index, and store a NULL in the array in the position defined by index.

If the character is a space, use strtoul() to convert to a byte, set index back to 0, and store a NULL in the array in the position defined by index.

I have connected two xbees S2 module , one with the arduino and the second xbee with the usb ttl .what i am trying is to simply print all the 22 frame bytes on serial monitor and it is working well, the problem is the first byte is not 7E.so should i have to worried ?

so should i have to worried ?

You should be scared sh*tless.

Or not. We can't see what code you have, or how the XBees are configured. So, maybe you have a problem, and maybe you don't.

[\You should be scared sh*tless.]

Sorry for the uncomplete information.and thanks for your reply.

xbee configuration:-

Router:- AT command mode
pan id : - 1234
channel verification:- enabled
IO sampling :- 1388 (5000 msec)

Coordinator :- API command mode
pan id :- 1234

and here is the code that i am using

xbee_frame_byte.ino (236 Bytes)

Why is one device in API mode and the other on AT mode?