Introduction: $15 Bluetooth With Python/Android
Bluetooth Low Energy is fantastic for wireless communication between devices - unfortunately, the documentation is less than fantastic. We're here to fix that!
We will be working with RFduino, a cheap microcontroller ($15 ea.) that includes a built-in BLE module. The RFduino works with Arduino sketches, so if you have previous experience with Arduino it's very easy to learn.
Our code demos the RFduino through a couple of simple echo programs, where we send a message to the RFduino, and it "echoes" it back. For Linux users, we have a python program that utilizes the "hcitool" and "gatttool" Linux commands; for Android users, we have an an echo app for those running 4.3 or higher.
Like this Instructable? Don't forget to follow us, favorite it, and check us out on Facebook!
The cost of this project will vary depending on what you have at hand - if you already have an FTDI programmer and some soldering tools, all you need is the $15 RFDuino, two 1k resistors, and a 10nF capacitor!
For those looking for an easy start, we recommend buying the following:
- RFduino Rapid Development Kit: $50
- Bluetooth LE Dongle: $10 (not necessary if your computer has built-in BLE)
- Android device running 4.3 or higher (We used a Nexus 7)
- Computer with Linux
- 15 minutes to download, install, and run the echo programs with the development kit
- Basic Arduino coding (uploading a sketch and installing a library)
- Using a Linux terminal (the proper commands will be provided)
- Coding in Python
- Basic Android programming (adding permissions, editing a layout, debugging on a hardware device)
Step 1: Try It Out!
After the libraries and drivers are installed, connect the RFduino to your PC. If you bought the dev kit, it should be as easy as plugging it into the USB port. For those going for the $15 option, you'll need to use an FTDI chip/programmer to emulate the RFDuino's USB shield (see schematic). This means soldering wires to power, ground, GPIO0, GPIO1, and RESET on the RFDuino (pins 8, 6, 11, 12, and 9 respectively). Hook these pins up to power, ground, RX, TX, and DTR on your FTDI module, with a 1k resistor in series on each of the RX/TX lines and a 10nF capacitor in series on the DTR line, to emulate the schematic.
Now upload the Arduino code to the RFduino. If all goes well, nothing will happen initially, but when you connect/disconnect to the RFduino it will notify you via serial.
Before you use the python code, you have to find the name of your bluetooth device. To do this, run "hcitool dev" to determine the name of your computer's bluetooth device - this will list the bluetooth devices on your computer (in the format of "hci#"). If there is more than one device, the first one will probably be the computer's built in bluetooth transceiver, and the others will be dongles or other Bluetooth devices.
Then, run "python rfduinoecho.py " in the Python folder. The script will search and connect to the RFduino, and then prompt you to enter a string. It will send the string, receive its echo, and print it.
Import the project into your Eclipse workspace. Make sure you have your Android device plugged in and ready to debug. If you're not sure how to do this, Google has great instructions. Click the "Run" button in Eclipse to run your program.
Press the "Connect" button to connect to the RFduino. You should see the words "Connected" at the top. Next, type the string you want to send in the text box that has the prompt "String to send." Then press the "Send" button to send the string to the RFduino - The RFduino's response will appear underneath "Echo."
So now that you've got it all working, let's dive in to the gory innards!
Step 2: How It Works: the RFduino
The RFduino must be programmed with the current beta version of Arduino; the latest stable version will not work.
The goal of this sketch is to wait for a BLE message, and then send that message back. Let's get into the code!
For debugging purposes, the setup function begins Serial and sets the pin mode of notificationLED to OUTPUT. To identify which MAC address belongs to this device later on, RFduinoBLE.advertisementData is set to "myEcho". RFduinoBLE.begin() is called to start advertising.
This sets the RFduino in ultra low power mode with RFduino_ULPDelay(INFINITE).
RFduinoBLE_onConnect and RFduinoBLE_onDisconnect:
These Print to serial, to help with debugging.
This is where the important stuff happens: where the RFduino receives data. In this example, we will print the characters, then pass them to the send function.
Read on to find out how Python talks to the RFduino!
Step 3: How It Works: Python
For the Python code, the three main functions to understand are find, send, and read.
This performs the hcitool lescan commands and searches the output for the name of the RFduino (set in the RFduino code). If the RFduino isn't found, then the function returns False. If it is found, the MAC address is stored for later use. hcitool lescan has a tendency to lock the bluetooth dongle, so before scanning, resetting the service is a good idea.
send is passed a string to be sent to the RFduino. The string is then converted into hex, and sent using the "gatttool --char-write" command with the string, the RFduino's MAC and receiving handle (0x0011).
read uses the "gatttool --char-read" command, the RFduino's MAC and sending handle (0x000e) to get the data. The received data is then decoded from hex back into characters and returned.
Next, we'll explain how the Android code works!
Step 4: How It Works: Android
Let's get into the good stuff: Android programming. It is a bit more complex, for good reason: instead of simple send and receive functions, you have more control over how the data is handled.
setScanning: This function checks that we aren't scanning or already connected, then calls the bluetoothAdapter.startLeScan.
scanCallback.onLeScan: This is called when the LE scan discovers a device. It checks if the device matches, and calls connect if it does.
connect: This checks that the required objects are instantiated, and uses bluetoothGatt to connect to the device.
statusReceiver/responseReceiver/updateStatusIntent/updateResponseIntent: The scanCallback and gattCallback occur in their own threads, so they cannot directly interact with the UI. Instead, we broadcast intents to update the connection status and RFduino response onscreen.
gattCallback.onConnectionStateChange: Fairly obvious, this is called when the connection state changes. It updates the connectionState variable and our UI.
gattCallback.onServicesDiscovered: This is called when services are discovered on a connected Bluetooth device. It finds the characteristics need to communicate with the RFduino and stores them for later use.
gattCallback.onCharacteristicRead: This is called when reading from a Bluetooth device. In the echo program, it prints the read value to the proper textview.
writeDataToCharacteristic: This writes the data in the edittext to the RFduino.
readDataFromCharacteristic: This reads the data from the RFduino.
Step 5: The Future
Hopefully, we've shown that BLE with the RFduino is pretty damn easy. Now that you have a microcontroller that can communicate with your computer, you can work on cool things like:
- a remote controlled fire-breathing duck
- a wireless light switch
- a wireless robotic arm
- a wireless breathalyzer
- wireless wires
- wireless anything, really!
We've got plenty more exciting new content on the way this summer, so if you enjoyed this Instructable, don't forget to favorite it and follow us on Facebook!