How to calculate checksum for 16bit address Xbee TX frame

I am working on a project intended to send 3 bits of data to control an RGB LED wirelessly over XBee.
Due to my application, I do need the transmitting Xbee to be an API to make sure the data is correct on the end points. Thus I need to send a 16bit address frame to it .

In XCTU I can create a frame using the tool. I can also copy and paste that frame into arduino, and then send that frame across. And my Xbee end node receiver works great. This is all well and good if the same value was sent. But it is not. Bit 9,10 and 11 will change depending on the value that gets set it’s way. And thus, the Checksum will need to change to do it’s job.

My question is about the calculations on the Checksum. I have been googling/binging/yahoo searching for the past week now, and have yet to find any solid answer on how to calculate a checksum in simple words.

Can you assist, or direct me into some explanation on how to calculate a checksum? It seams simple, but I can’t seam to understand or grasp what is going on in the complex examples.

   Sourced from this forum post:
   http://forum.arduino.cc/index.php?topic=119463.0
*/

#include <SoftwareSerial.h>

SoftwareSerial XBee(2, 3); // RX, TX

// needs to be a 0x00 number. use Find/Replace. replace space with ", 0x"

byte hello[] = {0x7e, 0x00, 0x10, 0x01, 0x00, 0xff, 0xff, 0x01, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0xe3}; // Broadcasts to all
byte first[] = {0x7E, 0x00, 0x08, 0x01, 0x03, 0xFF, 0xFF, 0x00, 0x37, 0x38, 0x39, 0x55};
byte frameOne[] = {0x7E, 0x00, 0x0D, 0x01, 0x01, 0xFF, 0xFF, 0x00, 0x2D, 0x46, 0x72, 0x61, 0x6D, 0x65, 0x30, 0x30, 0x87};

int Xbee_loop_count;
void setup()
{
  Serial.begin(9600);
  XBee.begin(19200);

}

void loop() {
  Xbee_loop_count++;
  //after various trials serial.print(Router_on,20); kept causing the overloaded ambiguous error
  //Serial.write(Router_on,20); does it with no problems
  //the 20 tells the compiler how long the array is
  //Thank you PaulS from the Arduino forum for helping with this



  XBee.write(hello, 20);
  XBee.write(frameOne, 17);
  XBee.write(first,12);
  XBee.write(first,12);

  delay(1);
  //Serial.println(Xbee_loop_count);

}


/*
   Send 16 bit data.
   Would look like this:
  012 = 7E 00 08 01 01 FF FF 00 30 31 32 6C
  345 = 7E 00 08 01 02 FF FF 00 33 34 35 63
  789 = 7E 00 08 01 03 FF FF 00 37 38 39 55

  Byte 1 = Start
  Byte 2 = Most significant bit (always 00)
  Byte 3 = Least significant bit = Count of bits after this bit. (LSB). Aka. Bytes 4 through 12 = 8 bits = 0x08.
  Byte 4 = Type of Request. 0x00 = 64bit Tx. 0x01 = 16bit Tx // See XCTU's Frame Builder. Frame Type drop down for list.
  Byte 5 = Frame ID  // Transmit Unit doesn't really care. But if your receiver wants to receive data asynchronous. (say read 5 before 2, after 3) Then you would use this ID.
  Byte 6 = Address MSB (FF = broadcast)
  Byte 7 = Address LSB (FF = Broadcast)
  Byte 8 = option
  Byte 9, 10, 11 = Data
  Byte 12 = Checksum

*/

Examples of data that would be sent out:

Purple value = 990099 = 7E 00 0B 01 01 FF FF 00 39 39 30 30 39 39 BB
Haft red = 550000 = 7E 00 0B 01 01 FF FF 00 35 35 30 30 30 30 D5
Green value = 009900 = 7E 00 0B 01 01 FF FF 00 30 30 39 39 30 30 CD

I looked at this: https://www.digi.com/videos/xbee-zb-checksum-calculation
It seems simple enough…

uint8_t *p = &packet;   // Get the address of the packet, to be used as an array of bytes.
cksum = 0;  // start with a zero checksum
for (byte i = 3; i < packetLength; i++) {  // skip the Start and len, start with byte 4.
                                           // (remembering that C arrays start at 0, not 1.)
    cksum += p[i];    // Add in this byte.
}  // next byte
cksum &= 0xFF;        // low order 8 bits
cksum = 0xFF - cksum; // subtract from 0xFF
packet.cksum = cksum;

@westfw,

Video gave me the general idea, but I can't get the code you posted to work.

Can you define for me what the "&packet" is and why it has a & symbol before it? is it suppose to be a byte? a string? a char?

Is it suppose to include some of final packet? Say just the data ( Example: Purple. 99 00 99) Or is it suppost to be the byte that is to be sent, but just with out the checksum at the end? (Example: 7E 00 0B 01 01 FF FF 00 39 39 30 30 39 39). I don't comprehend where it would go in the code?

Can you post the code you have now, so I can see how you are setting up and transmitting the packet?
the code I posted should be pretty obvious to someone with a bit of experience, but I keep forgetting how many people that leaves out...

The & is the address of operator. It says that the argument is the address of a memory location that the function can write to. The "packet" is the data that you want to compute the checksum for.

Current code with westfw’s code plugged in.

/*
   Sourced from this forum post:
   http://forum.arduino.cc/index.php?topic=119463.0
*/

#include <SoftwareSerial.h>
// XBee's DOUT (TX) is connected to pin 2 (Arduino's Software RX)
// XBee's DIN (RX) is connected to pin 3 (Arduino's Software TX)
SoftwareSerial XBee(2, 3); // RX, TX


// needs to be a 0x00 number. use Find/Replace. replace space with ", 0x"

byte first[] = {0x7E, 0x00, 0x08, 0x01, 0x03, 0xFF, 0xFF, 0x00, 0x37, 0x38, 0x39, 0x55};
byte framezero[] = {0x7E, 0x00, 0x08, 0x01, 0x02, 0xFF, 0xFF, 0x00, 0x33, 0x34, 0x35, 0x63};
byte frameOne[] = {0x7E, 0x00, 0x0D, 0x01, 0x01, 0xFF, 0xFF, 0x00, 0x2D, 0x46, 0x72, 0x61, 0x6D, 0x65, 0x30, 0x30, 0x87};
byte packet[] = {0x7E, 0x00, 0x0B, 0x01, 0x01, 0xFF, 0xFF, 0x00, 0x39, 0x39, 0x30, 0x30, 0x39, 0x39, 0xBB};

int Xbee_loop_count;
void setup()
{
  Serial.begin(9600);
  XBee.begin(19200);

}

void loop() {
  Xbee_loop_count++;

  XBee.write(hello, 20);
  XBee.write(frameOne, 17);
  ///XBee.write(125);
  XBee.write(first, 12);
  XBee.write(first, 12);


  uint8_t *p = &packet;   // Get the address of the packet, to be used as an array of bytes.
  cksum = 0;  // start with a zero checksum
  for (byte i = 3; i < packetLength; i++) {  // skip the Start and len, start with byte 4.
    // (remembering that C arrays start at 0, not 1.)
    cksum += p[i];    // Add in this byte.
  }  // next byte
  cksum &= 0xFF;        // low order 8 bits
  cksum = 0xFF - cksum; // subtract from 0xFF
  packet.cksum = cksum;

  


  delay(100);
  //Serial.println(Xbee_loop_count);

}

If this was analog/digital in/outs I would do well there. But dipping my feet into Hex, and byte is where I am all confused.

I plugged in the data you sent into the loop, and get errors when compiling. “cannot convert ‘byte ()[15] {aka unsigned char ()[15]}’ to ‘uint8_t* {aka unsigned char*}’ in initialization”

I am trying to get the xbee to simply communicate correctly. I can do that via the frame builder with XCTU. I am in the second step now, as to manually plug my R G B values in, to get the checksum to calculate correctly. Once I understand how to use the checksum, then my 3rd step is to figure out how to pull the R G B values from else where in the code, and plug them into the byte, then run the checksum. My style of codeing is to divide and concur one small step at a time.

I would think, that since the byte packet is already built, it shouldn’t have an issue grabbing the byte packet, and getting the info it wants.

I also see that ‘packetLength’ is also registering an error in the compiler. since it is not declared either.

I would think, that since the byte packet is already built, it shouldn't have an issue grabbing the byte packet, and getting the info it wants.

westfw's code assumes that packet is an instance of a struct. You don't have a struct.

You don't really need one, though. The only reason that code uses a struct is to keep the checksum separate from the payload. In your case, the checksum is the last element of the payload.

Huh. I had a nice long response but it has disappeared.
Anyway, here’s the code re-written and tested, based on the packet format you’re actually using.

/*
   Sourced from this forum post:
   http://forum.arduino.cc/index.php?topic=119463.0
*/

#include <SoftwareSerial.h>
// XBee's DOUT (TX) is connected to pin 2 (Arduino's Software RX)
// XBee's DIN (RX) is connected to pin 3 (Arduino's Software TX)
SoftwareSerial XBee(2, 3); // RX, TX

byte first[] = {0x7E, 0x00, 0x08, 0x01, 0x03, 0xFF, 0xFF, 0x00, 0x37, 0x38, 0x39, 0x55};
byte framezero[] = {0x7E, 0x00, 0x08, 0x01, 0x02, 0xFF, 0xFF, 0x00, 0x33, 0x34, 0x35, 0x63};
byte frameOne[] = {0x7E, 0x00, 0x0D, 0x01, 0x01, 0xFF, 0xFF, 0x00, 0x2D, 0x46, 0x72, 0x61, 0x6D, 0x65, 0x30, 0x30, 0x87};
byte packet[] = {0x7E, 0x00, 0x0B, 0x01, 0x01, 0xFF, 0xFF, 0x00, 0x39, 0x39, 0x30, 0x30, 0x39, 0x39, 0xBB};

int Xbee_loop_count;
void setup()
{
  Serial.begin(9600);
  XBee.begin(19200);
}
void loop() {
  Xbee_loop_count++;

  add_cksum(first, sizeof(first));
  add_cksum(framezero, sizeof(framezero));
  add_cksum(frameOne, sizeof(frameOne));
  add_cksum(packet, sizeof(packet));

 // XBee.write(hello, 20);
  XBee.write(frameOne, 17);
  ///XBee.write(125);
  XBee.write(first, 12);
  XBee.write(first, 12);

  delay(10000);
  //Serial.println(Xbee_loop_count);
  Serial.println();
}

#define DEBUG false   // change me!
void add_cksum(byte p[], int pktsize)
{
  int cksum = 0;  // start with a zero checksum
  for (byte i = 3; i < pktsize-1; i++) {  // skip the Start and len, start with byte 4.
    // (remembering that C arrays start at 0, not 1.)
    cksum += p[i];    // Add in this byte.
  }  // next byte
  cksum &= 0xFF;        // low order 8 bits
  cksum = 0xFF - cksum; // subtract from 0xFF
  p[pktsize-1] = cksum;
  if (DEBUG) {
    Serial.print("add_cksum got ");
    Serial.println(cksum, HEX);
  }
}

The “structure” overlay that Paul mentions would look something like this:

typedef struct xbeepkt_ {
    byte header[3];  // start byte and length, not checksummed.
    byte type;
    byte frameId;
    byte address[2];
    byte option;
    byte red, green, blue;  // user data
    byte cksum;
} xbeepkt;

This sort of thing is pretty common in networking code, and handy as your packet structure gets more complicated.
You might want to look into it.

This does work for the minute. Yes, I can see the checksum being calculated and can view it in the serial monitor. Which is all well and good. But I can not use the cksum value anywhere.
This does work for an ENTIRE packet that is already built. including the checksum. But won’t work since I will need to build it. If I remove the checksum from the end of the pre-built packet, I get a checksum value of F4. When the correct checksum value should be BB.

This is no good cause I am trying to create the checksum, not look at the existing checksum.

I did look at PaulS’s structure setup. And by itself, it seams to make some sence. Thou it now brings up my next question, how do I use it?

I did try to build it into a void sendDataFrame(xbeepktt_ 7E 00 0B, 01, 01, FF FF, 00, r_value g_value b_value, cksum)
But this failed. One failure point is the cksum is not defined. Could you explain how this to be used. I was thinking that I could use this in a void and send it out that way?

#include <SoftwareSerial.h>
SoftwareSerial XBee(2, 3); // RX, TX
// needs to be a 0x00 number. use Find/Replace. replace space with ", 0x"

byte packet[] = {0x7E, 0x00, 0x0B, 0x01, 0x01, 0xFF, 0xFF, 0x00, 0x39, 0x39, 0x30, 0x30, 0x39, 0x39, 0xBB};

int Xbee_loop_count;

void setup()
{
  Serial.begin(9600);
  XBee.begin(19200);

}

void loop() {

  add_cksum(packet, sizeof(packet));

  int r_value = 99;
  int g_value = 00;
  int b_value = 99;
  //Serial.println(cksum);  //  CANT USE IT HERE? Get error: not declared. 
  delay(100);


}



#define DEBUG true   // change me!
void add_cksum(byte p[], int pktsize)
{
  int cksum = 0;  // start with a zero checksum
  for (byte i = 3; i < pktsize - 1; i++) { // skip the Start and len, start with byte 4.
    // (remembering that C arrays start at 0, not 1.)
    cksum += p[i];    // Add in this byte.
  }  // next byte
  cksum &= 0xFF;        // low order 8 bits
  cksum = 0xFF - cksum; // subtract from 0xFF
  p[pktsize - 1] = cksum;
  if (DEBUG) {
    Serial.print("add_cksum got ");
    Serial.println(cksum, HEX);
  }

}


typedef struct xbeepkt_ {
  byte header[3];  // start byte and length, not checksummed.
  byte type;
  byte frameId;
  byte address[2];
  byte option;
  byte red, green, blue;  // user data
  byte cksum;
} xbeepkt;


// now to send this. I would put it all together? usng a *xbeepkt_ to tell the code to go point to typedef struct xbeepkt, for each of the sections?
// byte packet[] = {0x7E, 0x00, 0x0B, 0x01, 0x01, 0xFF, 0xFF, 0x00, 0x39, 0x39, 0x30, 0x30, 0x39, 0x39, 0xBB};

void sendDataFrame()
{
 // send header 7E 00 0B
 // send type 01
 // send frameID 01
 // send address FF FF
 // send option 00
 // send data r_value g_value b_value
 // send checksum = cksum

}