{"id":7,"date":"2007-08-06T23:53:25","date_gmt":"2007-08-07T04:53:25","guid":{"rendered":"http:\/\/www.tigoe.com\/pcomp\/code2\/?p=7"},"modified":"2008-01-21T21:30:55","modified_gmt":"2008-01-22T02:30:55","slug":"xbee-radio-received-signal-strength-and-data-graphing-program","status":"publish","type":"post","link":"https:\/\/www.tigoe.com\/pcomp\/code\/Processing\/7\/","title":{"rendered":"Xbee Radio Received Signal Strength and Data Graphing Program"},"content":{"rendered":"<p>This Processing program takes a string of values in the serial port. It assumes the string is the API string from a <a href=\"http:\/\/maxstream.net\/\">Maxstream<\/a> XBee radio. It parses the string and graphs the signal strength and the analog values represented in the string. See the <a href=\"http:\/\/maxstream.net\/products\/xbee\/manual_xb_oem-rf-modules_802.15.4.pdf\">XBee product manual<\/a> for more info on the protocol.<\/p>\n<p>The XBee radio in this program is attached to the computer&#8217;s serial port using an FTDI USB-to-serial module like <a href=\"http:\/\/www.sparkfun.com\/commerce\/product_info.php?products_id=718\">this one from Spark Fun<\/a>.<\/p>\n<p><!-- technorati tags start --><\/p>\n<p style=\"text-align:right;font-size:10px;\">Technorati Tags: <a href=\"http:\/\/www.technorati.com\/tag\/networked objects\" rel=\"tag\">networked objects<\/a>, <a href=\"http:\/\/www.technorati.com\/tag\/networks\" rel=\"tag\">networks<\/a>, <a href=\"http:\/\/www.technorati.com\/tag\/XBee\" rel=\"tag\">XBee<\/a><\/p>\n<p><!-- technorati tags end --><br \/>\n<!--more--><\/p>\n<pre>\/*  Xbee Packet Grapher\n Reads a packet from an Xbee radio and parses it, then graphs it.\n The packet should be 22 bytes long. It should be made up of the following:\n byte 1:     0x7E, the start byte value\n byte 2-3:   packet size, a 2-byte value  (not used here)\n byte 4:     API identifier value, a code that says what this response is (not used here)\n byte 5-6:   Sender's address\n byte 7:     RSSI, Received Signal Strength Indicator (not used here)\n byte 8:     Broadcast options (not used here)\n byte 9:     Number of samples to follow\n byte 10-11: Active channels indicator (not used here)\n byte 12-21: 5 10-bit values, each ADC samples from the sender \n \n Created 20 Mar. 2007\n by Tom Igoe\n *\/\n\nimport processing.serial.*;\n\nSerial xbee;                    \/\/ input serial port from the Xbee Radio\nint[] packet = new int[22];     \/\/ with 5 samples, the Xbee packet is 22 bytes long\nint byteCounter;                \/\/ keeps track of where you are in the packet\n\nint fontSize = 18;              \/\/ size of the text on the screen\nint lastReading = 0;            \/\/ value of the previous incoming byte\n\nint rssi = 0;                    \/\/ received signal strength\nint address = 0;                 \/\/ sender's address\nint average = 0;                 \/\/ average of the sensor data\n\nint firstRectPos = 25;           \/\/ horizontal pos of the first graph bar\n\nvoid setup () {\n  size(400, 300);                \/\/ window size\n\n  \/\/ create a font with the second font available to the system:\n  PFont myFont = createFont(PFont.list()[2], fontSize);\n  textFont(myFont);\n\n  \/\/ get a list of the serial ports:\n  println(Serial.list());   \n  \/\/ open the serial port attached to your Xbee radio:\n  xbee = new Serial(this, Serial.list()[0], 9600);\n}\n\nvoid draw() {\n  \/\/ set the background:\n  background(0);\n  \/\/ if you have new data and it's valid (&gt;0), graph it:\n  \/\/ write the numbers:\n  text(\"Xbee Radio Signal Strength test\", 10, 20);\n  text(\"From: \" + hex(address), 10, 40);\n\n  text (\"RSSI: -\" + rssi + \" dB\", 10, 60);\n  text(\"Sensor avg:\" + average, 10, 80);\n\n  \/\/ note that these graph bars aren't proportional, they just show change.\n  \/\/ RSSI should range from 0 to -92 dBm\n  drawBar(92 - rssi, 50, 0);\n  \/\/ average should range from 0 - 1023, so divide by 4 to keep it\n  \/\/ in the vertical space of the window:\n  drawBar(average\/4, 50, 1);\n}\n\nvoid drawBar(int rectHeight, int rectWidth, int rectNum ) {\n  if (rectHeight &gt; 0 ) {\n\n    \/\/ draw the rect:\n    stroke(23, 127, 255);\n    fill (23, 127, 255);\n    int rectPos = firstRectPos + (rectNum * 75);\n    rect(rectPos, height-rectHeight, rectWidth, height);\n  } \n}\n\nvoid serialEvent(Serial xbee) {\n  \/\/ read a byte from the port:\n  int thisByte = xbee.read();\n  \/\/ if the byte = 0x7E, the value of a start byte, you have a new packet:\n  if (thisByte == 0x7E) {   \/\/ start byte\n    \/\/ parse the previous packet if there's data:\n    if (packet[2] &gt; 0) {\n      parseData(packet);\n    }\n    \/\/ reset the byte counter:\n    byteCounter = 0;        \n   \n  }\n  \/\/ put the current byte into the packet at the current position:\n  packet[byteCounter] = thisByte;\n  \/\/  increment the byte counter:\n  byteCounter++;\n}\n\n\/* \n Once you've got a packet, you need to extract the useful data. \n This method gets the address of the sender and the 5 ADC readings.\n It then averages the ADC readings and gives you the result.\n *\/\nvoid parseData(int[] thisPacket) {\n  int adcStart = 11;              \/\/ ADC reading starts at the 12th byte\n  int numSamples = thisPacket[8];  \/\/ number of samples in the packet\n  int[] adcValues = new int[numSamples];   \/\/ array  to hold the 5 ARDC readings\n  int total = 0;                  \/\/ sum of all the ADC readings\n\n  \/\/ read the address. It's a two-byte value, so you\n  \/\/ add the two bytes as follows:\n  address = thisPacket[5] + thisPacket[4] * 256;\n\n  \/\/ get RSSI:\n  rssi = thisPacket[6];\n\n  \/\/ read numSamples 10-bit analog values, two at a time\n  \/\/ because each reading is two bytes long:\n  for (int i = 0; i &lt; numSamples * 2;  i=i+2) {\n    \/\/ 10-bit value = high byte * 256 + low byte:\n    int thisSample = (thisPacket[i + adcStart] * 256) + thisPacket[(i + 1) + adcStart];\n    \/\/ put the result in one of 5 bytes:\n    adcValues[i\/2] = thisSample;\n    \/\/ add the result to the total for averaging later:\n    total = total + thisSample;\n  }\n  \/\/ average the result:\n  average = total \/ numSamples;\n\n  \/\/ print the sender and the average reading:\n  print(\"From: \" + hex(address) + \":   \");\n  print(average + \"\\t\");\n  println(\"Signal Strength:\" + rssi);\n}\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>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&#8217;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&#8217;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&#8217;s valid (&gt;0), graph it: \/\/ write the numbers: text(&#8220;Xbee Radio Signal Strength test&#8221;, 10, 20); text(&#8220;From: &#8221; + hex(address), 10, 40); text (&#8220;RSSI: -&#8221; + rssi + &#8221; dB&#8221;, 10, 60); text(&#8220;Sensor avg:&#8221; + average, 10, 80); \/\/ note that these graph bars aren&#8217;t proportional, they just show change.  \/\/ RSSI should range from 0 to -92 dBm drawBar(92 &#8211; rssi, 50, 0); \/\/ average should range from 0 &#8211; 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 &gt; 0 ) { \/\/ draw the rect: stroke(23, 127, 255); fill (23, 127, 255); int rectPos = firstRectPos + (rectNum * 75); text(rectNum, rectPos, 30); 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&#8217;s data: if (packet[2] &gt; 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&#8217;ve got a packet, you need to extract the useful data.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7,21],"tags":[],"class_list":["post-7","post","type-post","status-publish","format-standard","hentry","category-Processing","category-XBee"],"_links":{"self":[{"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/posts\/7","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/comments?post=7"}],"version-history":[{"count":0,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/posts\/7\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/media?parent=7"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/categories?post=7"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/tags?post=7"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}