#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 /* Private variables */ static ahtxx_t Data; static Timer startTimer, getTimer; /* Private functions prototypes */ static ahtxx_st_t I2CWriteTo(uint8_t DataToSend); //static uint8_t Calc_CRC8(uint8_t *message, uint8_t Num); static ahtxx_st_t JH_Reset_REG(uint8_t addr); void _Init(void); void _GetData(void); void _StartMeasure(void); /** * Initialization */ void AHTxx_Init(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(); } void _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 = St_NoSensor; 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; // start polling sensors - once per two seconds startTimer.initializeMs(2000, _StartMeasure).start(); } void AHTxx_SoftReset(void) { ahtxx_st_t res; Data.Error = St_OK; res = I2CWriteTo(CMD_SRESET); if (res != St_OK) { Data.Error = res; return; } startTimer.restart(); } /** * @brief Start Sensor measure. */ void _StartMeasure(void) { 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; } getTimer.initializeMs(600, _GetData).startOnce(); } void AHTxx_GetData(ahtxx_t * data) { data->Error = Data.Error; data->Humidity = Data.Humidity; data->Temperature = Data.Temperature; } void _GetData(void) { 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; return; } if ((buf[0] & STATUS_BUSY) != 0) { Data.Error = St_Timeout; 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 } /* Reset register */ static ahtxx_st_t 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; } static ahtxx_st_t I2CWriteTo(uint8_t DataToSend) { Wire.beginTransmission(AHT_I2C_ADDR); Wire.write(DataToSend); return (ahtxx_st_t)Wire.endTransmission(); } /** * 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 */ /* static uint8_t 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; } */