<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:iweb="http://www.apple.com/iweb" version="2.0">
  <channel>
    <title>techBlog</title>
    <link>http://www.byteworks.us/Byte_Works/Blog/Blog.html</link>
    <description>Here’s the place to find out about the tech products from the Byte Works. We’ll explore different things people are doing with techBASIC and share tips and tricks for getting the most from all of our products.</description>
    <generator>iWeb 3.0.4</generator>
    <image>
      <url>http://www.byteworks.us/Byte_Works/Blog/Blog_files/iPadiPhone.jpg</url>
      <title>techBlog</title>
      <link>http://www.byteworks.us/Byte_Works/Blog/Blog.html</link>
    </image>
    <item>
      <title>Build Your Own Bluetooth low energy based circuits using the Blue Radios BR-XB-LE4.0-S2</title>
      <link>http://www.byteworks.us/Byte_Works/Blog/Entries/2012/12/28_Build_Your_Own_Bluetooth_low_energy_based_circuits_using_the_Blue_Radios_BR-XB-LE4.0-S2.html</link>
      <guid isPermaLink="false">9c3d0fc8-571b-4259-8dc3-e79b513675ee</guid>
      <pubDate>Fri, 28 Dec 2012 11:21:38 -0700</pubDate>
      <description>&lt;a href=&quot;http://www.byteworks.us/Byte_Works/Blog/Entries/2012/12/28_Build_Your_Own_Bluetooth_low_energy_based_circuits_using_the_Blue_Radios_BR-XB-LE4.0-S2_files/BR-XB-LE4.0-S2.jpg&quot;&gt;&lt;img src=&quot;http://www.byteworks.us/Byte_Works/Blog/Media/object006_2.jpg&quot; style=&quot;float:left; padding-right:10px; padding-bottom:10px; width:183px; height:137px;&quot;/&gt;&lt;/a&gt;The Blue Radios BR-XB-LE4.0-S2 is a Bluetooth low energy prototyping platform. Like the &lt;a href=&quot;Entries/2012/8/20_Controlling_Bluetooth_LE_Devices_with_techBASIC.html&quot;&gt;Texas Instruments Key Fob&lt;/a&gt; and &lt;a href=&quot;Entries/2012/10/31_Controlling_the_TI_SensorTag_with_techBASIC.html&quot;&gt;SensorTag&lt;/a&gt; covered in previous blogs, this one is a hardware reference platform the manufacturer is using to encourage people to use their services. In this case, though, the device is pretty open ended. In addition to a number of dedicated pins, the device has three unused digital I/O ports and five analog-to-digital (ADC) input ports. This means you can use the device to control all sorts of external electronics, often bypassing the need for a microprocessor like the Arduino. This makes it a great device for hobbyist use and prototyping alike. If you're building a one-off project, or even a few dozen highly specialized devices, you can use the &lt;a href=&quot;http://www.blueradios.com/BR-XB-LE4.0-S2.pdf&quot;&gt;BR-XB-LE4.0-S2&lt;/a&gt; as a component in your overall device. If you need a few thousand devices, you can take your design back to the manufacturer, &lt;a href=&quot;http://www.blueradios.com/&quot;&gt;Blue Radios&lt;/a&gt;, and have the components fabricated in quantity.&lt;br/&gt;&lt;br/&gt;This blog explores how to build simple circuits for digital I/O and analog input. You'll build several complete, working circuits based around the BR-XB-LE4.0-S2. The software interface will be both flexible and simple, allowing you to send AT commands to the BR-XB-LE4.0-S2 to read and write to the I/O ports.&lt;br/&gt;&lt;br/&gt;The BR-XB-LE4.0-S2 also supports a serial I/O capability. You can use it as a bridge device, connecting it to any serial device, creating a wireless serial connection to your iPhone or iPad. This blog covers using the built-in I/O ports; we'll come back to using the device as a Bluetooth low energy to serial bridge in a later blog.&lt;br/&gt;&lt;br/&gt;Blue Radios also builds a companion device called the BR-XB-LE4.0-D2. The difference between the two modules is that the –S2 version is a single-mode device which supports Bluetooth low energy, while the –D2 model is a dual mode device that supports both the Bluetooth low energy and original Bluetooth standards. Either works just fine for connecting to the iPhone using Bluetooth low energy. You really only need the dual mode version if you are connecting to other devices that support the original Bluetooth standard but not Bluetooth low energy.&lt;br/&gt;&lt;br/&gt;Hardware&lt;br/&gt;              Parts List </description>
      <enclosure url="http://www.byteworks.us/Byte_Works/Blog/Entries/2012/12/28_Build_Your_Own_Bluetooth_low_energy_based_circuits_using_the_Blue_Radios_BR-XB-LE4.0-S2_files/BR-XB-LE4.0-S2.jpg" length="107482" type="image/jpeg"/>
    </item>
    <item>
      <title>Collect Data from an iPhone Rocket Flight </title>
      <link>http://www.byteworks.us/Byte_Works/Blog/Entries/2012/10/31_Collect_Data_from_an_iPhone_Rocket_Flight.html</link>
      <guid isPermaLink="false">68d264c6-b0dc-4391-b121-005e2453a340</guid>
      <pubDate>Wed, 31 Oct 2012 13:47:36 -0600</pubDate>
      <description>&lt;a href=&quot;http://www.byteworks.us/Byte_Works/Blog/Entries/2012/10/31_Collect_Data_from_an_iPhone_Rocket_Flight_files/iPhone%20Rockets.jpg&quot;&gt;&lt;img src=&quot;http://www.byteworks.us/Byte_Works/Blog/Media/object000_1.jpg&quot; style=&quot;float:left; padding-right:10px; padding-bottom:10px; width:183px; height:137px;&quot;/&gt;&lt;/a&gt;It was a beautiful fall morning as I carefully packed the parachute, slid in the engine, and installed the igniter in my model rocket. I started the data collection program and slid the payload with a TI Bluetooth low energy SensorTag and an iPhone 4s into the payload bay. &lt;br/&gt;&lt;br/&gt;Yes, an iPhone. &lt;br/&gt;&lt;br/&gt;My wife's iPhone.&lt;br/&gt;&lt;br/&gt;Gulp.&lt;br/&gt;&lt;br/&gt;Silently, I recited the astronaut's prayer, &amp;quot;Dear Lord, please don't let me screw up.&amp;quot; Then I pushed the launch button.&lt;br/&gt;&lt;br/&gt;</description>
      <enclosure url="http://www.byteworks.us/Byte_Works/Blog/Entries/2012/10/31_Collect_Data_from_an_iPhone_Rocket_Flight_files/iPhone%20Rockets.jpg" length="78577" type="image/jpeg"/>
    </item>
    <item>
      <title>Controlling the TI SensorTag with techBASIC</title>
      <link>http://www.byteworks.us/Byte_Works/Blog/Entries/2012/10/31_Controlling_the_TI_SensorTag_with_techBASIC.html</link>
      <guid isPermaLink="false">6943e6e1-d009-4658-b5b7-2914dbd6a8ff</guid>
      <pubDate>Wed, 31 Oct 2012 02:51:50 -0600</pubDate>
      <description>&lt;a href=&quot;http://www.byteworks.us/Byte_Works/Blog/Entries/2012/10/31_Controlling_the_TI_SensorTag_with_techBASIC_files/%20SensorTag%204x3.jpg&quot;&gt;&lt;img src=&quot;http://www.byteworks.us/Byte_Works/Blog/Media/object007_2.jpg&quot; style=&quot;float:left; padding-right:10px; padding-bottom:10px; width:183px; height:137px;&quot;/&gt;&lt;/a&gt;The Internet of Things has a new addition, and it's a great way to learn more about Bluetooth low energy. Most Bluetooth low energy devices are designed for a very specific use, but the new SensorTag from Texas Instruments is a general-purpose device with a whopping six sensors that can be put to use in a wide variety of ways. It's intended as a reference platform—a device that lets hardware and software engineers see how to use TI's CC2541 chip by example. That's exactly how we will use it, writing software to access and display the sensor data. Once the software complete, though, you'll have a nice general-purpose sensor device that can be used for all sorts of things. We &lt;a href=&quot;Entries/2012/10/31_Collect_Data_from_an_iPhone_Rocket_Flight.html&quot;&gt;flew it in a model rocket&lt;/a&gt; to collect acceleration, rotation and pressure during the flight.&lt;br/&gt;&lt;br/&gt;This blog is the first in a series of seven blogs that explore this new device. This one is the starting place, where we'll explore setting up the SensorTag and writing the basic software used to access any Bluetooth low energy device. The other six blogs cover the six sensors and how to use them in detail. The software can be written entirely on your Bluetooth low energy equipped iPhone, iPad or iPod using techBASIC, the technical computing language for iOS. You don't need a Mac, XCode, knowledge of Objective C, or membership in Apple's developer program to make all of this work.&lt;br/&gt;&lt;br/&gt;Before we dive in, it's also important to realize that the basics of writing software to access a Bluetooth low energy device are the same for all Bluetooth low energy devices, and we've covered these basics once before. If you've read my blog on the &lt;a href=&quot;Entries/2012/8/20_Controlling_Bluetooth_LE_Devices_with_techBASIC.html&quot;&gt;TI Key Fob&lt;/a&gt;, a predecessor to the SensorTag, you really don't need to read this blog, too. In fact, some sections of this blog, and even some parts of the software, are identical to the material for the Key Fob. That's good—it shows you that you can take this program and quickly modify it to access any Bluetooth low energy device. So, if you've already read the Key Fob blog, skip to the end, grab the software, and move on to any of the six sensor blogs that interest you.&lt;br/&gt;&lt;br/&gt;What Will it Do?&lt;br/&gt;&lt;br/&gt;Bluetooth low energy, also known as Bluetooth 4.0, BLE, Bluetooth LE, and Bluetooth Smart, is a new twist on the old Bluetooth standard. It's designed for ultra-low energy sensors that can run off of coin cell batteries. Some of the Bluetooth low energy devices that are already available include sports fitness sensors like bicycle speedometers and pedometers built into Nike running shoes; health sensors like thermometers, blood pressure cuffs and heart rate monitors; and physics sensors like accelerometers and thermometers.&lt;br/&gt;&lt;br/&gt;The SensorTag is a peripheral from Texas Instruments designed to help hardware and software engineers learn about, and begin building, Bluetooth low energy peripherals and software using the CC2451 chip. It has these six sensors:&lt;br/&gt;&lt;br/&gt;• A three-axis accelerometer.&lt;br/&gt;• A three-axis magnetometer.&lt;br/&gt;• A three-axis gyroscope.&lt;br/&gt;• A dual-mode thermometer that measures ambient and remote temperatures.&lt;br/&gt;• A humidity sensor.&lt;br/&gt;• A barometer.&lt;br/&gt;&lt;br/&gt;Parts List&lt;br/&gt;</description>
      <enclosure url="http://www.byteworks.us/Byte_Works/Blog/Entries/2012/10/31_Controlling_the_TI_SensorTag_with_techBASIC_files/%20SensorTag%204x3.jpg" length="48690" type="image/jpeg"/>
    </item>
    <item>
      <title>Accessing the Bluetooth low energy Accelerometer on the TI SensorTag</title>
      <link>http://www.byteworks.us/Byte_Works/Blog/Entries/2012/10/31_Accessing_the_Bluetooth_low_energy_Accelerometer_on_the_TI_SensorTag.html</link>
      <guid isPermaLink="false">c70b635d-99e1-420a-9c24-bb5be03bdabb</guid>
      <pubDate>Wed, 31 Oct 2012 02:38:18 -0600</pubDate>
      <description>&lt;a href=&quot;http://www.byteworks.us/Byte_Works/Blog/Entries/2012/10/31_Accessing_the_Bluetooth_low_energy_Accelerometer_on_the_TI_SensorTag_files/SensorTag%20Accelerometer.jpg&quot;&gt;&lt;img src=&quot;http://www.byteworks.us/Byte_Works/Blog/Media/object008_1.jpg&quot; style=&quot;float:left; padding-right:10px; padding-bottom:10px; width:183px; height:137px;&quot;/&gt;&lt;/a&gt;Bluetooth low energy offers a great way for iPhone and iPad apps to connect to external devices. Bluetooth low energy is free of the shackles imposed by Apple's MFi program, so anyone can write apps to connect to Bluetooth low energy devices. This blog explores how to connect to the accelerometer on the new TI SensorTag, a Bluetooth low energy peripheral designed to be a hardware and software reference program for the CC2541 chip.&lt;br/&gt;&lt;br/&gt;The SensorTag supports a total of six sensors, including a thermometer, barometer, humidity meter, magnetometer and gyroscope. Those sensors are covered in companion blogs. And, just like with Lord of the Rings, there's one blog to control them all. See the blog &lt;a href=&quot;Entries/2012/10/31_Controlling_the_TI_SensorTag_with_techBASIC.html&quot;&gt;Controlling the TI SensorTag with techBASIC&lt;/a&gt; for an overview, as well as a complete GUI program that shows the readings on all six sensors. It covers the basics of connecting to a Bluetooth low energy device.&lt;br/&gt;&lt;br/&gt;While this blog is completely independent of the others, it does assume that you already have some idea how to connect to Bluetooth low energy devices. The basic connection code is presented without further comment. The complete program is a short, simple text-based program that makes it very easy to experiment with the accelerometer. It's presented at the end of the blog.  &lt;a href=&quot;Entries/2012/10/31_Controlling_the_TI_SensorTag_with_techBASIC.html&quot;&gt;Controlling the TI SensorTag with techBASIC&lt;/a&gt; has a more complete program that accesses all six sensors and presents the results in a GUI environment.&lt;br/&gt;&lt;br/&gt;What's an Accelerometer?&lt;br/&gt;&lt;br/&gt;An accelerometer measures acceleration by detecting the force exerted on a mass, then uses the equation&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;to find the acceleration. The exact way the force and mass are measured varies a lot from one brand of sensor to another, from measuring the capacitance as the plates making up the capacitor are deformed to looking at the voltage generated by a crystal as it is deformed. The SensorTag uses the &lt;a href=&quot;http://www.kionix.com/accelerometers/kxtj9&quot;&gt;KXTJ9 accelerometer&lt;/a&gt; from Kionox. It's a three-axis accelerometer with a selectable range of ±2G, ±4G or ±8G. The SensorTag's firmware uses the ±2G setting, exposing 8 bits of the 14-bit resolution of the chip, giving a precision of 0.015625G. If you saw the blog showing the &lt;a href=&quot;Entries/2012/10/31_Collect_Data_from_an_iPhone_Rocket_Flight.html&quot;&gt;iPhone on a rocket&lt;/a&gt;, you know TI has also prepared a special version of the firmware that supports the ±8G range, for a precision of 0.0625G.&lt;br/&gt;&lt;br/&gt;Accessing the Accelerometer&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;Looking at the Generic Attribute Profile (GATT) for the accelerometer, we find three attributes in the accelerometer service.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;Like all sensors, the accelerometer draws power. Keeping it off when not in use helps prolong the life of the battery. The 0xAA12 attribute is used to turn the accelerometer on and off. Our simple program just turns it on.&lt;br/&gt;&lt;br/&gt;CASE &amp;quot;F000AA12&amp;quot; &amp;amp; servicesHeader&lt;br/&gt;  DIM value(1) as INTEGER&lt;br/&gt;  value(1) = 1&lt;br/&gt;  peripheral.writeCharacteristic(characteristics(i), value, 1)&lt;br/&gt;&lt;br/&gt;Pass a 0 instead of a 1 to turn the accelerometer back off.&lt;br/&gt;&lt;br/&gt;0xAA11 is used to read the accelerometer. There are two ways to read the acceleration, either reading it when the program wants an acceleration value or asking the accelerometer to notify the program whenever a new sensor reading is available. The first step is to tell the accelerometer which way we want to read values. To receive notifications when a value is available, write a 1 and 0 to the characteristic, then ask it to start sending notifications.&lt;br/&gt;&lt;br/&gt;SELECT CASE characteristics(i).uuid&lt;br/&gt;  CASE &amp;quot;F000AA11&amp;quot; &amp;amp; servicesHeader&lt;br/&gt;    DIM value(2) as INTEGER&lt;br/&gt;    value = [0, 1]&lt;br/&gt;    peripheral.writeCharacteristic(characteristics(i), value, 0)&lt;br/&gt;    peripheral.setNotify(characteristics(i), 1)&lt;br/&gt;&lt;br/&gt;Use readCharacteristic to read a single value.&lt;br/&gt;&lt;br/&gt;    peripheral.readCharacteristic(characteristics(i), 1)&lt;br/&gt;&lt;br/&gt;The accelerometer sends samples about once a second unless you tell it otherwise. Use 0xAA13 to set the sample rate. The value is expressed in tens of milliseconds, so passing 100 gives the default sample rate of once per second. Keep in mind that the hardware uses the sample rate as a suggestion, not a firm value! If the time between samples is really important, record the time with the sample value.&lt;br/&gt;Whether you read the data once using readCharacteristic, or ask for notifications with setNotify, the values are always returned using a call to BLECharacteristicInfo.&lt;br/&gt;&lt;br/&gt;SUB BLECharacteristicInfo (time AS DOUBLE, peripheral AS BLEPeripheral, characteristic AS BLECharacteristic, kind AS INTEGER, message AS STRING, err AS LONG)&lt;br/&gt;IF kind = 2 THEN&lt;br/&gt;  DIM value(1) AS INTEGER&lt;br/&gt;  value = characteristic.value&lt;br/&gt;  SELECT CASE characteristic.uuid&lt;br/&gt;    CASE &amp;quot;F000AA11&amp;quot; &amp;amp; servicesHeader&lt;br/&gt;      ! Update the accelerometer.&lt;br/&gt;      c = 64.0&lt;br/&gt;      p% = value(1)&lt;br/&gt;      IF p% BITAND $0080 THEN p% = p% BITOR $FF00&lt;br/&gt;      x = p%/c&lt;br/&gt;&lt;br/&gt;      p% = value(2)&lt;br/&gt;      IF p% BITAND $0080 THEN p% = p% BITOR $FF00&lt;br/&gt;      y = p%/c&lt;br/&gt;&lt;br/&gt;      p% = value(3)&lt;br/&gt;      IF p% BITAND $0080 THEN p% = p% BITOR $FF00&lt;br/&gt;      z = p%/c&lt;br/&gt;&lt;br/&gt;      PRINT x, y, z&lt;br/&gt;    CASE ELSE&lt;br/&gt;      PRINT &amp;quot;Read from &amp;quot;; characteristic.uuid&lt;br/&gt;&lt;br/&gt;  END SELECT&lt;br/&gt;ELSE IF kind = 3 AND err &amp;lt;&gt; 0 THEN&lt;br/&gt;  PRINT &amp;quot;Error writing &amp;quot;; characteristic.uuid; &amp;quot;: (&amp;quot;; err; &amp;quot;) &amp;quot;; message&lt;br/&gt;END IF&lt;br/&gt;END SUB&lt;br/&gt;&lt;br/&gt;The value itself is returned as three bytes, where each byte is a signed value containing the acceleration along one axis. Naturally enough, the order is x, y and z. Dividing by 64 converts from the range of the byte value, with a range of -128 to 127, to G force, with a range of about -2G to 2G.&lt;br/&gt;&lt;br/&gt;Using the Accelerometer&lt;br/&gt;&lt;br/&gt;The first step in using any sensor is to calibrate it. There are differences in individual sensors, and converting from a byte value to ±2G by dividing by 64 isn't perfect. After all, we get 128 values to the left of zero, and 127 on the positive side—it can't be exact.&lt;br/&gt;&lt;br/&gt;Fortunately, we live on a pretty good calibration device. The surface of the Earth is, by definition, 1G. Lay the accelerometer on the table and run the program. The device may not be perfectly flat, but you can get the overall acceleration this way:&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;or, in BASIC,&lt;br/&gt;&lt;br/&gt;   a = SQR(x*x + y*y + z*z)&lt;br/&gt;&lt;br/&gt;If you like, collect a few hundred measurements and average the results. They should be 1G. Are they? If not, adjust all of your measurements by an appropriate factor so they are.&lt;br/&gt;&lt;br/&gt;If you're really up on your physics, you may realize that the Earth's gravity is not the same strength everywhere. It varies because the Earth is not perfectly round, because it spins, and because of mineral deposits. This variation is smaller than 1%, though, and the precision of the accelerometer is about 1.5% of a gravity, so it's an error we can safely ignore.&lt;br/&gt;&lt;br/&gt;Many people are familiar with one of the basic formulas of physics that allows us to calculate the distance something has traveled based on the time and acceleration. Here it is.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;To do anything useful, we also need to remember that&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;The accelerometer gives us acceleration. To keep things simple, let's assume we get back one sample every 0.1 second from sliding the SensorTag across a table, and the samples are 0.1G, 0.2G and 0.3G along the direction we slide the SensorTag. Using this equation, and starting at rest, after one tenth of a second&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;The factor of 9.81 converts from gravities to meters per second squared.&lt;br/&gt;&lt;br/&gt;Continuing on for the next two measurements,&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;After 0.3 seconds, the SensorTag has traveled about 2.5cm (almost an inch) across the table, and is traveling at a little over a half meter per second.&lt;br/&gt;&lt;br/&gt;So now you're equipped to tape a SensorTag to any moving object and track where it is and how fast it's going, right? Ah, if life were only that simple. It works fine in theory, but in practice, an accelerometer is not a good way to track movement. The problem is the errors that crop in. There are two kinds. One is random error, where the measurements are off by a bit, but vary around the correct reading. The other is systematic error, where the values are off in a specific direction. Real measurements have both, and they add up fast. The longer you take measurements, the more error will accumulate. While I personally find the whole subject of error analysis fascinating, that's not what this blog is about, and you may not share my fascination. If you'd like to know more about these errors, start with web searches on systematic error, random error and error analysis. The short version, though, is that calculating velocity and distance using an accelerometer is going to work a lot better for short, rapid movements like a rocket flight than for long, slow ones like tracking the progress of a robot. Error is still an issue for short, rapid movements; too, it's just not as big an issue.&lt;br/&gt;&lt;br/&gt;The Source&lt;br/&gt;&lt;br/&gt;Here's the source for the accelerometer program. It's pretty simple, writing the values to the console. This is a great program to experiment a bit with the accelerometer. For another, see the source code for the main article, &lt;a href=&quot;Entries/2012/10/31_Controlling_the_TI_SensorTag_with_techBASIC.html&quot;&gt;Controlling the TI SensorTag with techBASIC&lt;/a&gt;. That article displays all six SensorTag sensors in a nice GUI environment.&lt;br/&gt;&lt;br/&gt;! Simple program to access the accelerometer on the TI SensorTag.&lt;br/&gt;&lt;br/&gt;! Set up variables to hold the peripheral and the characteristics&lt;br/&gt;! for the battery and buzzer.&lt;br/&gt;DIM sensorTag AS BLEPeripheral&lt;br/&gt;&lt;br/&gt;! We will look for these services.&lt;br/&gt;DIM servicesHeader AS STRING, services(1) AS STRING&lt;br/&gt;servicesHeader = &amp;quot;-0451-4000-B000-000000000000&amp;quot;&lt;br/&gt;services(1) = &amp;quot;F000AA10&amp;quot; &amp;amp; servicesHeader : ! Accelerometer&lt;br/&gt;accel% = 1&lt;br/&gt;&lt;br/&gt;! Start the BLE service and begin scanning for devices.&lt;br/&gt;debug = 0&lt;br/&gt;BLE.startBLE&lt;br/&gt;DIM uuid(0) AS STRING&lt;br/&gt;BLE.startScan(uuid)&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;! Called when a peripheral is found. If it is a Sensor Tag, we&lt;br/&gt;! initiate a connection to it and stop scanning for peripherals.&lt;br/&gt;!&lt;br/&gt;! Parameters:&lt;br/&gt;!    time - The time when the peripheral was discovered.&lt;br/&gt;!    peripheral - The peripheral that was discovered.&lt;br/&gt;!    services - List of services offered by the device.&lt;br/&gt;!    advertisements - Advertisements (information provided by the&lt;br/&gt;!        device without the need to read a service/characteristic)&lt;br/&gt;!    rssi - Received Signal Strength Indicator&lt;br/&gt;!&lt;br/&gt;SUB BLEDiscoveredPeripheral (time AS DOUBLE, peripheral AS BLEPeripheral, services() AS STRING, advertisements(,) AS STRING, rssi)&lt;br/&gt;IF peripheral.bleName = &amp;quot;TI BLE Sensor Tag&amp;quot; THEN&lt;br/&gt;  sensorTag = peripheral&lt;br/&gt;  BLE.connect(sensorTag)&lt;br/&gt;  BLE.stopScan&lt;br/&gt;END IF&lt;br/&gt;END SUB&lt;br/&gt;&lt;br/&gt;! Called to report information about the connection status of the&lt;br/&gt;! peripheral or to report that services have been discovered.&lt;br/&gt;!&lt;br/&gt;! Parameters:&lt;br/&gt;!    time - The time when the information was received.&lt;br/&gt;!    peripheral - The peripheral.&lt;br/&gt;!    kind - The kind of call. One of&lt;br/&gt;!        1 - Connection completed&lt;br/&gt;!        2 - Connection failed&lt;br/&gt;!        3 - Connection lost&lt;br/&gt;!        4 - Services discovered&lt;br/&gt;!    message - For errors, a human-readable error message.&lt;br/&gt;!    err - If there was an error, the Apple error number. If there&lt;br/&gt;!        was no error, this value is 0.&lt;br/&gt;!&lt;br/&gt;SUB BLEPeripheralInfo (time AS DOUBLE, peripheral AS BLEPeripheral, kind AS INTEGER, message AS STRING, err AS LONG)&lt;br/&gt;IF kind = 1 THEN&lt;br/&gt;  ! The connection was established. Look for available services.&lt;br/&gt;  IF debug THEN PRINT &amp;quot;Connection made.&amp;quot;&lt;br/&gt;  peripheral.discoverServices(uuid)&lt;br/&gt;ELSE IF kind = 2 OR kind = 3 THEN&lt;br/&gt;  IF debug THEN PRINT &amp;quot;Connection lost: &amp;quot;; kind&lt;br/&gt;  BLE.connect(sensorTag)&lt;br/&gt;ELSE IF kind = 4 THEN&lt;br/&gt;  ! Services were found. If it is one of the ones we are interested&lt;br/&gt;  ! in, begin discovery of its characteristics.&lt;br/&gt;  DIM availableServices(1) AS BLEService&lt;br/&gt;  availableServices = peripheral.services&lt;br/&gt;  FOR s = 1 to UBOUND(services, 1)&lt;br/&gt;    FOR a = 1 TO UBOUND(availableServices, 1)&lt;br/&gt;      IF services(s) = availableServices(a).uuid THEN&lt;br/&gt;        IF debug THEN PRINT &amp;quot;Discovering characteristics for &amp;quot;; services(s)&lt;br/&gt;        peripheral.discoverCharacteristics(uuid, availableServices(a))&lt;br/&gt;      END IF&lt;br/&gt;    NEXT&lt;br/&gt;  NEXT&lt;br/&gt;END IF&lt;br/&gt;END SUB&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;! Called to report information about a characteristic or included&lt;br/&gt;! services for a service. If it is one we are interested in, start&lt;br/&gt;! handling it.&lt;br/&gt;!&lt;br/&gt;! Parameters:&lt;br/&gt;!    time - The time when the information was received.&lt;br/&gt;!    peripheral - The peripheral.&lt;br/&gt;!    service - The service whose characteristic or included&lt;br/&gt;!        service was found.&lt;br/&gt;!    kind - The kind of call. One of&lt;br/&gt;!        1 - Characteristics found&lt;br/&gt;!        2 - Included services found&lt;br/&gt;!    message - For errors, a human-readable error message.&lt;br/&gt;!    err - If there was an error, the Apple error number. If there&lt;br/&gt;!        was no error, this value is 0.&lt;br/&gt;!&lt;br/&gt;SUB BLEServiceInfo (time AS DOUBLE, peripheral AS BLEPeripheral, service AS BLEService, kind AS INTEGER, message AS STRING, err AS LONG)&lt;br/&gt;IF kind = 1 THEN&lt;br/&gt;  ! Get the characteristics.&lt;br/&gt;  DIM characteristics(1) AS BLECharacteristic&lt;br/&gt;  characteristics = service.characteristics&lt;br/&gt;  FOR i = 1 TO UBOUND(characteristics, 1)&lt;br/&gt;    IF service.uuid = services(accel%) THEN&lt;br/&gt;      ! Found the accelerometer.&lt;br/&gt;      SELECT CASE characteristics(i).uuid&lt;br/&gt;        CASE &amp;quot;F000AA11&amp;quot; &amp;amp; servicesHeader&lt;br/&gt;          ! Tell the accelerometer to begin sending data.&lt;br/&gt;          IF debug THEN PRINT &amp;quot;Start accelerometer.&amp;quot;&lt;br/&gt;          DIM value(2) as INTEGER&lt;br/&gt;          value = [0, 1]&lt;br/&gt;          peripheral.writeCharacteristic(characteristics(i), value, 0)&lt;br/&gt;          peripheral.setNotify(characteristics(i), 1)&lt;br/&gt;&lt;br/&gt;        CASE &amp;quot;F000AA12&amp;quot; &amp;amp; servicesHeader&lt;br/&gt;          ! Turn the accelerometer sensor on.&lt;br/&gt;          IF debug THEN PRINT &amp;quot;Accelerometer on.&amp;quot;&lt;br/&gt;          DIM value(1) as INTEGER&lt;br/&gt;          value(1) = 1&lt;br/&gt;          peripheral.writeCharacteristic(characteristics(i), value, 1)&lt;br/&gt;&lt;br/&gt;        CASE &amp;quot;F000AA13&amp;quot; &amp;amp; servicesHeader&lt;br/&gt;          ! Set the sample rate to 500ms.&lt;br/&gt;          DIM value(1) as INTEGER&lt;br/&gt;          value(1) = 50&lt;br/&gt;          IF debug THEN PRINT &amp;quot;Setting accelerometer sample rate to &amp;quot;; value(1)&lt;br/&gt;          peripheral.writeCharacteristic(characteristics(i), value, 1)&lt;br/&gt;      END SELECT&lt;br/&gt;    END IF&lt;br/&gt;  NEXT&lt;br/&gt;END IF&lt;br/&gt;END SUB&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;! Called to return information from a characteristic.&lt;br/&gt;!&lt;br/&gt;! Parameters:&lt;br/&gt;!    time - The time when the information was received.&lt;br/&gt;!    peripheral - The peripheral.&lt;br/&gt;!    characteristic - The characteristic whose information&lt;br/&gt;!        changed.&lt;br/&gt;!    kind - The kind of call. One of&lt;br/&gt;!        1 - Called after a discoverDescriptors call.&lt;br/&gt;!        2 - Called after a readCharacteristics call.&lt;br/&gt;!        3 - Called to report status after a writeCharacteristics&lt;br/&gt;!            call.&lt;br/&gt;!    message - For errors, a human-readable error message.&lt;br/&gt;!    err - If there was an error, the Apple error number. If there&lt;br/&gt;!        was no error, this value is 0.&lt;br/&gt;!&lt;br/&gt;SUB BLECharacteristicInfo (time AS DOUBLE, peripheral AS BLEPeripheral, characteristic AS BLECharacteristic, kind AS INTEGER, message AS STRING, err AS LONG)&lt;br/&gt;IF kind = 2 THEN&lt;br/&gt;  DIM value(1) AS INTEGER&lt;br/&gt;  value = characteristic.value&lt;br/&gt;  SELECT CASE characteristic.uuid&lt;br/&gt;    CASE &amp;quot;F000AA11&amp;quot; &amp;amp; servicesHeader&lt;br/&gt;      ! Update the accelerometer.&lt;br/&gt;      c = 64.0&lt;br/&gt;      p% = value(1)&lt;br/&gt;      IF p% BITAND $0080 THEN p% = p% BITOR $FF00&lt;br/&gt;      x = p%/c&lt;br/&gt;&lt;br/&gt;      p% = value(2)&lt;br/&gt;      IF p% BITAND $0080 THEN p% = p% BITOR $FF00&lt;br/&gt;      y = p%/c&lt;br/&gt;&lt;br/&gt;      p% = value(3)&lt;br/&gt;      IF p% BITAND $0080 THEN p% = p% BITOR $FF00&lt;br/&gt;      z = p%/c&lt;br/&gt;&lt;br/&gt;      PRINT x, y, z&lt;br/&gt;    CASE ELSE&lt;br/&gt;      PRINT &amp;quot;Read from &amp;quot;; characteristic.uuid&lt;br/&gt;&lt;br/&gt;  END SELECT&lt;br/&gt;ELSE IF kind = 3 AND err &amp;lt;&gt; 0 THEN&lt;br/&gt;  PRINT &amp;quot;Error writing &amp;quot;; characteristic.uuid; &amp;quot;: (&amp;quot;; err; &amp;quot;) &amp;quot;; message&lt;br/&gt;END IF&lt;br/&gt;END SUB&lt;br/&gt;</description>
      <enclosure url="http://www.byteworks.us/Byte_Works/Blog/Entries/2012/10/31_Accessing_the_Bluetooth_low_energy_Accelerometer_on_the_TI_SensorTag_files/SensorTag%20Accelerometer.jpg" length="38638" type="image/jpeg"/>
    </item>
    <item>
      <title>Accessing the Bluetooth low energy Thermometer on the TI SensorTag</title>
      <link>http://www.byteworks.us/Byte_Works/Blog/Entries/2012/10/31_Accessing_the_Bluetooth_low_energy_Thermometer_on_the_TI_SensorTag.html</link>
      <guid isPermaLink="false">eac56d57-08b2-4676-b290-84094c0931e5</guid>
      <pubDate>Wed, 31 Oct 2012 02:23:26 -0600</pubDate>
      <description>&lt;a href=&quot;http://www.byteworks.us/Byte_Works/Blog/Entries/2012/10/31_Accessing_the_Bluetooth_low_energy_Thermometer_on_the_TI_SensorTag_files/SensorTag%20Thermometer.jpg&quot;&gt;&lt;img src=&quot;http://www.byteworks.us/Byte_Works/Blog/Media/object006_1.jpg&quot; style=&quot;float:left; padding-right:10px; padding-bottom:10px; width:183px; height:137px;&quot;/&gt;&lt;/a&gt;This blog explores how to read temperatures using new TI SensorTag, a Bluetooth low energy peripheral designed to be a hardware and software reference program for the CC2541 chip. It shows a simple, text-based program that's great for experimenting with the thermometer. The complete listing appears at the end of the blog. A companion blog, &lt;a href=&quot;Entries/2012/10/31_Controlling_the_TI_SensorTag_with_techBASIC.html&quot;&gt;Controlling the TI SensorTag with techBASIC&lt;/a&gt;, gives background information about Bluetooth low energy devices, the TI SensorTag, and accessing Bluetooth devices using an iPhone or iPad. It also gives a complete program that accesses all six sensors on the TI SensorTag, showing the values using a GUI interface.&lt;br/&gt;&lt;br/&gt;The TMP006 Thermometer&lt;br/&gt;&lt;br/&gt;The SensorTag uses the &lt;a href=&quot;http://www.ti.com/ww/en/analog/tmp006/index.shtml?DCMP=hpa-tmp-tmp006&amp;HQS=Other+OT+tmp006&quot;&gt;TMP006&lt;/a&gt; chip to read temperature. The amazing thing about this chip is not that it can sense temperature. Heck, a thermocouple can do that. The amazing thing is that it can sense temperature remotely by examining the infra-red heat signature from an object. The thermometer actually returns two temperatures. One is the temperature on the circuit board, called the die temperature. The other is the temperature of the object the thermometer is looking at through the window on the front of the SensorTag. This is called the target temperature.&lt;br/&gt;&lt;br/&gt;Accessing the Thermometer&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;Here's the Generic Attribute Profile (GATT) for the thermometer service. It's pretty simple, with just two attributes.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;Attribute 0xAA02 turns the sensor on or off. Our program turns it on by writing a 1 to this attribute. You can turn it off by writing a zero, but this simple program doesn't turn the sensor off.&lt;br/&gt;&lt;br/&gt;CASE &amp;quot;F000AA02&amp;quot; &amp;amp; servicesHeader&lt;br/&gt;  DIM value(1) as INTEGER&lt;br/&gt;  value(1) = 1&lt;br/&gt;  peripheral.writeCharacteristic(characteristics(i), value, 1)&lt;br/&gt;&lt;br/&gt;0xAA01 is used to read the thermometer. There are two ways to read sensors on the SensorTag, either reading it when the program wants the temperature or asking the thermometer to notify the program whenever a new sensor reading is available. The first step is to tell the thermometer which way we want to read values. Write a 1 and 0 to the characteristic to receive notifications when a value is available, then ask it to start sending notifications.&lt;br/&gt;&lt;br/&gt;CASE &amp;quot;F000AA01&amp;quot; &amp;amp; servicesHeader&lt;br/&gt;  DIM value(2) as INTEGER&lt;br/&gt;  value = [0, 1]&lt;br/&gt;  peripheral.writeCharacteristic(characteristics(i), value, 0)&lt;br/&gt;  peripheral.setNotify(characteristics(i), 1)&lt;br/&gt;&lt;br/&gt;Use readCharacteristic to read a single value.&lt;br/&gt;&lt;br/&gt;    peripheral.readCharacteristic(characteristics(i), 1)&lt;br/&gt;&lt;br/&gt;Whether you read the data once using readCharacteristic or ask for notifications with setNotify, the values are always returned using a call to BLECharacteristicInfo. The returned value has two different temperatures stored in four bytes. Bytes 3 and 4 are the die temperature, while bytes 1 and 2 contain the raw data used to calculate the target temperature. Both are unsigned values stores least-significant byte first. The conversion to degrees Celsius is&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;where t1,2 is the raw value returned in the first two bytes, and t3,4 is the raw value returned in the second pair of bytes. Here's what we get after converting the equations to BASIC.&lt;br/&gt;&lt;br/&gt;SUB BLECharacteristicInfo (time AS DOUBLE, peripheral AS BLEPeripheral, characteristic AS BLECharacteristic, kind AS INTEGER, message AS STRING, err AS LONG)&lt;br/&gt;IF kind = 2 THEN&lt;br/&gt;  DIM value(1) AS INTEGER&lt;br/&gt;  value = characteristic.value&lt;br/&gt;  SELECT CASE characteristic.uuid&lt;br/&gt;    CASE &amp;quot;F000AA01&amp;quot; &amp;amp; servicesHeader&lt;br/&gt;      ! Update the thermometer.&lt;br/&gt;      temp&amp;amp; = (value(3) BITOR (value(4) &amp;lt;&amp;lt; 8)) BITAND $00FFFF&lt;br/&gt;      temp = temp&amp;amp;/128.0&lt;br/&gt;&lt;br/&gt;      target&amp;amp; = (value(1) BITOR (value(2) &amp;lt;&amp;lt; 8)) BITAND $00FFFF&lt;br/&gt;      target = target&amp;amp;*0.00000015625&lt;br/&gt;      die2 = 273.15 + temp&lt;br/&gt;      s0 = 6.4e-14&lt;br/&gt;      a1 = 1.75e-3&lt;br/&gt;      a2 = -1.678e-5&lt;br/&gt;      b0 = -2.9e-5&lt;br/&gt;      b1 = -5.7e-7&lt;br/&gt;      b2 = 4.63e-9&lt;br/&gt;      c2 = 13.4&lt;br/&gt;      tref = 298.15&lt;br/&gt;      dt2 = (die2 - tref)*(dies2 - tref)&lt;br/&gt;      S = s0*(1 + a1*(die2 - tref) + a2*dt2)&lt;br/&gt;      Vos = b0 + b1*(die2 - tref) + b2*dt2&lt;br/&gt;      fObj = (target - Vos) + c2*((target - Vos)*(target - Vos))&lt;br/&gt;      tObj = (die2^4 + fObj/S)^0.25&lt;br/&gt;      tObj = tObj - 273.15&lt;br/&gt;      if Math.isNaN(tObj) then&lt;br/&gt;        tObj = 1&lt;br/&gt;      end if&lt;br/&gt;&lt;br/&gt;      PRINT &amp;quot;Die temperature: &amp;quot;; temp; &amp;quot;  Target temperature: &amp;quot;; tObj&lt;br/&gt;    CASE ELSE&lt;br/&gt;      PRINT &amp;quot;Read from &amp;quot;; characteristic.uuid&lt;br/&gt;&lt;br/&gt;  END SELECT&lt;br/&gt;ELSE IF kind = 3 AND err &amp;lt;&gt; 0 THEN&lt;br/&gt;  PRINT &amp;quot;Error writing &amp;quot;; characteristic.uuid; &amp;quot;: (&amp;quot;; err; &amp;quot;) &amp;quot;; message&lt;br/&gt;END IF&lt;br/&gt;END SUB&lt;br/&gt;&lt;br/&gt;Using the Thermometer&lt;br/&gt;&lt;br/&gt;The target temperature tends to jump around a bit as the chip sees various temperatures. I'd suggest keeping a running average of the last few values returned to keep this stable. It will make the thermometer slower to respond to a change, but it will also give a steadier reading that is less inclined to jump around due to noise.&lt;br/&gt;&lt;br/&gt;Of course, if you're after the temperature at the SensorTag, you can just use the die temperature. This would be fine for a weather station. The SensorTag doesn't use much power, so it won't heat the thermometer much.&lt;br/&gt;&lt;br/&gt;The Source&lt;br/&gt;&lt;br/&gt;Here's the source for the thermometer program. It dumps both the die and remote temperature to the console as they are returned from the SensorTag. See the source code from, &lt;a href=&quot;Entries/2012/10/31_Controlling_the_TI_SensorTag_with_techBASIC.html&quot;&gt;Controlling the TI SensorTag with techBASIC&lt;/a&gt; for a program that displays the target temperature using a nice GUI.&lt;br/&gt;&lt;br/&gt;! Simple program to access the theromoeter on the TI SensorTag.&lt;br/&gt;&lt;br/&gt;! Set up variables to hold the peripheral and the characteristics&lt;br/&gt;! for the battery and buzzer.&lt;br/&gt;DIM sensorTag AS BLEPeripheral&lt;br/&gt;&lt;br/&gt;! We will look for these services.&lt;br/&gt;DIM servicesHeader AS STRING, services(1) AS STRING&lt;br/&gt;servicesHeader = &amp;quot;-0451-4000-B000-000000000000&amp;quot;&lt;br/&gt;services(1) = &amp;quot;F000AA00&amp;quot; &amp;amp; servicesHeader : ! Thermometer&lt;br/&gt;therm% = 1&lt;br/&gt;&lt;br/&gt;! Start the BLE service and begin scanning for devices.&lt;br/&gt;debug = 0&lt;br/&gt;BLE.startBLE&lt;br/&gt;DIM uuid(0) AS STRING&lt;br/&gt;BLE.startScan(uuid)&lt;br/&gt;&lt;br/&gt;! Called when a peripheral is found. If it is a Sensor Tag, we&lt;br/&gt;! initiate a connection to it and stop scanning for peripherals.&lt;br/&gt;!&lt;br/&gt;! Parameters:&lt;br/&gt;!    time - The time when the peripheral was discovered.&lt;br/&gt;!    peripheral - The peripheral that was discovered.&lt;br/&gt;!    services - List of services offered by the device.&lt;br/&gt;!    advertisements - Advertisements (information provided by the&lt;br/&gt;!        device without the need to read a service/characteristic)&lt;br/&gt;!    rssi - Received Signal Strength Indicator&lt;br/&gt;!&lt;br/&gt;SUB BLEDiscoveredPeripheral (time AS DOUBLE, peripheral AS BLEPeripheral, services() AS STRING, advertisements(,) AS STRING, rssi)&lt;br/&gt;IF peripheral.bleName = &amp;quot;TI BLE Sensor Tag&amp;quot; THEN&lt;br/&gt;  sensorTag = peripheral&lt;br/&gt;  BLE.connect(sensorTag)&lt;br/&gt;  BLE.stopScan&lt;br/&gt;END IF&lt;br/&gt;END SUB&lt;br/&gt;&lt;br/&gt;! Called to report information about the connection status of the&lt;br/&gt;! peripheral or to report that services have been discovered.&lt;br/&gt;!&lt;br/&gt;! Parameters:&lt;br/&gt;!    time - The time when the information was received.&lt;br/&gt;!    peripheral - The peripheral.&lt;br/&gt;!    kind - The kind of call. One of&lt;br/&gt;!        1 - Connection completed&lt;br/&gt;!        2 - Connection failed&lt;br/&gt;!        3 - Connection lost&lt;br/&gt;!        4 - Services discovered&lt;br/&gt;!    message - For errors, a human-readable error message.&lt;br/&gt;!    err - If there was an error, the Apple error number. If there&lt;br/&gt;!        was no error, this value is 0.&lt;br/&gt;!&lt;br/&gt;SUB BLEPeripheralInfo (time AS DOUBLE, peripheral AS BLEPeripheral, kind AS INTEGER, message AS STRING, err AS LONG)&lt;br/&gt;IF kind = 1 THEN&lt;br/&gt;  ! The connection was established. Look for available services.&lt;br/&gt;  IF debug THEN PRINT &amp;quot;Connection made.&amp;quot;&lt;br/&gt;  peripheral.discoverServices(uuid)&lt;br/&gt;ELSE IF kind = 2 OR kind = 3 THEN&lt;br/&gt;  IF debug THEN PRINT &amp;quot;Connection lost: &amp;quot;; kind&lt;br/&gt;  BLE.connect(sensorTag)&lt;br/&gt;ELSE IF kind = 4 THEN&lt;br/&gt;  ! Services were found. If it is one of the ones we are interested&lt;br/&gt;  ! in, begin discovery of its characteristics.&lt;br/&gt;  DIM availableServices(1) AS BLEService&lt;br/&gt;  availableServices = peripheral.services&lt;br/&gt;  FOR s = 1 to UBOUND(services, 1)&lt;br/&gt;    FOR a = 1 TO UBOUND(availableServices, 1)&lt;br/&gt;      IF services(s) = availableServices(a).uuid THEN&lt;br/&gt;        IF debug THEN PRINT &amp;quot;Discovering characteristics for &amp;quot;; services(s)&lt;br/&gt;        peripheral.discoverCharacteristics(uuid, availableServices(a))&lt;br/&gt;      END IF&lt;br/&gt;    NEXT&lt;br/&gt;  NEXT&lt;br/&gt;END IF&lt;br/&gt;END SUB&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;! Called to report information about a characteristic or included&lt;br/&gt;! services for a service. If it is one we are interested in, start&lt;br/&gt;! handling it.&lt;br/&gt;!&lt;br/&gt;! Parameters:&lt;br/&gt;!    time - The time when the information was received.&lt;br/&gt;!    peripheral - The peripheral.&lt;br/&gt;!    service - The service whose characteristic or included&lt;br/&gt;!        service was found.&lt;br/&gt;!    kind - The kind of call. One of&lt;br/&gt;!        1 - Characteristics found&lt;br/&gt;!        2 - Included services found&lt;br/&gt;!    message - For errors, a human-readable error message.&lt;br/&gt;!    err - If there was an error, the Apple error number. If there&lt;br/&gt;!        was no error, this value is 0.&lt;br/&gt;!&lt;br/&gt;SUB BLEServiceInfo (time AS DOUBLE, peripheral AS BLEPeripheral, service AS BLEService, kind AS INTEGER, message AS STRING, err AS LONG)&lt;br/&gt;IF kind = 1 THEN&lt;br/&gt;  ! Get the characteristics.&lt;br/&gt;  DIM characteristics(1) AS BLECharacteristic&lt;br/&gt;  characteristics = service.characteristics&lt;br/&gt;  FOR i = 1 TO UBOUND(characteristics, 1)&lt;br/&gt;    IF service.uuid = services(therm%) THEN&lt;br/&gt;      ! Found the thermometer.&lt;br/&gt;      SELECT CASE characteristics(i).uuid&lt;br/&gt;        CASE &amp;quot;F000AA01&amp;quot; &amp;amp; servicesHeader&lt;br/&gt;          ! Tell the thermometer to begin sending data.&lt;br/&gt;          IF debug THEN PRINT &amp;quot;Start thermometer.&amp;quot;&lt;br/&gt;          DIM value(2) as INTEGER&lt;br/&gt;          value = [0, 1]&lt;br/&gt;          peripheral.writeCharacteristic(characteristics(i), value, 0)&lt;br/&gt;          peripheral.setNotify(characteristics(i), 1)&lt;br/&gt;&lt;br/&gt;        CASE &amp;quot;F000AA02&amp;quot; &amp;amp; servicesHeader&lt;br/&gt;          ! Turn the thermometer sensor on.&lt;br/&gt;          IF debug THEN PRINT &amp;quot;Thermometer on.&amp;quot;&lt;br/&gt;          DIM value(1) as INTEGER&lt;br/&gt;          value(1) = 1&lt;br/&gt;          peripheral.writeCharacteristic(characteristics(i), value, 1)&lt;br/&gt;      END SELECT&lt;br/&gt;    END IF&lt;br/&gt;  NEXT&lt;br/&gt;END IF&lt;br/&gt;END SUB&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;! Called to return information from a characteristic.&lt;br/&gt;!&lt;br/&gt;! Parameters:&lt;br/&gt;!    time - The time when the information was received.&lt;br/&gt;!    peripheral - The peripheral.&lt;br/&gt;!    characteristic - The characteristic whose information&lt;br/&gt;!        changed.&lt;br/&gt;!    kind - The kind of call. One of&lt;br/&gt;!        1 - Called after a discoverDescriptors call.&lt;br/&gt;!        2 - Called after a readCharacteristics call.&lt;br/&gt;!        3 - Called to report status after a writeCharacteristics&lt;br/&gt;!            call.&lt;br/&gt;!    message - For errors, a human-readable error message.&lt;br/&gt;!    err - If there was an error, the Apple error number. If there&lt;br/&gt;!        was no error, this value is 0.&lt;br/&gt;!&lt;br/&gt;SUB BLECharacteristicInfo (time AS DOUBLE, peripheral AS BLEPeripheral, characteristic AS BLECharacteristic, kind AS INTEGER, message AS STRING, err AS LONG)&lt;br/&gt;IF kind = 2 THEN&lt;br/&gt;  DIM value(1) AS INTEGER&lt;br/&gt;  value = characteristic.value&lt;br/&gt;  SELECT CASE characteristic.uuid&lt;br/&gt;    CASE &amp;quot;F000AA01&amp;quot; &amp;amp; servicesHeader&lt;br/&gt;      ! Update the thermometer.&lt;br/&gt;      temp = value(3) BITOR (value(4) &amp;lt;&amp;lt; 8)&lt;br/&gt;      temp = temp/128.0&lt;br/&gt;&lt;br/&gt;      target = value(1) BITOR (value(2) &amp;lt;&amp;lt; 8)&lt;br/&gt;      target = target*0.00000015625&lt;br/&gt;      die2 = 273.15 + temp&lt;br/&gt;      s0 = 6.4e-14&lt;br/&gt;      a1 = 1.75e-3&lt;br/&gt;      a2 = -1.678e-5&lt;br/&gt;      b0 = -2.9e-5&lt;br/&gt;      b1 = -5.7e-7&lt;br/&gt;      b2 = 4.63e-9&lt;br/&gt;      c2 = 13.4&lt;br/&gt;      tref = 298.15&lt;br/&gt;      dt2 = (die2 - tref)*(dies2 - tref)&lt;br/&gt;      S = s0*(1 + a1*(die2 - tref) + a2*dt2)&lt;br/&gt;      Vos = b0 + b1*(die2 - tref) + b2*dt2&lt;br/&gt;      fObj = (target - Vos) + c2*((target - Vos)*(target - Vos))&lt;br/&gt;      tObj = (die2^4 + fObj/S)^0.25&lt;br/&gt;      tObj = tObj - 273.15&lt;br/&gt;      if Math.isNaN(tObj) then&lt;br/&gt;        tObj = 1&lt;br/&gt;      end if&lt;br/&gt;&lt;br/&gt;      PRINT &amp;quot;Die temperature: &amp;quot;; temp; &amp;quot;  Target temperature: &amp;quot;; tObj&lt;br/&gt;    CASE ELSE&lt;br/&gt;      PRINT &amp;quot;Read from &amp;quot;; characteristic.uuid&lt;br/&gt;&lt;br/&gt;  END SELECT&lt;br/&gt;ELSE IF kind = 3 AND err &amp;lt;&gt; 0 THEN&lt;br/&gt;  PRINT &amp;quot;Error writing &amp;quot;; characteristic.uuid; &amp;quot;: (&amp;quot;; err; &amp;quot;) &amp;quot;; message&lt;br/&gt;END IF&lt;br/&gt;END SUB</description>
      <enclosure url="http://www.byteworks.us/Byte_Works/Blog/Entries/2012/10/31_Accessing_the_Bluetooth_low_energy_Thermometer_on_the_TI_SensorTag_files/SensorTag%20Thermometer.jpg" length="28258" type="image/jpeg"/>
    </item>
  </channel>
</rss>
