TI SensorTag Temperature Readings

Now that I’m a little more familiar with the Texas Instruments SensorTag, it’s time to process more of the sensors. I went over basic gatttool usage in my previous post, I would suggest giving that a read if you haven’t already.

This time I want to grab simple temperature reading from the BLE (Bluetooth Low Energy) handle. Reading the TearDown specs I managed to find the GATT table for the Infrared and Ambient temperature sensor:

screen-shot-2016-09-10-at-10-26-33-am

Apparently, this is using the TMP007 sensor. The specifications for this component are located at http://www.ti.com/lit/ds/symlink/tmp007.pdf. Section 7.3.7 gives of a bit of detail on how to calculate temperatures:

screen-shot-2016-09-10-at-10-30-39-am

Alright, with that out of the way, let’s get into reading reading some BLE handles.

The first handle from our GATT table is to read temperature data. It provides values for both IR and Ambient temperatures, and does so using MSB (most significant byte) and LSB (least significant bit). I’ll explain this in much more detail once we’ve gather some readings.

Handle Type Description/Value (text)
0x21 Temp Data ObjectLSB:ObjectMSB:AmbientLSB:AmbientMSB

The last handle we need is to have the sensor start (and stop) reading temperature data:

Handle Type Description/Value (text)
0x24 Temp Config Write “01” to start Sensor and Measurements, “00” to put to sleep

Let’s jump into gatttool and do some exploration:

$ sudo gatttool -b A0:XX:XX:XX:XX:XX -I
[A0:XX:XX:XX:XX:XX][LE]> connect
Attempting to connect to A0:XX:XX:XX:XX:XX
Connection successful

If we try to read from the temperature data handle, and the sensor is not measuring we will receive empty sets:

[A0:XX:XX:XX:XX:XX][LE]> char-read-hnd 0x21
Characteristic value/descriptor: 00 00 00 00

However, once we enable measuring, we get that sweet, sweet data 😀

[A0:XX:XX:XX:XX:XX][LE]> char-write-cmd 0x24 01
[A0:XX:XX:XX:XX:XX][LE]> char-read-hnd 0x21
Characteristic value/descriptor: 78 09 9c 0c

I’m now going to turn off measuring, we’ve captured the data we want.

[A0:XX:XX:XX:XX:XX][LE]> char-write-cmd 0x24 00

I’m going to take the values returned for ambient temperature and demonstrate converting to Celsius in Python:

In [1]: ((0x0c * 256 + 0x9c) / 4) * 0.03125
Out[1]: 25.21875

The measurement here is close to the reading from SensorTag’s iPhone application:

screen-shot-2016-09-10-at-10-49-58-am

So how does this formula work?

Well in the above example for ambient temperature, the MSB was 0c, while the LSB was 9c. Let’s have a look at these hexadecimal numbers in Python, with their binary representations:

In [1]: 0x0c
Out[1]: 12

In [2]: bin(0x0c)
Out[2]: '0b1100'

In [3]: 0x9c
Out[3]: 156

In [4]: bin(0x9c)
Out[4]: '0b10011100'

We know a binary byte consists of 8 bits, so the below should also make sense, I’m just padding our MSB with zeros to show a full binary byte:

In [1]: int('00001100', 2)
Out[1]: 12

In [2]: int('10011100', 2)
Out[2]: 156

So here is where it gets fun. What we do is merge the full binary representations of MSB and LSB and form 16 bit value, this is what the first part of the formula does:

In [1]: int('0000110010011100', 2)
Out[1]: 3228

In [2]: (0x0c * 256 + 0x9c)
Out[2]: 3228

The next part of the formula performs the right shift by two (explained in the sensor specifications above):

In [1]: int('00001100100111', 2)
Out[1]: 807

In [2]: ((0x0c * 256 + 0x9c) / 4)
Out[2]: 807

And finally, we multiply by 0.03125, also mentioned in the sensor specifications:

In [1]: int('00001100100111', 2) * 0.03125
Out[1]: 25.21875

In [2]: ((0x0c * 256 + 0x9c) / 4) * 0.03125
Out[2]: 25.21875

Hope you enjoyed, and maybe learned something. It took me some time, and digging to fully comprehend this specification.

RaspberryPi 3 and SensorTag

I’ve been in a hackey type of mood these last couple of days. Picking up a new Raspberry Pi 3 probably did that, up until now I’ve only had the Raspberry Pi Model B.

The new features that come with the Pi 3 are great. What do I have to say, you had me at build in wifi, bluetooth and 1 GB of memory.

To take full advantage of the bluetooth I decided to learn a little about BLE (Bluetooth low energy). I began poking at my Fitbit Charge HR, but wasn’t able to do anything more than pull the device name. This led me to find the TI SensorTag. This device packs a number of sensors into a tiny package, and offers wireless communication using BLE!

screen-shot-2016-09-08-at-6-55-50-pm

After getting my Pi 3 setup with Raspbian, I installed a few bluetooth packages from the official repositories:

pi@raspberrypi:~ $ dpkg -l | grep blue
ii blueman 1.99~alpha1-1+deb8u1 armhf Graphical bluetooth manager
ii bluez 5.23-2+rpi2 armhf Bluetooth tools and daemons
ii bluez-firmware 1.2-3+rpi1 all Firmware for Bluetooth devices
ii libbluetooth3:armhf 5.23-2+rpi2 armhf Library to use the BlueZ Linux Bluetooth stack
ii pi-bluetooth 0.1.1 armhf Raspberry Pi 3 bluetooth

Using the hcitool tool provided by bluez, I scanned the area for BLE devices and found the Sensor Tag (and it’s Hardware Address).

This tool can take either lescan or scan as a parameter, where the latter will search for traditional bluetooth devices.

pi@raspberrypi:~ $ sudo hcitool lescan
LE Scan ...
A0:XX:XX:XX:XX:XX CC2650 SensorTag

Bluez also provides us gatttool, this tool provides a way to connect to the SensorTag in interactive mode (the -I flag).

Gatttool allows us to communicate with a BLE devices using the GATT protocol.

pi@raspberrypi:~ $ sudo gatttool -b A0:XX:XX:XX:XX:XX -I
[A0:XX:XX:XX:XX:XX][LE]> connect
Attempting to connect to A0:XX:XX:XX:XX:XX
Connection successful

Gatttool provides a number of useful commands, check them all out using the help command:

[A0:XX:XX:XX:XX:XX][LE]> help
help Show this help
exit Exit interactive mode
quit Exit interactive mode
connect [address [address type]] Connect to a remote device
disconnect Disconnect from a remote device
primary [UUID] Primary Service Discovery
included [start hnd [end hnd]] Find Included Services
characteristics [start hnd [end hnd [UUID]]] Characteristics Discovery
char-desc [start hnd] [end hnd] Characteristics Descriptor Discovery
char-read-hnd <handle> Characteristics Value/Descriptor Read by handle
char-read-uuid <UUID> [start hnd] [end hnd] Characteristics Value/Descriptor Read by UUID
char-write-req <handle> <new value> Characteristic Value Write (Write Request)
char-write-cmd <handle> <new value> Characteristic Value Write (No response)
sec-level [low | medium | high] Set security level. Default: low
mtu <value> Exchange MTU for GATT/ATT

The one that I’m the most interested in is char-desc, this command works as discovery, and will give us every handle on the device:

[A0:XX:XX:XX:XX:XX][LE]> char-desc
handle: 0x0001, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0002, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0003, uuid: 00002a00-0000-1000-8000-00805f9b34fb
handle: 0x0004, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0005, uuid: 00002a01-0000-1000-8000-00805f9b34fb
handle: 0x0006, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0007, uuid: 00002a04-0000-1000-8000-00805f9b34fb
handle: 0x0008, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0009, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x000a, uuid: 00002a05-0000-1000-8000-00805f9b34fb
handle: 0x000b, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x000c, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x000d, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x000e, uuid: 00002a23-0000-1000-8000-00805f9b34fb
handle: 0x000f, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0010, uuid: 00002a24-0000-1000-8000-00805f9b34fb
handle: 0x0011, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0012, uuid: 00002a25-0000-1000-8000-00805f9b34fb
handle: 0x0013, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0014, uuid: 00002a26-0000-1000-8000-00805f9b34fb
handle: 0x0015, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0016, uuid: 00002a27-0000-1000-8000-00805f9b34fb
handle: 0x0017, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0018, uuid: 00002a28-0000-1000-8000-00805f9b34fb
handle: 0x0019, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x001a, uuid: 00002a29-0000-1000-8000-00805f9b34fb
handle: 0x001b, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x001c, uuid: 00002a2a-0000-1000-8000-00805f9b34fb
handle: 0x001d, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x001e, uuid: 00002a50-0000-1000-8000-00805f9b34fb
handle: 0x001f, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0020, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0021, uuid: f000aa01-0451-4000-b000-000000000000
handle: 0x0022, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x0023, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0024, uuid: f000aa02-0451-4000-b000-000000000000
handle: 0x0025, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0026, uuid: f000aa03-0451-4000-b000-000000000000
handle: 0x0027, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0028, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0029, uuid: f000aa21-0451-4000-b000-000000000000
handle: 0x002a, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x002b, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x002c, uuid: f000aa22-0451-4000-b000-000000000000
handle: 0x002d, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x002e, uuid: f000aa23-0451-4000-b000-000000000000
handle: 0x002f, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0030, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0031, uuid: f000aa41-0451-4000-b000-000000000000
handle: 0x0032, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x0033, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0034, uuid: f000aa42-0451-4000-b000-000000000000
handle: 0x0035, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0036, uuid: f000aa44-0451-4000-b000-000000000000
handle: 0x0037, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0038, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0039, uuid: f000aa81-0451-4000-b000-000000000000
handle: 0x003a, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x003b, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x003c, uuid: f000aa82-0451-4000-b000-000000000000
handle: 0x003d, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x003e, uuid: f000aa83-0451-4000-b000-000000000000
handle: 0x003f, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0040, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0041, uuid: f000aa71-0451-4000-b000-000000000000
handle: 0x0042, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x0043, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0044, uuid: f000aa72-0451-4000-b000-000000000000
handle: 0x0045, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0046, uuid: f000aa73-0451-4000-b000-000000000000
handle: 0x0047, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0048, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0049, uuid: 0000ffe1-0000-1000-8000-00805f9b34fb
handle: 0x004a, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x004b, uuid: 00002901-0000-1000-8000-00805f9b34fb
handle: 0x004c, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x004d, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x004e, uuid: f000aa65-0451-4000-b000-000000000000
handle: 0x004f, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0050, uuid: f000aa66-0451-4000-b000-000000000000
handle: 0x0051, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0052, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0053, uuid: f000ac01-0451-4000-b000-000000000000
handle: 0x0054, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x0055, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0056, uuid: f000ac02-0451-4000-b000-000000000000
handle: 0x0057, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0058, uuid: f000ac03-0451-4000-b000-000000000000
handle: 0x0059, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x005a, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x005b, uuid: f000ccc1-0451-4000-b000-000000000000
handle: 0x005c, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x005d, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x005e, uuid: f000ccc2-0451-4000-b000-000000000000
handle: 0x005f, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0060, uuid: f000ccc3-0451-4000-b000-000000000000
handle: 0x0061, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0062, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0063, uuid: f000ffc1-0451-4000-b000-000000000000
handle: 0x0064, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x0065, uuid: 00002901-0000-1000-8000-00805f9b34fb
handle: 0x0066, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0067, uuid: f000ffc2-0451-4000-b000-000000000000
handle: 0x0068, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x0069, uuid: 00002901-0000-1000-8000-00805f9b34fb

Oh boy, that is a lot of text! Luckily Texas Instruments provides a full GATT Table on the devices TearDown page.

To start out easy, I picked a handle that looked descriptive and straight forward, the Device Name!

Handle Type Permissions
0x3 Device Name R

Back in gatttool I’m going to use the char-read-hnd command to read from this handle:

[A0:XX:XX:XX:XX:XX][LE]> char-read-hnd 0x3
Characteristic value/descriptor: 53 65 6e 73 6f 72 54 61 67 20 32 2e 30

It is also worth noting we can use the longer hex value (0x0003) returned from char-desc to get the same value:

[A0:XX:XX:XX:XX:XX][LE]> char-read-hnd 0x0003
Characteristic value/descriptor: 53 65 6e 73 6f 72 54 61 67 20 32 2e 30

The value returned is a set of hexadecimal values. Using Python I can  decode them and learn their secrets 😛

In [1]: val = '53 65 6e 73 6f 72 54 61 67 20 32 2e 30'

In [2]: [ i.decode('hex') for i in val.split() ]
Out[2]: ['S', 'e', 'n', 's', 'o', 'r', 'T', 'a', 'g', ' ', '2', '.', '0']

In [3]: ''.join([ i.decode('hex') for i in val.split() ])
Out[3]: 'SensorTag 2.0'

Check back soon, I plan to post more as I learn about this sweet device.