#include "AHTxx.h" /* Defines */ #define AHT_I2C_ADDR (uint8_t)0x38 #define CMD_GET_STATUS (uint8_t)0x71 #define CMD_INIT (uint8_t)0xbe #define CMD_MEASURE (uint8_t)0xac #define CMD_MEASURE_CTL (uint8_t)0x33 #define CMD_MEASURE_NOP (uint8_t)0x00 #define CMD_SRESET (uint8_t)0xba #define CMD_CALIBR1 (uint8_t)0x1b #define CMD_CALIBR2 (uint8_t)0x1c #define CMD_CALIBR3 (uint8_t)0x1e #define STATUS_BUSY (uint8_t)0x80 #define STATUS_CMD (uint8_t)0x40 #define STATUS_CYC (uint8_t)0x20 #define STATUS_CAL (uint8_t)0x08 #define STATUS_CALB (uint8_t)0x18 /* Functions prototypes */ /* uint8_t Calc_CRC8(uint8_t *message, uint8_t Num); ahtxx_st_t JH_Reset_REG(uint8_t addr); */ static bool ReadyToRequest; static ahtxx_t Data; /** * Initialization */ AHTxx::AHTxx(void) { // Just powered on, it takes time for the product chip to be ready internally, // the delay is 100~500ms, and 500ms is recommended auto timer = new AutoDeleteTimer; timer->initializeMs<500>(Init); timer->startOnce(); ReadyToRequest = false; } void AHTxx::Init(void) { ahtxx_st_t res; uint8_t data; // When power on, send 0x71 to read the status word for the first time, // and judge whether the status word is 0x18. Wire.beginTransmission(AHT_I2C_ADDR); Wire.write(CMD_GET_STATUS); res = (ahtxx_st_t)Wire.endTransmission(); if (res != St_OK) { Data.Error = res; return; } Wire.requestFrom(AHT_I2C_ADDR, 1); data = Wire.read(); if ((data & STATUS_CALB) != STATUS_CALB) { //reinitialize registers res = JH_Reset_REG(0x1b); if (res != St_OK) { Data.Error = res; return; } res = JH_Reset_REG(0x1c); if (res != St_OK) { Data.Error = res; return; } res = JH_Reset_REG(0x1e); if (res != St_OK) { Data.Error = res; return; } delay(1); } Data.Error = St_OK; ReadyToRequest = true; } void AHTxx::SoftReset(void) { ahtxx_st_t res; Data.Error = St_OK; res = I2CWriteTo(CMD_SRESET); if (res != St_OK) { Data.Error = res; return; } } void AHTxx::StartMeasure(void) { if (ReadyToRequest == false) { return; } ahtxx_st_t res; Data.Error = St_OK; Wire.beginTransmission(AHT_I2C_ADDR); Wire.write(CMD_MEASURE); Wire.write(CMD_MEASURE_CTL); Wire.write(CMD_MEASURE_NOP); res = (ahtxx_st_t)Wire.endTransmission(); if (res != St_OK) { Data.Error = res; return; } } void AHTxx::GetData(ahtxx_t * data) { if (ReadyToRequest == false) { return; } ahtxx_st_t res; uint8_t buf[8] = {0}, i = 0; Data.Error = St_OK; /* Now read 7 bytes of data */ Wire.requestFrom(AHT_I2C_ADDR, 7); while (Wire.available()) { buf[i] = Wire.read(); i ++; } if (i < 7) { Data.Error = St_NACK_Data; data->Error = Data.Error; return; } if ((buf[0] & STATUS_BUSY) != 0) { Data.Error = St_Timeout; data->Error = Data.Error; return; } /* Calculate values */ uint32_t result; /* Humidity = Srh * 100% / 2^20 */ result = buf[1]; result <<= 8; result |= buf[2]; result <<= 8; result |= buf[3]; result >>= 4; result *= 1000; result += 524288; result /= 256; result /= 256; result /= 16; Data.Humidity = (uint16_t)result; // in xx.x % /* Temperature = St * 200 / 2^20 - 50 */ result = buf[3] & 0xf; result <<= 8; result |= buf[4]; result <<= 8; result |= buf[5]; result *= 2000; result += 524288; result /= 256; result /= 256; result /= 16; Data.Temperature = (int16_t)(result - 500); // in xx.x *C data->Error = Data.Error; data->Humidity = Data.Humidity; data->Temperature = Data.Temperature; } /** * CRC check type: CRC8/MAXIM * Polynomial: X8+X5+X4+1 * Poly: 0011 0001 0x31 * When the high bit is placed in the back, it becomes 1000 1100 0x8c */ uint8_t AHTxx::Calc_CRC8(uint8_t *message, uint8_t Num) { uint8_t i; uint8_t byte; uint8_t crc = 0xFF; for (byte=0; byte0; --i) { if (crc & 0x80) { crc = (crc << 1) ^ 0x31; } else { crc = (crc << 1); } } } return crc; } /* Reset register */ ahtxx_st_t AHTxx::JH_Reset_REG(uint8_t addr) { ahtxx_st_t res; uint8_t Byte_first, Byte_second, Byte_third; Wire.beginTransmission(AHT_I2C_ADDR); Wire.write((uint8_t)0x70); Wire.write(addr); Wire.write((uint8_t)0x00); Wire.write((uint8_t)0x00); res = (ahtxx_st_t)Wire.endTransmission(); if (res != St_OK) { return res; } delay(5); //Delay about 5ms Wire.beginTransmission(AHT_I2C_ADDR); Wire.write((uint8_t)0x71); res = (ahtxx_st_t)Wire.endTransmission(); if (res != St_OK) { return res; } Wire.requestFrom(AHT_I2C_ADDR, 3); Byte_first = Wire.read(); Byte_second = Wire.read(); Byte_third = Wire.read(); delay(10); //Delay about 10ms Wire.beginTransmission(AHT_I2C_ADDR); Wire.write((uint8_t)0x70); Wire.write((uint8_t)(0xB0|addr)); //register command Wire.write(Byte_second); Wire.write(Byte_third); res = (ahtxx_st_t)Wire.endTransmission(); if (res != St_OK) { return res; } return St_OK; } ahtxx_st_t AHTxx::I2CWriteTo(uint8_t DataToSend) { Wire.beginTransmission(AHT_I2C_ADDR); Wire.write(DataToSend); return (ahtxx_st_t)Wire.endTransmission(); } bool AHTxx::IsReadyToRequest(void) { return ReadyToRequest; }