xbee serial.write question

I have two xbees up, configured, and communicating (Coordinator API & Router AT). I can send hex commands using x-ctu without issue. I'm also trying to keep this sketch very light, so I want to write my own, thin packet processing.

What am I doing wrong? This does not work; I get no response.

byte turnondata[] = { 0x7E, 0x00, 0x10, 0x17, 0x05, 0x00, 0x13, 0xA2, 0x00, 0x40, 0x7E, 0x71, 0x53, 0xFF, 0xFE, 0x02, 0x44, 0x32, 0x05, 0x32 };
byte turnoffdata[] = { 0x7E, 0x00, 0x10, 0x17, 0x05, 0x00, 0x13, 0xA2, 0x00, 0x40, 0x7E, 0x71, 0x53, 0xFF, 0xFE, 0x02, 0x44, 0x32, 0x04, 0x33 };

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.write(turnondata, sizeof(turnondata));
  delay(5000);
  
  Serial.write(turnoffdata, sizeof(turnoffdata));
  delay(5000);
  
}

Any assistance is appreciated!
Thanks!

Does it turn D2 on and off on the remote XBee?

This does not work; I get no response.

No response from what? What is the other XBee attached to? Is this code on the coordinator or router?

I have two xbees up, configured, and communicating (Coordinator API & Router AT).

I don't think that this is a legitimate combination. I think they need to be both API or both AT, not a mix.

D2 turns off and on (test LED) on the remote xbee, but only when I send the packet using x-ctu.

With this program I get no response, local or remote.

Thanks!

This is a legitimate combination. See digi KB article:
http://www.digi.com/support/kbase/kbaseresultdetl.jsp?id=3221

shawshaw:
This is a legitimate combination. See digi KB article:
http://www.digi.com/support/kbase/kbaseresultdetl.jsp?id=3221

Yes, absolutely.

You need to use AP=2 and escaped characters. The 0x13 is not an allowed character, replace it with 0x7D, 0x33, recalculate the checksum and it should be good.

Not sure about that fifth byte (0x05), I use 0x01.

holy schnikes, that might be it. I didn't even catch that.

Thanks. I will test and report later.

PaulS:

I have two xbees up, configured, and communicating (Coordinator API & Router AT).

I don't think that this is a legitimate combination. I think they need to be both API or both AT, not a mix.

API vs. AT only specifies how the XBee communicates on the serial link with whatever it's connected to (an MCU or whatever). The radio communication between two XBees is the same, regardless of their mode (API or AT).

shawshaw:
schnikes

New word, will add to my repertoire XD

I honestly don't know why un-escaped API mode (AP=1) even exists. Not sure why a person would not want to use escaped mode "just in case". Even funnier, I think the first part of the 64-bit address (0x0013A200) will be the same for all ZigBee modules made by Digi International. So that puts the flaps down on a lot of AP=1 scenarios right there, LOL!

I don't think that this is a legitimate combination.

I did not say that it wasn't. I'm happy to hear that it is, and that there is a useful reason to do so, AND what exactly the modes mean.

Opps, checksums are always calculated on the un-escaped data. :blush:

Let me try this:
0x7E, Start Sentinel
0x00, 0x10, two bytes of length (looks right)
0x17, frame type = Remote AT
0x05, frame id (I usually use 1)
0x00, 0x13, 0xA2, 0x00, 0x40, 0x7E, 0x71, 0x53, eight bytes of address
0xFF, 0xFE, two bytes of network address (Broadcast or Unknown)
0x02, remote command options (bitfield, this says 'save changes'
0x44, 0x32, actual AT command (B space???)
0x05, command parameter
0x32 checksum

er, uh, what were you sending again??

And, the API 1 restricted characters ONLY apply to the payload. I use API 1 all the time because I hate having to escape the characters and can't read them when they come back.

Oh, and you can mix api and at modes, I do it all the time. The over-the-air messages are all API, it gets translated for you before the serial output when you assign AT mode. That also means there is an overhead over the air that most people don't realize, see what a simple AT command turns into? So, one XBee can be in AT and the other in API.

draythomp:
0x44, 0x32, actual AT command (B space???)

D2... he's just turning D2 on and off on a remote XBee.

And, the API 1 restricted characters ONLY apply to the payload. I use API 1 all the time because I hate having to escape the characters and can't read them when they come back.

What part of the frame is the payload? According to the S2 product manual, p98, everything but the start delimiter, including the length and the checksum itself, is subject to be escaped.

xbee.JPG

I'm still following this thread and haven't gotten any iteration of these to be successful.

I was using AP=1. However x-ctu seemed to be able to send my packet over unescaped (according to the log), which is puzzling.
I'm trying A=2 and escaping without much luck, but I'm continuing to tinker.

To answer some other questions, yes I'm just trying to turn D2 on/off remotely. It's harder than it looks!

Yes, that drawing drove me nuts also. And I did a crap job of explaining it; let me try again. Turns out, the data doesn't have to be escaped unless you're using API 2. See, this is for parsers that look for a start sentinel of 7e to reset. If you rely on the length and checksums, you can send anything you want to including a 7e inside the data packet.

The arduino XBee library uses the 7e to reset itself for the next packet. I use the length and follow it to find the end of the packet. That way I can send any thing I want to and not worry about it. I do occasionally get a garbage packet that exceeds the length. Then I reset and look for a 7e to start the next one, which may be messed up also because of the collision, but it will settle in a couple of packets and work just fine. Similarly, the 7e based parsers can terminate early on a collision packet and have the same problem, just a different recovery technique.

The real reason they included it was the XON, XOFF flow control characters for software based systems. Which meant they could include the start sentinel to ease parsing sometimes, and of course, the escape character.

Now, I only have to learn how to look in the correct column for the ascii translation...... he's sending an ATD4 5 to turn on pin 4, got it.

So, what's wrong, it should work. I get 32 as the checksum and 10 as the length also. At this point, I would be looking at the lights and seeing if the device actually joined the network.

Ah crap, I think I know what it is. There's nulls in there and I'll bet serial.write is messing up. Try putting it in a loop like:

for(int i = 0; i<sizeof(array);i++){
serial.write(array+i);
}

I bet you get different results. (not much though)

shawshaw:
I'm still following this thread and haven't gotten any iteration of these to be successful.

I was using AP=1. However x-ctu seemed to be able to send my packet over unescaped (according to the log), which is puzzling.
I'm trying A=2 and escaping without much luck, but I'm continuing to tinker.

To answer some other questions, yes I'm just trying to turn D2 on/off remotely. It's harder than it looks!

Someone said, "It was pretty easy, it just took a while to find out how easy it was." :wink:

Anyway, I stopped parsing when I saw the 0x13. But there is also a 0x7E in the XBee's 64-bit address, this must be your lucky day! Make sure AP=2 and then try:

byte turnondata[] = {0x7e, 0x00, 0x10, 0x17, 0x01, 0x00, 0x7d, 0x33, 0xa2, 0x00, 0x40, 0x7d, 0x5e, 0x71, 0x53, 0xff, 0xfe, 0x02, 0x44, 0x32, 0x05, 0x36}
byte turnoffdata[] = {0x7e, 0x00, 0x10, 0x17, 0x01, 0x00, 0x7d, 0x33, 0xa2, 0x00, 0x40, 0x7d, 0x5e, 0x71, 0x53, 0xff, 0xfe, 0x02, 0x44, 0x32, 0x04, 0x37}

Ok, it's time to look at a working example. I cut this out of my code that is running right now and doing this every single day. Strangely, I didn't have any trouble getting it to work. So...

const char acidPumpOnCommand[] PROGMEM = {0x10,0x01,0x00,0x00,0x00,0x00,
    0x00,0x00,0xff,0xff,0xff,0xfe,0x00,0x00,'A','c','i','d','O','n','\r'};

void sendXbee_P(const char* command, int length){
  byte checksum = 0;
  int i;
  Dbuf[0] = 0x7e;  // begin frame
  Dbuf[1] = length >>8;
  Dbuf[2] = length & 0xff;
  // copy command into buffer calculating checksum at the same time
  for(i = 0; i<length; i++){
    char c = pgm_read_byte(command + i); // can't use command[i]
    Dbuf[i+3] = c;
    checksum += c;
    printByteData(Dbuf[i+3]);
    Serial.print(" ");
  }
  Dbuf[i+3] = 0xff - checksum;
  Serial.println();
  for(i = 0; i<length + 4; i++){
    Serial1.print(Dbuf[i]);
    printByteData(Dbuf[i]);
    Serial.print(" ");
  }
  Serial.println();
}

void printByteData(uint8_t Byte){
  Serial.print((uint8_t)Byte >> 4, HEX);
  Serial.print((uint8_t)Byte & 0x0f, HEX);
}


//and then somewhere in the code somewhere I put

void acidPumpOn(){
  sendXbee_P(acidPumpOnCommand, sizeof(acidPumpOnCommand));
}

I run in API mode 1 and send in broadcast so I can watch my XBee network with an XBee plugged into the side of my laptop. That way I can see how bad a problem I have with collisions and also inject commands from time to time to see if things are working right. My coordinator is a separate device that is up in the attic so most of the devices can see it easily and does almost nothing except coordinate and send the current time over the network to sync the various devices. I use progmem because I got tired of running out of memory on the smaller devices, hence the way the array is defined. I calculate the checksum in the code because I got pretty tired of putting together commands and having the checksum wrong. The debug is in there because I (naturally) want to be able to see the hex data that is being sent. My network protocol is totally readable ascii; I want to be able to tell what the heck is going on without checking bytes.

This should give you a clue on what to do next.

edit: Oh, and I took this from a mega2560 board, that's why I use Serial1 as the XBee output and Serial as the debug. I do the same thing on a regular arduino but the XBee is on a SoftwareSerial port there.

draythomp:
Ok, it's time to look at a working example. ...

Well that is one example with no bytes that need to be escaped, so AP=1 or AP=2 would be equivalent I suppose. Good idea, though, I was going to suggest to the OP that he could write a function to add the start delimiter, length, checksum, do the escapes, and still have a pretty thin solution.

draythomp, are you using S1 or S2? Not sure if all this API/escape business is the same between the two, I'm only familiar with S2.

And how's broadcast working for you? There were some pretty dire-sounding warnings about broadcast causing a lot of network discovery overhead. But I guess it depends on network size too. Haven't tried broadcast, myself. BTW, checked out your web site some time back, very impressive project!

I only have S2. I never even looked at the S1 because I wanted to have all the stuff you get from Zigbee. And, as you know, it works. I can put a device 100 yards away, and if it doesn't reach, just put one in the middle to relay the data. That is so cool.

Regarding broadcast. Yes, there are some problems related to collisions and some others that I really don't understand, but all in all, it works darn nicely. I could eliminate all the problems by just going to a query, response protocol, but then the devices wouldn't be nearly as autonomous and it's nice to be able to put a monitor XBee anywhere and have it pick up the various devices talking. One device though is fully API. I have a thermometer that sends its temperature to a specific device and I can't see it on the network by just monitoring. I don't really like that and will eventually change it to use an ardweeny and broadcast. But, it was an experiment to see if I could do it that worked and worked itself into being a 'necessary' part of the project. Funny how that happens.

It's funny though Jack, I had some initial problems with getting the XBees to talk, but after a little messing around, I add XBees at a whim. I can set one up to tell me the coffee pot turned on in about 20 minutes and have it work first try. I'm not the sharpest tool in the shed and make stupid mistakes all the time, but I don't seem to have anywhere near the problems with these little devices that other people do. Has that been your experience, or am I just lucky?