Your very own IoT: Digging deep on sensors - Embedded.com

Your very own IoT: Digging deep on sensors

Welcome back to my CC3200 series!

If you haven't read three of the previous posts on the TI LaunchPad hardware and the Energia development environment, I suggest you do so now. We also talked about WiFi and made a small program that allows you to connect your board to home network, including a few adjustments to core WiFi library. Today we will make a small break from connectivity and talk about sensors in general, and those that come bundled with CC3200 LaunchPad in particular. I can easily admit that sensors and data acquisition and processing are two of my favorite subjects, so this post is extra fun for me to write.

Sensors come in many shapes and flavors. Some can be extremely simple – nothing more than two wires that can detect submersion in water (since any but distilled water is conductive), and some can be extremely complicated – like image sensors that can capture photons in quantum wells and create digital pictures. The most common sensors I seem to encounter over and over in hobbyist world are members of three big families: image sensors, inertial sensors, and environmental sensors.

Image sensors are quite self-explanatory – as their name suggests they capture stills or video. From the other two: inertial sensors include accelerometers, gyroscopes, tilt sensors, and magnetic flux sensors (aka compasses). Environmental sensors include temperature, humidity, barometric pressure, HAL effect, and various gas sensors.

I suppose it is therefore not surprising that our LaunchPad includes one representative of each from inertial and environmental families (including an image sensor would tremendously affect the cost – these are very expensive). To be precise – LaunchPad contains a tri-axial accelerometer and a thermopile temperature sensor.  (After reading the datasheet for the accelerometer, you will discover that it contains a temperature sensor of its own as well!)

To communicate with a sensor, you must first figure out the way it is connected to your board. Some sensors can be connected in more than one way, so be careful! Here are the most common ways a sensor can be connected (I will try to write them in decreasing order of likelihood, although first few ways are fairly equivalent).

  1. I2C (pronounced “eye-squared-see”), is also known as two-wire connection – so called because it only requires two extra wires to connect a device. Sensors connected this way require total of four pins – VCC, GND, SDA, SCL. These are, respectively, power line, ground line, data line, and clock line. The advantage of this type of connection is that it allows multiple devices connected to a bus, each device (sensor – in our case) having its own address by which it can be reached.
  1. ADC direct – this means our sensor is giving out straightforward analog values which we can easily pick up and read via analog-to-digital converter pin (ADC, for short). This kind of sensor would present VCC, GND, DATA pins. Readout is very easy technically, but can be tricky in terms of timing – not all the analog sensors have their data ready at all times. It is (as always) important to pay attention to the datasheet.
  1. 1-Wire (pronounced “one-wire”) connection – is an interesting variation somewhat similar to I2C, but with a twist. It only requires two pins to operate, GND and DATA. A sensor that communicates via 1-wire needs to have a small capacitor inside to store enough power to keep it alive when no data is transmitted over the bus.
  1. SPI – As this is the most advanced serial protocol of all the above, it is rarely found in small sensors and more commonly found in more complicated components like WiFi, BT, memory modules, etc. The connection requires six pins altogether – VCC,GND,MOSI,MISO,SCLK,CS.

The communication is full duplex – MOSI means Master Out Slave In, MISO means Master In Slave Out, This way master and slave can send messages roughly at the same time. CS is a Chip Select pin — since more than one slave can be attached to a single master, this is the way the master can request slave's attention. For each slave connected to SPI bus, the master needs to dedicate on CS line, so having multiple devices consumes more physical pins.

Luckily for us – our LaunchPad board has only I2C sensors on it, this will make our life a little easier.

But before we dive into the fine details of reaching out to our sensors, let's say a few words about the two specimens we will be dealing with.

What is a Thermopile-based temperature sensor? A thermopile is an array of thermocouples – elements that react to temperature difference by producing electrical current. Connecting multiple thermocouples (usually in a series) we can create a cascade to generate a more meaningful measurement than from a single thermocouple. This is what thermopile is all about — an array of thermocouples connected as a cascade and creating a single heat sensing pixel. It has the big advantage of sensing heat from a distance, so no physical contact is required with the target surface to measure the temperature. A thermopile-based temperature sensor enables remote temperature measurement of an object. It does so by collecting emitted infrared energy of an object, and then comparing the measurement to a baseline temperature measured on the sensor (remember – Thermopile measures CHANGES in temperature, not temperature itself). In a simplified way we can think about the measurement as an operation of adding the measured difference to the baseline, and this gives us the temperature of the remote object.

However, measuring temperature is a surprisingly tricky business, but much more so when we are talking remote measurement. The remote measurement is affected by distance from object and the material from which it is made, which requires a calibration values that would best fit the expected use case. We end up with a rather complicated formula.

What is an accelerometer? An accelerometer is a device that measures acceleration, usually by means of internal changes in capacitance. Our sensor is tri-axial, which means it measures acceleration along three orthogonal axes, namely X, Y, and Z. Why is it good for us? Let's remember a tiny bit of high school physics: acceleration equals to sum of forces acting on an object divided by the mass of the object. In other words – knowing the acceleration equals to knowing the acting forces. Knowing the forces in all three dimensions we can faithfully reconstruct the forces acting on our sensors at any given time. One other fringe benefit is the fact that one force always acts on our sensor, and that is the gravity – directed straight down along Z axis, measuring 9.8 meters per second squared. Finding out where is the gravity pointing for our sensor equals to finding out which direction is down, or in more exciting words – finding our sensor's orientation in 3D space!

Now to the practical part – two paths lie in from of us: an easy path – opening examples for each of those sensors bundled together with Energia, or a fun path – building the program ourselves.

You have guessed correctly – we will choose the fun path.

Next page >>

As mentioned before – these are I2C sensors, a library that encapsulates access to I2C bus is called and it is borrowed from Arduino environment.

General scheme of communication over I2C is always the same:

  • send address (to reach a specific slave)
  • send data (to give instruction change register value)
  • send address (again – to reach specific slave)
  • get data (to request data from a slave)

Now that we understand those two, let’s talk business.

Our board has a Texas Instruments TMP006 IR Thermopile sensor, and Bosh BMA222 Tri-Axis accelerometer.

Both are connected to I2C bus.

BMA222 responds to I2C address 0x18 . By default BMA222 is configured to measure accelerations of plus or minus 2Gs (roughly ±19.6 [ms2]) – this is the most precise mode, so we will keep it this way. To read the values off of the chip we need to query three registers – each responsible for a different axis. Register 0x3 gives us the X axis value, register 0x5 gives us Y and 0x7 gives us Z. The binary registers we read need to be translated into physical acceleration values, and a brief look at the datasheet tells us that precision for our mode of operation is 15.6 mili-G per LSB, or in human words – each value we read from I2C needs to be multiplied by 0.0156 to get the G values, or 0.15288 to get meters per second squared.

Here is a sample code to get acceleration measurements: 

#define ACC_X 0x3#define ACC_Y 0x5#define ACC_Z 0x7#define ACC_ADDR 0x18#define BIT2G 0.0156ffloat x = 0.0f;float y = 0.0f;float z = 0.0f;
Wire.beginTransmission(ACC_ADDR);Wire.write(ACC_X);Wire.endTransmission();Wire.requestFrom(ACC_ADDR, 1, false);x = BIT2G * (float)(int8_t)Wire.read();
Wire.beginTransmission(ACC_ADDR);Wire.write(ACC_Y);Wire.endTransmission();Wire.requestFrom(ACC_ADDR, 1, false);y = BIT2G * (float)(int8_t)Wire.read();
Wire.beginTransmission(ACC_ADDR);Wire.write(ACC_Z);Wire.endTransmission();Wire.requestFrom(ACC_ADDR, 1, false);z = BIT2G * (float)(int8_t)Wire.read();

By its nature, an accelerometer is a “jumpy” sensor, so reading and using the values immediately will introduce some level of jitter and randomness into your data. Therefore a small bit of extra processing one might wish to do on those values is smoothing. Simplest smoothing, also known as low-pass-filter can look like this:

Xn=*Xmeasured+(1-)*Xn-1:=0...1 

meaning that each step contributes only part of the innovation, and the other part is taken from historical values. This method prevents large sudden spikes from having a strong effect on your measurement.

TMP006 responds to I2C address 0x41 and has two main registers – register 0 which is 16 bit wide and holds the Voltage measured by thermopile in units of 156.25 nano volts per LSB, and register 1 which is 14 bits wide and holds the die temperature

Looking at a data sheet we get this rather unfriendly list of formulae:

TObj=4TDie4+(f(VObj)S)
where
VObj=Voltage read from register 0
S=S0*[1+a1(TDie-TRef)+a2(TDie-TRef)2]
TRef=298.15K(temperature in Kelvin)
TDie=Die temperature, as read from register 1
f(VObj)=(VObj-VOS)+c2(VObj-VOS)2
VOS=b0+b1(TDie-TRef)+b2(TDie-TRef)2
S0= sensitivity factor, should be found by process of calibration. Here we will use 610-14
a1=1.7510-3
a2=-1.67810-5
b0=-2.9410-5
b1=-5.710-7
b2=4.6310-9
c2=13.4

…yes, it will be on the final exam!

In other words – we read two registers, plug the values into the equations and end up with temperature of the remote object.

Sample code for this would look something like this (I will trust the reader to be able to implement conversion function based on the above formulae, as it will take too much space to place here):

#define TMP_ADDR 0x41#define CONF_REG 0x02#define VOBJ_REG 0x0#define TDIE_REG 0x1#define RAW2CELSIUS (0.03125f)#define RAW2MICROVOLTS (0.15625f)
// configure the sensorWire.beginTransmission(TMP_ADDR);Wire.write(0x02); //configuration registerWire.write(0x74); //=01110100b:            // 0 - normal operation,            // 111 - continuous op,            // 010 - 1 conversion/sec, average of 4 samples            // 0 - data ready pin disabledWire.write(0x0);  // unused portionWire.endTransmission();while(true) { int16_t die_raw = 0; int16_t obj_raw = 0; float die, obj; // read die temperature Wire.beginTransmission(TMP_ADDR); Wire.write(TDIE_REG); Wire.endTransmission(); Wire.requestFrom(TMP_ADDR, 2, false); die_raw = Wire.read(); die_raw <<= 8; die_raw |= Wire.read(); die_raw >>= 2; die = RAW2CELSIUS * (float)die_raw ; // read remote object IR measurement Wire.beginTransmission(TMP_ADDR); Wire.write(VOBJ_REG); Wire.endTransmission(); Wire.requestFrom(TMP_ADDR, 2, false); obj_raw = Wire.read(); obj_raw <<= 8; obj_raw |= Wire.read(); obj = RAW2MICROVOLTS * (float)obj_raw; Serial.println(convert_to_temp(die,obj)); Delay(1000);} 

If all the steps were done correctly – at the end of this you will have a fairly good approximation of both ambient temperature (read on the die) and temperature of a remote object (a finger, for example) held at about half centimeter distance from the sensor.

I hope you will find this helpful, and would love to hear your personal results and questions in the comments.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.