A few days ago I was messing around with an Arduino board and a wireless shield mounted on it with a Series 1 XBee. Along with that another XBee was acting as a stand alone actuator. Unfortunately I had some troubles with reading the API packets the standalone XBee was sending back (X-CTU and any terminal really) displays the incoming data in a pretty much unreadable format for humans to directly interpret it. Garbled ASCII or HEX values aren’t particularly easy on the not-so-well trained eye. That’s why I decided to quickly whip up a packet interpreter program in the Arduino IDE.
Here’s my first basic version:
float vref = 3.3;
int resolution = 1024;
float result = 0;
byte join[2] = {0,0};
int numOfBytes = 0;
int sourceAddr = 0;
int numOfSamples = 0;
int data = 0;
byte adcStatus = 0x0;
float adcVal[6] = {0,0,0,0,0,0};
byte dioStatus = 0x0;
byte dioVal = 0x0;
void setup() {
Serial.begin(9600);
}
void loop()
{
numOfBytes = 0;
sourceAddr = 0;
numOfSamples = 0;
data = 0;
adcStatus = 0x0;
for(int i = 0; i < 6; i++)
adcVal[i] = 0;
dioStatus = 0x0;
if(Serial.available() >= 28) // Check for at least one complete frame
if(Serial.read() == 0x7E) // Start at beginning of frame
{
Serial.print("Start Byte: 0x7E");
//-------------- Number of Bytes in Frame ---------//
Serial.print("\nNr Of Bytes: ");
join[0] = Serial.read();
Serial.print(join[0], HEX); // MSB length
Serial.print(" ");
join[1] = Serial.read();
Serial.print(join[1], HEX); // LSB length
numOfBytes = join[1] + (join[0] << 8);
Serial.print(" --> DEC Value: ");
Serial.print(numOfBytes);
//-------------- Source Address Checking ---------//
Serial.print("\nAddress Mode: ");
Serial.print(Serial.read(), HEX); // 83 = 16bit address
Serial.print("\nSource Address: ");
join[0] = Serial.read();
Serial.print(join[0], HEX); // MSB Address
Serial.print(" ");
join[1] = Serial.read();
Serial.print(join[1], HEX); // LSB Address
sourceAddr = join[1] + (join[0] << 8);
//-------------- RSSI Checking ---------//
Serial.print("\nRSSI (signal strength in -dBm): ");
Serial.print(Serial.read(), DEC);
//-------------- Number of Samples in Frame ---------//
Serial.print("\nNr of Samples: ");
join[0] = Serial.read();
Serial.print(join[0], HEX); // MSB samples
Serial.print(" ");
join[1] = Serial.read();
Serial.print(join[1], HEX); // LSB samples
numOfSamples = join[1] + (join[0] << 8);
Serial.print(" --> DEC Value: ");
Serial.print(numOfSamples);
//-------------- Channel Indicator ---------//
Serial.print("\nChannel Bitfield: ");
adcStatus = Serial.read();
Serial.print(adcStatus, BIN); // Neglecting D8
Serial.print(" ");
dioStatus = Serial.read();
Serial.print(dioStatus, BIN);
//-------------- Fetching Data word DIO ---------//
if(dioStatus > 0x0)
{
Serial.print("\nData DIO: ");
Serial.print(Serial.read(), BIN);
Serial.print(" ");
dioVal = Serial.read(); // Neglecting D8
Serial.print(dioVal, BIN);
Serial.print(" --> ");
for(int i = 0; i <= 7; i++)
{
Serial.print("D");
Serial.print(i);
if(bitRead(dioVal, i))
Serial.print("H");
else
Serial.print("L");
Serial.print(" ");
}
}
else
Serial.print("\nNo DIO data in frame");
//-------------- Fetching Data word ADC ---------//
if(adcStatus > 0x0)
{
for(int i = 1; i <= 6; i++)
{
if(bitRead(adcStatus, i))
{
//Serial.print("\nData ADC #");
//Serial.print(i);
//Serial.print(": ");
join[0] = Serial.read();
//Serial.print(join[0], BIN); // MSB Data
//Serial.print(" ");
join[1] = Serial.read();
//Serial.print(join[1], BIN); // LSB Data
data = join[1] + (join[0] << 8);
//Serial.print(" --> DEC Value: ");
//Serial.print(data);
result = (vref/resolution)*data;
adcVal[i-1] = result;
//Serial.print(" - Voltage: ");
//Serial.print(result);
}
}
Serial.print("\nData ADC: ");
for(int i = 0; i < 6; i++)
{
if(bitRead(adcStatus, i+1))
{
Serial.print("ADC");
Serial.print(i);
Serial.print(": ");
Serial.print(adcVal[i]);
Serial.print(" ");
}
}
}
else
Serial.print("\nNo ADC data in frame");
Serial.print("\n------------------\n");
}
} |
float vref = 3.3;
int resolution = 1024;
float result = 0;
byte join[2] = {0,0};
int numOfBytes = 0;
int sourceAddr = 0;
int numOfSamples = 0;
int data = 0;
byte adcStatus = 0x0;
float adcVal[6] = {0,0,0,0,0,0};
byte dioStatus = 0x0;
byte dioVal = 0x0;
void setup() {
Serial.begin(9600);
}
void loop()
{
numOfBytes = 0;
sourceAddr = 0;
numOfSamples = 0;
data = 0;
adcStatus = 0x0;
for(int i = 0; i < 6; i++)
adcVal[i] = 0;
dioStatus = 0x0;
if(Serial.available() >= 28) // Check for at least one complete frame
if(Serial.read() == 0x7E) // Start at beginning of frame
{
Serial.print("Start Byte: 0x7E");
//-------------- Number of Bytes in Frame ---------//
Serial.print("\nNr Of Bytes: ");
join[0] = Serial.read();
Serial.print(join[0], HEX); // MSB length
Serial.print(" ");
join[1] = Serial.read();
Serial.print(join[1], HEX); // LSB length
numOfBytes = join[1] + (join[0] << 8);
Serial.print(" --> DEC Value: ");
Serial.print(numOfBytes);
//-------------- Source Address Checking ---------//
Serial.print("\nAddress Mode: ");
Serial.print(Serial.read(), HEX); // 83 = 16bit address
Serial.print("\nSource Address: ");
join[0] = Serial.read();
Serial.print(join[0], HEX); // MSB Address
Serial.print(" ");
join[1] = Serial.read();
Serial.print(join[1], HEX); // LSB Address
sourceAddr = join[1] + (join[0] << 8);
//-------------- RSSI Checking ---------//
Serial.print("\nRSSI (signal strength in -dBm): ");
Serial.print(Serial.read(), DEC);
//-------------- Number of Samples in Frame ---------//
Serial.print("\nNr of Samples: ");
join[0] = Serial.read();
Serial.print(join[0], HEX); // MSB samples
Serial.print(" ");
join[1] = Serial.read();
Serial.print(join[1], HEX); // LSB samples
numOfSamples = join[1] + (join[0] << 8);
Serial.print(" --> DEC Value: ");
Serial.print(numOfSamples);
//-------------- Channel Indicator ---------//
Serial.print("\nChannel Bitfield: ");
adcStatus = Serial.read();
Serial.print(adcStatus, BIN); // Neglecting D8
Serial.print(" ");
dioStatus = Serial.read();
Serial.print(dioStatus, BIN);
//-------------- Fetching Data word DIO ---------//
if(dioStatus > 0x0)
{
Serial.print("\nData DIO: ");
Serial.print(Serial.read(), BIN);
Serial.print(" ");
dioVal = Serial.read(); // Neglecting D8
Serial.print(dioVal, BIN);
Serial.print(" --> ");
for(int i = 0; i <= 7; i++)
{
Serial.print("D");
Serial.print(i);
if(bitRead(dioVal, i))
Serial.print("H");
else
Serial.print("L");
Serial.print(" ");
}
}
else
Serial.print("\nNo DIO data in frame");
//-------------- Fetching Data word ADC ---------//
if(adcStatus > 0x0)
{
for(int i = 1; i <= 6; i++)
{
if(bitRead(adcStatus, i))
{
//Serial.print("\nData ADC #");
//Serial.print(i);
//Serial.print(": ");
join[0] = Serial.read();
//Serial.print(join[0], BIN); // MSB Data
//Serial.print(" ");
join[1] = Serial.read();
//Serial.print(join[1], BIN); // LSB Data
data = join[1] + (join[0] << 8);
//Serial.print(" --> DEC Value: ");
//Serial.print(data);
result = (vref/resolution)*data;
adcVal[i-1] = result;
//Serial.print(" - Voltage: ");
//Serial.print(result);
}
}
Serial.print("\nData ADC: ");
for(int i = 0; i < 6; i++)
{
if(bitRead(adcStatus, i+1))
{
Serial.print("ADC");
Serial.print(i);
Serial.print(": ");
Serial.print(adcVal[i]);
Serial.print(" ");
}
}
}
else
Serial.print("\nNo ADC data in frame");
Serial.print("\n------------------\n");
}
}
This will output something like the following:
Start Byte: 0x7E
Nr Of Bytes: 0 10 –> DEC Value: 16
Address Mode: 83
Source Address: 50 0
RSSI (signal strength in -dBm): 35
Nr of Samples: 0 1 –> DEC Value: 1
Channel Bitfield: 100110 11101000
Data DIO: 0 10001000 –> D0L D1L D2L D3H D4L D5L D6L D7H
Data ADC: ADC0: 2.31 ADC1: 1.80 ADC4: 1.41
——————
Personally, I like this layout, you can quickly see what the status is of every XBee IO pin. I was thinking of adding a graphical interface but then again the gain is little and it’s not really worth the effort.
If you have any questions, suggestions or feedback, please let me know and I’ll get back to you.
Update: Check out my GUI version, XBeeP.
Update 2: And just because I can, an improved version in PHP (the Arduino version contains some small errors in the logic).
$packet = "835678220005060002C003FF"; // Example input (only payload)
function parsePacket($packet)
{
$bytes = str_split($packet, 2);
foreach($bytes as $val)
echo $val . " ";
//$api_type = $bytes[0]; // ----> SHOULD ALWAYS BE 83!
$source = dechex(intval($bytes[2], 16) + (intval($bytes[1], 16) << 8));
//$rssi = $bytes[3];
//$samples = $bytes[5] + ($bytes[4] << 8);
$adcStatus = (intval($bytes[6], 16) >> 1);
$dioStatus = intval($bytes[7], 16);
$c = 8;
if($dioStatus > 0)
{
$dioMSB = $bytes[$c++];
$dioVal = intval($bytes[$c++], 16);
}
if($adcStatus > 0)
{
for($i = 0; $i <= 5; $i++)
{
if($adcStatus & (1 << $i))
{
$adcVal[$i] = (intval($bytes[$c+1+$i], 16) + (intval($bytes[$c+$i], 16) << 8));
$adcString .= "ADC" . $i . " " . $adcVal[$i]/1024*3.3;
$c++;
}
}
}
echo "Source " .
$source . " ADC " .
decbin($adcStatus) . " DIO " .
decbin($dioStatus) . " dioVal" .
$dioVal . " adcval" .
$adcString;
} |
$packet = "835678220005060002C003FF"; // Example input (only payload)
function parsePacket($packet)
{
$bytes = str_split($packet, 2);
foreach($bytes as $val)
echo $val . " ";
//$api_type = $bytes[0]; // ----> SHOULD ALWAYS BE 83!
$source = dechex(intval($bytes[2], 16) + (intval($bytes[1], 16) << 8));
//$rssi = $bytes[3];
//$samples = $bytes[5] + ($bytes[4] << 8);
$adcStatus = (intval($bytes[6], 16) >> 1);
$dioStatus = intval($bytes[7], 16);
$c = 8;
if($dioStatus > 0)
{
$dioMSB = $bytes[$c++];
$dioVal = intval($bytes[$c++], 16);
}
if($adcStatus > 0)
{
for($i = 0; $i <= 5; $i++)
{
if($adcStatus & (1 << $i))
{
$adcVal[$i] = (intval($bytes[$c+1+$i], 16) + (intval($bytes[$c+$i], 16) << 8));
$adcString .= "ADC" . $i . " " . $adcVal[$i]/1024*3.3;
$c++;
}
}
}
echo "Source " .
$source . " ADC " .
decbin($adcStatus) . " DIO " .
decbin($dioStatus) . " dioVal" .
$dioVal . " adcval" .
$adcString;
}