HCesp/AHT2x.cpp

208 lines
5.6 KiB
C++

#include "AHT2x.h"
#define AHT_STATUS_BUSY 0x01
#define AHT_STATUS_CALIBRATED 0x10
#define AHT_CMD_INIT 0xBE
#define AHT_CMD_TRIGGER 0xAC
#define AHT_CMD_RESET 0xBA
#define AHT_CRC_POLYNOMIAL 0x31
#define AHT_CRC_MSB 0x80
#define AHT_CRC_INIT 0xFF
#ifndef DPRINTF
#define DPRINTF(...)
#endif
AHT2x aht25(Wire);
AHT2x aht10_0x39(Wire);
const uint8_t cmd_init[3] = { 0xBE, 0x08, 0x00 };
AHT2x::AHT2x(TwoWire &i2c) : _i2c(i2c) {};
bool AHT2x::setup(uint8_t address, bool crc) {
m_nAddress = address;
_active_crc = crc;
m_nErrorCount = 0;
m_nTemp = -9999;
m_nRH = -9999;
bRequested = false;
m_bSensor = false;
m_bScan = false;
tickRequested = millis();
delay(40);
if (scan()) {
while (!isCalibrated()) {
calibrate();
}
requestMeasurement(tickRequested);
delay(82);
humid[3] = -9999;
temp[3] = -9999;
if (readSensor(tickRequested + 82)) {
for (int i = 0; i < 3; i++) {
humid[i] = humid[3];
temp[i] = temp[3];
}
}
return true;
}
return false;
}
bool AHT2x::scan() {
//DPRINTF("AHTx0 - Scanning AHTx0 Device at %X\n", m_nAddress);
int i;
for (i = 0; i < 5; i++) {
Wire.beginTransmission(m_nAddress);
if (Wire.endTransmission() == 0) {
DPRINTF("AHTx0 - FOUND I2C Device at %X\n", m_nAddress);
bool ret = false;
//sendCommand(m_nAddress, 0xBE, 0x08, 0x00)) { // AHT20 init command
uint8_t cmd[3] = { 0xBE, 0x08, 0x00 };
_i2c.beginTransmission(m_nAddress);
_i2c.write((uint8_t *)cmd_init, 3);
if (_i2c.endTransmission() == 0) {
m_bSensor = true;
DPRINTF("AHT2x - Found AHT2x at %X\n", m_nAddress);
break;
}
}
delay(2);
}
if (i == 5) {
DPRINTF("AHTx0 - I2C Transmission Error at %X\n", m_nAddress);
}
return m_bSensor;
}
bool AHT2x::isReady() {
if (status() & AHT_STATUS_BUSY) {
return false;
}
return measure();
}
bool AHT2x::isCalibrated() {
return status() & AHT_STATUS_CALIBRATED;
}
void AHT2x::reset() {
uint8_t cmd = AHT_CMD_RESET;
_i2c.beginTransmission(m_nAddress);
_i2c.write(cmd);
_i2c.endTransmission();
delay(20);
while (!isCalibrated()) {
calibrate();
}
}
uint8_t AHT2x::status() {
_i2c.requestFrom(m_nAddress, (uint8_t)6);
for (int i = 0; i < 6; i++) {
_buf[i] = _i2c.read();
}
if (!_active_crc || (crc8() == _buf[6])) {
return _buf[0];
}
return AHT_STATUS_BUSY;
}
void AHT2x::calibrate() {
uint8_t cmd[] = {AHT_CMD_INIT, 0x08, 0x00};
_i2c.beginTransmission(m_nAddress);
_i2c.write(cmd, 3);
_i2c.endTransmission();
delay(10);
}
void AHT2x::requestMeasurement(unsigned long tick) {
uint8_t cmd[] = {AHT_CMD_TRIGGER, 0x33, 0x00};
_i2c.beginTransmission(m_nAddress);
_i2c.write(cmd, 3);
_i2c.endTransmission();
tickRequested = tick;
bRequested = true;
}
bool AHT2x::readSensor(unsigned long tick) {
if (m_bScan) {
// Re-Scan sensor for any hardware change or failure
scan();
m_bScan = false;
}
bool ret = false;
if (bRequested) {
if (tick - tickRequested > 80) {
_i2c.requestFrom(m_nAddress, (uint8_t)6);
ret = true;
for (int i = 0; i < 6; i++) {
if (Wire.available()) {
_buf[i] = _i2c.read();
} else {
ret = false; // If data is unavailable, return false
break;
}
}
if (ret && (!_active_crc || (crc8() == _buf[6]))) {
humid[0] = humid[1];
humid[1] = humid[2];
humid[2] = humid[3];
uint32_t hum32 = (_buf[1] << 12) | (_buf[2] << 4) | (_buf[3] >> 4);
humid[3] = (int16_t) roundf(hum32 * 10000.0f / 0x100000);
if (m_nRH > 2000 && m_nRH <= 10000) {
if (humid[3] - m_nRH < -1500 || humid[3] - m_nRH> 1500)
humid[3] = m_nRH;
}
m_nRH = (int16_t)((humid[0] + humid[1] + humid[2] + humid[3]) / 4);
temp[0] = temp[1];
temp[1] = temp[2];
temp[2] = temp[3];
uint32_t temp32 = ((_buf[3] & 0xF) << 16) | (_buf[4] << 8) | _buf[5];
temp[3] = (int16_t) roundf(temp32 * 20000.0f / 0x100000 - 5000);
if (m_nTemp > 2000 && m_nTemp <= 3000) {
if (temp[3] - m_nTemp < -1000 || temp[3] - m_nTemp> 1000)
temp[3] = m_nTemp;
}
m_nTemp = (int16_t)((temp[0] + temp[1] + temp[2] + temp[3]) / 4);
m_nErrorCount = 0;
ret = true;
} else {
if (++m_nErrorCount > 4) {
m_nTemp = -9999;
m_nRH = -9999;
m_nErrorCount = 0;
}
}
} else {
// tick - tickRequested <= 80
// do nothing;
return false;
}
}
requestMeasurement(tick);
return ret;
}
uint8_t AHT2x::crc8() {
uint8_t crc = AHT_CRC_INIT;
for (int i = 0; i < 6; i++) {
crc ^= _buf[i];
for (int j = 0; j < 8; j++) {
if (crc & AHT_CRC_MSB) {
crc = (crc << 1) ^ AHT_CRC_POLYNOMIAL;
} else {
crc <<= 1;
}
}
}
return crc;
}