Pages: [1]   Go Down
Author Topic: Implementing supplemental error correction for XBEE?  (Read 1327 times)
0 Members and 1 Guest are viewing this topic.
Washington
Offline Offline
God Member
*****
Karma: 39
Posts: 805
Firefox & Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am thinking of implementing supplementary error correction for an XBEE connection.
The problem is, when the XBEE is near the end of range, the "native" error correction is insufficient and it drops bytes at random.
I need to transfer about 1K of data intact between the computer and an Arduino. Speed is not all that critical.
I am thinking of sending a data index with each byte and then request a resend of missing bytes. The issue with this method is, it would require at 16bit data index which would mean three bytes would be transferred for each byte. If the data connection were reliable, this would not be a problem. But since the data connection isn't reliable, if a byte is dropped, how do you know if the next byte received is either the first or second byte of the data index or if it is the data byte?
Can you suggest a method to handle this? Dealing with randomly dropped bytes is no easy task!
Logged

Avoid throwing electronics out as you or someone else might need them for parts or use.
Solid state rectifiers are the only REAL rectifiers.
Resistors for LEDS!

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 644
Posts: 50457
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
The issue with this method is, it would require at 16bit data index which would mean three bytes would be transferred for each byte.
If you create packets that contain a start marker, a packet number, 20 bytes, a checksum and an end marker, the receiving end can find the start and end markers, compute the checksum, and determine if packet n was received correctly. If not, don't acknowledge it. The sender would then need to send packet n again. If the nth packet was acknowledged, the sender would know that it was not necessary to send that packet again.

You can change the size of the packet. Larger packets have less overhead (the start and end markers, the packet number, and the checksum). The tradeoff is that larger packets are harder to send/receive without lost/mangled bytes.

Reliable power and proper XBee selection and configuration have a lot to do with packets getting through intact. You haven't told us anything about the XBees you have, the range the data is being transmitted, or how the XBees are configured or powered.
Logged

Washington
Offline Offline
God Member
*****
Karma: 39
Posts: 805
Firefox & Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
The issue with this method is, it would require at 16bit data index which would mean three bytes would be transferred for each byte.
If you create packets that contain a start marker, a packet number, 20 bytes, a checksum and an end marker, the receiving end can find the start and end markers, compute the checksum, and determine if packet n was received correctly. If not, don't acknowledge it. The sender would then need to send packet n again. If the nth packet was acknowledged, the sender would know that it was not necessary to send that packet again.
Easier said then implemented but I am working on it.
Quote
You can change the size of the packet. Larger packets have less overhead (the start and end markers, the packet number, and the checksum). The tradeoff is that larger packets are harder to send/receive without lost/mangled bytes.
I chose 1 start byte + 1 byte packet number + 2 byte checksum + 16 byte data + 1 end byte totaling of 21 byte packet.
Quote
Reliable power and proper XBee selection and configuration have a lot to do with packets getting through intact. You haven't told us anything about the XBees you have, the range the data is being transmitted, or how the XBees are configured or powered.
XBees are 1mW Wire antenna with retries set to maximum. No chance of using higher power version since power consumption has to be low. 300+ mA is not acceptable even in bursts.
Distance is about 120-200 feet (36-61m).
My prototype code (just for testing):
Computer:
Code:
#include <c:/ko.c>
#include <stdio.h>
int cksum(unsigned char *a, int start, int len){
int t=0,i;
for(i = start;i < (start + len);i++){
t+=a[i];
}
return t;
 }
int main(){
int x,di=0,t,ic,ck,nack=0;
unsigned char stat;
FILE *f = fopen("COM6", "w+b");
printf("Opening port: %s\n", f? "success": "failed");
if(!f){return 1;}
for(x = 0;x < 64;x++){
resend:
ck = cksum(data, di, 16);
fprintf(f, "%c%c%c%c", 0x7B, x, (ck & 0xFF00) >> 8, ck & 0xFF);
printf("Generating packet %d, cksum = %x, data index=%d\n", x, ck, di);
for(t = di;t < di + 16;t++){fprintf(f, "%c", data[t]);}
fprintf(f, "%c", 0x7C);
fflush(f);
printf("Waiting for ACK\n");
ic = time(NULL);
while(time(NULL) - ic < 2){
if(!feof(f)){
printf("BT:");
fread(&stat, 1, 1, f);
printf("%d\n", stat);
if(stat != 0x7D){
printf("Resending packet %d (bad ACK)\n", x);
nack++;
goto resend;
} else {printf("PKT OK\n"); goto np;}
}
}
printf("Resending packet %d (timeout waiting for ACK)\n", x);
nack++;
goto resend;
np:
di += 16;
}
printf("-%d resends-\n", nack);
system("PAUSE");
return 0;
}

Arduino:
Code:
#include <NewSoftSerial.h>
NewSoftSerial S(2, 12);
int cksum(unsigned char *a, int start, int len){
        int t=0,i;
        for(i = start;i < (start + len);i++){
                t+=a[i];
        }
        return t;
 }
void setup(){
  Serial.begin(9600);
  S.begin(115200);
}
unsigned char pn,opn=-1,r;
unsigned char pktbuf[24];
int cksm;
int t;
void loop(){
  while(!Serial.available());
  while(Serial.read() != 0x7B);
  while(!Serial.available());
  pn = Serial.read();
  S.print("Packet number=");
  S.println((int)pn);
  if(pn == opn){ //Received a duplicate packet. Trash it and send ACK anyway
    while(Serial.read() != 0x7C);
    Serial.write(0x7D);
    S.println("DUP");
  }
  while(!Serial.available());
  cksm = Serial.read() << 8;
  while(!Serial.available());
  cksm |= Serial.read();
  S.print("CKSM=");
  S.println((int)cksm);
  for(t = 0;t < 16;t++){
      while(!Serial.available());
      pktbuf[t] = Serial.read();
  }
  while(!Serial.available());
  r = Serial.read();
  if(cksum(pktbuf, 0, 16) != cksm){Serial.write(0xA); S.println("Checksum bad");} else {
    Serial.write(0x7D);
    S.println("ACK SENT");
    opn = pn;
  }
}
Strangely enough, it worked once and now it just hangs.
A serial LCD screen is attached to a softserial pin on the Arduino for debugging.
Output from computer:
Code:
Opening port: success
Generating packet 0, cksum = f01, data index=0
Waiting for ACK
BT:
Output from Arduino:


* Cam0Pic12-04-30_15.25.10.jpg (48.31 KB, 640x480 - viewed 8 times.)
Logged

Avoid throwing electronics out as you or someone else might need them for parts or use.
Solid state rectifiers are the only REAL rectifiers.
Resistors for LEDS!

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 95
Posts: 4092
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

If you create packets that contain a start marker, a packet number, 20 bytes, a checksum and an end marker, the receiving end can find the start and end markers, compute the checksum, and determine if packet n was received correctly. If not, don't acknowledge it. The sender would then need to send packet n again. If the nth packet was acknowledged, the sender would know that it was not necessary to send that packet again.
Easier said then implemented but I am working on it.

That's a pretty good description of API mode. And there's no need to reinvent the wheel:
http://code.google.com/p/xbee-arduino/
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Washington
Offline Offline
God Member
*****
Karma: 39
Posts: 805
Firefox & Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you create packets that contain a start marker, a packet number, 20 bytes, a checksum and an end marker, the receiving end can find the start and end markers, compute the checksum, and determine if packet n was received correctly. If not, don't acknowledge it. The sender would then need to send packet n again. If the nth packet was acknowledged, the sender would know that it was not necessary to send that packet again.
Easier said then implemented but I am working on it.

That's a pretty good description of API mode. And there's no need to reinvent the wheel:
http://code.google.com/p/xbee-arduino/
Does that implement the necessary error correction? I am not sure it does.
Logged

Avoid throwing electronics out as you or someone else might need them for parts or use.
Solid state rectifiers are the only REAL rectifiers.
Resistors for LEDS!

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 95
Posts: 4092
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Does that implement the necessary error correction? I am not sure it does.

Yes, a Transmit Request frame is checksummed. After the transmit completes, a Transmit Status frame is sent which includes delivery status. If the status is not successful, then the Transmit Request could be retried.

EDIT: A Frame ID between 1 and 255 is part of the Transmit Request frame, and this Frame ID is returned in the Transmit Status frame, allowing the sender to determine which packet(s) should be retransmitted. (A Frame ID of zero will disable the Status frame from being sent.)

Check out that library, it includes API transmit examples for S1 and S2 XBees.
« Last Edit: April 30, 2012, 07:39:30 pm by Jack Christensen » Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Washington
Offline Offline
God Member
*****
Karma: 39
Posts: 805
Firefox & Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Does that implement the necessary error correction? I am not sure it does.

Yes, a Transmit Request frame is checksummed. After the transmit completes, a Transmit Status frame is sent which includes delivery status. If the status is not successful, then the Transmit Request could be retried.

EDIT: A Frame ID between 1 and 255 is part of the Transmit Request frame, and this Frame ID is returned in the Transmit Status frame, allowing the sender to determine which packet(s) should be retransmitted. (A Frame ID of zero will disable the Status frame from being sent.)

Check out that library, it includes API transmit examples for S1 and S2 XBees.
Upon further examination, it does not look like it will work.
I have an Arduino on one end but the XBEE is attached directly to the computer on the other end.
Now I am thinking of using this: http://arduino.cc/playground/Code/SerialIP and allowing TCP to do the heavy lifting.
Logged

Avoid throwing electronics out as you or someone else might need them for parts or use.
Solid state rectifiers are the only REAL rectifiers.
Resistors for LEDS!

Pages: [1]   Go Up
Jump to: