Bluetooth Smart (LE) with Arduino and Linux
Overview
This is a work in progress. I am working toward getting Bluetooth modules working with Arduino and Raspberry Pi, and I'm testing on a Linux computer. Many people testing Bluetooth modules are using Android devices or iPhones, or are connecting Bluetooth devices like mice and keyboards to Linux systems. What I'm trying to do seems relatively uncommon.
Classic Bluetooth and Bluetooth Smart, also known as Bluetooth LE (Low Energy)
(Note: "Classic" Bluetooth refers to versions below 4.0; BLE refers to 4.0 and above.) I won't go into the differences between these except to note that if you are using Low Energy (BLE) devices, then both ends of the connection need to be able to handle it. I have an older USB dongle that doesn't handle BLE, and a newer one that does. If I'm connecting to a BLE modules, I need a BLE-capable dongle.
Bluetooth LE module
I got the Bluetooth module on eBay, and there are many similar ones. Some identify themselves as HM-10. Mine looked like this:The back looks like this:
The ZS-040 is common to many of these. The device indicates that VCC can be from 3.6 to 6 V, however the RXD and TXD lines operate at 3.3V logic levels, regardless of VCC.
A closer look reveals that the chipset used is from Texas Instruments, specifically the CC2541.
Arduino connections
The EN and STATE pins were left unconnected.
Since the Arduino Uno is a 5V device, the voltage divider on RXD was used to avoid overvoltage on the pin.
Arduino sketch
The Arduino sketch I used was very simple:Linux testing
First, see if you can locate the Bluetooth dongle on the computer:
bash-4.3# hcitool dev
Devices:
hci0 00:11:22:33:44:55
Now you can check the status of the device:
bash-4.3# hciconfig -a
hci0: Type: BR/EDR Bus: USB
BD Address: 00:11:22:33:44:55 ACL MTU: 339:8 SCO MTU: 128:2
DOWN
.
.
.
The last line above indicates the interface is down. To change that:
bash-4.3# hciconfig hci0 up bash-4.3# hciconfig -a hci0: Type: BR/EDR Bus: USB BD Address: 00:11:22:33:44:55 ACL MTU: 339:8 SCO MTU: 128:2 UP RUNNING RX bytes:930 acl:0 sco:0 events:35 errors:0 TX bytes:131 acl:0 sco:0 commands:35 errors:0 Features: 0xff 0x3e 0x85 0x30 0x18 0x18 0x00 0x00 Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3 Link policy: RSWITCH HOLD SNIFF Link mode: SLAVE ACCEPT . . .Note that the dongle is originally configured as a slave. If we want to change it to a master:
bash-4.3# hciconfig -a hci0 lm master bash-4.3# hciconfig -a hci0: Type: BR/EDR Bus: USB BD Address: 00:11:22:33:44:55 ACL MTU: 339:8 SCO MTU: 128:2 UP RUNNING RX bytes:1496 acl:0 sco:0 events:43 errors:0 TX bytes:187 acl:0 sco:0 commands:43 errors:0 Features: 0xff 0x3e 0x85 0x30 0x18 0x18 0x00 0x00 Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3 Link policy: RSWITCH HOLD SNIFF Link mode: MASTER Name: '' Class: 0x000104 Service Classes: Unspecified Device Class: Computer, Desktop workstation HCI Version: 2.0 (0x3) Revision: 0xc5c LMP Version: 2.0 (0x3) Subversion: 0xc5c Manufacturer: Cambridge Silicon Radio (10)Note that is is now configured as a master. There is a lot of information given including the manufacturer.
Now that the device is working, we can look for BLE devices in the vicintiy:
bash-4.3# hcitool lescan
LE Scan ...
CC:FF:11:11:66:22 (unknown)
CC:FF:11:11:66:22 (unknown)
CC:FF:11:11:66:22 MLT-BT05
.
.
.
One device shows up.
It identifies itself as MLT-BT05.
We can find out more about the device:
bash-4.3# hcitool leinfo CC:FF:11:11:66:22
Requesting information ...
Handle: 71 (0x0047)
LMP Version: 4.0 (0x6) LMP Subversion: 0x132
Manufacturer: Texas Instruments Inc. (13)
Features: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00
(As mentioned above, the chipset manufacturer is identified as Texas
Instruments.)
Does the dongle support BLE?
bash-4.3# hciconfig hci0 commands
hci0: Type: BR/EDR Bus: USB
BD Address: 00:11:22:33:44:55 ACL MTU: 339:8 SCO MTU: 128:2
Commands: Octet 0 = 0xff (Bit 0 1 2 3 4 5 6 7)
Octet 1 = 0xff (Bit 0 1 2 3 4 5 6 7)
Octet 2 = 0xff (Bit 0 1 2 3 4 5 6 7)
Octet 3 = 0x03 (Bit 0 1)
Octet 4 = 0xce (Bit 1 2 3 6 7)
Octet 5 = 0xff (Bit 0 1 2 3 4 5 6 7)
Octet 6 = 0xff (Bit 0 1 2 3 4 5 6 7)
Octet 7 = 0xff (Bit 0 1 2 3 4 5 6 7)
Octet 8 = 0xff (Bit 0 1 2 3 4 5 6 7)
Octet 9 = 0xff (Bit 0 1 2 3 4 5 6 7)
Octet 10 = 0xff (Bit 0 1 2 3 4 5 6 7)
Octet 11 = 0xff (Bit 0 1 2 3 4 5 6 7)
Octet 12 = 0x33 (Bit 0 1 4 5)
Octet 13 = 0x0f (Bit 0 1 2 3)
Octet 14 = 0xe8 (Bit 3 5 6 7)
Octet 15 = 0xff (Bit 0 1 2 3 4 5 6 7)
Octet 16 = 0x3f (Bit 0 1 2 3 4 5)
'Inquiry' 'Inquiry Cancel' 'Periodic Inquiry Mode'
'Exit Periodic Inquiry Mode' 'Create Connection' 'Disconnect'
'Add SCO Connection' 'Cancel Create Connection'
'Accept Connection Request' 'Reject Connection Request'
'Link Key Request Reply' 'Link Key Request Negative Reply'
'PIN Code Request Reply' 'PIN Code Request Negative Reply'
'Change Connection Packet Type' 'Authentication Requested'
'Set Connection Encryption' 'Change Connection Link Key'
'Master Link Key' 'Remote Name Request' 'Cancel Remote Name Request'
'Read Remote Supported Features' 'Read Remote Extended Features'
'Read Remote Version Information' 'Read Clock Offset'
'Read LMP Handle' 'Hold Mode' 'Sniff Mode' 'Exit Sniff Mode'
'QoS Setup' 'Role Discovery' 'Switch Role' 'Read Link Policy Settings'
'Write Link Policy Settings' 'Read Default Link Policy Settings'
'Write Default Link Policy Settings' 'Flow Specification'
'Set Event Mask' 'Reset' 'Set Event Filter' 'Flush' 'Read PIN Type'
'Write PIN Type' 'Create New Unit Key' 'Read Stored Link Key'
'Write Stored Link Key' 'Delete Stored Link Key' 'Write Local Name'
'Read Local Name' 'Read Connection Accept Timeout'
'Write Connection Accept Timeout' 'Read Page Timeout'
'Write Page Timeout' 'Read Scan Enable' 'Write Scan Enable'
'Read Page Scan Activity' 'Write Page Scan Activity'
'Read Inquiry Scan Activity' 'Write Inquiry Scan Activity'
'Read Authentication Enable' 'Write Authentication Enable'
'Read Encryption Mode' 'Write Encryption Mode' 'Read Class Of Device'
'Write Class Of Device' 'Read Voice Setting' 'Write Voice Setting'
'Read Automatic Flush Timeout' 'Write Automatic Flush Timeout'
'Read Num Broadcast Retransmissions'
'Write Num Broadcast Retransmissions' 'Read Hold Mode Activity'
'Write Hold Mode Activity' 'Read Transmit Power Level'
'Read Synchronous Flow Control Enable'
'Write Synchronous Flow Control Enable'
'Set Host Controller To Host Flow Control' 'Host Buffer Size'
'Host Number Of Completed Packets' 'Read Link Supervision Timeout'
'Write Link Supervision Timeout' 'Read Number of Supported IAC'
'Read Current IAC LAP' 'Write Current IAC LAP'
'Read Page Scan Period Mode' 'Write Page Scan Period Mode'
'Read Page Scan Mode' 'Write Page Scan Mode'
'Set AFH Channel Classification' 'Read Inquiry Scan Type'
'Write Inquiry Scan Type' 'Read Page Scan Type' 'Write Page Scan Type'
'Read AFH Channel Assessment Mode' 'Write AFH Channel Assessment Mode'
'Read Local Version Information' 'Read Local Supported Features'
'Read Local Extended Features' 'Read Buffer Size' 'Read Country Code'
'Read BD ADDR' 'Read Failed Contact Counter'
'Reset Failed Contact Counter' 'Get Link Quality' 'Read RSSI'
'Read AFH Channel Map' 'Read BD Clock' 'Read Loopback Mode'
'Write Loopback Mode' 'Enable Device Under Test Mode'
'Setup Synchronous Connection' 'Accept Synchronous Connection'
'Reject Synchronous Connection'
bash-4.3#
The above one does not. The following one
does:
bash-4.3# hciconfig hci0 commands
hci0: Type: BR/EDR Bus: USB
BD Address: 00:11:22:33:44:55 ACL MTU: 339:8 SCO MTU: 128:2
Commands: Octet 0 = 0xff (Bit 0 1 2 3 4 5 6 7)
Octet 1 = 0xff (Bit 0 1 2 3 4 5 6 7)
Octet 2 = 0xff (Bit 0 1 2 3 4 5 6 7)
Octet 3 = 0x03 (Bit 0 1)
.
.
.
'Send Keypress Notification' 'IO Capability Request Negative Reply'
'Read Encryption Key Size' 'Read Enhanced Transmit Power Level'
'Read LE Host Support' 'Write LE Host Support' 'LE Set Event Mask'
'LE Read Buffer Size' 'LE Read Local Supported Features'
'LE Set Random Address' 'LE Set Advertising Parameters'
'LE Read Advertising Channel TX Power' 'LE Set Advertising Data'
'LE Set Scan Response Data' 'LE Set Advertise Enable'
'LE Set Scan Parameters' 'LE Set Scan Enable' 'LE Create Connection'
'LE Create Connection Cancel' 'LE Read White List Size'
'LE Clear White List' 'LE Add Device To White List'
'LE Remove Device From White List' 'LE Connection Update'
'LE Set Host Channel Classification' 'LE Read Channel Map'
'LE Read Remote Used Features' 'LE Encrypt' 'LE Rand'
'LE Start Encryption' 'LE Long Term Key Request Reply'
'LE Long Term Key Request Negative Reply' 'LE Read Supported States'
'LE Receiver Test' 'LE Transmitter Test' 'LE Test End'
bash-4.3#
All of the LE commands at the end indicate that this dongle supports
BLE.
There are several commands that hcitool has specifically for BLE devices.
bash-4.3# hcitool
hcitool - HCI Tool ver 5.40
Usage:
hcitool [options] <command> [command parameters]
Options:
--help Display help
-i dev HCI device
Commands:
dev Display local devices
.
.
.
clock Read local or remote clock
lescan Start LE scan
leinfo Get LE remote information
lewladd Add device to LE White List
lewlrm Remove device from LE White List
lewlsz Read size of LE White List
lewlclr Clear LE White List
lerladd Add device to LE Resolving List
lerlrm Remove device from LE Resolving List
lerlclr Clear LE Resolving List
lerlsz Read size of LE Resolving List
lerlon Enable LE Address Resolution
lerloff Disable LE Address Resolution
lecc Create a LE Connection
ledc Disconnect a LE Connection
lecup LE Connection Update
For more information on the usage of each command use:
hcitool <command> --help
bash-4.3$
To connect with the device:
bash-4.3# hcitool lecc CC:FF:11:11:66:22
Connection handle 71
bash-4.3#
You should see that the formerly flashing LED on the module now stays on, indicating a connection.
To disconnect from the device:
bash-4.3# hcitool ledc 71
bash-4.3#
To monitor traffic from the remote device:
bash-4.3# hcidump --raw hci0
HCI sniffer - Bluetooth packet analyzer ver 5.40
device: hci0 snap_len: 1500 filter: 0xffffffff
> 02 47 20 0D 00 09 00 04 00 1B 25 00 74 65 73 74 0D 0A
The string 74 65 73 74 translates to ASCII as
test, (followed by carriage return (0D) linefeed (0A)),
which was sent from the Arduino with the module.
Linux testing using bluetoothctl
bluetoothctl is an alternative Linux tool for testing Bluetooth.
bash-4.3# bluetoothctl
[bluetooth]#
Notice that it operates in interactive mode.
Find local controller:
[bluetooth]# list
Controller 00:11:22:33:44:55 BlueZ 5.40 [default]
[bluetooth]#
Look for remote devices:
[bluetooth]# scan on
Discovery started
[CHG] Controller 00:1A:7D:DA:71:0A Discovering: yes
[CHG] Device CC:FF:11:11:66:22 RSSI: -58
[NEW] Device 57:3F:C6:DD:3B:63 57-3F-C6-DD-3B-63
[bluetooth]#
Connect to remote device:
[bluetooth]# connect CC:FF:11:11:66:22
Attempting to connect to CC:FF:11:11:66:22
[CHG] Device CC:FF:11:11:66:22 Connected: yes
Connection successful
[MLT-BT05]#
The prompt has changed to the name of the connected device.
Disconnecting is similar:
[MLT-BT05]# disconnect
Attempting to disconnect from CC:FF:11:11:66:22
Successful disconnected
[CHG] Device CC:FF:11:11:66:22 Connected: no
[bluetooth]#
The prompt has returned to its non-specific state.
If a device is already connected when the program is started, the prompt will reflect that:
bash-4.3# bluetoothctl
[NEW] Controller 00:11:22:33:44:55 BlueZ 5.40 [default]
[NEW] Device CC:FF:11:11:66:22 MLT-BT05
[MLT-BT05]#
There are many commands:
[MLT-BT05]# help
Available commands:
list List available controllers
show [ctrl] Controller information
select <ctrl> Select default controller
devices List available devices
paired-devices List paired devices
power <on/off> Set controller power
pairable <on/off> Set controller pairable mode
discoverable <on/off> Set controller discoverable mode
agent <on/off/capability> Enable/disable agent with given capability
default-agent Set agent as the default one
set-scan-filter-uuids [uuid1 uuid2 ...] Set scan filter uuids
set-scan-filter-rssi [rssi] Set scan filter rssi, and clears pathloss
set-scan-filter-pathloss [pathloss] Set scan filter pathloss, and clears rssi
set-scan-filter-transport [transport] Set scan filter transport
set-scan-filter-clear Clears discovery filter.
scan <on/off> Scan for devices
info [dev] Device information
pair [dev] Pair with device
trust [dev] Trust device
untrust [dev] Untrust device
block [dev] Block device
unblock [dev] Unblock device
remove <dev> Remove device
connect <dev> Connect device
disconnect [dev] Disconnect device
list-attributes [dev] List attributes
select-attribute <attribute> Select attribute
attribute-info [attribute] Select attribute
read Read attribute value
write <data=[xx xx ...]> Write attribute value
notify <on/off> Notify attribute value
register-profile <UUID ...> Register profile to connect
unregister-profile Unregister profile
version Display version
quit Quit program
[MLT-BT05]#
The info command returns information about the remote
device.
[MLT-BT05]# info
Device CC:FF:11:11:66:22
Name: MLT-BT05
Alias: MLT-BT05
Paired: no
Trusted: yes
Blocked: no
Connected: yes
LegacyPairing: no
UUID: Generic Access Profile (00001800-0000-1000-8000-00805f9b34fb)
UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)
UUID: Device Information (0000180a-0000-1000-8000-00805f9b34fb)
UUID: Unknown (0000ffe0-0000-1000-8000-00805f9b34fb)
Modalias: bluetooth:v000Dp0000d0110
[MLT-BT05]#