{"id":14,"date":"2009-11-01T12:50:49","date_gmt":"2009-11-01T18:50:49","guid":{"rendered":"http:\/\/nootropicdesign.com\/projectlab\/?p=14"},"modified":"2018-11-02T09:24:53","modified_gmt":"2018-11-02T14:24:53","slug":"wireless-temperature-sensor","status":"publish","type":"post","link":"https:\/\/nootropicdesign.com\/projectlab\/2009\/11\/01\/wireless-temperature-sensor\/","title":{"rendered":"Wireless Temperature Sensor"},"content":{"rendered":"<p><strong><em>Difficulty Level = 5<\/em><\/strong> <a href=\"\/projectlab\/difficulty-levels\/\">[What&#8217;s this?]<\/a><\/p>\n<p><span class=\"highlight\">UPDATE<\/span>: I have re-done this project using simple 434MHz RF transmitter\/receiver devices.  <a href=\"https:\/\/nootropicdesign.com\/projectlab\/2010\/12\/26\/rf-wireless-temperature-sensor\/\">Check out the new project!<\/a>.<\/p>\n<hr\/>\n<p><span class=\"highlight\">UPDATE<\/span>: Also see this project for an easy way to display a temperature reading:  <a href=\"https:\/\/nootropicdesign.com\/projectlab\/2011\/03\/19\/digit-shield-temp-display\/\">Digit Shield Temperature Display<\/a>.<\/p>\n<hr\/>\n<p>I decided to explore the more advanced features of <a href=\"http:\/\/www.digi.com\/products\/wireless\/zigbee-mesh\/\">XBee<\/a> radios by building a remote temperature sensor.  You can get quite a bit of control over an XBee radio without a microcontroller at all.  You can configure the radio to send sensor readings at particular intervals when it detects changes on certain input pins.  For the details on configuring XBee radios, see the <a href=\"http:\/\/ftp1.digi.com\/support\/documentation\/90000866_C.pdf\">documentation at Digi International<\/a>.<\/p>\n<p>For this project, I configured the radio at the sensor end to read the analog input of pin 19 every 4 seconds and to send a sensor reading packet.  <strong>Both the sender and receiver radios must be running the API firmware.<\/strong>  This does not work if they are running the default AT firmware.  And the &#8220;API&#8221; parameter is not the same as running the API firmware.  You literally need to write a different firmware image to your radios using the X-CTU tool from Digi.  I have Series 2 radios, so if you are using Series 1, you need to read the correct documentation for your radios and modify the code.<\/p>\n<p>Input pin 19 on my sensor radio is configured (parameter D1) with value &#8216;2&#8217; which means that it will read analog input, and the IO sampling rate (parameter IR) is set to &#8216;1000&#8217; which sends a sample every 4096ms.<\/p>\n<p>An LM34 temperature sensor outputs a variable voltage depending on the temperature.  The mapping is extremely simple: 10mV for every Fahrenheit degree.  So, at 72 degrees F, the output is 720mV.<\/p>\n<p>Why did I choose pin 19?  I started with pin 20, but I burned it out.  The pins can only handle an analog input of up to 1.2V, and I <em>think<\/em> I may have sent too much into the pin.  How?  Well, let&#8217;s say it involved holding a cold Pepsi can on the circuit to cool off the temperature sensor, and I shorted out a connection with the can.  Oops.  I&#8217;m lucky I didn&#8217;t burn out the entire XBee chip.<\/p>\n<div id=\"attachment_5\" style=\"width: 650px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-5\" class=\"size-full wp-image-5\" title=\"sensor\" src=\"https:\/\/nootropicdesign.com\/projectlab\/wp-content\/uploads\/2009\/11\/sensor.jpg\" alt=\"Remote temperature sensor\" width=\"640\" height=\"480\" srcset=\"https:\/\/nootropicdesign.com\/projectlab\/wp-content\/uploads\/2009\/11\/sensor.jpg 640w, https:\/\/nootropicdesign.com\/projectlab\/wp-content\/uploads\/2009\/11\/sensor-300x225.jpg 300w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><p id=\"caption-attachment-5\" class=\"wp-caption-text\">Remote temperature sensor<\/p><\/div>\n<p\/>\n<p\/>\nHere is the circuit for the remote sensor:<\/p>\n<div id=\"attachment_6\" style=\"width: 623px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-6\" class=\"size-full wp-image-6\" title=\"sensorSchematic\" src=\"https:\/\/nootropicdesign.com\/projectlab\/wp-content\/uploads\/2009\/11\/sensorSchematic1.png\" alt=\"Schematic for remote sensor circuit\" width=\"613\" height=\"481\" \/><p id=\"caption-attachment-6\" class=\"wp-caption-text\">Schematic for remote sensor circuit<\/p><\/div>\n<p\/>\n<p\/>\nFor the receiving side, I used an Arduino with an XBee shield and a two digit LED display:<br \/>\n<!--more--><\/p>\n<div id=\"attachment_7\" style=\"width: 650px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-7\" class=\"size-full wp-image-7\" title=\"display\" src=\"https:\/\/nootropicdesign.com\/projectlab\/wp-content\/uploads\/2009\/11\/display.jpg\" alt=\"Arduino with XBee shield and LED display\" width=\"640\" height=\"480\" srcset=\"https:\/\/nootropicdesign.com\/projectlab\/wp-content\/uploads\/2009\/11\/display.jpg 640w, https:\/\/nootropicdesign.com\/projectlab\/wp-content\/uploads\/2009\/11\/display-300x225.jpg 300w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><p id=\"caption-attachment-7\" class=\"wp-caption-text\">Arduino with XBee shield and LED display<\/p><\/div>\n<p\/>\n<p\/>\nHere&#8217;s the Arduino code for reading incoming packets from the XBee and displaying the received analog sample on the LED display.  Parsing an XBee packet is quite complex, unfortunately.  But after studying the documentation for a while, it isn&#8217;t that hard.<\/p>\n<pre class=\"codeblockscroll\">#define NUM_DIGITAL_SAMPLES 12\r\n#define NUM_ANALOG_SAMPLES 4\r\n\r\nint groundPins[7] = {8, 2, 3, 4, 5, 9, 7};\r\nint digitPins[2] = {11, 10};\r\nint ON = HIGH;\r\nint OFF = LOW;\r\nint number[10][7];\r\nint digit[2];\r\nint TOP = 0;\r\nint UPPER_L = 1;\r\nint LOWER_L = 2;\r\nint BOTTOM = 3;\r\nint LOWER_R = 4;\r\nint UPPER_R = 5;\r\nint MIDDLE = 6;\r\n\r\nint index;\r\nint n = 0;\r\n\r\nint packet[32];\r\nint digitalSamples[NUM_DIGITAL_SAMPLES];\r\nint analogSamples[NUM_ANALOG_SAMPLES];\r\n\r\nvoid setup()\r\n{\r\n  Serial.begin(9600);\r\n\r\n  for(int i=0;i&lt;7;i++) {\r\n    pinMode(groundPins[i], OUTPUT);\r\n  }\r\n  for(int i=0;i&lt;2;i++) {\r\n    pinMode(digitPins[i], OUTPUT);\r\n  }\r\n  initNumber();\r\n\r\n  setDigit(n);\r\n}\r\n\r\nvoid loop() {\r\n  readPacket();\r\n  drawDisplay();\r\n}\r\n\r\nvoid readPacket() {\r\n  if (Serial.available() &gt; 0) {\r\n    int b = Serial.read();\r\n    if (b == 0x7E) {\r\n      packet[0] = b;\r\n      packet[1] = readByte();\r\n      packet[2] = readByte();\r\n      int dataLength = (packet[1] &lt;&lt; 8) | packet[2];\r\n\r\n      for(int i=1;i&lt;=dataLength;i++) {\r\n        packet[2+i] = readByte();\r\n      }\r\n      int apiID = packet[3];\r\n      packet[3+dataLength] = readByte(); \/\/ checksum\r\n\r\n      printPacket(dataLength+4);\r\n\r\n      if (apiID == 0x92) {\r\n        int analogSampleIndex = 19;\r\n        int digitalChannelMask = (packet[16] &lt;&lt; 8) | packet[17];\r\n        if (digitalChannelMask &gt; 0) {\r\n          int d = (packet[19] &lt;&lt; 8) | packet[20];\r\n          for(int i=0;i &lt; NUM_DIGITAL_SAMPLES;i++) {\r\n            digitalSamples[i] = ((d &gt;&gt; i) &amp; 1);\r\n          }\r\n          analogSampleIndex = 21;\r\n        }\r\n\r\n        int analogChannelMask = packet[18];\r\n        for(int i=0;i&lt;4;i++) {\r\n          if ((analogChannelMask &gt;&gt; i) &amp; 1) {\r\n            analogSamples[i] = (packet[analogSampleIndex] &lt;&lt; 8) | packet[analogSampleIndex+1];\r\n            analogSampleIndex += 2;\r\n          } else {\r\n            analogSamples[i] = -1;\r\n          }\r\n        }\r\n      }\r\n    }\r\n\r\n    int reading = analogSamples[1];  \/\/ pin 19\r\n    \/\/ convert reading to millivolts\r\n    float v = ((float)reading\/(float)0x3FF)*1200.0;\r\n\r\n    \/\/ convert to Fahrenheit.  10mv per Fahrenheit degree\r\n    float f = v \/ 10.0;\r\n\r\n    \/\/ round to nearest int\r\n    n = (int)(f+0.5);\r\n    setDigit(n);\r\n  }\r\n}\r\n\r\nvoid drawDisplay() {\r\n  for(int g=0;g&lt;7;g++) {\r\n    digitalWrite(groundPins[g], LOW);\r\n    for(int i=0;i&lt;2;i++) {\r\n      if (digit[i] &lt; 0) {\r\n        continue;\r\n      }\r\n      digitalWrite(digitPins[i], number[digit[i]][g]);\r\n    }\r\n    delay(0);  \/\/ for some reason, this is required even if the value is 0\r\n    digitalWrite(groundPins[g], HIGH);\r\n  }\r\n}\r\n\r\nvoid setDigit(int n) {\r\n  n = n % 100;\r\n  digit[0] = n % 10;\r\n  digit[1] = (n \/ 10) % 10;\r\n  if ((digit[1] == 0) &amp;&amp; (n &lt; 10)) {\r\n    digit[1] = -1;\r\n  }\r\n}\r\n\r\nvoid initNumber() {\r\n  number[0][0] = ON;\r\n  number[0][1] = ON;\r\n  number[0][2] = ON;\r\n  number[0][3] = ON;\r\n  number[0][4] = ON;\r\n  number[0][5] = ON;\r\n  number[0][6] = OFF;\r\n\r\n  number[1][0] = OFF;\r\n  number[1][1] = OFF;\r\n  number[1][2] = OFF;\r\n  number[1][3] = OFF;\r\n  number[1][4] = ON;\r\n  number[1][5] = ON;\r\n  number[1][6] = OFF;\r\n\r\n  number[2][0] = ON;\r\n  number[2][1] = OFF;\r\n  number[2][2] = ON;\r\n  number[2][3] = ON;\r\n  number[2][4] = OFF;\r\n  number[2][5] = ON;\r\n  number[2][6] = ON;\r\n\r\n  number[3][0] = ON;\r\n  number[3][1] = OFF;\r\n  number[3][2] = OFF;\r\n  number[3][3] = ON;\r\n  number[3][4] = ON;\r\n  number[3][5] = ON;\r\n  number[3][6] = ON;\r\n\r\n  number[4][0] = OFF;\r\n  number[4][1] = ON;\r\n  number[4][2] = OFF;\r\n  number[4][3] = OFF;\r\n  number[4][4] = ON;\r\n  number[4][5] = ON;\r\n  number[4][6] = ON;\r\n\r\n  number[5][0] = ON;\r\n  number[5][1] = ON;\r\n  number[5][2] = OFF;\r\n  number[5][3] = ON;\r\n  number[5][4] = ON;\r\n  number[5][5] = OFF;\r\n  number[5][6] = ON;\r\n\r\n  number[6][0] = ON;\r\n  number[6][1] = ON;\r\n  number[6][2] = ON;\r\n  number[6][3] = ON;\r\n  number[6][4] = ON;\r\n  number[6][5] = OFF;\r\n  number[6][6] = ON;\r\n\r\n  number[7][0] = ON;\r\n  number[7][1] = OFF;\r\n  number[7][2] = OFF;\r\n  number[7][3] = OFF;\r\n  number[7][4] = ON;\r\n  number[7][5] = ON;\r\n  number[7][6] = OFF;\r\n\r\n  number[8][0] = ON;\r\n  number[8][1] = ON;\r\n  number[8][2] = ON;\r\n  number[8][3] = ON;\r\n  number[8][4] = ON;\r\n  number[8][5] = ON;\r\n  number[8][6] = ON;\r\n\r\n  number[9][0] = ON;\r\n  number[9][1] = ON;\r\n  number[9][2] = OFF;\r\n  number[9][3] = ON;\r\n  number[9][4] = ON;\r\n  number[9][5] = ON;\r\n  number[9][6] = ON;\r\n}\r\nvoid printPacket(int l) {\r\n  for(int i=0;i &lt; l;i++) {\r\n    if (packet[i] &lt; 0xF) {\r\n      \/\/ print leading zero for single digit values\r\n      Serial.print(0);\r\n    }\r\n    Serial.print(packet[i], HEX);\r\n    Serial.print(\" \");\r\n  }\r\n  Serial.println(\"\");\r\n} \r\n\r\nint readByte() {\r\n    while (true) {\r\n      if (Serial.available() &gt; 0) {\r\n      return Serial.read();\r\n    }\r\n  }\r\n}<\/pre>\n<p>Here&#8217;s how I wired the back of the LED display.  The code displays each digit separately to save Arduino pins but toggles between the digits so fast you can&#8217;t see any flicker.<\/p>\n<div id=\"attachment_8\" style=\"width: 650px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-8\" class=\"size-full wp-image-8\" title=\"displayCircuit\" src=\"https:\/\/nootropicdesign.com\/projectlab\/wp-content\/uploads\/2009\/11\/displayCircuit.jpg\" alt=\"Back of LED display.  The pin positions are designed to fit the XBee shield.\" width=\"640\" height=\"480\" srcset=\"https:\/\/nootropicdesign.com\/projectlab\/wp-content\/uploads\/2009\/11\/displayCircuit.jpg 640w, https:\/\/nootropicdesign.com\/projectlab\/wp-content\/uploads\/2009\/11\/displayCircuit-300x225.jpg 300w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><p id=\"caption-attachment-8\" class=\"wp-caption-text\">Back of LED display.  The pin positions are designed to fit the XBee shield.<\/p><\/div>\n<p\/>\n<p\/>\nHere&#8217;s how it looks in the dark!<\/p>\n<div id=\"attachment_9\" style=\"width: 650px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-9\" class=\"size-full wp-image-9\" title=\"display-dark\" src=\"https:\/\/nootropicdesign.com\/projectlab\/wp-content\/uploads\/2009\/11\/display-dark.jpg\" alt=\"In the dark!\" width=\"640\" height=\"480\" srcset=\"https:\/\/nootropicdesign.com\/projectlab\/wp-content\/uploads\/2009\/11\/display-dark.jpg 640w, https:\/\/nootropicdesign.com\/projectlab\/wp-content\/uploads\/2009\/11\/display-dark-300x225.jpg 300w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><p id=\"caption-attachment-9\" class=\"wp-caption-text\">In the dark!<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Difficulty Level = 5 [What&#8217;s this?] UPDATE: I have re-done this project using simple 434MHz RF transmitter\/receiver devices. Check out the new project!. UPDATE: Also see this project for an easy way to display a temperature reading: Digit Shield Temperature Display. I decided to explore the more advanced features of XBee radios by building a [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","footnotes":""},"categories":[3,5],"tags":[],"class_list":["post-14","post","type-post","status-publish","format-standard","hentry","category-arduino","category-xbee"],"_links":{"self":[{"href":"https:\/\/nootropicdesign.com\/projectlab\/wp-json\/wp\/v2\/posts\/14","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nootropicdesign.com\/projectlab\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nootropicdesign.com\/projectlab\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nootropicdesign.com\/projectlab\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/nootropicdesign.com\/projectlab\/wp-json\/wp\/v2\/comments?post=14"}],"version-history":[{"count":20,"href":"https:\/\/nootropicdesign.com\/projectlab\/wp-json\/wp\/v2\/posts\/14\/revisions"}],"predecessor-version":[{"id":1980,"href":"https:\/\/nootropicdesign.com\/projectlab\/wp-json\/wp\/v2\/posts\/14\/revisions\/1980"}],"wp:attachment":[{"href":"https:\/\/nootropicdesign.com\/projectlab\/wp-json\/wp\/v2\/media?parent=14"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nootropicdesign.com\/projectlab\/wp-json\/wp\/v2\/categories?post=14"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nootropicdesign.com\/projectlab\/wp-json\/wp\/v2\/tags?post=14"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}