Bluetooth Low Energy is all about services and attributes. Exploring these attributes is an interesting way to gain more insight in how a device works and is invaluable for testing. In order to make this process more comfortable a testing tool is invaluable. Hence the BTLE-explorer was born.
continue reading on the Productize Lab blog.
Showing posts with label bt4. Show all posts
Showing posts with label bt4. Show all posts
Friday, March 7, 2014
Tuesday, December 24, 2013
using madparts for making electronics footprints: an eleborate example
In this blog post I'm discussing a more complex footprint I've made and how I made it with madparts based on the vendor's specification. More specifically I'm making a footprint for the Bluegiga BLE113 Bluetooth Low Energy module.
Lets start by collecting all the needed data.
Define the size of the pad as found in the recommended landing pattern:
The horizontal pads need an adjustment from the center of the module. The landing pattern defines 5.35mm between the two columns of pads, and we orient from the center of the pad so in total this gives and adjustment value of:
The landing pattern tells us the distance between pads:
The pinout description gives the number of pins:
The physical dimension tells us the distance from the bottom of the module to the center of the bottom left and right pad. This works because the pad centers are the same for the physical diagram and the landing pattern.
Now this gets a bit tricky. We need to calculate the vertical adjustment needed for the column of pads, but this is relative to the center of the module. The trick is to take pad 18, move it to the 0 point, then to the bottom of the module, and then use the lr_pad_to_bottom adjust value specified in the spec.
Let's draw a rectangle to document the module shape, and draw a silk around it to make it easily visible on the board later.
Let's define the pad shape with the earlier defined constant. we want 100% round corners.
Now lets make the left row of pads. First make them, then adjust the x and y by the values we calculated earlier.
Next the bottom row. clone and rotate the pad, and create a horizontal row of pads. Adjust the y as specified in the landing pattern figure. Finally renumber starting with the number after the last number we used for the first column of pads.
Finally the right row. Again a single row of pads. Reverse the order. Renumber starting after the last number used for the down pads.
Let's add a name somewhere inside the module, a bit below the top:
Let's add a rectangular for the restrict area. This is a but messy but it boils down to placing it right above pas 36 and 3.5mm on the right of the left side of the module.
Finally combine it all in a list and we're done.
The latest version of the full file can be found at https://github.com/andete/madparts-parts/blob/master/3ca17b8bc41648d2b968c33ae8f35092.coffee
This is a screenshot:
And this is the part in eagle cad:
And in kicad:
Lets start by collecting all the needed data.
The physical dimensions of the module are found in the spec page 16:
This will be used to define the physical boundaries of the package.
Next is the landing pattern. It can be found on page 17 of the specification:
This is used to define the pads for the module.
The order of the pins can be found on page 7:
Finally the specification also gives a clearance for the antenna on page 20:
This means we'll have to add a restrict area to the part for this clearance area.
let's write code!
Define the size of the module as found in the physical dimensions:
module_dx = 9.15 module_dy = 15.74
Define the size of the pad as found in the recommended landing pattern:
pad_dx = 2 pad_dy = 0.5
The horizontal pads need an adjustment from the center of the module. The landing pattern defines 5.35mm between the two columns of pads, and we orient from the center of the pad so in total this gives and adjustment value of:
pad_hadj = (5.35+pad_dx)/2
The landing pattern tells us the distance between pads:
pad_between = 0.8
The pinout description gives the number of pins:
n_left = 18 n_down = 6 n_right = 12
The physical dimension tells us the distance from the bottom of the module to the center of the bottom left and right pad. This works because the pad centers are the same for the physical diagram and the landing pattern.
lr_pad_from_bottom = 1.45
Now this gets a bit tricky. We need to calculate the vertical adjustment needed for the column of pads, but this is relative to the center of the module. The trick is to take pad 18, move it to the 0 point, then to the bottom of the module, and then use the lr_pad_to_bottom adjust value specified in the spec.
pad_vadj = ((n_left-1)/2)*pad_between # move pad 18 to 0 pad_vadj -= module_dy/2 # move pad 18 down to bottom pad_vadj += lr_pad_from_bottom # and back up by 1.45
Let's draw a rectangle to document the module shape, and draw a silk around it to make it easily visible on the board later.
r1 = make_rect module_dx, module_dy, 0.1, 'docu' r2 = make_rect module_dx+0.2, module_dy+0.2, 0.1, 'silk'
Let's define the pad shape with the earlier defined constant. we want 100% round corners.
pad = new Smd pad.dx = pad_dx pad.dy = pad_dy pad.ro = 100
Now lets make the left row of pads. First make them, then adjust the x and y by the values we calculated earlier.
l1 = single pad, n_left, pad_between l1 = adjust_x l1, -pad_hadj l1 = adjust_y l1 , pad_vadj
Next the bottom row. clone and rotate the pad, and create a horizontal row of pads. Adjust the y as specified in the landing pattern figure. Finally renumber starting with the number after the last number we used for the first column of pads.
l2 = rot_single (rotate90pad clone pad), n_down, pad_between l2 = adjust_y l2, -module_dy/2+lr_pad_from_bottom-0.55 l2 = generate_names l2, n_left
Finally the right row. Again a single row of pads. Reverse the order. Renumber starting after the last number used for the down pads.
l3 = single pad, n_right, pad_between l3 = reverse l3 l3 = generate_names l3, n_left+n_down l3 = adjust_x l3, pad_hadj l3 = adjust_y l3, pad_vadj+(n_right-n_left)/2*pad_between
Let's add a name somewhere inside the module, a bit below the top:
name = new Name (module_dy/2-1)
Let's add a rectangular for the restrict area. This is a but messy but it boils down to placing it right above pas 36 and 3.5mm on the right of the left side of the module.
k = new Rect k.type = 'restrict' k.dx = module_dx k.dy = module_dy/2-l3[n_right-1].y k.x = -module_dx/2+3.5+k.dx/2 k.y = l3[n_right-1].y+pad_dy/2+k.dy/2
Finally combine it all in a list and we're done.
combine [name, r1,r2, l1, l2,l3, k]
The latest version of the full file can be found at https://github.com/andete/madparts-parts/blob/master/3ca17b8bc41648d2b968c33ae8f35092.coffee
This is a screenshot:
And this is the part in eagle cad:
And in kicad:
Labels:
ble113,
bluegiga,
bt4,
electronics,
lab,
madparts,
programming
Tuesday, August 13, 2013
Experiments with Bluetooth Low Energy (4.0) under Linux
With iPhônes liberated from the apple authentication chip by it, and Android also having added support in the latest Android 4.3, Bluetooth Low Energy (4.0) is starting to look more interesting.
In this blog post I'm going to use a bluegiga BT111 based USB bluetooth dongle on Linux as a client and a TI CC2541 SensorTag as server.
The SensorTag is a nice little bluetooth 4 example device provided by Texas Instruments.
In this case the bluetooth mac address of the BT111 is 00:07:80:60:CE:4D.
It returns us a prompt. Let's connect to the device.
The CON indication tells us that the connection is established.
Now the primary command can be used to find the primary services of the device.
Attributes in GATT have uuids and handles. UUIDs (unique identifiers) define a certain type of entry, handles can be used to access a value. To make things more complicated there is also nesting involved. Certain UUIDs are defined in the standard and always have to be provided. Others can just be vendor specific and provide the actual data for the service. It's beyond the scope of this blog post to further look into how all that fits together.
So far so good, but no useful data. We first need to enable the sensor. This is done by writing 1 in the Config handle.
Let's retry reading the value now.
That's more like it. Using the math provided on the website and a python script, this gives the temperature and the humidity.
So 25 Celsius and 50% humidity. That agrees with my local weather sensor. Nice :)
Instead of reading values it is also possible to use notifications.
Finally let's disable the sensor and disconnect.
In this blog post I'm going to use a bluegiga BT111 based USB bluetooth dongle on Linux as a client and a TI CC2541 SensorTag as server.
![]() |
USB dongle in computer |
Device
First step is put the device in the computer. As my laptop already has an existing bluetooth device build-in, the new one will enumerate as "hci1". This can be found out also by using hcitool.
$ hcitool dev Devices: hci1 00:07:80:60:CE:4D hci0 EC:55:F9:F4:A0:xx
In this case the bluetooth mac address of the BT111 is 00:07:80:60:CE:4D.
Scanning for a device
Normal bluetooth scanning is done with hcitool scan. Low Energy scanning is done with hcitool lescan.
Make sure to press the button on the side of the SensorTag first to make it discoverable. Scanning is continuous to stop it with Ctrl-C. Low Energy devices require root access hence the sudo. I would expect being in the bluetooth group to be enough but for some reason it isn't.
$ sudo hcitool -i hci1 lescan LE Scan ... BC:6A:29:AC:2E:B4 (unknown) BC:6A:29:AC:2E:B4 SensorTag BC:6A:29:AC:2E:B4 (unknown) BC:6A:29:AC:2E:B4 SensorTag BC:6A:29:AC:2E:B4 (unknown) ^C
Using gatttool to access the device
Now we know the address of the SensorTag: BC:6A:29:AC:2E:B4. In contrast with regular Bluetooth where there are a whole range of protocols, with Bluetooth Low Energy there is only one protocol at the top and it is GATT (Generic Attribute).
The actual functionality of a device is implemented by means of attributes which can be read, written to or notification/indication enabled for, depending on the attribute.
gatttool is a simple Linux tool that can be used to manipulate these attributes with a Bluetooth Low Energy device. It can be used as a simple command line tool but I find it easier to use it in it's interactive mode.
Let's enter the interactive mode.
$ sudo gatttool -i hci1 -b BC:6A:29:AC:2E:B4 -I [ ][BC:6A:29:AC:2E:B4][LE]>
It returns us a prompt. Let's connect to the device.
[ ][BC:6A:29:AC:2E:B4][LE]> connect [CON][BC:6A:29:AC:2E:B4][LE]>
The CON indication tells us that the connection is established.
Now the primary command can be used to find the primary services of the device.
[CON][BC:6A:29:AC:2E:B4][LE]> primary [CON][BC:6A:29:AC:2E:B4][LE]> attr handle: 0x0001, end grp handle: 0x000b uuid: 00001800-0000-1000-8000-00805f9b34fb attr handle: 0x000c, end grp handle: 0x000f uuid: 00001801-0000-1000-8000-00805f9b34fb attr handle: 0x0010, end grp handle: 0x0022 uuid: 0000180a-0000-1000-8000-00805f9b34fb attr handle: 0x0023, end grp handle: 0x002a uuid: f000aa00-0451-4000-b000-000000000000 attr handle: 0x002b, end grp handle: 0x0035 uuid: f000aa10-0451-4000-b000-000000000000 attr handle: 0x0036, end grp handle: 0x003d uuid: f000aa20-0451-4000-b000-000000000000 attr handle: 0x003e, end grp handle: 0x0048 uuid: f000aa30-0451-4000-b000-000000000000 attr handle: 0x0049, end grp handle: 0x0054 uuid: f000aa40-0451-4000-b000-000000000000 attr handle: 0x0055, end grp handle: 0x005c uuid: f000aa50-0451-4000-b000-000000000000 attr handle: 0x005d, end grp handle: 0x0061 uuid: 0000ffe0-0000-1000-8000-00805f9b34fb attr handle: 0x0062, end grp handle: 0x0068 uuid: f000aa60-0451-4000-b000-000000000000 attr handle: 0x0069, end grp handle: 0xffff uuid: f000ffc0-0451-4000-b000-000000000000
Attributes in GATT have uuids and handles. UUIDs (unique identifiers) define a certain type of entry, handles can be used to access a value. To make things more complicated there is also nesting involved. Certain UUIDs are defined in the standard and always have to be provided. Others can just be vendor specific and provide the actual data for the service. It's beyond the scope of this blog post to further look into how all that fits together.
SensorTag attributes
Luckily for us, the meaning of the sensortag attributes are defined on the user guide at http://processors.wiki.ti.com/index.php/SensorTag_User_Guide.
For this blog I'm looking at the humidity sensor as it is the easiest and the values shown in the document are actually correct :) http://processors.wiki.ti.com/index.php/SensorTag_User_Guide#Humidity_Sensor_2
As you can see on that page, there are 3 important handles for the humidity sensor, Data (0x38), DataNotification (0x39) and Config (0x3C).
Let's try reading from the Data handle:
Let's try reading from the Data handle:
[CON][BC:6A:29:AC:2E:B4][LE]> char-read-hnd 38 [CON][BC:6A:29:AC:2E:B4][LE]> Characteristic value/descriptor: 00 00 00 00
So far so good, but no useful data. We first need to enable the sensor. This is done by writing 1 in the Config handle.
[CON][BC:6A:29:AC:2E:B4][LE]> char-write-req 3c 01 [CON][BC:6A:29:AC:2E:B4][LE]> Characteristic value was written successfully
Let's retry reading the value now.
[CON][BC:6A:29:AC:2E:B4][LE]> char-read-hnd 38 [CON][BC:6A:29:AC:2E:B4][LE]> Characteristic value/descriptor: 68 68 4e 72
That's more like it. Using the math provided on the website and a python script, this gives the temperature and the humidity.
>>> -46.85 + 175.72/65536 * 0x6868 24.8151025390625 >>> -6.0 + 125.0/65536 * (0x72e4 & ~3) 50.09893798828125
So 25 Celsius and 50% humidity. That agrees with my local weather sensor. Nice :)
Instead of reading values it is also possible to use notifications.
[CON][BC:6A:29:AC:2E:B4][LE]> char-write-req 39 0100 [CON][BC:6A:29:AC:2E:B4][LE]> Characteristic value was written successfully Notification handle = 0x0038 value: 68 68 f6 71 [CON][BC:6A:29:AC:2E:B4][LE]> ...This will provide the temperature and the humidity every second automatically. Let's disable it again it is spamming me :)
[CON][BC:6A:29:AC:2E:B4][LE]> char-write-req 39 0000 [CON][BC:6A:29:AC:2E:B4][LE]> Characteristic value was written successfully
Finally let's disable the sensor and disconnect.
[CON][BC:6A:29:AC:2E:B4][LE]> char-write-req 3c 00 [CON][BC:6A:29:AC:2E:B4][LE]> Characteristic value was written successfully [CON][BC:6A:29:AC:2E:B4][LE]> disconnect [ ][BC:6A:29:AC:2E:B4][LE]>
Conclusion
Bluetooth Low Energy might look a bit different/strange at first but it is really quite nice! I'm certainly going to explore it further!
Shameless plug!
Don't forget to check out the very nice BT111 based USB dongle available for sale at my tindie store!

Subscribe to:
Posts (Atom)