How to send data from an Arduino BT or 101 to PC in real-time

5/5 - (18 votes)

How to send data from my Arduino to a computer via Bluetooth in real-time?

In this tutorial, I am going to explain how to stream your measured data in Arduino to receive them in a Linux-based computer like a raspberry PI. Later we can plot the data on real-time I am using KST2.

The problem to solve is simple:

An Arduino connected to some sensors, which streams data continuously to a BLE device (a computer or a Raspberry Pi in this case).

Let’s start!

Arduino Side

On the Arduino, a normal c-code is running to read the data, process them if needed and send them through BLE.

I am using the new Arduino from Intel Curie 101, which I find very powerful and interesting.

For the measurement examples, I am going to use the eHealth sensor board to read values from some attached sensors: an electrocardiogram, temperature, air-flow and skin conductance sensors.

Arduino with the red eHealth board and some sensors attached

The Arduino code is:

#include 

SensorSuit Sensor;

void setup() {
  delay(5000);
    Sensor.initSystem();
    Sensor.initBLE();
  
    
}

void loop() {
  while(Sensor.amIconnected()==0){
    //Waiting for a Master to connect
    }
    Serial.println("Connected to central"); //Serial.println(central.address());//print the central's MAC address:
        
        //Serial.print("I am connected = "); Serial.println(Sensor.amIconnected());
        
        while (Sensor.amIconnected()) {
        delay(100);
      //long currentMillis = millis();
        Sensor.updateSensors();
        Sensor.decodeConfigBLE();
     }

  Serial.println("Disconnected from central ");


}//end loop

//================================================
//!Interrupt Service Routine
//================================================
//Interrupt for Serial incomming bytes
void serialEvent() {

    Sensor.decodeSerialInput();
    
}

You need to add my modified eHealth library: SensorSuitBLE.zip

Unzip this folder and add it to your libraries directory. If you are using windows it should be something similar to ~/documents/Arduino/libraries

Computer Side

On the computer, a script in python is going to read the data coming from the Arduino via bluetooth low energy (BLE).

The laptop is using the internal built-in bluetooth device, but also another external USB devices can be use. For example, when I run this in my Odroid XU4 (a kind of raspery Pi) it needs a bluetooth USB dongle to work.

The python script is writing all the data into a CSV (comma separated values) file, which is plotted in real time using kst. Here I explain how to use kst to plot easily and effective data from a text or csv file.

The Python script uses the BluePy library

##############################################################################
# Connecto to eHealth via BLE
# September 2017
# www.misCircuitos.com Alberto Lopez
##############################################################################

#devices owned
EHEALTH = "84:68:3e:00:19:98"
UUID_SUIT = "19b10010-e8f2-537e-4f6c-d104768a1313"

import csv #handle csv files
from struct import * #conversions
import time #for time delays
import binascii #convert
from bluepy import btle #Bluetooth low energy lib
from datetime import datetime #fortimestamp
import subprocess #to call unix command

class MyDelegate(btle.DefaultDelegate):
def __init__(self):
self.skin = 0
self.temperature = 0
self.heartRate = 0
self.airFlow = 0
btle.DefaultDelegate.__init__(self)

def handleNotification(self, cHandle, data):
#process data...
if(cHandle == 0x0d): #skin conductivity
read = unpack('4B',data) #read blocks of 4 hex character
valor1 = format(read[1],'0b').rjust(8,'0') + format(read[0],'0b').rjust(8,'0')
self.skin = int(valor1[0:16],2)
if(cHandle == 0x010):
read = unpack('4B',data) #read blocks of 4 hex character
valor1 = format(read[1],'0b').rjust(8,'0') + format(read[0],'0b').rjust(8,'0')
self.temperature = int(valor1[0:16],2)
if(cHandle == 0x16):
read = unpack('4B',data) #read blocks of 4 hex character
valor1 = format(read[1],'0b').rjust(8,'0') + format(read[0],'0b').rjust(8,'0')
self.heartRate = int(valor1[0:16],2)
if(cHandle == 0x013): #airflow
t0 = time.time()
read = unpack('4B',data) #read blocks of 4 hex character
valor1 = format(read[1],'0b').rjust(8,'0') + format(read[0],'0b').rjust(8,'0')
self.airFlow = int(valor1[0:16],2)

writeData(self.skin, self.temperature, self.heartRate, self.airFlow)
duration = time.time() - t0 #for debugging purposes
print(duration)

def StartCMD():
#enable the notifications
#ehealth.writeCharacteristic(0x0e,bytes("\x01\x00",'utf-8'),withResponse=True)                      #activate the notif. for skin conductivity
#ehealth.writeCharacteristic(0x11,bytes("\x01\x00",'utf-8'),withResponse=True)                      #activate the notif. for Temperature
ehealth.writeCharacteristic(0x14,bytes("\x01\x00",'utf-8'),withResponse=True) #activate the notif. for Airflow
ehealth.writeCharacteristic(0x17,bytes("\x01\x00",'utf-8'),withResponse=True) #activate the notif. for Heartrate

SuitSensorConfig.write(bytes("\x30",'utf-8'),True)

'''#list of bits for commands:
bit0: skin conductance
bit1: Temperature
bit2: pulse
bit3: oxygen
bit4: Heart Rate
bit5: airFlow
bit6: accelometer

'''
time.sleep(2.0) # wait 1 second
print("Configuration command sent")
return

def writeData(skin_, temperature_, heartRate_,airFlow_):
text = str(datetime.now().strftime("%Y/%m/%d %H:%M:%S.%f")) + "," + str(skin_) + "," + str(temperature_) + "," + str(heartRate_) + "," + str(airFlow_) + "\n"
ehealthFile.write(text)
return

def newFile():
ehealthFile.write("Time,skin,temperature,heartRate,airFlow\n")
return

def askDeviceInfo():
###Generic Information
GenericConstructor = btle.UUID(0x1800)
GenericService = ehealth.getServiceByUUID(GenericConstructor)
DeviceNameCharac = GenericService.getCharacteristics()[0]
ConnectionNCharac = GenericService.getCharacteristics()[1]
return

######## MAIN #######
print("Connecting...")
ehealth = btle.Peripheral(EHEALTH) #,btle.ADDR_TYPE_RANDOM,0) #BT device is hci0

print("connected")
#askDeviceInfo()

with open('Health.csv','w',1) as ehealthFile:
newFile()

###Data from Sensors
DatosConstructor = btle.UUID(UUID_SUIT)
DatosService = ehealth.getServiceByUUID(DatosConstructor)

SuitSensorConfig = DatosService.getCharacteristics()[0]
SuitSensorVal1 = DatosService.getCharacteristics()[1] #skin conductance
SuitSensorVal2 = DatosService.getCharacteristics()[2] #temperature
SuitSensorVal3 = DatosService.getCharacteristics()[3] #heartRate
SuitSensorVal4 = DatosService.getCharacteristics()[4] #airFlow

subprocess.Popen(["kst2", "Health.kst"]) #open the real time plotter

print(str(datetime.now()))

#enable sensors and notifications
ehealth.withDelegate(MyDelegate()) #create a notification object
print("Waiting for notifications")
StartCMD()

while True:
if ehealth.waitForNotifications(1.0):
#handleNotification() calling
continue
eHealth.disconnect()

The python script is calling to run the program kst, which is in charge of plotting the data.

I already save the layout and configuration setting in a file for this specific application (under the file “Health.kst”), you can download this file and use it or create your own configuration file.

This can be made opening first the kst2 program with the:

sudo kst2

and selecting the file you want to plot, in this case “Health.csv”. More info about how to configure kst was explained by me:

How to use kst to plot data in Real-time

Here is how the plotting looks like. Note in this example I had only the heart rate sensor and airflow sensor attached to the board.

Leave a Comment

Your email address will not be published. Required fields are marked *