Creating a Temperature Sensor for iOS Using BLE and Arduino

Today we’ll create something cool, a temperature sensor and an iOS app that connects to it. For this project, we’ll be using an Arduino with a BLE breakout circuit. On the iOS side, we’ll be using CoreBluetooth. Don’t worry if some of these things are unfamiliar to you, I’ll try to give you step-by-step instructions on how to create this. We’ll be sending a string instead of a float with temperature using the BLE, this way, you can reuse the circuit for some other projects you might derive out of this one. In the first part of this post, we’ll talk about the Arduino, and in the second part about the iOS app. So let’s get started.

Arduino

For this project to work, you’ll need an Arduino, there are many versions of it, but I would recommend you get the official starter pack from amazon, check it out here. In this pack, you’ll have pretty much everything you’ll need to start working with it, along with a nice example book. If you’re interested in learning more about Arduino, and how to use it, Arduino for Dummies is a great book to start you off.

Another piece of hardware you’ll need is a BLE breakout circuit by Adafruit. You could use any other circuit, but I used this one, and the Arduino sketch is written for this circuit.

Bluetooth Low Energy

BLE stands for Bluetooth Low Energy, sometimes called Bluetooth Smart, or Bluetooth 4.1. It’s a Bluetooth standard that’s using very low energy to transmit small chunks of data over short distances. It’s very popular in the IoT projects, it allows you to create a local network of connected devices. BLE is very different than your standard Bluetooth, and if you want to learn more about it, I would recommend a book called Getting Started with Bluetooth Low Energy.

BLE is very structured, you have your peripheral (the device), which can contain many services, a service can contain many characteristics. Each of these is identified by a UUID. Characteristics can be notifying. What this means is, every time their value changes, they notify the observer (iOS app, in our case). We’ll use this in our project, we’ll be writing the temperature data in our characteristic, and it will be read automatically by our iOS app.

You can see this depicted in the following diagram:

Arduino Hardware

Let’s hook up the hardware. If you got the same kit as I do, you can go to Adafruit website, and follow the instructions on how to wire the BLE to your Arduino. This is the wiring diagram from their website:

Image source: learn.adafruit.com

You’ll also need a temperature sensor. If you bought the kit I recommended you’ll find the diagram with the example code in the book included in the kit. If you didn’t, that’s ok, just wire the sensor output, to the analog A0 input on the Arduino.

This is my setup:

Now that we have everything wired up, let’s write some Arduino code.

Arduino Software

To write software for Arduino you’ll need to install Arduino IDE, it’s available for Mac, so you can just go to their website, and download it. They have a great guide on their website on how to set up your IDE. Once you installed the IDE, you’ll need to install the Adafruit libraries. Adafruit has a great tutorial on how to do this, so go and check it out.

Now we have the hardware wired up, and all the libraries we need. The only thing that’s left is to write some code and upload it to our Arduino board. The code is not that long, so I’ll just show the whole source file here:

In this code, we’re handling two things. BLE breakout circuit and the temperature sensor. Let’s go over the BLE code first.

At the top of the class, we create an instance of the BLE UART with the corresponding pins. In the setup method, we set the device name, and start our BLE chip. On Arduino, the setup method is executed once when the Arduino is started, and the loop method is executed constantly. So all our processing is done within the loop method. In this method, we get the current state of the BLE, and if it’s connected we send our temperature data. We can only send 20 bytes at a time, and once we get our temperature data (formatted as a string), we write it into our object. This will be our notifying RX characteristic that our iOS app will read from.

Our temperature sensor is connected to the analog A0 input, and since we’ll be sampling the data at a very high frequency we need to smooth out the data, in order to prevent spiking. To smooth the data we’ll be using the ‘averageValue’ function. This function will take the last 50 measurements and give you an average value. We’ll be sampling the data many times a second, so this will give us a smooth sample. Once we get the smoothed out data, we need to convert the raw sensor value to the actual temperature. We’ll do this in the ‘temperature’ method. This method will take the sensor input value, convert it to the voltage, and then into the temperature. This string is what we’re writing into our BLE RX characteristic.

That’s pretty much it on the Arduino side, we have a piece of hardware that’ s transmitting sensor data over BLE. The only thing left to do is to read that data in the iOS app.

iOS Project

Once you create a new project got to your project capabilities tab, enable ‘Background Modes’ and select ‘Uses Bluetooth LE accessories’ in order for this to work, like so:

BLEManager

Now we’re ready to start coding. We’ll only need one class to hook everything up. We’ll call this class ‘BLEManager’, and it will be around 200 lines of code. That’s all we need. Amazing, right 🙂 Obviously we’ll be using the Core Bluetooth, so we need to import that.

This is the core of the class:

The main method here is ‘startScanning’. We call this method right from our constructor. After we do some sanity checks, we start scanning for peripherals that have a service with a specific UUID. That would be our temperature service.

Once we start scanning for services, we’ll wait for our callback from the central manager. Here are the delegate methods that we’ll implement:

In the ‘didDiscover’ callback we connect to the discovered peripheral. It’s important to note here that we need to keep a strong reference to the peripheral we’re trying to connect to (connectingPeripheral property) since it’s not retained. And in the ‘didConnect’ delegate callback we discover available services for our TemperatureService, we’ll set our peripheral delegate here, so we can read data from our RX characteristic. In the ‘centralManagerDidUpdateState’ we’re starting a scan if we started a scan while the Bluetooth was powered off. Also, if we power the Bluetooth off we cancel the peripheral connection and raise the flag to start scanning when the device powers back up. This method will get called when you power off the Bluetooth on your device, or on the Arduino.

We used central manager delegate to start the service discovery, we’ll use the peripheral delegate callbacks to discover our characteristic, and read data from it. Here are the callbacks that we’ll implement:

When the peripheral delegate get’s called with the discovered services, we’ll filter the array to find our temperature service, and then we’ll start the characteristics discovery for our RX characteristic. When the characteristics are discovered, we’ll set the notify value to true for the RX characteristic. This way we’ll get notified every time Arduino writes something into the RX characteristic.

Now every time the characteristic updates, ‘didUpdateValueFor’ will get called. We’ll read the data from the .value property, and convert it into a string. The last thing left to do is to inform the delegate with the temperature string, and that’s it.

View Controller

We’ll keep the view controller simple, just a label with a temperature value. This is the whole view controller:

In the ‘viewWillAppear’ we add the view controller as a delegate, and in the ‘viewDidDisappear’ we remove the view controller as the delegate. In the delegate callbacks, we change the colour of the temperature label. Red if Arduino is not connected, and black when it’s connected. And, of course, in the ‘receivedDataString’ we get our temperature value, so we simply update the label with the new value.

This is how the view looks when everything is hooked up:

If the Bluetooth is disconnected, the label turns red, like so:

Conclusion

In this article, we saw how to hook up an Arduino with your app. We have a temperature sensor on our Arduino board, but we can easily connect any other sensor to it. With the IoT now becoming a thing, you can hook up a bunch of sensors, and automate your home, for example. Maybe in one of the future posts, we’ll see how to establish a two-way communication between Arduino and iOS, so you can control physical devices with your phone. This was a fun little project that you can actually use every day to measure the room temperature (I’ll keep mine in the living room 🙂 ).

You can find all the code (iOS project and Arduino sketch) on my GitHub account. I hope you’ll find this project useful and fun.

Have a nice day 🙂

Dejan.

More resources

0

2 thoughts on “Creating a Temperature Sensor for iOS Using BLE and Arduino

  1. mamaro7

    how would you add other characteristics ? like if we wanted to add more sensors that use the i2c serial ports on the arduino how do we differentiate between each sensors data while sending to the app. and how would you make more views to display each sensors data on the app.. sorry if this is too many questions I’m just trying to make a app for my plants health.

    Reply
    1. Dejan Agostini Post author

      If you’re using the same Adafruit BLE breakout circuit as me then you can’t add new characteristics. You only get the TX and RX characteristics. So, if you want to pass data from multiple sensors you would have to send them all using the same characteristic. You can separate the data with a delimiter, for example, if you wanted to send a temperature and a speed, you could format your string like this “23.3|55.3” and in the app you would tokenise the string into an array of doubles, you know the first value is the temperature, and the second is the speed.

      About making more views. I assume you want to create another view controller (let’s say, to display the speed information from the example above), there are many ways of doing this. Take a look at my other post about passing data to your Apple Watch (http://agostini.tech/2017/02/27/sending-data-from-your-app-to-apple-watch-using-wcsession/), and let me know if it helps to make things a bit clearer for you.

      Reply

Leave a Reply