Creating machines that interact with the physical world is an incredibly satisfying thing. Controlling them via Bluetooth with your iOS device is just plain awesome!
In the past, the only way to create an Apple-approved Bluetooth device was by being part of the MFi program. With Bluetooth Low Energy 4.0, individuals and small companies can develop their own products and market them without the overhead of Apple’s MFi regulations. That means you can talk to devices over Bluetooth LE with very little configuration and code, which opens up an entire world of opportunity for iOS developers.
This tutorial will teach you how to integrate Bluetooth LE and iOS using standard off-the-shelf components and an Arduino. Since the focus of this project is building a BLE device, you’ll be using the iOS Core Bluetooth framework. If you’re unfamiliar with Core Bluetooth, check out our Introduction to Core Bluetooth: Building a Heart Rate Monitor tutorial.
Aside from the Arduino and BLE shield components listed below, you’ll also need to run the companion app on a real iOS device – that means you’ll need a paid iOS developer account.
Let the building begin!
Getting Started
Using off-the-shelf components for this build makes creating a Bluetooth device a snap. Here’s an image showing the basic elements you’ll use in this project:
Here’s the list of parts you’ll need to complete the project, and where to obtain them:
- iPhone 4s or newer with Bluetooth LE
- Arduino Red Board, $19.95 at SparkFun.com
- USB Mini-B Cable, $3.95 at SparkFun.com
- Servo Motor, $8.95 at SparkFun.com
- Jumper Wires, $4.95 at SparkFun.com)
- Black Widow Long Range BLE Shield based on Bluegiga’s BLE121LR Module, $69.00 at www.back-40.com.
The Arduino, servo and jumper wires can be purchased together from SparkFun.com in the SparkFun Inventor’s Kit for Arduino. This kit comes with many useful components and tutorials to get you started in the hardware world.
You can find less-expensive BLE Shields other than the one listed in this tutorial, but be aware that many of them sacrifice flexibility to save on cost. The Black Widow BLE Shield allows you to program your own custom BLE Services and Characteristics onto the module. This means you can take full advantage of the Bluetooth 4.0 data structure. Plus, it gives you extra long range with the built-in BLE121LR module.
That takes care of the hardware side of things – there are a few extra software pieces to take care of as well.
Download the Xcode starter project here. The starter project includes the view controller and base Core Bluetooth implementation to save you time. You’ll add more code to interface with the BLE Shield later on in the tutorial.
Next, download and install the Arduino IDE from the Arduino Download page; it’s available for Windows, Mac OS X and Linux platforms. You’ll use the Arduino IDE to write and compile the code for the Arduino. Ensure you grab the latest release version, not the beta or nightly builds.
The Basic Design of your App
Your finished project will consist of an iOS app that will send messages via Bluetooth to the BLE Shield module. The module will then send the message to the Arduino board to tell the servo which position it should rotate to.
Here’s an example use-case of your project:
- The user of the iOS app moves the slider to the middle position.
- The app sends the number 90, which represents 90 degrees in this case, to the BLE Shield module using the active Bluetooth connection.
- The BLE Shield transfers the number 90 to the Arduino board.
- The Arduino board rotates the servo to the 90 degree position.
Seems pretty straightforward! To begin, you’ll work with the Arduino IDE and program the board logic.
Programming the Arduino
Start the Arduino IDE; you’ll see the editor appear with a blank document, or “sketch”, as shown below:
Before doing anything else, click File\Save in the top menu and save the current file to a convenient location as Arduino_Servo_Controller. This creates a folder in your save location that contains a file with a .ino
file extension.
Before you start writing code, you’ll need to set up the IDE to communicate with the Arduino Uno board.
Select Tools\Board\Arduino Uno to let the IDE know what kind of board you’ll be dealing with. Next, connect the Uno to your computer with the USB cable as shown below:
This lets the Arduino IDE recognize the serial port to which the Uno is connected.
Once that’s done, select Tools\Serial Port\… and select the USB port the Arduino is connected to. Generally it’s similar to /dev/tty.usbserial… or /dev/tty.usbmodem….
At this point the Arduino IDE is ready for programming.
Add the code below to your project using the Arduino IDE:
// Arduino Bluetooth LE Servo Controlled by iOS void setup() // Called only once per startup { } void loop() // Continuous loop { } |
Arduino programs are typically split into two main functions: setup()
and loop()
.
The setup()
function does exactly what it is says: it’s called only once on startup and is a great place for setting up your hardware and software. The loop()
function is called once setup()
is done. loop()
will be called over and over again until you reset or power down the board.
Click the Verify button (the checkmark icon) to ensure everything compiles correctly. If so, you’ll see a confirmation message similar to below:
Now that you have the basic framework of the Arduino program in place, it’s time to add some logic to control the board.
Illuminating an LED
The main objective of your Arduino program in this project is to receive the one-byte messages coming from the BLE Shield and use the contents of the message to set the servo’s position. But before you get too involved into the servo code, it would be nice to test your current connections.
The easiest way to do this is to write a small program that controls the built-in LED on the Uno. Think of it as the “hello world” equivalent on the Arduino. :]
Replace the code in your project with the following:
// Arduino Bluetooth LE Servo Controlled by iOS int LED = 13; // Most Arduino boards have an onboard LED on pin 13 void setup() // Called only once per startup { pinMode(LED, OUTPUT); // Set pin as an output digitalWrite(LED, HIGH); // Turn on LED (ie set to HIGH voltage) } void loop() // Continuous loop { delay(500); digitalWrite(LED, LOW); delay(500); digitalWrite(LED, HIGH); } |
Since most Arduino boards have an onboard LED on pin 13, you can use the illumination of the LED as confirmation that your Arduino program is executing properly. You set the LED
variable to 13 to refer to that pin.
In setup()
, you set the initial state of the board. pinMode(LED, OUTPUT)
sets pin 13 as a digital output, which means that the voltage on this pin can be set to HIGH (+5v) or LOW (0v). digitalWrite()
sets the pin’s voltage; in the code above you’ve set it to HIGH to illuminate the LED.
After setup()
has finished, loop()
will run continuously. delay()
will wait a certain number of milliseconds which you’ll use to get the LED to blink. After a 500ms delay, you turn the LED off by writing the value LOW; after another delay, you turn the LED back on.
Click the Verify button again to compile the program and check for any syntax errors. If your program compiles without issue, you’ll see Done Compiling in the status bar of the Arduino IDE. If not, read the status bar message for an indication of where you’ve messed up, fix the error and click the Verify button to make sure you’ve squashed the bug for good.
Now it’s time to program the code to the Arduino board and test the LED.
Make sure your Arduino is connected to your computer with the USB cable then click the Upload button (the one with the right arrow icon) to program the Arduino board. Once the upload process has finished, the Done uploading message should appear in the status bar as shown below:
Check your Arduino board, and you should see the LED start to blink.
If an error occurred, try the following things to diagnose your issue:
- Check that Arduino Uno is selected in the Tools/Board menu.
- Check that /dev/tty.usbserial… or /dev/tty.usbmodem… (or similar) is selected in the Tools/Serial Port menu.
- Check that you installed any required drivers for your Arduino board as noted earlier.
- Check that the BLE Shield is not assembled on the Arduino board during programming of the board.
If the LED works, you can be sure that the Arduino IDE is set up properly. You can now add some code to control the servo.
Interfacing With the Servo Control
A servo is a motor with a changeable rotational position. You control a servo by sending different frequencies of electric pulses to its control line.
Replace the blinking LED code in the current sketch with the following:
// Arduino Bluetooth LE Servo Controlled by iOS #include <Servo.h> int LED = 13; // Most Arduino boards have an onboard LED on pin 13 Servo myservo; // Create servo object to control the servo |
The above code imports the Servo
library and create a variable as an instance of the Servo
class. By including the Servo
library, you can create Servo
objects which can be easily configured to control the servo hardware.
Next, add the following function:
void setup() // Called only once per startup { pinMode(LED, OUTPUT); // Set pin as an output digitalWrite(LED, HIGH); // Turn on LED (ie set to HIGH voltage) myservo.attach(9); // Attach the servo object to pin 9 myservo.write(0); // Initialize servo position to 0 } |
myServo.attach(9)
indicates that output pin 9 of the Arduino Uno board will be connected to the servo, while write(0)
sets the position of the servo to zero degrees.
That takes care of the servo initialization, but you’ll still need some code to handle the BLE communication. Before you tackle that, you should read through the following section on the fundamentals of serial communication.
Serial Communication
Serial communication is much like using a telephone. The speaker held to your ear is the receiver (RX) and the microphone is the transmitter (TX). Your transmitter is connected to the receiver of the person with whom you are talking, and your receiver is connected to their transmitter. This allows for bi-directional communication where either person can send or receive information.
By default, the Arduino uses pin 0 and pin 1 for serial communication. To communicate with the Black Widow BLE Shield, this needs to be changed to pin 4 (RX) and pin 5 (TX). This guards against any data collision when the PC is uploading to the Arduino.
Add the following include to the top of the file:
#include <SoftwareSerial.h> |
This will allow you to use the serial communication library.
Add the following variable underneath the LED and myservo variable declarations:
SoftwareSerial BLE_Shield(4,5); |
This will create an instance of SoftwareSerial
named BLE_Shield
. The two parameters are pin numbers, so the BLE shield will use RX and TX lines 4 and 5 respectively.
Add the following line to the end of the setup()
function:
BLE_Shield.begin(9600); // Setup the serial port at 9600 bps. This is the BLE Shield default baud rate. |
This sets the serial communication, or baud rate, which is the speed at which data bits are transmitted. In order for two devices to communicate, they must use the same baud rate. Since the BLE Shield’s default baud rate is 9600, you set the Arduino serial port to match.
Finally, add the following function to the bottom of the sketch:
void loop() // Continuous loop { // See if new position data is available if (BLE_Shield.available()) { myservo.write(BLE_Shield.read()); // Write position to servo } } |
Eventually, your iOS device will be feeding data to the BLE shield. loop()
has one job now: look for new bytes from the BLE shield’s RX line and pass them to the servo.
First, it calls BLE_Shield.available()
to see if any bytes are available. If so, read the available bytes and write them to myServo
. If there is no new data from the BLE Shield, then it loops around and checks again…and again…and again.
Save your Arduino project then click the Upload button to upload your new program to the Arduino board. The Done uploading message should appear at the bottom of the IDE. You’ll see the LED light up and stay lit, letting you know main()
finished.
At this point, your Arduino code is complete and ready for communication with your iOS app via the BLE Shield. You can power down the board by unplugging the USB cable. You won’t need the Arduino IDE from this point on – the board actually saves the last-uploaded sketch to its internal memory. The next time you connect the USB cable, the sketch you just wrote will run automatically without clicking the Upload button from the Arduino IDE!
The next logical step is to get familiar with how the BLE Shield functions; you’ll cover this in the next section.
The Inner Workings of the BLE Shield
The Black Widow BLE Shield from Back Forty is based on Bluegiga’s BLE121LR module which supports Bluetooth Low Energy 4.0. The BLE121LR, with or without the Shield component, is a great module for interfacing with iOS devices. It can be programmed with custom scripts to run without the need for an additional processor.
In this project, you’ll focus on using the BLE Shield as comes out of the box. It’s preprogrammed with a BLE Service and some characteristics geared toward basic communication.
What type of communication do you think will be used between the Arduino board and BLE Shield? Hint: The answer was mentioned earlier in the Serial Communication section.
Here are the preprogrammed Service and Characteristics that come with this specific BLE device as found in the Black Widow BLE Shield – Datasheet:
- Service
Name: Black Widow BLE
UUID: 025A7775-49AA-42BD-BBDB-E2AE77782966 - Characteristic
Name: TX
UUID: F38A2C23-BC54-40FC-BED0-60EDDA139F47
Description: The iOS device sends data to the BLE Shield’s TX characteristic which is then received on the RX pin of the Arduino. The maximum amount of data which can be sent at once is 20 bytes due to BLE121LR restrictions. - Characteristic
Name: RX
UUID: A9CD2F86-8661-4EB1-B132-367A3434BC90
Description: The RX characteristic is used to receive data on the iOS Side. Data written to the BLE Shield’s TX pin will be notified/indicated on the RX characteristic on the iOS device.
Since your project is based on one-way communication from your iOS device to the Arduino board, you’ll only make use of the Black Widow BLE service and the TX characteristic.
Hardware Connections
Now it’s time to work on the hardware connections of the project. Be sure the USB cable is unplugged from the Arduino board before working with the hardware.
To make your life easier, gather the following parts below before you begin:
- Arduino Uno Board
- Black Widow BLE Shield
- Servo
- Three jumper wires
Assemble the BLE Shield onto the Arduino board as shown below:
Be sure to match up the pins before applying any pressure to seat the BLE Shield. Inserting misaligned pins can cause damage to the hardware.
Once you’re done, the entire assembly should look like this:
The servo motor requires three connections: +5v (red), Ground (black) and Position Signal (white). The +5v and Ground connections provide the servo with the power it needs to change and maintain its rotational position. The Position Signal connection is used to set the position of the servo. To prevent possible damage to the servo, ensure you don’t swap any of the connections.
Attach the three wires to the servo motor as shown in the image below:
It’s a good idea to use the same color wires as the servo leads so that you don’t get mixed up as to which wire goes where.
Connect the red wire to the BLE Shield’s 5v pin. Connect the black wire to the GND pin and the white wire to pin 9 as shown below:
Your hardware is connected and ready to go. All that’s left is to finish writing your iOS app to tie it all together!
Fleshing out the iOS App
The app uses a slider to wirelessly control the position of the servo. When you move the slider button up and down, the position data will be sent to the Arduino’s BLE Shield. The Connect/Disconnect icon at the bottom will indicate the Bluetooth connection status.
Open the downloaded starter project in Xcode, plug in your iPhone and build and run your app. The app will open and you will see an image similar to the one below:
The app isn’t quite ready to communication with the Arduino, but that’s where you come in.
Click the Stop button in Xcode.
Starter Project Overview
When the app starts, ViewController
creates an instance of BTDiscovery
to begin searching for BLE devices in range with a specific Service UUID. BTDiscovery
manages the discovery of and connections to Bluetooth devices. It also notifies the app when a Bluetooth device connects or disconnects.
ViewController
has a vertical slider control that sends the slider’s position value to BTService and updates the Bluetooth image with the connection status. BTService handles the communication to the BLE shield module.
Before moving on, open BTService.swift — there are a few important things in this file that help the app communicate with the BLE Shield, so it’s worth taking a minute to review them.
Towards the top of the file you’ll see a couple of UUIDs and one notification name defined as constants with let
.
BLEServiceUUID
represents the 128-bit service UUID of the Arduino’s BLE Shield. You’ll notice that this UUID matches the Black Widow BLE Service UUID listed earlier in the tutorial. Similarly, PositionCharUUID
matches the BLE Shield’s TX UUID. Both hex values must match in order for the app to discover and communicate with the BLE Shield.
Finally, you’ll use BLEServiceChangedStatusNotification
to notify the rest of the app when a peripheral connects or disconnectes from the app. The main view controller of your app uses this value to toggle the connection image on the home screen.
No code needs to be added here, so you can move on. Open ViewController.swift and replace the implementation of sendPosition
with the following:
// Valid position range: 0 to 180 func sendPosition(position: UInt8) { // 1 if !allowTX { return } // 2 // Validate value if position == lastPosition { return } // 3 else if ((position < 0) || (position > 180)) { return } // 4 // Send position to BLE Shield (if service exists and is connected) if let bleService = btDiscoverySharedInstance.bleService { bleService.writePosition(position) lastPosition = position // 5 // Start delay timer allowTX = false if timerTXDelay == nil { timerTXDelay = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("timerTXDelayElapsed"), userInfo: nil, repeats: false) } } } |
This method is called from positionSliderChanged
each time the user moves the slider. Here’s what happens in this method:
- Only continue if no other send occurred in the last 0.1 seconds to avoid flooding the BLE connection with too much data.
- Prevent the same value from being written multiple times. To keep traffic and power use to a minimum, you always want to take advantage of any opportunity to prevent sending duplicate data.
- Make sure that the values being sent are in the correct range. The Arduino’s Servo object accepts values between 0 and 180. If you take a peek at the storyboard file, you will see that the slider’s minimum and maximum values have been set to the same range.
- Ensure that the
BTService
exists and is ready for action, then write the slider value to the position characteristic. - The timer prevents you from flooding the BLE Shield with data. First, you set
allowTX
tofalse
to prevent sending more data; then you set up a timer to fire in 0.1 seconds which will set it back totrue
after the delay.
Now you have to implement the part of BTService
that transmits the data. Open BTService.m and replace the implementation of writePosition
with the following:
func writePosition(position: UInt8) { // See if characteristic has been discovered before writing to it if self.positionCharacteristic == nil { return } // Need a mutable var to pass to writeValue function var positionValue = position let data = NSData(bytes: &positionValue, length: sizeof(UInt8)) self.peripheral?.writeValue(data, forCharacteristic: self.positionCharacteristic, type: CBCharacteristicWriteType.WithResponse) } |
To start, the method will return immediately if the proper characteristic matching the expected UUID hasn’t been discovered yet. If it has, you need to wrap the data — simply the position
value — in an NSData
object. Then, you write the value out to the Core Bluetooth peripheral.
Since your positionCharacteristic
UUID matches the BLE Shield’s TX characteristic, the BLE Shield transmits the data to the RX of the Arduino. The Arduino code written earlier uses this piece of data to set the servo’s position.
Build your app to make sure everything compiles. You app is now complete and ready for testing!
Putting it All Together
The Arduino, BLE Shield, and servo should already be fully assembled as shown in the image below:
Plug the USB cord into the Arduino to supply power. Next make sure your iPhone’s Bluetooth is on and your iPhone is connected to your computer.
Run your app from Xcode; within a couple seconds you should see the app’s Bluetooth icon change from Disconnected to Connected and the BLE Shield’s LED should illuminate. Now move the slider up and down. You should see the servo motor rotate based on the slider movement.
(Here’s a direct link to the QuickTime movie file if you can’t see the above action video.)
Where To Go From Here?
You can download the final project here; it includes both the iOS and the Arduino code.
You’ve seen how simple it is to pass data wirelessly from the iPhone to the Arduino, and then write a sketch on the Arduino to do something with that incoming data. Hopefully this project has spurred you to dream up other projects that use Bluetooth LE and iOS.
For example, you could use this tutorial’s servo motor to automatically unlock the front door of your house. Or, you could create an iOS remote control for your water sprinklers and never forget to water your lawn again!
This project gave you a small taste of what it takes to create your own BLE device. If you’re interested in learning more about this topic, you might enjoy my book Integrating iOS Bluetooth LE with PIC18 Microcontrollers. It gives an in-depth look at creating a BLE device at the microcontroller level.
In addition, the book provides practical lessons on how to program and configure your own services and characteristics for machine control. The main project of the book is based on the iO Xtreme PCB. The book and the iO Xtreme board are available on my website at www.back-40.com.
I hope you enjoyed the tutorial. If you have any questions or comments, please join the discussion in the forums!
Arduino Tutorial: Integrating Bluetooth LE and iOS with Swift is a post from: Ray Wenderlich
The post Arduino Tutorial: Integrating Bluetooth LE and iOS with Swift appeared first on Ray Wenderlich.