diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c45eceb --- /dev/null +++ b/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2018, Sensirion AG +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of Sensirion AG nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH diff --git a/README.md b/README.md new file mode 100644 index 0000000..0c79157 --- /dev/null +++ b/README.md @@ -0,0 +1,45 @@ +# Arduino library for Sensirion SDP3x and SDP8xx series + +This is an unofficial library for Sensirion SDP3x and SDP8xx sensors. Both 500Pa +and 125Pa sensor types are supported. + +## Getting started + +To get started, have a look at the `sdp_generic` example from the "Examples" menu. +Follow the steps below to initialize for your sensor: + +### Initializing for SDP3x on I2C address 0x21 + +I2C address is the default for the SDP3x series. The `sdp_generic` sample +will do that by default, without requiring any changes. + +### Initializing for SDP3x on an I2C address other than 0x21 + +To use an address other than 0x21, you can pass an argument when setting up +the sensor. In the example, comment out line 6, and uncomment line 10, like so: + +```c++ +// SDP3XSensor sdp; + +// If your SDP3x is not using the default I2C address of 0x21, uncomment the +// line below: +SDP3XSensor sdp(SDP3X_I2C_ADDR_22); +``` +Alternatively, you can use `SDP3X_I2C_ADDR_23` instead of `SDP3X_I2C_ADDR_22` + +### Initializing for SDP8xx + +To use it with an SDP8xx series sensor, comment out line 6, and uncomment +line 14, like so: + +```c++ +// SDP3XSensor sdp; + +// If your SDP3x is not using the default I2C address of 0x21, uncomment the +// line below: +// SDP3XSensor sdp(SDP3X_I2C_ADDR_22); + + +// If you're using an SDP8xx, uncomment the line below instead: +SDP8XXSensor sdp; +``` diff --git a/examples/sdp_generic/sdp_generic.ino b/examples/sdp_generic/sdp_generic.ino new file mode 100644 index 0000000..b52be10 --- /dev/null +++ b/examples/sdp_generic/sdp_generic.ino @@ -0,0 +1,50 @@ +#include + +#include + +// use this for an SDP3x on the default I2C address of 0x21: +SDP3XSensor sdp; + +// If your SDP3x is not using the default I2C address of 0x21, uncomment the +// line below: +// SDP3XSensor sdp(SDP3X_I2C_ADDR_22); + + +// If you're using an SDP8xx, uncomment the line below instead: +// SDP8XXSensor sdp; + + +void setup() { + Wire.begin(); + Serial.begin(9600); + delay(1000); // let serial console settle + + int ret = sdp.init(); + if (!ret) { + Serial.print("init(): success\n"); + } else { + Serial.print("init(): failed, ret = "); + Serial.println(ret); + while (true) { + delay(1000); + } + } +} + +void loop() { + int ret = sdp.readSample(); + if (!ret) { + Serial.print("Differential pressure: "); + Serial.print(sdp.getDifferentialPressure()); + Serial.print("Pa | "); + + Serial.print("Temp: "); + Serial.print(sdp.getTemperature()); + Serial.print("C\n"); + } else { + Serial.print("Error in readSample(), ret = "); + Serial.println(ret); + } + + delay(500); +} diff --git a/i2chelper.cpp b/i2chelper.cpp new file mode 100644 index 0000000..599be4a --- /dev/null +++ b/i2chelper.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2015-2018, Sensirion AG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Sensirion AG nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include "i2chelper.h" + +int8_t I2CHelper::i2c_read(uint8_t addr, uint8_t* data, uint16_t count) +{ + Wire.requestFrom(addr, count); + if (Wire.available() != count) { + return -1; + } + for (int i = 0; i < count; ++i) { + data[i] = Wire.read(); + } + return 0; +} + +int8_t I2CHelper::i2c_write(uint8_t addr, const uint8_t* data, uint16_t count, bool appendCrc) +{ + Wire.beginTransmission(addr); + for (int i = 0; i < count; ++i) { + if (Wire.write(data[i]) != 1) { + return 1; + } + } + if (appendCrc) { + uint8_t crc = crc8(data, count); + if (Wire.write(crc) != 1) { + return 2; + } + } + + if (Wire.endTransmission() != 0) { + return 3; + } + return 0; +} + +uint8_t I2CHelper::crc8(const uint8_t* data, uint8_t len) +{ + // adapted from SHT21 sample code from http://www.sensirion.com/en/products/humidity-temperature/download-center/ + + uint8_t crc = 0xff; + uint8_t byteCtr; + for (byteCtr = 0; byteCtr < len; ++byteCtr) { + crc ^= (data[byteCtr]); + for (uint8_t bit = 8; bit > 0; --bit) { + if (crc & 0x80) { + crc = (crc << 1) ^ 0x31; + } else { + crc = (crc << 1); + } + } + } + return crc; +} diff --git a/i2chelper.h b/i2chelper.h new file mode 100644 index 0000000..6945eca --- /dev/null +++ b/i2chelper.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015-2018, Sensirion AG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Sensirion AG nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef __SDP_I2C_HELPER +#define __SDP_I2C_HELPER + +#include + +class I2CHelper +{ +public: + static int8_t i2c_write(uint8_t addr, const uint8_t* data, uint16_t count, bool appendCrc=false); + static int8_t i2c_read(uint8_t addr, uint8_t* data, uint16_t count); + static uint8_t crc8(const uint8_t* data, uint8_t len); +}; + +#endif /* __SCD_I2C_HELPER */ diff --git a/keywords.txt b/keywords.txt new file mode 100644 index 0000000..7e4dc72 --- /dev/null +++ b/keywords.txt @@ -0,0 +1,28 @@ +####################################### +# Syntax Coloring Map For arduino-scd +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +SDP3XSensor KEYWORD1 +SDP8XXSensor KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +init KEYWORD2 +readSample KEYWORD2 +getDifferentialPressure KEYWORD2 +getHumidity KEYWORD2 +getTemperature KEYWORD2 + +####################################### +# Instances (KEYWORD2) +####################################### + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/library.properties b/library.properties new file mode 100644 index 0000000..36414a2 --- /dev/null +++ b/library.properties @@ -0,0 +1,10 @@ +name=arduino-sdp +version=0.0.1-pre +author=Johannes Winkelmann +maintainer=Johannes Winkelmann +sentence=Support for Sensirion's Differential Pressure sensors +paragraph=Supported sensors: SDP3x, SDP8xx +category=Sensors +url=https://developer.sensirion.com +architectures=* +includes=sdpsensor.h diff --git a/sdpsensor.cpp b/sdpsensor.cpp new file mode 100644 index 0000000..b51c91a --- /dev/null +++ b/sdpsensor.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2018, Sensirion AG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Sensirion AG nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +#include "sdpsensor.h" +#include "i2chelper.h" + +int SDPSensor::init() +{ + // try to read product id + const uint8_t CMD_LEN = 2; + uint8_t cmd0[CMD_LEN] = { 0x36, 0x7C }; + uint8_t cmd1[CMD_LEN] = { 0xE1, 0x02 }; + + const uint8_t DATA_LEN = 18; + uint8_t data[DATA_LEN] = { 0 }; + + uint8_t ret = I2CHelper::i2c_write(mI2CAddress, cmd0, CMD_LEN); + if (ret != 0) { + return 1; + } + ret = I2CHelper::i2c_write(mI2CAddress, cmd1, CMD_LEN); + if (ret != 0) { + return 2; + } + ret = I2CHelper::i2c_read(mI2CAddress, data, DATA_LEN); + if (ret != 0) { + return 3; + } + + // at this point, we don't really care about the data just yet, but + // we may use that in the future. Either way, the sensor responds, and + return 0; +} + +int SDPSensor::readSample() +{ + const uint8_t CMD_LEN = 2; + uint8_t cmd[CMD_LEN] = { 0x36, 0x2F }; + + const uint8_t DATA_LEN = 9; + uint8_t data[DATA_LEN] = { 0 }; + + if (I2CHelper::i2c_write(mI2CAddress, cmd, CMD_LEN) != 0) { + return 1; + } + + delay(100); // theoretically 45ms + + if (I2CHelper::i2c_read(mI2CAddress, data, DATA_LEN) != 0) { + return 1; + } + + // TODO: check CRC + + int16_t dp_raw = (int16_t)data[0] << 8 | data[1]; + int16_t temp_raw = (int16_t)data[3] << 8 | data[4]; + int8_t dp_scale = (int16_t)data[7] << 8 | data[7]; + + mDifferentialPressure = dp_raw / (float)dp_scale; + mTemperature = temp_raw / 200.0; + + return 0; +} + +float SDPSensor::getDifferentialPressure() const +{ + return mDifferentialPressure; +} + +float SDPSensor::getTemperature() const +{ + return mTemperature; +} diff --git a/sdpsensor.h b/sdpsensor.h new file mode 100644 index 0000000..c5bb7f7 --- /dev/null +++ b/sdpsensor.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, Sensirion AG + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Sensirion AG nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef SDPSENSOR_H +#define SDPSENSOR_H + +class SDPSensor +{ +public: + const static int SDP3X_I2C_ADDR_21 = 0x21; + const static int SDP3X_I2C_ADDR_22 = 0x22; + const static int SDP3X_I2C_ADDR_23 = 0x23; + const static int SDP3X_I2C_ADDR_DEFAULT = SDP3X_I2C_ADDR_21; + + const static int SDP8XX_I2C_ADDR_DEFAULT = 0x25; + + SDPSensor(uint8_t i2cAddr) : mI2CAddress(i2cAddr) {} + + /** + * initialize the sensor + * @return 0 on sucess, error code otherwise + */ + int init(); + + /** + * read sensor data from sensor + * @return 0 on success, error code otherwise + */ + int readSample(); + + /** + * Returns the last differential pressure value read - does NOT trigger a new measurement + * @return last differential pressure value read + */ + float getDifferentialPressure() const; + + /** + * Returns the last temperature value read - does NOT trigger a new measurement + * @return last temperature value read + */ + float getTemperature() const; + +private: + uint8_t mI2CAddress; + + float mDifferentialPressure; + float mTemperature; +}; + +class SDP3XSensor : public SDPSensor +{ +public: + SDP3XSensor() : SDPSensor(SDPSensor::SDP3X_I2C_ADDR_DEFAULT) {} + SDP3XSensor(uint8_t i2cAddr) : SDPSensor(i2cAddr) {} +}; + +class SDP8XXSensor : public SDPSensor +{ +public: + SDP8XXSensor() : SDPSensor(SDPSensor::SDP8XX_I2C_ADDR_DEFAULT) {} +}; + +#endif /* SDPSENSOR_H */