GY-63_MS5611/libraries/AM232X/AM232X.cpp

369 lines
6.4 KiB
C++
Raw Normal View History

//
// FILE: AM232X.cpp
// AUTHOR: Rob Tillaart
2023-10-16 09:42:56 -04:00
// VERSION: 0.5.0
// PURPOSE: AM232X library for AM2320 for Arduino.
2023-01-12 11:33:55 -05:00
// URL: https://github.com/RobTillaart/AM232X
2021-01-29 06:31:58 -05:00
2021-01-29 06:31:58 -05:00
#include "AM232X.h"
2021-01-29 06:31:58 -05:00
2021-02-03 11:20:20 -05:00
const uint8_t AM232X_ADDRESS = 0x5C;
////////////////////////////////////////////////////////////////////
//
// PUBLIC
//
2021-01-29 06:31:58 -05:00
AM232X::AM232X(TwoWire *wire)
{
2022-06-17 06:53:44 -04:00
_wire = wire;
2022-01-06 08:05:38 -05:00
// reset() or begin() ?
2022-06-17 06:53:44 -04:00
_humidity = 0.0;
_temperature = 0.0;
_humOffset = 0.0;
_tempOffset = 0.0;
_lastRead = 0;
_readDelay = 2000;
2022-06-18 03:51:07 -04:00
_suppressError = false;
2021-01-29 06:31:58 -05:00
}
bool AM232X::begin()
{
2021-01-29 06:31:58 -05:00
if (! isConnected()) return false;
this->read();
2021-01-29 06:31:58 -05:00
return true;
}
2021-04-07 07:31:22 -04:00
bool AM232X::isConnected(uint16_t timeout)
2021-01-29 06:31:58 -05:00
{
2021-04-07 07:31:22 -04:00
uint32_t start = micros();
while (micros() - start < timeout)
{
_wire->beginTransmission(AM232X_ADDRESS);
if ( _wire->endTransmission() == 0) return true;
yield();
delayMicroseconds(100);
}
return false;
}
2021-01-29 06:31:58 -05:00
int AM232X::read()
{
2022-01-06 08:05:38 -05:00
if (millis() - _lastRead < _readDelay)
{
return AM232X_READ_TOO_FAST;
}
2022-06-17 06:53:44 -04:00
_lastRead = millis();
2022-06-18 03:51:07 -04:00
// READ HUMIDITY AND TEMPERATURE REGISTERS
int rv = _readRegister(0x00, 4);
if (rv < 0) return rv;
2022-06-18 03:51:07 -04:00
if (rv != AM232X_OK)
{
if (_suppressError == false)
{
_humidity = AM232X_INVALID_VALUE;
_temperature = AM232X_INVALID_VALUE;
}
return rv; // propagate error value
}
2022-06-18 03:51:07 -04:00
// EXTRACT HUMIDITY AND TEMPERATURE
_humidity = (_bits[2] * 256 + _bits[3]) * 0.1;
int16_t t = ((_bits[4] & 0x7F) * 256 + _bits[5]);
if (t == 0)
{
2022-06-18 03:51:07 -04:00
_temperature = 0.0; // prevent -0.0;
}
2022-06-18 03:51:07 -04:00
else
{
_temperature = t * 0.1;
if ((_bits[4] & 0x80) == 0x80 )
{
_temperature = -_temperature;
}
}
2022-10-27 11:22:29 -04:00
2022-06-18 03:51:07 -04:00
#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;
}
2021-01-29 06:31:58 -05:00
2022-01-06 08:05:38 -05:00
float AM232X::getHumidity()
{
2022-06-17 06:53:44 -04:00
float _hum = _humidity;
if (_humOffset != 0.0) _hum += _humOffset;
return _hum;
}
2022-01-06 08:05:38 -05:00
float AM232X::getTemperature()
{
2022-06-17 06:53:44 -04:00
float _tem = _temperature;
if (_tempOffset != 0.0) _tem += _tempOffset;
return _tem;
}
2023-10-16 09:42:56 -04:00
void AM232X::setReadDelay(uint16_t readDelay)
2022-06-17 06:53:44 -04:00
{
2023-10-16 09:42:56 -04:00
_readDelay = readDelay;
2022-06-17 06:53:44 -04:00
if (_readDelay == 0)
{
_readDelay = 2000; // reset
}
2022-01-06 08:05:38 -05:00
};
int AM232X::getModel()
{
int rv = _readRegister(0x08, 2);
if (rv < 0) return rv;
2022-02-07 11:43:28 -05:00
return (_bits[2] * 256) + _bits[3];
}
2021-01-29 06:31:58 -05:00
int AM232X::getVersion()
{
int rv = _readRegister(0x0A, 1);
if (rv < 0) return rv;
2022-02-07 11:43:28 -05:00
return _bits[2];
}
2021-01-29 06:31:58 -05:00
uint32_t AM232X::getDeviceID()
{
int rv = _readRegister(0x0B, 4);
if (rv < 0) return rv;
2022-02-07 11:43:28 -05:00
uint32_t _deviceID = (_bits[2] * 256) + _bits[3];
_deviceID = _deviceID * 256 + _bits[4];
_deviceID = _deviceID * 256 + _bits[5];
return _deviceID;
}
2021-01-29 06:31:58 -05:00
int AM232X::getStatus()
{
int rv = _readRegister(0x0F, 1);
if (rv < 0) return rv;
2022-02-07 11:43:28 -05:00
return _bits[2];
}
2021-01-29 06:31:58 -05:00
int AM232X::getUserRegisterA()
{
int rv = _readRegister(0x10, 2);
if (rv < 0) return rv;
2022-02-07 11:43:28 -05:00
return (_bits[2] * 256) + _bits[3];
}
2021-01-29 06:31:58 -05:00
int AM232X::getUserRegisterB()
{
int rv = _readRegister(0x12, 2);
if (rv < 0) return rv;
2022-02-07 11:43:28 -05:00
return (_bits[2] * 256) + _bits[3];
}
2021-01-29 06:31:58 -05:00
int AM232X::setStatus(uint8_t value)
{
int rv = _writeRegister(0x0F, 1, value);
if (rv < 0) return rv;
return AM232X_OK;
}
2021-01-29 06:31:58 -05:00
int AM232X::setUserRegisterA(int value)
{
int rv = _writeRegister(0x10, 2, value);
if (rv < 0) return rv;
return AM232X_OK;
}
2021-01-29 06:31:58 -05:00
int AM232X::setUserRegisterB(int value)
{
int rv = _writeRegister(0x12, 2, value);
if (rv < 0) return rv;
return AM232X_OK;
}
2021-01-29 06:31:58 -05:00
////////////////////////////////////////////////////////////////////
//
2022-06-17 06:53:44 -04:00
// PROTECTED
//
int AM232X::_readRegister(uint8_t reg, uint8_t count)
{
2022-02-07 11:43:28 -05:00
// HANDLE PENDING IRQ
yield();
// WAKE UP the sensor
2021-04-07 07:31:22 -04:00
if (! wakeUp() ) return AM232X_ERROR_CONNECT;
// request the data
2021-01-29 06:31:58 -05:00
_wire->beginTransmission(AM232X_ADDRESS);
_wire->write(0x03);
_wire->write(reg);
_wire->write(count);
2021-02-03 11:20:20 -05:00
int rv = _wire->endTransmission();
if (rv < 0) return rv;
// request 4 extra, 2 for cmd + 2 for CRC
2021-02-03 11:20:20 -05:00
rv = _getData(count + 4);
return rv;
}
2021-01-29 06:31:58 -05:00
int AM232X::_writeRegister(uint8_t reg, uint8_t cnt, int16_t value)
{
2021-04-07 07:31:22 -04:00
if (! wakeUp() ) return AM232X_ERROR_CONNECT;
// prepare data to send
2022-02-07 11:43:28 -05:00
_bits[0] = 0x10;
_bits[1] = reg;
_bits[2] = cnt;
2017-12-12 07:21:02 -05:00
if (cnt == 2)
2017-12-12 07:21:02 -05:00
{
2022-02-07 11:43:28 -05:00
_bits[4] = value & 0xFF;
_bits[3] = (value >> 8) & 0xFF;
2017-12-12 07:21:02 -05:00
}
else
2017-12-12 07:21:02 -05:00
{
2022-02-07 11:43:28 -05:00
_bits[3] = value & 0xFF;
2017-12-12 07:21:02 -05:00
}
// send data
uint8_t length = cnt + 3; // 3 = cmd, startReg, #bytes
2021-01-29 06:31:58 -05:00
_wire->beginTransmission(AM232X_ADDRESS);
2021-02-03 11:20:20 -05:00
for (int i = 0; i < length; i++)
{
2022-02-07 11:43:28 -05:00
_wire->write(_bits[i]);
}
// send the CRC
2022-02-07 11:43:28 -05:00
uint16_t crc = _crc16(_bits, length);
2021-01-29 06:31:58 -05:00
_wire->write(crc & 0xFF);
_wire->write(crc >> 8);
2021-02-03 11:20:20 -05:00
int rv = _wire->endTransmission();
if (rv < 0) return rv;
// wait for the answer
2021-02-03 11:20:20 -05:00
rv = _getData(length);
return rv;
}
int AM232X::_getData(uint8_t length)
{
2021-01-29 06:31:58 -05:00
int bytes = _wire->requestFrom(AM232X_ADDRESS, length);
2022-02-07 11:43:28 -05:00
if (bytes == 0) return AM232X_ERROR_CONNECT;
2021-02-03 11:20:20 -05:00
for (int i = 0; i < bytes; i++)
{
2022-02-07 11:43:28 -05:00
_bits[i] = _wire->read();
}
// ANALYZE ERRORS
2022-01-06 08:05:38 -05:00
// will not detect if we requested 1 byte as that will
// return 5 bytes as requested. E.g. getStatus()
// design a fix if it becomes a problem.
if (bytes != length)
{
2022-02-07 11:43:28 -05:00
switch (_bits[3])
{
2021-02-03 11:20:20 -05:00
case 0x80: return AM232X_ERROR_FUNCTION;
case 0x81: return AM232X_ERROR_ADDRESS;
case 0x82: return AM232X_ERROR_REGISTER;
2021-10-19 05:51:07 -04:00
case 0x83: return AM232X_ERROR_CRC_1; // previous write had a wrong CRC
2021-02-03 11:20:20 -05:00
case 0x84: return AM232X_ERROR_WRITE_DISABLED;
default: return AM232X_ERROR_UNKNOWN;
}
}
// CRC is LOW Byte first
2022-02-07 11:43:28 -05:00
uint16_t crc = _bits[bytes - 1] * 256 + _bits[bytes - 2];
if (_crc16(&_bits[0], bytes - 2) != crc)
{
return AM232X_ERROR_CRC_2; // read itself has wrong CRC
}
return AM232X_OK;
}
2021-01-29 06:31:58 -05:00
2021-02-03 11:20:20 -05:00
uint16_t AM232X::_crc16(uint8_t *ptr, uint8_t len)
{
2021-02-03 11:20:20 -05:00
uint16_t crc = 0xFFFF;
2022-06-17 06:53:44 -04:00
while(len--)
{
crc ^= *ptr++;
2022-06-17 06:53:44 -04:00
for (uint8_t i = 0; i < 8; i++)
{
if (crc & 0x01)
{
crc >>= 1;
crc ^= 0xA001;
}
else
{
crc >>= 1;
}
}
}
return crc;
}
2022-01-06 08:05:38 -05:00
2022-06-17 06:53:44 -04:00
/////////////////////////////////////////////////////////////////////////////
//
// AM232X derived classes
//
AM2320::AM2320(TwoWire *wire) : AM232X(wire)
{
}
AM2321::AM2321(TwoWire *wire) : AM232X(wire)
{
}
AM2322::AM2322(TwoWire *wire) : AM232X(wire)
{
}
2020-11-27 05:10:47 -05:00
// -- END OF FILE --
2022-01-06 08:05:38 -05:00