This Processing program takes a string of values in the serial port. It assumes the string is the API string from a Maxstream XBee radio. It parses the string and graphs the signal strength and the analog values represented in the string. See the XBee product manual for more info on the protocol.
The XBee radio in this program is attached to the computer’s serial port using an FTDI USB-to-serial module like this one from Spark Fun.
Technorati Tags: networked objects, networks, XBee
/* Xbee Packet Grapher Reads a packet from an Xbee radio and parses it, then graphs it. The packet should be 22 bytes long. It should be made up of the following: byte 1: 0x7E, the start byte value byte 2-3: packet size, a 2-byte value (not used here) byte 4: API identifier value, a code that says what this response is (not used here) byte 5-6: Sender's address byte 7: RSSI, Received Signal Strength Indicator (not used here) byte 8: Broadcast options (not used here) byte 9: Number of samples to follow byte 10-11: Active channels indicator (not used here) byte 12-21: 5 10-bit values, each ADC samples from the sender Created 20 Mar. 2007 by Tom Igoe */ import processing.serial.*; Serial xbee; // input serial port from the Xbee Radio int[] packet = new int[22]; // with 5 samples, the Xbee packet is 22 bytes long int byteCounter; // keeps track of where you are in the packet int fontSize = 18; // size of the text on the screen int lastReading = 0; // value of the previous incoming byte int rssi = 0; // received signal strength int address = 0; // sender's address int average = 0; // average of the sensor data int firstRectPos = 25; // horizontal pos of the first graph bar void setup () { size(400, 300); // window size // create a font with the second font available to the system: PFont myFont = createFont(PFont.list()[2], fontSize); textFont(myFont); // get a list of the serial ports: println(Serial.list()); // open the serial port attached to your Xbee radio: xbee = new Serial(this, Serial.list()[0], 9600); } void draw() { // set the background: background(0); // if you have new data and it's valid (>0), graph it: // write the numbers: text("Xbee Radio Signal Strength test", 10, 20); text("From: " + hex(address), 10, 40); text ("RSSI: -" + rssi + " dB", 10, 60); text("Sensor avg:" + average, 10, 80); // note that these graph bars aren't proportional, they just show change. // RSSI should range from 0 to -92 dBm drawBar(92 - rssi, 50, 0); // average should range from 0 - 1023, so divide by 4 to keep it // in the vertical space of the window: drawBar(average/4, 50, 1); } void drawBar(int rectHeight, int rectWidth, int rectNum ) { if (rectHeight > 0 ) { // draw the rect: stroke(23, 127, 255); fill (23, 127, 255); int rectPos = firstRectPos + (rectNum * 75); rect(rectPos, height-rectHeight, rectWidth, height); } } void serialEvent(Serial xbee) { // read a byte from the port: int thisByte = xbee.read(); // if the byte = 0x7E, the value of a start byte, you have a new packet: if (thisByte == 0x7E) { // start byte // parse the previous packet if there's data: if (packet[2] > 0) { parseData(packet); } // reset the byte counter: byteCounter = 0; } // put the current byte into the packet at the current position: packet[byteCounter] = thisByte; // increment the byte counter: byteCounter++; } /* Once you've got a packet, you need to extract the useful data. This method gets the address of the sender and the 5 ADC readings. It then averages the ADC readings and gives you the result. */ void parseData(int[] thisPacket) { int adcStart = 11; // ADC reading starts at the 12th byte int numSamples = thisPacket[8]; // number of samples in the packet int[] adcValues = new int[numSamples]; // array to hold the 5 ARDC readings int total = 0; // sum of all the ADC readings // read the address. It's a two-byte value, so you // add the two bytes as follows: address = thisPacket[5] + thisPacket[4] * 256; // get RSSI: rssi = thisPacket[6]; // read numSamples 10-bit analog values, two at a time // because each reading is two bytes long: for (int i = 0; i < numSamples * 2; i=i+2) { // 10-bit value = high byte * 256 + low byte: int thisSample = (thisPacket[i + adcStart] * 256) + thisPacket[(i + 1) + adcStart]; // put the result in one of 5 bytes: adcValues[i/2] = thisSample; // add the result to the total for averaging later: total = total + thisSample; } // average the result: average = total / numSamples; // print the sender and the average reading: print("From: " + hex(address) + ": "); print(average + "\t"); println("Signal Strength:" + rssi); }