GY-63_MS5611/libraries/AM2315/AM2315.cpp
2023-01-21 15:19:08 +01:00

240 lines
4.4 KiB
C++

//
// FILE: AM2315.cpp
// AUTHOR: Rob.Tillaart@gmail.com
// VERSION: 0.1.7
// PURPOSE: AM2315 Temperature and Humidity sensor library for Arduino
// URL: https://github.com/RobTillaart/AM2315
//
// HISTORY: see changelog.md
#include "AM2315.h"
const uint8_t AM2315_ADDRESS = 0x5C;
// READ_DELAY for blocking read
const uint16_t AM2315_READ_DELAY = 2000;
/////////////////////////////////////////////////////
//
// PUBLIC
//
AM2315::AM2315(TwoWire *wire)
{
_wire = wire;
// reset() or begin() ?
_humidity = 0.0;
_temperature = 0.0;
_humOffset = 0.0;
_tempOffset = 0.0;
_lastRead = 0;
_waitForRead = false;
_suppressError = false;
}
#if defined(ESP8266) || defined(ESP32)
bool AM2315::begin(const uint8_t dataPin, const uint8_t clockPin)
{
if ((dataPin < 255) && (clockPin < 255))
{
_wire->begin(dataPin, clockPin);
} else {
_wire->begin();
}
if (! isConnected()) return false;
this->read();
return true;
}
#endif
bool AM2315::begin()
{
_wire->begin();
if (! isConnected()) return false;
this->read();
return true;
}
bool AM2315::isConnected(uint16_t timeout)
{
uint32_t start = micros();
while (micros() - start < timeout)
{
_wire->beginTransmission(AM2315_ADDRESS);
if ( _wire->endTransmission() == 0) return true;
yield();
delayMicroseconds(100);
}
return false;
}
// return values:
// AM2315_OK
// AM2315_ERROR_CONNECT
// AM2315_MISSING_BYTES
// AM2315_ERROR_CHECKSUM;
// AM2315_HUMIDITY_OUT_OF_RANGE
// AM2315_TEMPERATURE_OUT_OF_RANGE
int AM2315::read()
{
while (millis() - _lastRead < AM2315_READ_DELAY)
{
if (!_waitForRead) return AM2315_WAITING_FOR_READ;
yield();
}
int rv = _read();
_lastRead = millis();
return rv;
}
float AM2315::getHumidity()
{
float _hum = _humidity;
if (_humOffset != 0.0) _hum += _humOffset;
return _hum;
}
float AM2315::getTemperature()
{
float _tem = _temperature;
if (_tempOffset != 0.0) _tem += _tempOffset;
return _tem;
}
///////////////////////////////////////////////////////////
//
// PRIVATE
//
// return values:
// AM2315_OK
// AM2315_ERROR_CONNECT
// AM2315_MISSING_BYTES
// AM2315_ERROR_CHECKSUM;
// AM2315_HUMIDITY_OUT_OF_RANGE
// AM2315_TEMPERATURE_OUT_OF_RANGE
int AM2315::_read()
{
// READ VALUES
int rv = _readSensor();
if (rv != AM2315_OK)
{
if (_suppressError == false)
{
_humidity = AM2315_INVALID_VALUE;
_temperature = AM2315_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 AM2315_VALUE_OUT_OF_RANGE
// TEST OUT OF RANGE
if (_humidity > 100)
{
return AM2315_HUMIDITY_OUT_OF_RANGE;
}
if ((_temperature < -40) || (_temperature > 125))
{
return AM2315_TEMPERATURE_OUT_OF_RANGE;
}
#endif
return AM2315_OK;
}
// return values:
// AM2315_OK
// AM2315_ERROR_CONNECT
// AM2315_MISSING_BYTES
// AM2315_ERROR_CHECKSUM;
int AM2315::_readSensor()
{
// HANDLE PENDING IRQ etc.
yield();
// WAKE UP the sensor
if (! isConnected() ) return AM2315_ERROR_CONNECT;
// SEND COMMAND
_wire->beginTransmission(AM2315_ADDRESS);
_wire->write(0X03);
_wire->write(0);
_wire->write(4);
int rv = _wire->endTransmission();
if (rv < 0) return rv;
// REQUEST DATA
const int length = 8;
int bytes = _wire->requestFrom((int)AM2315_ADDRESS, length);
if (bytes == 0) return AM2315_ERROR_CONNECT;
if (bytes < length) return AM2315_MISSING_BYTES;
// READ DATA
for (int i = 0; i < bytes; i++)
{
_bits[i] = _wire->read();
}
// TEST CHECKSUM
uint16_t crc = _bits[bytes - 1] * 256 + _bits[bytes - 2];
if (_crc16(_bits, bytes - 2) != crc)
{
return AM2315_ERROR_CHECKSUM;
}
return AM2315_OK;
}
uint16_t AM2315::_crc16(uint8_t *ptr, uint8_t len)
{
uint16_t crc = 0xFFFF;
while(len--)
{
crc ^= *ptr++;
for (uint8_t i = 0; i < 8; i++)
{
if (crc & 0x01)
{
crc >>= 1;
crc ^= 0xA001;
}
else
{
crc >>= 1;
}
}
}
return crc;
}
// -- END OF FILE --