diff --git a/examples/c++/CMakeLists.txt b/examples/c++/CMakeLists.txt index 55dcb21f..cef8d08a 100644 --- a/examples/c++/CMakeLists.txt +++ b/examples/c++/CMakeLists.txt @@ -268,6 +268,7 @@ add_example (bmp280) add_example (bno055) add_example (l3gd20) add_example (bmx055) +add_example (ms5611) # These are special cases where you specify example binary, source file and module(s) include_directories (${PROJECT_SOURCE_DIR}/src) diff --git a/examples/c++/ms5611.cxx b/examples/c++/ms5611.cxx new file mode 100644 index 00000000..f3622d49 --- /dev/null +++ b/examples/c++/ms5611.cxx @@ -0,0 +1,63 @@ +/* + * Author: Henry Bruce + * Copyright (c) 2016 Intel Corporation. + * + * 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 +#include +#include +#include "ms5611.hpp" + + +static int is_running = 0; + +void +sig_handler(int signo) +{ + printf("got signal\n"); + if (signo == SIGINT) { + is_running = 1; + } +} + +//! [Interesting] +int +main(int argc, char **argv) +{ + upm::MS5611* sensor = new upm::MS5611(0); + signal(SIGINT, sig_handler); + + while (!is_running) { + int value = sensor->getTemperatureCelsius(); + std::cout << "Temperature = " << value << "C" << std::endl; + value = sensor->getPressurePa(); + std::cout << "Pressure = " << value << "Pa" << std::endl; + sleep(1); + } + + std::cout << "exiting application" << std::endl; + + delete sensor; + + return 0; +} +//! [Interesting] diff --git a/examples/javascript/ms5611.js b/examples/javascript/ms5611.js new file mode 100644 index 00000000..36756659 --- /dev/null +++ b/examples/javascript/ms5611.js @@ -0,0 +1,50 @@ +/*jslint node:true, vars:true, bitwise:true, unparam:true */ +/*jshint unused:true */ + +/* + * Author: Henry Bruce + * Copyright (c) 2016 Intel Corporation. + * + * 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. + */ + +var factory = require('jsupm_ms5611'); + +// Instantiate a MS5611 instance using default i2c bus and address +var sensor = new factory.MS5611(); + +// now output data every 250 milliseconds +setInterval(function() +{ + var temperature = sensor.getTemperatureCelsius(); + var pressure = sensor.getPressurePa(); + console.log("Temperature: " + temperature + " C"); + console.log("Pressure: " + pressure + " Pa"); +}, 250); + +// exit on ^C +process.on('SIGINT', function() +{ + sensor = null; + sensorObj.cleanUp(); + sensorObj = null; + console.log("Exiting."); + process.exit(0); +}); diff --git a/src/ms5611/CMakeLists.txt b/src/ms5611/CMakeLists.txt new file mode 100644 index 00000000..1de88755 --- /dev/null +++ b/src/ms5611/CMakeLists.txt @@ -0,0 +1,6 @@ +include_directories(..) +set (libname "ms5611") +set (libdescription “Pressure and temperature sensor”) +set (module_src ${libname}.cxx) +set (module_hpp ${libname}.hpp) +upm_module_init() diff --git a/src/ms5611/javaupm_ms5611.i b/src/ms5611/javaupm_ms5611.i new file mode 100644 index 00000000..fcfb434e --- /dev/null +++ b/src/ms5611/javaupm_ms5611.i @@ -0,0 +1,8 @@ +%module javaupm_ms5611 +%include "../upm.i" + +%{ + #include "ms5611.hpp" +%} + +%include "ms5611.hpp" diff --git a/src/ms5611/jsupm_ms5611.i b/src/ms5611/jsupm_ms5611.i new file mode 100644 index 00000000..529dee29 --- /dev/null +++ b/src/ms5611/jsupm_ms5611.i @@ -0,0 +1,8 @@ +%module jsupm_ms5611 +%include "../upm.i" + +%{ + #include "ms5611.hpp" +%} + +%include "ms5611.hpp" diff --git a/src/ms5611/ms5611.cxx b/src/ms5611/ms5611.cxx new file mode 100644 index 00000000..2883f7a6 --- /dev/null +++ b/src/ms5611/ms5611.cxx @@ -0,0 +1,215 @@ +/* + * Author: Henry Bruce + * Copyright (c) 2016 Intel Corporation. + * + * 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 +#include +#include +#include +#include "ms5611.hpp" + + +// Used to prevent silent failure in mraa_i2c_write() +// Value come from I2C_SMBUS_I2C_BLOCK_MAX in i2c driver +#define MAX_I2C_WRITE_SIZE 32 + +#define MS5611_CMD_ADC_READ (0x00) +#define MS5611_CMD_RESET (0x1E) +#define MS5611_CMD_CONV_D1 (0x40) +#define MS5611_CMD_CONV_D2 (0x50) +#define MS5611_CMD_READ_PROM (0xA0) + +#define MS5611_OSR_ULTRA_LOW_POWER 0x00 +#define MS5611_OSR_LOW_POWER 0x02 +#define MS5611_OSR_STANDARD 0x04 +#define MS5611_OSR_HIGH_RES 0x06 +#define MS5611_OSR_ULTRA_HIGH_RES 0x08 + +#define MS5611_PROM_SIZE 8 + + +using namespace upm; + + +MS5611::MS5611(int i2cBus, int address) +{ + status = mraa::ERROR_INVALID_RESOURCE; + i2c = new mraa::I2c(2); + this->address = address; + i2c->address(address); + prom = new uint16_t[MS5611_PROM_SIZE]; + status = i2c->writeByte(MS5611_CMD_RESET); + if (status != mraa::SUCCESS) + UPM_THROW("Reset failed."); + delayms(5); + for (int i = 0; i < MS5611_PROM_SIZE; ++i) { + uint8_t buf[2]; + int bytesRead = i2c->readBytesReg(MS5611_CMD_READ_PROM + 2*i, buf, 2); + if (bytesRead != 2) + UPM_THROW("PROM address failed."); + prom[i] = buf[0] << 8; + prom[i] |= buf[1]; + // printf("Read PROM entry %d = %04x\n", i, prom[i]); + } + + // printf("CRC = %X\n", promCrc4()); + if (promCrc4() != (prom[7] & 0x000F)) + UPM_THROW("PROM checksum error."); + setOverSampling(ULTRA_HIGH_RES); +} + + +MS5611::~MS5611() +{ + delete[] prom; + delete i2c; +} + + +int MS5611::promCrc4() { + unsigned int n_rem; + unsigned int crc_read; + unsigned char n_bit; + n_rem = 0x00; + crc_read = prom[7]; + prom[7]=(0xFF00 & (prom[7])); + for (int cnt = 0; cnt < 16; cnt++) { + if (cnt%2 == 1) { + n_rem ^= (unsigned short) ((prom[cnt>>1]) & 0x00FF); + } else { + n_rem ^= (unsigned short) (prom[cnt>>1]>>8); + } + for (n_bit = 8; n_bit > 0; n_bit--) { + if (n_rem & (0x8000)) { + n_rem = (n_rem << 1) ^ 0x3000; + } else { + n_rem = (n_rem << 1); + } + } + } + n_rem= (0x000F & (n_rem >> 12)); + prom[7]=crc_read; + return (n_rem ^ 0x0); +} + + +// Set oversampling value +void MS5611::setOverSampling(OsrMode osrMode) +{ + switch (osrMode) + { + case ULTRA_LOW_POWER: + osr = MS5611_OSR_ULTRA_LOW_POWER; + samplePeriod = 1; + break; + case LOW_POWER: + osr = MS5611_OSR_LOW_POWER; + samplePeriod = 2; + break; + case STANDARD: + osr = MS5611_OSR_STANDARD; + samplePeriod = 3; + break; + case HIGH_RES: + osr = MS5611_OSR_HIGH_RES; + samplePeriod = 5; + break; + case ULTRA_HIGH_RES: + osr = MS5611_OSR_ULTRA_HIGH_RES; + samplePeriod = 10; + break; + } +} + + +void MS5611::delayms(int millisecs) +{ + struct timespec sleepTime, rem; + uint64_t nanosecs = 1000ULL * millisecs; + sleepTime.tv_sec = millisecs / 1000; + sleepTime.tv_nsec = (millisecs % 1000) * 1000000; + while ((nanosleep( &sleepTime, &sleepTime ) != 0 ) && ( errno == EINTR ) ); +} + +uint32_t MS5611::readADC(int adcReg) +{ + uint32_t value; + uint8_t buf[3]; + i2c->address(address); + status = i2c->writeByte(adcReg + osr); + if (status != mraa::SUCCESS) + UPM_THROW("Convert D2 failed"); + delayms(100); + int bytesRead = i2c->readBytesReg(MS5611_CMD_ADC_READ, buf, 3); + if (bytesRead != 3) + UPM_THROW("ADC read failed"); + // printf("%02X%02X%02X\n", buf[0], buf[1], buf[2]); + value = ((uint32_t)buf[0] << 16) | ((uint32_t)buf[1] << 8) | buf[2]; + return value; +} + +uint32_t MS5611::readRawTemperature() +{ + return readADC(MS5611_CMD_CONV_D2); +} + +uint32_t MS5611::readRawPressure() +{ + return readADC(MS5611_CMD_CONV_D1); +} + +int MS5611::getTemperatureCelsius() +{ + uint32_t D2 = readRawTemperature(); + int64_t dT = D2 - ((uint64_t)prom[5] << 8); + int32_t temp = 2000 + ((int64_t)dT * (int64_t)prom[6]) / (int64_t)(1 << 23); + return (temp + 50) / 100; +} + + +int MS5611::getPressurePa() +{ + int32_t rawTemp = readRawTemperature(); + int32_t rawPressure = readRawPressure(); + int64_t dT = rawTemp - ((uint64_t)prom[5] << 8); + int64_t offset = ((uint32_t)prom[2] << 16) + ((dT * (prom[4]) >> 7)); //was OFF = (C[2] << 17) + dT * C[4] / (1 << 6); + int64_t scaler = ((uint32_t)prom[1] << 15) + ((dT * (prom[3]) >> 8)); //was SENS = (C[1] << 16) + dT * C[3] / (1 << 7); + int32_t temp = 2000 + (int64_t)dT * (int64_t)prom[6] / (int64_t)(1 << 23); + + if(temp < 2000) { + float T1 = (temp - 2000) * (temp - 2000); + int64_t offsetDelta = (5 * T1) / 2; + int64_t scalerDelta = (5 * T1) / 4; + + if(temp < -1500) { + T1 = (temp + 1500) * (temp + 1500); + offsetDelta += 7 * T1; + scalerDelta += 11 * T1 / 2; + } + offset -= offsetDelta; + scaler -= scalerDelta; + } + int pressure = ((((int64_t)rawPressure * scaler ) >> 21) - offset) / (double) (1 << 15); + return pressure; +} + diff --git a/src/ms5611/ms5611.hpp b/src/ms5611/ms5611.hpp new file mode 100644 index 00000000..25342bdc --- /dev/null +++ b/src/ms5611/ms5611.hpp @@ -0,0 +1,89 @@ +/* + * Author: Henry Bruce + * Copyright (c) 2016 Intel Corporation. + * + * 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 "upm/iPressureSensor.hpp" +#include "upm/iTemperatureSensor.hpp" +#include "mraa/i2c.hpp" + +namespace upm +{ + +#define MS5611_ADDRESS 0x76 +/** + * @brief ms5611 Barometric Pressure Sensor library + * @defgroup ms5611 libupm-ms5611 + * @ingroup meas i2c temp pressure + */ + +/** + * @brief API for MS5611 Barometric Pressure Sensor library + * + * Measurement Specialties + * [MS5611-01BA03](http://www.te.com/usa-en/product-CAT-BLPS0036.html) + * Automotive Catalog Low-EMI, High-Performance 4-Channel LED Driver + * + * @library ms5611 + * @sensor ms5611 + * @comname Meas-Spec MS5611 Barometric Pressure Sensor library + * @altname MS5611 + * @type temp pressure + * @man meas + * @con i2c + * @if ilightcontroller + * + */ + +class MS5611 : public IPressureSensor, ITemperatureSensor +{ +public: + enum OsrMode + { + ULTRA_LOW_POWER, LOW_POWER, STANDARD, ULTRA_HIGH_RES, HIGH_RES + }; + + MS5611(int i2cBus = 0, int address = MS5611_ADDRESS); + ~MS5611(); + const char* getModuleName() { return "ms5611"; } + void setOverSampling(OsrMode osrMode); + int getTemperatureCelsius(); + int getPressurePa(); + +private: + int promCrc4(); + uint32_t readADC(int adcReg); + void delayms(int millisecs); + uint32_t readRawPressure(); + uint32_t readRawTemperature(); + + mraa::Result status; + mraa::I2c* i2c; + int address; + uint16_t *prom; + int osr; + int samplePeriod; +}; + + +} + diff --git a/src/ms5611/pyupm_ms5611.i b/src/ms5611/pyupm_ms5611.i new file mode 100644 index 00000000..fcfa1e06 --- /dev/null +++ b/src/ms5611/pyupm_ms5611.i @@ -0,0 +1,9 @@ +%module pyupm_ms5611 +%include "../upm.i" + +%feature("autodoc", "3"); + +%include "ms5611.hpp" +%{ + #include "ms5611.hpp" +%}