2022-01-06 06:08:13 -05:00
|
|
|
//
|
|
|
|
// FILE: AM2315.cpp
|
|
|
|
// AUTHOR: Rob.Tillaart@gmail.com
|
2022-01-12 15:04:52 -05:00
|
|
|
// VERSION: 0.1.1
|
2022-01-06 06:08:13 -05:00
|
|
|
// PURPOSE: AM2315 Temperature and Humidity sensor library for Arduino
|
|
|
|
// URL: https://github.com/RobTillaart/AM2315
|
|
|
|
//
|
|
|
|
// HISTORY:
|
|
|
|
// 0.1.0 2022-01-05 initial version
|
2022-01-12 15:04:52 -05:00
|
|
|
// 0.1.1 2022-01-11 fix handshake.
|
2022-01-06 06:08:13 -05:00
|
|
|
|
|
|
|
|
|
|
|
#include "AM2315.h"
|
|
|
|
|
|
|
|
|
|
|
|
// these defines are not for user to adjust
|
|
|
|
// READ_DELAY for blocking read
|
|
|
|
#define AM2315_READ_DELAY 2000
|
|
|
|
|
|
|
|
#define AM2315_ADDRESS 0x5C
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// PUBLIC
|
|
|
|
//
|
|
|
|
AM2315::AM2315(TwoWire *wire)
|
|
|
|
{
|
|
|
|
_wire = wire;
|
|
|
|
_temperature = 0;
|
|
|
|
_humidity = 0;
|
|
|
|
_humOffset = 0;
|
|
|
|
_tempOffset = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#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();
|
|
|
|
}
|
|
|
|
return isConnected();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
bool AM2315::begin()
|
|
|
|
{
|
|
|
|
_wire->begin();
|
|
|
|
return isConnected();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-01-12 15:04:52 -05:00
|
|
|
bool AM2315::isConnected(uint16_t timeout)
|
2022-01-06 06:08:13 -05:00
|
|
|
{
|
2022-01-12 15:04:52 -05:00
|
|
|
uint32_t start = micros();
|
|
|
|
while (micros() - start < timeout)
|
|
|
|
{
|
|
|
|
_wire->beginTransmission(AM2315_ADDRESS);
|
|
|
|
if ( _wire->endTransmission() == 0) return true;
|
|
|
|
yield();
|
|
|
|
delayMicroseconds(100);
|
|
|
|
}
|
|
|
|
return false;
|
2022-01-06 06:08:13 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int AM2315::read()
|
|
|
|
{
|
|
|
|
// reset readDelay
|
2022-01-12 15:04:52 -05:00
|
|
|
if (_readDelay == 0) _readDelay = AM2315_READ_DELAY;
|
2022-01-06 06:08:13 -05:00
|
|
|
while (millis() - _lastRead < _readDelay)
|
|
|
|
{
|
|
|
|
if (!_waitForRead) return AM2315_WAITING_FOR_READ;
|
|
|
|
yield();
|
|
|
|
}
|
|
|
|
int rv = _read();
|
|
|
|
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
|
|
|
|
//
|
|
|
|
int AM2315::_read()
|
|
|
|
{
|
|
|
|
// READ VALUES
|
|
|
|
int rv = _readSensor();
|
|
|
|
|
|
|
|
_lastRead = millis();
|
|
|
|
|
|
|
|
if (rv != AM2315_OK)
|
|
|
|
{
|
|
|
|
if (_suppressError == false)
|
|
|
|
{
|
|
|
|
_humidity = AM2315_INVALID_VALUE;
|
|
|
|
_temperature = AM2315_INVALID_VALUE;
|
|
|
|
}
|
|
|
|
return rv; // propagate error value
|
|
|
|
}
|
|
|
|
|
|
|
|
_humidity = (_bits[0] * 256 + _bits[1]) * 0.1;
|
|
|
|
int16_t t = ((_bits[2] & 0x7F) * 256 + _bits[3]);
|
|
|
|
if (t == 0)
|
|
|
|
{
|
|
|
|
_temperature = 0.0; // prevent -0.0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_temperature = t * 0.1;
|
|
|
|
if ((_bits[2] & 0x80) == 0x80 )
|
|
|
|
{
|
|
|
|
_temperature = -_temperature;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TEST OUT OF RANGE
|
|
|
|
#ifdef AM2315_VALUE_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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// PRIVATE
|
|
|
|
//
|
|
|
|
|
|
|
|
// return values:
|
|
|
|
// AM2315_OK
|
|
|
|
// AM2315_ERROR_CONNECT
|
|
|
|
// AM2315_MISSING_BYTES
|
2022-01-12 15:04:52 -05:00
|
|
|
// AM2315_ERROR_CHECKSUM;
|
2022-01-06 06:08:13 -05:00
|
|
|
int AM2315::_readSensor()
|
|
|
|
{
|
|
|
|
// EMPTY BUFFER
|
|
|
|
for (uint8_t i = 0; i < 5; i++) _bits[i] = 0;
|
|
|
|
|
|
|
|
// HANDLE PENDING IRQ
|
|
|
|
yield();
|
|
|
|
|
|
|
|
// WAKE UP the sensor
|
|
|
|
_wire->beginTransmission(AM2315_ADDRESS);
|
|
|
|
for (int i = 0; i < 10; i++) _wire->write(0);
|
|
|
|
int rv = _wire->endTransmission();
|
|
|
|
if (rv < 0) return rv;
|
|
|
|
|
|
|
|
// REQUEST DATA
|
|
|
|
_wire->beginTransmission(AM2315_ADDRESS);
|
|
|
|
_wire->write(0X03);
|
|
|
|
_wire->write(0);
|
|
|
|
_wire->write(4);
|
|
|
|
rv = _wire->endTransmission();
|
|
|
|
if (rv < 0) return rv;
|
|
|
|
|
2022-01-12 15:04:52 -05:00
|
|
|
delayMicroseconds(1500);
|
2022-01-06 06:08:13 -05:00
|
|
|
// GET DATA
|
|
|
|
const int length = 8;
|
|
|
|
int bytes = _wire->requestFrom(AM2315_ADDRESS, length);
|
|
|
|
if (bytes == 0) return AM2315_ERROR_CONNECT;
|
|
|
|
if (bytes < length) return AM2315_MISSING_BYTES;
|
|
|
|
|
|
|
|
uint8_t buffer[12];
|
|
|
|
for (int i = 0; i < bytes; i++)
|
|
|
|
{
|
|
|
|
buffer[i] = _wire->read();
|
|
|
|
}
|
|
|
|
_bits[0] = buffer[2];
|
|
|
|
_bits[1] = buffer[3];
|
|
|
|
_bits[2] = buffer[4];
|
|
|
|
_bits[3] = buffer[5];
|
|
|
|
|
2022-01-12 15:04:52 -05:00
|
|
|
// TEST CHECKSUM
|
|
|
|
uint16_t crc0 = buffer[7] * 256 + buffer[6];
|
|
|
|
uint16_t crc1 = _crc16(buffer, bytes - 2);
|
|
|
|
// Serial.print("CRC: ");
|
|
|
|
// Serial.print(crc0 - crc1);
|
|
|
|
// Serial.print("\t");
|
|
|
|
// Serial.print(crc1);
|
|
|
|
// Serial.println();
|
|
|
|
if (crc0 != crc1) return AM2315_ERROR_CHECKSUM;
|
2022-01-06 06:08:13 -05:00
|
|
|
|
|
|
|
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 --
|
|
|
|
|