From f89e90f02a5b481a1382364e4372068f7b512eb6 Mon Sep 17 00:00:00 2001 From: rob tillaart Date: Sat, 18 Jun 2022 09:51:07 +0200 Subject: [PATCH] 0.4.3 AM232X --- libraries/AM232X/AM232X.cpp | 53 +++++++++++--- libraries/AM232X/AM232X.h | 24 ++++++- libraries/AM232X/README.md | 91 ++++++++++++++++++------- libraries/AM232X/keywords.txt | 7 ++ libraries/AM232X/library.json | 2 +- libraries/AM232X/library.properties | 2 +- libraries/AM232X/test/unit_test_001.cpp | 17 +++++ 7 files changed, 157 insertions(+), 39 deletions(-) diff --git a/libraries/AM232X/AM232X.cpp b/libraries/AM232X/AM232X.cpp index dba1eabe..ca25ceff 100644 --- a/libraries/AM232X/AM232X.cpp +++ b/libraries/AM232X/AM232X.cpp @@ -1,7 +1,7 @@ // // FILE: AM232X.cpp // AUTHOR: Rob Tillaart -// VERSION: 0.4.1 +// VERSION: 0.4.3 // PURPOSE: AM232X library for AM2320 for Arduino. // // HISTORY: @@ -31,7 +31,11 @@ // added some unit tests // fix _lastRead bug // minor edits. - +// 0.4.3 2022-06-17 add get/setSuppressError() +// add AM232X_HUMIDITY_OUT_OF_RANGE +// add AM232X_TEMPERATURE_OUT_OF_RANGE +// fix return -0.0 (from AM2315 lib) +// major rewrite readme.md (sync AM2315) #include "AM232X.h" @@ -44,7 +48,6 @@ const uint8_t AM232X_ADDRESS = 0x5C; // // PUBLIC // - AM232X::AM232X(TwoWire *wire) { _wire = wire; @@ -55,6 +58,7 @@ AM232X::AM232X(TwoWire *wire) _tempOffset = 0.0; _lastRead = 0; _readDelay = 2000; + _suppressError = false; } @@ -104,18 +108,49 @@ int AM232X::read() return AM232X_READ_TOO_FAST; } _lastRead = millis(); + // READ HUMIDITY AND TEMPERATURE REGISTERS int rv = _readRegister(0x00, 4); if (rv < 0) return rv; - // CONVERT AND STORE - _humidity = (_bits[2] * 256 + _bits[3]) * 0.1; - _temperature = ((_bits[4] & 0x7F) * 256 + _bits[5]) * 0.1; - - if (_bits[4] & 0x80) + if (rv != AM232X_OK) { - _temperature = -_temperature; + if (_suppressError == false) + { + _humidity = AM232X_INVALID_VALUE; + _temperature = AM232X_INVALID_VALUE; + } + return rv; // propagate error value } + + // EXTRACT HUMIDITY AND TEMPERATURE + _humidity = (_bits[2] * 256 + _bits[3]) * 0.1; + int16_t t = ((_bits[4] & 0x7F) * 256 + _bits[5]); + if (t == 0) + { + _temperature = 0.0; // prevent -0.0; + } + else + { + _temperature = t * 0.1; + if ((_bits[4] & 0x80) == 0x80 ) + { + _temperature = -_temperature; + } + } + +#ifdef AM232X_VALUE_OUT_OF_RANGE + // TEST OUT OF RANGE + if (_humidity > 100) + { + return AM232X_HUMIDITY_OUT_OF_RANGE; + } + if ((_temperature < -40) || (_temperature > 80)) + { + return AM232X_TEMPERATURE_OUT_OF_RANGE; + } +#endif + return AM232X_OK; } diff --git a/libraries/AM232X/AM232X.h b/libraries/AM232X/AM232X.h index 97d4383f..22e85107 100644 --- a/libraries/AM232X/AM232X.h +++ b/libraries/AM232X/AM232X.h @@ -3,7 +3,7 @@ // FILE: AM232X.h // AUTHOR: Rob Tillaart // PURPOSE: AM232X Temperature and Humidity sensor library for Arduino -// VERSION: 0.4.2 +// VERSION: 0.4.3 // URL: https://github.com/RobTillaart/AM232X // // AM232X PIN layout AM2315 COLOR @@ -23,7 +23,7 @@ #include "Wire.h" -#define AM232X_LIB_VERSION (F("0.4.2")) +#define AM232X_LIB_VERSION (F("0.4.3")) #define AM232X_OK 0 @@ -49,6 +49,20 @@ 0x84: Write disabled */ + +// optionally detect out of range values. +// occurs seldom so not enabled by default. +// #define AM232X_VALUE_OUT_OF_RANGE +#define AM232X_HUMIDITY_OUT_OF_RANGE -100 +#define AM232X_TEMPERATURE_OUT_OF_RANGE -101 + + +// allows to overrule AM232X_INVALID_VALUE e.g. to prevent spike in graphs. +#ifndef AM232X_INVALID_VALUE +#define AM232X_INVALID_VALUE -999 +#endif + + class AM232X { public: @@ -92,6 +106,10 @@ public: float getHumOffset() { return _humOffset; }; float getTempOffset() { return _tempOffset; }; + // suppress error values of -999 => check return value of read() instead + bool getSuppressError() { return _suppressError; }; + void setSuppressError(bool b) { _suppressError = b; }; + bool wakeUp() { return isConnected(); }; protected: @@ -103,6 +121,8 @@ protected: uint32_t _lastRead = 0; uint16_t _readDelay = 2000; + bool _suppressError = false; + int _readRegister(uint8_t reg, uint8_t cnt); int _writeRegister(uint8_t reg, uint8_t cnt, int16_t value); int _getData(uint8_t length); diff --git a/libraries/AM232X/README.md b/libraries/AM232X/README.md index aae1e77e..473b5250 100644 --- a/libraries/AM232X/README.md +++ b/libraries/AM232X/README.md @@ -19,16 +19,20 @@ the AM232X has a fixed address **0x5C** so one need to implement a multiplexing strategy to have multiple sensors in practice. See multiplexing below. +This library works also for the **AM2315** which has a library of its own - https://github.com/RobTillaart/AM2315 -Typical parameters + +#### Typical parameters | | range | accuracy | repeatability | |:------------|:----------:|:--------:|:-------------:| | Temperature | -40 - 80 | 0.5°C | ±0.1 | -| Humidity | 0.0 - 99.9 | 3% | ±0.1 | +| Humidity | 0.0 - 99.9 | ±3% | ±0.1 | | Sample time | 2 seconds | | | +#### Hardware connection + ``` // AM232X PIN layout AM2315 COLOR // ============================================ @@ -43,7 +47,12 @@ Typical parameters // do not forget pull up resistors between SDA, SCL and VDD. ``` -This library works for the **AM2315** which has a library of its own - https://github.com/RobTillaart/AM2315 + +### I2C clock speed + +The datasheet states the AM2320 should be used on 100 KHz I2C only. + +TODO measure and verify (see AM2315) ## Interface @@ -53,20 +62,27 @@ Since 0.4.2 the library provides specific classes for the AM2320, AM2321 and AM2 ### Constructor -- **AM232X(TwoWire \*wire = &Wire)** constructor, optionally set Wire0..WireN. Default is Wire. -- **bool begin(uint8_t sda, uint8_t scl)** for ESP32 alike devices, returns true if device address 0x5C is connected. -- **bool begin()** for AVR alike devices, returns true if device address 0x5C is connected. -- **bool isConnected(uint16_t timeout = 3000)** returns true if device address 0x5C is found on I2C bus. +- **AM232X(TwoWire \*wire = &Wire)** constructor, default using Wire (I2C bus), optionally set to Wire0 .. WireN. +- **bool begin(uint8_t dataPin, uint8_t clockPin)** begin for ESP32 et al, to set I2C bus pins. +Returns true if device address 0x5C is connected. +- **bool begin()** initializer for non ESP32 e.g. AVR. +Returns true if device address 0x5C is connected. +- **bool isConnected(uint16_t timeout = 3000)** returns true if the device address 0x5C is found on I2C bus. As the device can be in sleep modus it will retry for the defined timeout (in micros) with a minimum of 1 try. minimum = 800 us and maximum = 3000 us according to datasheet. -### Base calls +### Core -- **int read()** fetches the values from the sensor. -- **uint32_t lastRead()** returns milliseconds since start of last read. -- **float getHumidity()** returns the last read humidity. -- **float getTemperature()** returns the last read temperature. +- **int read()** read the sensor and store the values internally. +Returns the status of the read which should be **AM232X_OK** == 0. +- **float getHumidity()** returns the last read humidity + optional offset, +or **AM232X_INVALID_VALUE** == -999 in case of error. +This error can be suppressed, see below. +- **float getTemperature()** returns the last read temperature + optional offset, +or **AM232X_INVALID_VALUE** == -999 in case of error. +This error can be suppressed, see below. +- **uint32_t lastRead()** returns the timestamp in milliseconds since startup of the last successful read. ### Offset @@ -81,15 +97,17 @@ Default offset = 0, so no parameter will reset the offset. ### Control -Functions to adjust the interval time the sensor may be called again. -Default = 2000 ms (from datasheet). +Functions to adjust the communication with the sensor. - **void setReadDelay(uint16_t rd = 0)** Tunes the time it waits before actual read can be done. -Set readDelay to 0 will reset it to 2000 ms effictive the next **read()**. +Set readDelay to 0 will reset it to 2000 ms effective the next **read()**. - **uint16_t getReadDelay()** returns the above setting. Note that a value of zero (reset) will return 0 before the call and 2000 after the call to **read()**. - **bool wakeUp()** function that will try for 3 milliseconds to wake up the sensor. This can be done before an actual read to minimize the **read()** call. +- **void setSuppressError(bool b)** suppress error values of **AM232X_INVALID_VALUE** == -999 => you need to check the return value of read() instead. +This can be used to keep spikes out of your graphs / logs. +- **bool getSuppressError()** returns the above setting. ### Metadata @@ -113,6 +131,27 @@ Check datasheet for details. - **int getUserRegisterB()** +### Error codes + +| name | value | notes | +|:----------------------------------|------:|:------------| +| AM232X_OK | 0 | +| AM232X_ERROR_UNKNOWN | -10 | +| AM232X_ERROR_CONNECT | -11 | +| AM232X_ERROR_FUNCTION | -12 | +| AM232X_ERROR_ADDRESS | -13 | +| AM232X_ERROR_REGISTER | -14 | +| AM232X_ERROR_CRC_1 | -15 | +| AM232X_ERROR_CRC_2 | -16 | +| AM232X_ERROR_WRITE_DISABLED | -17 | +| AM232X_ERROR_WRITE_COUNT | -18 | +| AM232X_MISSING_BYTES | -19 | +| AM232X_READ_TOO_FAST | -20 | +| AM232X_HUMIDITY_OUT_OF_RANGE | -100 | not used by default. +| AM232X_TEMPERATURE_OUT_OF_RANGE | -101 | not used by default. +| AM232X_INVALID_VALUE | -999 | can be suppressed. + + ## Operation See examples @@ -122,8 +161,8 @@ the Wire library and do an initial **read()** to fill the variables temperature To access these values one must use **getTemperature()** and **getHumidity()**. Multiple calls will give the same values until **read()** is called again. -Note that the sensor can go into sleep mode and one might need to call **wakeUp()** -before the **read()**. +Note that the sensor can go into sleep mode after 3 seconds after last read, +so one might need to call **wakeUp()** before the **read()**. ## Multiplexing @@ -138,22 +177,22 @@ the sensor takes to boot and to be ready for the first measurement. pin of the sensors. This way one can enable / disable communication per sensor. This will still need an IO pin per sensor but does not have the "boot time" constraint mentioned above. -you may use a **PCF8574** to control these AND ports. +you may use a **PCF8574** to control the AND gates. +https://github.com/RobTillaart/PCF8574 3. Use a **TCA9548A** I2C Multiplexer, or similar. https://github.com/RobTillaart/TCA9548 Which method fit your application depends on your requirements and constraints. -## Warning - -The library has not been tested extensively yet so use at own risk. - -See also LICENSE - - ## Future - update documentation - test more (other platforms) - keep in sync with AM2315 class - + - merge in a far future. +- update unit test +- add examples +- I2C performance measurements + - clock speed > 170 - see AM2315 + + diff --git a/libraries/AM232X/keywords.txt b/libraries/AM232X/keywords.txt index 24221acb..2e32dd68 100644 --- a/libraries/AM232X/keywords.txt +++ b/libraries/AM232X/keywords.txt @@ -35,6 +35,8 @@ getReadDelay KEYWORD2 setReadDelay KEYWORD2 lastRead KEYWORD2 +getSuppressError KEYWORD2 +setSuppressError KEYWORD2 # Constants (LITERAL1) AM232X_LIB_VERSION LITERAL1 @@ -52,3 +54,8 @@ AM232X_ERROR_WRITE_COUNT LITERAL1 AM232X_MISSING_BYTES LITERAL1 AM232X_READ_TOO_FAST LITERAL1 +AM232X_HUMIDITY_OUT_OF_RANGE LITERAL1 +AM232X_TEMPERATURE_OUT_OF_RANGE LITERAL1 +AM232X_INVALID_VALUE LITERAL1 + + diff --git a/libraries/AM232X/library.json b/libraries/AM232X/library.json index 0835d77b..abf25bb5 100644 --- a/libraries/AM232X/library.json +++ b/libraries/AM232X/library.json @@ -15,7 +15,7 @@ "type": "git", "url": "https://github.com/RobTillaart/AM232X" }, - "version": "0.4.2", + "version": "0.4.3", "license": "MIT", "frameworks": "arduino", "platforms": "*", diff --git a/libraries/AM232X/library.properties b/libraries/AM232X/library.properties index 2a4ffcc5..03fb163f 100644 --- a/libraries/AM232X/library.properties +++ b/libraries/AM232X/library.properties @@ -1,5 +1,5 @@ name=AM232X -version=0.4.2 +version=0.4.3 author=Rob Tillaart maintainer=Rob Tillaart sentence=Arduino library for AM2320 AM2321 and AM2323 I2C temperature and humidity sensor. diff --git a/libraries/AM232X/test/unit_test_001.cpp b/libraries/AM232X/test/unit_test_001.cpp index d79e0b39..7f484f59 100644 --- a/libraries/AM232X/test/unit_test_001.cpp +++ b/libraries/AM232X/test/unit_test_001.cpp @@ -154,6 +154,23 @@ unittest(test_AM2322_hum_temp) } +unittest(test_AM232X_surpress_error) +{ + AM232X AM; + + Wire.begin(); + + assertTrue(AM.begin()); + assertTrue(AM.isConnected()); + + assertFalse(AM.getSuppressError()); + AM.setSuppressError(true); + assertTrue(AM.getSuppressError()); + AM.setSuppressError(false); + assertFalse(AM.getSuppressError()); +} + + unittest_main() // --------