Bluetooth low energy offers a great way for iPhone and iPad apps to connect to external devices. Bluetooth low energy is free of the shackles imposed by Apple's MFi program, so anyone can write apps to connect to Bluetooth low energy devices. This blog explores how to connect to the accelerometer on the new TI SensorTag, a Bluetooth low energy peripheral designed to be a hardware and software reference program for the CC2541 chip.

The SensorTag supports a total of six sensors, including a thermometer, barometer, humidity meter, magnetometer and gyroscope. Those sensors are covered in companion blogs. And, just like with Lord of the Rings, there's one blog to control them all. See the blog Controlling the TI SensorTag with techBASIC for an overview, as well as a complete GUI program that shows the readings on all six sensors. It covers the basics of connecting to a Bluetooth low energy device.

While this blog is completely independent of the others, it does assume that you already have some idea how to connect to Bluetooth low energy devices. The basic connection code is presented without further comment. The complete program is a short, simple text-based program that makes it very easy to experiment with the accelerometer. It's presented at the end of the blog. Controlling the TI SensorTag with techBASIC has a more complete program that accesses all six sensors and presents the results in a GUI environment.

What's an Accelerometer?

An accelerometer measures acceleration by detecting the force exerted on a mass, then uses the equation

to find the acceleration. The exact way the force and mass are measured varies a lot from one brand of sensor to another, from measuring the capacitance as the plates making up the capacitor are deformed to looking at the voltage generated by a crystal as it is deformed. The SensorTag uses the KXTJ9 accelerometer from Kionox. It's a three-axis accelerometer with a selectable range of ±2G, ±4G or ±8G. The SensorTag's firmware uses the ±2G setting, exposing 8 bits of the 14-bit resolution of the chip, giving a precision of 0.015625G. If you saw the blog showing the iPhone on a rocket, you know TI has also prepared a special version of the firmware that supports the ±8G range, for a precision of 0.0625G.

Accessing the Accelerometer

Looking at the Generic Attribute Profile (GATT) for the accelerometer, we find three attributes in the accelerometer service.

Like all sensors, the accelerometer draws power. Keeping it off when not in use helps prolong the life of the battery. The 0xAA12 attribute is used to turn the accelerometer on and off. Our simple program just turns it on.

CASE "F000AA12" & servicesHeader

DIM value(1) as INTEGER

value(1) = 1

peripheral.writeCharacteristic(characteristics(i), value, 1)

Pass a 0 instead of a 1 to turn the accelerometer back off.

0xAA11 is used to read the accelerometer. There are two ways to read the acceleration, either reading it when the program wants an acceleration value or asking the accelerometer to notify the program whenever a new sensor reading is available. The first step is to tell the accelerometer which way we want to read values. To receive notifications when a value is available, write a 1 and 0 to the characteristic, then ask it to start sending notifications.

SELECT CASE characteristics(i).uuid

CASE "F000AA11" & servicesHeader

DIM value(2) as INTEGER

value = [0, 1]

peripheral.writeCharacteristic(characteristics(i), value, 0)

peripheral.setNotify(characteristics(i), 1)

Use readCharacteristic to read a single value.

peripheral.readCharacteristic(characteristics(i), 1)

The accelerometer sends samples about once a second unless you tell it otherwise. Use 0xAA13 to set the sample rate. The value is expressed in tens of milliseconds, so passing 100 gives the default sample rate of once per second. Keep in mind that the hardware uses the sample rate as a suggestion, not a firm value! If the time between samples is really important, record the time with the sample value.

Whether you read the data once using readCharacteristic, or ask for notifications with setNotify, the values are always returned using a call to BLECharacteristicInfo.

SUB BLECharacteristicInfo (time AS DOUBLE, peripheral AS BLEPeripheral, characteristic AS BLECharacteristic, kind AS INTEGER, message AS STRING, err AS LONG)

The value itself is returned as three bytes, where each byte is a signed value containing the acceleration along one axis. Naturally enough, the order is x, y and z. Dividing by 64 converts from the range of the byte value, with a range of -128 to 127, to G force, with a range of about -2G to 2G.

Using the Accelerometer

The first step in using any sensor is to calibrate it. There are differences in individual sensors, and converting from a byte value to ±2G by dividing by 64 isn't perfect. After all, we get 128 values to the left of zero, and 127 on the positive side—it can't be exact.

Fortunately, we live on a pretty good calibration device. The surface of the Earth is, by definition, 1G. Lay the accelerometer on the table and run the program. The device may not be perfectly flat, but you can get the overall acceleration this way:

or, in BASIC,

a = SQR(x*x + y*y + z*z)

If you like, collect a few hundred measurements and average the results. They should be 1G. Are they? If not, adjust all of your measurements by an appropriate factor so they are.

If you're really up on your physics, you may realize that the Earth's gravity is not the same strength everywhere. It varies because the Earth is not perfectly round, because it spins, and because of mineral deposits. This variation is smaller than 1%, though, and the precision of the accelerometer is about 1.5% of a gravity, so it's an error we can safely ignore.

Many people are familiar with one of the basic formulas of physics that allows us to calculate the distance something has traveled based on the time and acceleration. Here it is.

To do anything useful, we also need to remember that

The accelerometer gives us acceleration. To keep things simple, let's assume we get back one sample every 0.1 second from sliding the SensorTag across a table, and the samples are 0.1G, 0.2G and 0.3G along the direction we slide the SensorTag. Using this equation, and starting at rest, after one tenth of a second

The factor of 9.81 converts from gravities to meters per second squared.

Continuing on for the next two measurements,

After 0.3 seconds, the SensorTag has traveled about 2.5cm (almost an inch) across the table, and is traveling at a little over a half meter per second.

So now you're equipped to tape a SensorTag to any moving object and track where it is and how fast it's going, right? Ah, if life were only that simple. It works fine in theory, but in practice, an accelerometer is not a good way to track movement. The problem is the errors that crop in. There are two kinds. One is random error, where the measurements are off by a bit, but vary around the correct reading. The other is systematic error, where the values are off in a specific direction. Real measurements have both, and they add up fast. The longer you take measurements, the more error will accumulate. While I personally find the whole subject of error analysis fascinating, that's not what this blog is about, and you may not share my fascination. If you'd like to know more about these errors, start with web searches on systematic error, random error and error analysis. The short version, though, is that calculating velocity and distance using an accelerometer is going to work a lot better for short, rapid movements like a rocket flight than for long, slow ones like tracking the progress of a robot. Error is still an issue for short, rapid movements; too, it's just not as big an issue.

The Source

Here's the source for the accelerometer program. It's pretty simple, writing the values to the console. This is a great program to experiment a bit with the accelerometer. For another, see the source code for the main article, Controlling the TI SensorTag with techBASIC. That article displays all six SensorTag sensors in a nice GUI environment.

Programs in this blog use some features from techBASIC 2.4. We had expected Apple to release it by now. Once they do, it will be a free upgrade to the current version, techBASIC 2.3. techBASIC 2.3 is available now in the App Store.