Connecting to Gauges with Bluetooth

20 March, 2012

Over the past few days I’ve worked on connecting Gauges to my computer over Bluetooth. I have the physical gauges attached to an Arduino and a breadboard, and I am using a Sparkfun BlueSmirf Silver to receive streaming data from my laptop.

I wrote a Python script using the PyBlueZ stack to connect to the Bluesmirf. I had tried using PySerial, a great package, to write directly to the symbolic /dev/rfcomm0 representing serial bluetooth devices in Linux, but the connection had problems. The problems I thought I could avoid by switching to PyBlueZ popped up again, and I am still hunting for a solution.

When I start the Python script, which I call “gauges-daemon” since eventually it will run as a Linux daemon, or background task, the connection opens fine and the gauges respond. However, after a certain period of activity the script suddenly encounters BluetoothError #11, “Resource Temporaily Unavailable.” To counter this error I thought I could have the script re-open the connection, but then I get error #16, “Device or Resource Busy”.

I did some permuting and found that I can start the script, wait for it to fail, and then re-start the BlueSmirf. This allows the script to reconnect. The evidence seems to suggest that the problem is with the BlueSmirf, though I have pored over the datasheet (PDF) and found no mention about necessary steps to keep connections alive.

EDIT: The problem was a buffer overflow on the PC. I was sending Bluetooth messages to the Gauges, which would respond with status text. Because the Python script never read the port for incoming messages, these incoming packets collected in the Bluetooth serial buffer and everything halted until the buffer was cleared.

I fixed the Python script to represent the necessary changes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import psutil
import serial
import string
import time
import bluetooth

sampleTime = 1
numSamples = 5
lastTemp = 0

TEMP_CHAR = 't'
USAGE_CHAR = 'u'
SENSOR_NAME = 'TC0D'

filename = '/sys/bus/platform/devices/applesmc.768/temp2_input'

def parseSensorsOutputLinux(output):
return int(round(float(output) / 1000))

def connect():
while(True):
try:
gaugeSocket = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
gaugeSocket.connect(('00:06:66:42:22:96', 1))
break;
except bluetooth.btcommon.BluetoothError as error:
gaugeSocket.close()
print "Could not connect: ", error, "; Retrying in 10s..."
time.sleep(10)
return gaugeSocket;

gaugeSocket = connect()
while(True):
usage = psutil.cpu_percent(interval=sampleTime)
sensorFile = open(filename)
temp = parseSensorsOutputLinux(sensorFile.read())
try:
gaugeSocket.send(USAGE_CHAR)
gaugeSocket.send(chr(int(usage)))
#print("Wrote usage: " + str(int(usage)))

gaugeSocket.send(TEMP_CHAR)
gaugeSocket.send(chr(temp))
print gaugeSocket.recv(1024)
#print("Wrote temp: " + str(temp))
except bluetooth.btcommon.BluetoothError as error:
print "Caught BluetoothError: ", error
time.sleep(5)
gaugeSocket = connect()
pass

gaugeSocket.close()