208 lines
5.6 KiB
C++
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;
|
|
}
|