mirror of
https://github.com/eclipse/upm.git
synced 2025-03-23 17:00:03 +03:00

Signed-off-by: Andrei Vasiliu <andrei.vasiliu@intel.com> Signed-off-by: Mihai Tudor Panu <mihai.tudor.panu@intel.com>
328 lines
8.2 KiB
C++
328 lines
8.2 KiB
C++
/*
|
|
* Author: William Penner <william.penner@intel.com>
|
|
* Copyright (c) 2014 Intel Corporation.
|
|
*
|
|
* This application code supports the mpl3115a2 digital barometric pressure
|
|
* and temperature sensor from Freescale. The datasheet is available
|
|
* from their website:
|
|
* http://cache.freescale.com/files/sensors/doc/data_sheet/MPL3115A2.pdf
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*/
|
|
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <stdexcept>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "mpl3115a2.h"
|
|
|
|
using namespace upm;
|
|
|
|
MPL3115A2::MPL3115A2 (int bus, int devAddr, uint8_t mode) : m_i2ControlCtx(bus)
|
|
{
|
|
int id;
|
|
|
|
m_name = MPL3115A2_NAME;
|
|
|
|
m_controlAddr = devAddr;
|
|
m_bus = bus;
|
|
|
|
mraa::Result ret = m_i2ControlCtx.address(m_controlAddr);
|
|
if (ret != mraa::SUCCESS) {
|
|
throw std::runtime_error(std::string(__FUNCTION__) +
|
|
": mraa_i2c_address() failed");
|
|
return;
|
|
}
|
|
|
|
setOversampling(mode);
|
|
|
|
id = i2cReadReg_8(MPL3115A2_WHO_AM_I);
|
|
if (id != MPL3115A2_DEVICE_ID) {
|
|
throw std::runtime_error(std::string(__FUNCTION__) +
|
|
": incorrect device id");
|
|
return;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Function to test the device and verify that is appears operational
|
|
* Typically functioning sensors will return "noisy" values and would
|
|
* be expected to change a bit. This fuction will check for this
|
|
* variation.
|
|
*/
|
|
|
|
int
|
|
MPL3115A2::testSensor(void)
|
|
{
|
|
int i, iTries;
|
|
int iError = 0;
|
|
float pressure, temperature;
|
|
float fPMin, fPMax, fTMin, fTMax;
|
|
|
|
fprintf(stdout, "Executing Sensor Test.\n" );
|
|
|
|
pressure = getPressure(true);
|
|
temperature = getTemperature(false);
|
|
fPMin = fPMax = pressure;
|
|
fTMin = fTMax = temperature;
|
|
|
|
iTries = 20;
|
|
do {
|
|
sampleData();
|
|
pressure = getPressure(true);
|
|
temperature = getTemperature(false);
|
|
if (pressure < fPMin) fPMin = pressure;
|
|
if (pressure > fPMax) fPMax = pressure;
|
|
if (temperature < fTMin) fTMin = temperature;
|
|
if (temperature > fTMax) fTMax = temperature;
|
|
}
|
|
while(fPMin == fPMax && fTMin == fTMax && --iTries);
|
|
|
|
if (fPMin == fPMax && fTMin == fTMax) {
|
|
fprintf(stdout, " Warning - sensor values not changing.\n" );
|
|
return -1;
|
|
}
|
|
|
|
fprintf(stdout, " Test complete.\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Function to dump out the i2c register block to the screen
|
|
*/
|
|
|
|
void
|
|
MPL3115A2::dumpSensor(void)
|
|
{
|
|
int i, j, ival;
|
|
|
|
fprintf(stdout, "Dumping i2c block from %s\n", MPL3115A2_NAME);
|
|
for (i=0; i < 256; i+=16) {
|
|
fprintf(stdout, " %02x: ", i);
|
|
for (j=i; j < i+16; j++) {
|
|
fprintf(stdout, "%02x ", i2cReadReg_8(j));
|
|
}
|
|
fprintf(stdout, "\n");
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Function used to soft RESET the MPL3115A2 device to ensure
|
|
* it is in a known state. This function can be used to reset
|
|
* the min/max temperature and pressure values.
|
|
*/
|
|
|
|
int
|
|
MPL3115A2::resetSensor(void)
|
|
{
|
|
fprintf(stdout, "Resetting MPL3115A2 device\n" );
|
|
i2cWriteReg(MPL3115A2_CTRL_REG1, MPL3115A2_CTRL_RESET);
|
|
usleep(50000);
|
|
i2cWriteReg(MPL3115A2_CTRL_REG1, MPL3115A2_CTRL_RESET |
|
|
MPL3115A2_SETOVERSAMPLE(m_oversampling));
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
MPL3115A2::sampleData(void)
|
|
{
|
|
int val;
|
|
mraa::Result ret;
|
|
int tries = 15;
|
|
uint32_t us_delay;
|
|
|
|
// trigger measurement
|
|
ret = i2cWriteReg(MPL3115A2_CTRL_REG1,
|
|
MPL3115A2_CTRL_OST | MPL3115A2_SETOVERSAMPLE(m_oversampling));
|
|
if (mraa::SUCCESS != ret) {
|
|
fprintf(stdout, "Write to trigger measurement failed\n");
|
|
return -1;
|
|
}
|
|
|
|
// Calculate and delay the appopriate time for the measurement
|
|
us_delay = ((1 << m_oversampling) * 4 + 2) * 1000;
|
|
usleep(us_delay);
|
|
|
|
// Loop waiting for the ready bit to become active
|
|
while (tries-- > 0) {
|
|
val = i2cReadReg_8(MPL3115A2_CTRL_REG1);
|
|
|
|
/* wait for data ready, i.e. OST cleared */
|
|
if (!(val & MPL3115A2_CTRL_OST))
|
|
break;
|
|
usleep(20000);
|
|
}
|
|
if (tries < 0) {
|
|
throw std::runtime_error(std::string(__FUNCTION__) +
|
|
": timeout during measurement");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int32_t
|
|
MPL3115A2::getPressureReg(int reg) {
|
|
return ((i2cReadReg_16(reg) << 8)|(uint32_t)i2cReadReg_8(reg+2))*100/64;
|
|
}
|
|
|
|
int32_t
|
|
MPL3115A2::getTempReg(int reg) {
|
|
return (int32_t)((int16_t)i2cReadReg_16(reg)) * 1000 / 256;
|
|
}
|
|
|
|
float
|
|
MPL3115A2::getPressure(int bSampleData) {
|
|
int ret;
|
|
|
|
// Trigger request to make a measurement
|
|
if (bSampleData) {
|
|
ret = sampleData();
|
|
if (ret < 0) {
|
|
fprintf(stdout, "Error sampling pressure\n");
|
|
return -1;
|
|
}
|
|
}
|
|
m_iPressure = getPressureReg(MPL3115A2_OUT_PRESS);
|
|
|
|
return (float)m_iPressure / 100;
|
|
}
|
|
|
|
float
|
|
MPL3115A2::getTemperature(int bSampleData) {
|
|
int ret;
|
|
|
|
// Trigger request to make a measurement
|
|
if (bSampleData) {
|
|
ret = sampleData();
|
|
if (ret < 0) {
|
|
fprintf(stdout, "Error sampling temperature\n");
|
|
return -1;
|
|
}
|
|
}
|
|
m_iTemperature = getTempReg(MPL3115A2_OUT_TEMP);
|
|
|
|
return (float)m_iTemperature / 1000;
|
|
}
|
|
|
|
float
|
|
MPL3115A2::getSealevelPressure(float altitudeMeters) {
|
|
float fPressure = (float)m_iPressure / 100.0;
|
|
return fPressure / pow(1.0-altitudeMeters/44330, 5.255);
|
|
}
|
|
|
|
float
|
|
MPL3115A2::getAltitude (float sealevelPressure) {
|
|
float fPressure = (float)m_iPressure / 100.0;
|
|
return 44330 * (1.0 - pow(fPressure /sealevelPressure,0.1903));
|
|
}
|
|
|
|
void
|
|
MPL3115A2::setOversampling(uint8_t oversampling)
|
|
{
|
|
if (oversampling > MPL3115A2_MAXOVERSAMPLE)
|
|
oversampling = MPL3115A2_MAXOVERSAMPLE;
|
|
m_oversampling = oversampling;
|
|
}
|
|
|
|
uint8_t
|
|
MPL3115A2::getOversampling(void)
|
|
{
|
|
return m_oversampling;
|
|
}
|
|
|
|
float
|
|
MPL3115A2::getTemperatureMax(void)
|
|
{
|
|
return (float)getTempReg(MPL3115A2_T_MAX) / 1000;
|
|
}
|
|
|
|
float
|
|
MPL3115A2::getTemperatureMin(void)
|
|
{
|
|
return (float)getTempReg(MPL3115A2_T_MIN) / 1000;
|
|
}
|
|
|
|
float
|
|
MPL3115A2::getPressureMax(void)
|
|
{
|
|
return (float)getPressureReg(MPL3115A2_P_MAX) / 1000;
|
|
}
|
|
|
|
float
|
|
MPL3115A2::getPressureMin(void)
|
|
{
|
|
return (float)getPressureReg(MPL3115A2_P_MIN) / 1000;
|
|
}
|
|
|
|
float
|
|
MPL3115A2::convertTempCtoF(float fTemp)
|
|
{
|
|
return(fTemp * 9 / 5 + 32);
|
|
}
|
|
|
|
/*
|
|
* This is set for 15degC (Pa = 0.0002961 in Hg)
|
|
*/
|
|
float
|
|
MPL3115A2::convertPaToinHg(float fPressure)
|
|
{
|
|
return(fPressure * 0.0002961);
|
|
}
|
|
|
|
/*
|
|
* Functions to read and write data to the i2c device
|
|
*/
|
|
|
|
mraa::Result
|
|
MPL3115A2::i2cWriteReg (uint8_t reg, uint8_t value) {
|
|
mraa::Result error = mraa::SUCCESS;
|
|
|
|
uint8_t data[2] = { reg, value };
|
|
m_i2ControlCtx.address (m_controlAddr);
|
|
error = m_i2ControlCtx.write (data, 2);
|
|
|
|
if (error != mraa::SUCCESS)
|
|
throw std::runtime_error(std::string(__FUNCTION__) +
|
|
":mraa_i2c_write() failed");
|
|
return error;
|
|
}
|
|
|
|
uint16_t
|
|
MPL3115A2::i2cReadReg_16 (int reg) {
|
|
uint16_t data;
|
|
|
|
m_i2ControlCtx.address(m_controlAddr);
|
|
data = (uint16_t)m_i2ControlCtx.readReg(reg) << 8;
|
|
data |= (uint16_t)m_i2ControlCtx.readReg(reg+1);
|
|
|
|
return data;
|
|
}
|
|
|
|
uint8_t
|
|
MPL3115A2::i2cReadReg_8 (int reg) {
|
|
m_i2ControlCtx.address(m_controlAddr);
|
|
return m_i2ControlCtx.readReg(reg);
|
|
}
|
|
|