Remote Thermo Couple Sending Temp to iPhone

Craig Liesinger
4 min readMay 26, 2021

Intro

After my first experiment of using a simple build iPhone app to send info to control an external lamp I wanted to try something with data flowing in the other direction. So I chose to set up a simple circuit with a temperature sensor, and then send this data to a simple iPhone app to display the temperature.

Ingredients

  • Arduino (Genuino) Uno, Microcontroller
  • Red Bear Labs BLE Shield 2.1
  • Breadboard
  • Temperature Sensor (TMP36)
  • Power Source (computer via USB or 9V battery)
  • Jumper Wires
  • iPhone

Set Up The Circuit

Nothing complicated here. The temp sensor has 3 pins: run one to power, one to ground, and one to an analog input port on our Arduino. I used my laptop to power the board for this quick hack, but of course a battery to power the board is also an option.

Program The MicroController

Here is where the learning really started for me on this project. How would I send the data package? How would it be received by the phone and will I need to process it at all? My first thought was ‘I want to read the temperate as a float value (like 24.12 C), so I would capture and pass a float’. Makes sense and is certainly possible but I quickly realized the float was wanting to send a large data packet for this one simple number ,as the float is stored down to many many decimal places.

So I changed my approach for a simpler one. I would capture the temperature value as a float on the Arduino, then convert it to a string with only 2 decimal places and then send this simple 5 character string via bluetooth to the app. (I hard coded ‘5 characters assuming a temp range of 10 C and 99C for this quick experiment project). Code below:

#include 
#include
#include
#include

const int tempPin = A0;

void setup() {
// put your setup code here, to run once:
Serial.begin(9600);

pinMode(tempPin, INPUT);

// Set your BLE Shield name here, max. length 10
ble_set_name("Thermostat");

// Init. and start BLE library.
ble_begin();

}

void loop() {
// put your main code here, to run repeatedly:

if(ble_connected()){
Serial.print(" BLE connected ");
} else {
Serial.print(" [ERROR] BLE NOT connected ");
}
while(ble_connected()){
Serial.print(" BLE is available ");
// Read analog value from temperature sensor
int tempAnalog = analogRead(tempPin);
Serial.println(tempAnalog);
// Map the analog input to the Cecius temperature range per the sensor's data sheet
float tempValue = ((tempAnalog/1024.0) * 5.0 - 0.5) * 100.0;
// Capture the float with only 2 decimals as a string
String tempString = String(tempValue, 2);
// Print to serial for debug check
Serial.println(tempString);
// Create a character array to be filled with temperature string.
char buffer[5];
// Fill up the buffer with the temperature string.
tempString.toCharArray(buffer, 5);
// Send temperature value to BLE to broadcast
for(int x = 0; x < 5; x++) {
ble_write(tempString[x]);
}
// wait one second to pace communication / power saving
delay(1000);
//Send the 'write' actions.
ble_do_events();
}

}

Program The App

Once again, my life is made easy thanks to the Read Bear Labs framework. I initiate a global instance of the framework class (not good coding, but quick and easy for my test here) and fire up the read method on the view load of my main view controller. I also add a variable property to the BLE class called tempValue and initiated it with a value of 0. Within the BLE method

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?)

I capture the updated value received and send a notification to the notification center.

if let str = String(data: characteristic.value!, encoding: String.Encoding.utf8) {
print(str)
tempValue = str
} else {
print("not a valid UTF-8 sequence")
}
NotificationCenter.default.post(name: Notification.Name(rawValue: "refresh"), object: nil, userInfo: nil)

In the main view controller I watch for updates for this notification, and when there is one I pull the BLE class property value of tempValue variable, set that value to the label text and update the view.

import UIKit

let myBLE = BLE()

class ViewController: UIViewController {
@IBOutlet weak var tempValue: UILabel!
var delivTemp: Int = 0

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
myBLE.read()
tempValue.text = "waiting"
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.newTemp(_:)), name: NSNotification.Name(rawValue: "refresh"), object: nil)
}

func newTemp(_ notification: Notification) {
//Check value in log for debuging
print(" value to VC: (myBLE.tempValue)")
tempValue.text = myBLE.tempValue
tempValue.reloadInputViews()
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Result

Power the circuit and fire up the app and voila — room temperature updated every second. Or squeeze the thermocouple in my fingers and watch the temperature rise. :)

--

--

Craig Liesinger

Father, Husband, Tinkerer, Learner, Project Manager, Programmer, Engineer, Expat