Quantcast
Channel: The Raspberry Pi Hobbyist
Viewing all articles
Browse latest Browse all 60

Using the MPL115A2 to read Temperature and Barometric Pressure

$
0
0
This post is a continuation of the series on my weather station system.

My weather station uses the MPL115A2, available from Adafruit.  It is an inexpensive sensor for measuring temperature and barometric pressure.  It is only moderately accurate - the MPL3115A2, which only slightly more expensive, would probably have been a better choice.  Both sensors are interfaced using an I2C bus and are fairly simple to use.

In order to compute the correct pressure, several coefficient values must be read from the device first.  These coefficients are unique to each device and provide the calibration necessary to arrive at an accurate reading.  Since they don't change, they only need to be read once.

After reading the coefficients, the data capture and conversion are started by writing a zero to register address 0x12.  The program must then pause briefly to allow the conversion to complete.  The results are stored in the device registers and are read with the standard I2C commands.  The temperature value is taken directly from the register values, with some simple adjustments to get it to degrees Celsius.  The pressure is then computed by a formula that applies the coefficients read earlier as well as the temperature.  The value is in kilo Pascals.  For use by an American like myself, these are finally converted to degrees Fahrenheit and inches of Mercury.

Below is an example, in C, of the code similar to what I use.

/*
example to test mpl115a2 (temp/baro sensor) on i2c
ted.b.hale@gmail.com
*/

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>


int main(int argc, char *argv[])
{
int i, n, fd;
// command string to get coefficients
unsigned char coef_request[3] = {3, 4, 8};
// command string to request conversion
unsigned char conv_request[3] = {0, 0x12, 0};
// variables for the final results
float baro, celsius, farenheit;

// variables to hold the integer values of coefficients
int16_t a0coeff;
int16_t b1coeff;
int16_t b2coeff;
int16_t c12coeff;
// variables to hold the floating point coefficients
float a0;
float b1;
float b2;
float c12;
// some intermediate values
int pressure, temp;
float pressureComp;

// open a file descriptor to the device on the I2C bus
fd = wiringPiI2CSetup(0x60); // 0x60 is bus address of mpl115a2
if (fd==-1)
{
printf("wiringPiI2CSetup failed\n");
return 0;
}

// get the coefficients. This only needs to be done once.
// Note on C language: the << and >> operators perform bit shifting
a0coeff = (( (uint16_t) wiringPiI2CReadReg8(fd,4) << 8) | wiringPiI2CReadReg8(fd,5));
b1coeff = (( (uint16_t) wiringPiI2CReadReg8(fd,6) << 8) | wiringPiI2CReadReg8(fd,7));
b2coeff = (( (uint16_t) wiringPiI2CReadReg8(fd,8) << 8) | wiringPiI2CReadReg8(fd,9));
c12coeff = (( (uint16_t) (wiringPiI2CReadReg8(fd,10) << 8) | wiringPiI2CReadReg8(fd,11))) >> 2;
printf("%d %d %d %d\n",a0coeff,b1coeff,b2coeff,c12coeff);
// convert coefficients to floating point
a0 = (float)a0coeff / 8;
b1 = (float)b1coeff / 8192;
b2 = (float)b2coeff / 16384;
c12 = (float)c12coeff;
c12 /= 4194304.0;
printf("%f %f %f %f\n\n",a0,b1,b2,c12);

// start conversion and wait a tiny bit
wiringPiI2CWriteReg8(fd,0x12,0);
delay(5);

// get the results by reading the device registers
pressure = (( (uint16_t) wiringPiI2CReadReg8(fd,0) << 8) | wiringPiI2CReadReg8(fd,1)) >> 6;
temp = (( (uint16_t) wiringPiI2CReadReg8(fd,2) << 8) | wiringPiI2CReadReg8(fd,3)) >> 6;

// compute temperature compensation for pressure
pressureComp = a0 + (b1 + c12 * temp ) * pressure + b2 * temp;

// get the pressure in kiloPascals
baro = ((65.0F / 1023.0F) * pressureComp) + 50.0F; // kPa
// get the temperature in celsius degrees
celsius = ((float) temp - 498.0F) / -5.35F +25.0F; // C

// convert kilo-Pascals to inches of mercury
baro = baro * 0.295299830714;
// convert Celsius to Farenheit
farenheit = (celsius * 1.8) + 32.0;

//show the results
printf("%f %f\n\n",baro,farenheit);

return 0;
}

The device comes with a 6x1 header which allows it to be mounted simply on a circuit board.  I mounted it directly on the interface board that I built for the weather station.  This is in a weatherproof enclosure, but that should have negligible effect on the reading of  pressure since the enclosure is not completely air-tight.  This will, however, affect temperature reading.  Therefore, while I do record the temperature value, it is not the primary source for temperature that my weather station uses.  For that I use the AM2315 sensor, which is described in my previous post.

Viewing all articles
Browse latest Browse all 60

Trending Articles