| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570 |
- /**
- * @file SHT3X_ATY.c
- *
- * @param Project DEVICE_GENERAL_ATY_LIB
- *
- * @author ATY
- *
- * @copyright
- * - Copyright 2017 - 2026 MZ-ATY
- * - This code follows:
- * - MZ-ATY Various Contents Joint Statement -
- * <a href="https://mengze.top/MZ-ATY_VCJS">
- * https://mengze.top/MZ-ATY_VCJS</a>
- * - CC 4.0 BY-NC-SA -
- * <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
- * https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
- * - Your use will be deemed to have accepted the terms of this statement.
- *
- * @brief functions of SHT3X tem&hum transistor for all devices
- *
- * @version
- * - 1_01_200318 > ATY
- * -# Preliminary version, first Release
- * - 1_02_231229 > ATY
- * -# add multy addr and channel
- ********************************************************************************
- */
- #ifndef __SHT3X_ATY_C
- #define __SHT3X_ATY_C
- #include "SHT3X_ATY.h"
- /* ------------------------ Dev-style helpers & APIs ------------------------ */
- static uint8_t _sht3x_calc_crc(uint8_t* data, uint8_t len)
- {
- uint8_t bit_t;
- uint8_t crc = 0xFF;
- uint8_t i;
- for(i = 0; i < len; i++)
- {
- crc ^= data[i];
- for(bit_t = 8; bit_t > 0; --bit_t)
- {
- if(crc & 0x80)
- crc = (crc << 1) ^ POLYNOMIAL;
- else
- crc = (crc << 1);
- }
- }
- return crc;
- }
- static uint8_t _sht3x_check_crc(uint8_t* data, uint8_t len, uint8_t checksum)
- {
- return (_sht3x_calc_crc(data, len) != checksum);
- }
- static int _sht3x_write_cmd(SHT3X_ATY_Dev* dev, uint16_t cmd)
- {
- uint8_t buf[2];
- buf[0] = (uint8_t)(cmd >> 8);
- buf[1] = (uint8_t)(cmd & 0xFF);
- return dev && dev->i2c_write ? dev->i2c_write(dev->addr, buf, 2, dev->channel) : -1;
- }
- static void _sht3x_value_process(SHT3X_ATY_Dev* dev, uint16_t* temperature, uint16_t* humidity)
- {
- if(!dev || !temperature || !humidity) return;
- dev->lastTemperatureC = -45.0f + 175.0f * (1.0f * (*temperature) / 65535.0f);
- dev->lastHumidityPct = 100.0f * (1.0f * (*humidity) / 65535.0f);
- dev->warningFlag = 0;
- if(dev->lastTemperatureC < 0 || dev->lastTemperatureC > 65)
- dev->warningFlag = 1;
- else if(dev->lastTemperatureC < -40)
- {
- dev->warningFlag = 2;
- dev->lastTemperatureC = -40;
- }
- else if(dev->lastTemperatureC > 120)
- {
- dev->warningFlag = 2;
- dev->lastTemperatureC = 120;
- }
- if(dev->lastHumidityPct < 10 || dev->lastHumidityPct > 90)
- dev->warningFlag = 1;
- else if(dev->lastHumidityPct < 0)
- {
- dev->warningFlag = 2;
- dev->lastHumidityPct = 0;
- }
- else if(dev->lastHumidityPct > 100)
- {
- dev->warningFlag = 2;
- dev->lastHumidityPct = 100;
- }
- }
- static int _sht3x_read_data_and_crc(SHT3X_ATY_Dev* dev, uint16_t* temperature, uint16_t* humidity)
- {
- if(!dev || !dev->i2c_read) return -1;
- uint8_t bytes[6] = {0};
- int rc = dev->i2c_read(dev->addr, bytes, 6, dev->channel);
- if(rc) return rc;
- if(!_sht3x_check_crc(bytes, 2, bytes[2]))
- *temperature = (uint16_t)((bytes[0] << 8) | bytes[1]);
- else return -2;
- if(!_sht3x_check_crc(bytes + 3, 2, bytes[5]))
- *humidity = (uint16_t)((bytes[3] << 8) | bytes[4]);
- else return -3;
- _sht3x_value_process(dev, temperature, humidity);
- return 0;
- }
- void SHT3X_InitDev(SHT3X_ATY_Dev* dev, uint8_t addr, uint8_t channel)
- {
- if(!dev) return;
- dev->addr = addr;
- dev->channel = channel;
- dev->lastTemperatureC = 0.0f;
- dev->lastHumidityPct = 0.0f;
- dev->warningFlag = 0;
- if(dev->lock) dev->lock(1);
- SHT3X_StartPeriodicDev(dev, REPEATAB_HIGH, FREQUENCY_10HZ);
- for(int i = 0; i < 3; i++)
- {
- if(dev->delay_ms) dev->delay_ms(110);
- (void)SHT3X_ReadMeasurementDev(dev);
- }
- if(dev->lock) dev->lock(0);
- }
- void SHT3X_StartPeriodicDev(SHT3X_ATY_Dev* dev, sht3xRepeatability repeatability, sht3xFrequency frequency)
- {
- if(!dev) return;
- if(dev->lock) dev->lock(1);
- switch(repeatability)
- {
- case REPEATAB_LOW:
- switch(frequency)
- {
- case FREQUENCY_HZ5: _sht3x_write_cmd(dev, CMD_MEAS_PERI_05_L); break;
- case FREQUENCY_1HZ: _sht3x_write_cmd(dev, CMD_MEAS_PERI_1_L); break;
- case FREQUENCY_2HZ: _sht3x_write_cmd(dev, CMD_MEAS_PERI_2_L); break;
- case FREQUENCY_4HZ: _sht3x_write_cmd(dev, CMD_MEAS_PERI_4_L); break;
- case FREQUENCY_10HZ: _sht3x_write_cmd(dev, CMD_MEAS_PERI_10_L); break;
- default: break;
- }
- break;
- case REPEATAB_MEDIUM:
- switch(frequency)
- {
- case FREQUENCY_HZ5: _sht3x_write_cmd(dev, CMD_MEAS_PERI_05_M); break;
- case FREQUENCY_1HZ: _sht3x_write_cmd(dev, CMD_MEAS_PERI_1_M); break;
- case FREQUENCY_2HZ: _sht3x_write_cmd(dev, CMD_MEAS_PERI_2_M); break;
- case FREQUENCY_4HZ: _sht3x_write_cmd(dev, CMD_MEAS_PERI_4_M); break;
- case FREQUENCY_10HZ: _sht3x_write_cmd(dev, CMD_MEAS_PERI_10_M); break;
- default: break;
- }
- break;
- case REPEATAB_HIGH:
- switch(frequency)
- {
- case FREQUENCY_HZ5: _sht3x_write_cmd(dev, CMD_MEAS_PERI_05_H); break;
- case FREQUENCY_1HZ: _sht3x_write_cmd(dev, CMD_MEAS_PERI_1_H); break;
- case FREQUENCY_2HZ: _sht3x_write_cmd(dev, CMD_MEAS_PERI_2_H); break;
- case FREQUENCY_4HZ: _sht3x_write_cmd(dev, CMD_MEAS_PERI_4_H); break;
- case FREQUENCY_10HZ: _sht3x_write_cmd(dev, CMD_MEAS_PERI_10_H); break;
- default: break;
- }
- break;
- default: break;
- }
- if(dev->lock) dev->lock(0);
- }
- int SHT3X_ReadMeasurementDev(SHT3X_ATY_Dev* dev)
- {
- if(!dev) return -1;
- if(dev->lock) dev->lock(1);
- int rc = _sht3x_write_cmd(dev, CMD_FETCH_DATA);
- if(rc == 0)
- {
- uint16_t t = 0, h = 0;
- rc = _sht3x_read_data_and_crc(dev, &t, &h);
- }
- if(dev->lock) dev->lock(0);
- return rc;
- }
- int SHT3X_GetTempAndHumiClkStretchDev(SHT3X_ATY_Dev* dev, sht3xRepeatability repeatability)
- {
- if(!dev) return -1;
- if(dev->lock) dev->lock(1);
- switch(repeatability)
- {
- case REPEATAB_LOW: _sht3x_write_cmd(dev, CMD_MEAS_CLOCKSTR_L); break;
- case REPEATAB_MEDIUM: _sht3x_write_cmd(dev, CMD_MEAS_CLOCKSTR_M); break;
- case REPEATAB_HIGH: _sht3x_write_cmd(dev, CMD_MEAS_CLOCKSTR_H); break;
- default: break;
- }
- uint16_t t = 0, h = 0;
- int rc = _sht3x_read_data_and_crc(dev, &t, &h);
- if(dev->lock) dev->lock(0);
- return rc;
- }
- float SHT3X_GetTemperatureCDev(const SHT3X_ATY_Dev* dev)
- {
- return dev ? dev->lastTemperatureC : 0.0f;
- }
- float SHT3X_GetHumidityPctDev(const SHT3X_ATY_Dev* dev)
- {
- return dev ? dev->lastHumidityPct : 0.0f;
- }
- uint8_t SHT3X_GetWarningFlagDev(const SHT3X_ATY_Dev* dev)
- {
- return dev ? dev->warningFlag : 0;
- }
- /******************************* For user *************************************/
- /******************************************************************************/
- #if 0 /* legacy implementation disabled in Dev refactor */
- float temperatureSHT3X = 0.0;
- float humiditySHT3X = 0.0;
- /* 0: 0-65T, 10-90H, Best accuracy
- 1: -40-0/65-120T, 0-10/90-100H, not good accuracy, warning
- 2: out of limit data, error
- */
- uint8_t warningFlag = 0;
- /**
- * @brief calc crc with SHT3X data
- * @param sht3xData data to calc
- * @param nbrOfBytes length of data to calc
- * @return uint8_t crc value
- */
- uint8_t SHT3X_CalcCrc(uint8_t* sht3xData, uint8_t nbrOfBytes)
- {
- uint8_t bit_t; // bit mask
- uint8_t crc = 0xFF; // calculated checksum
- uint8_t byteCtr; // byte counter
- // calculates 8-Bit checksum with given polynomial
- for(byteCtr = 0; byteCtr < nbrOfBytes; byteCtr++)
- {
- crc ^= sht3xData[byteCtr];
- for(bit_t = 8; bit_t > 0; --bit_t)
- {
- if(crc & 0x80)
- crc = (crc << 1) ^ POLYNOMIAL;
- else
- crc = (crc << 1);
- }
- }
- return crc;
- }
- /**
- * @brief check crc with SHT3X data
- * @param sht3xData data to check
- * @param nbrOfBytes length of data to check
- * @param checksum compare value with calculated crc
- * @return !0: wrong, 0: success
- */
- uint8_t SHT3X_CheckCrc(uint8_t* sht3xData, uint8_t nbrOfBytes, uint8_t checksum)
- {
- // calculates 8-Bit checksum
- uint8_t crc = SHT3X_CalcCrc(sht3xData, nbrOfBytes);
- if(crc != checksum)
- return 1;
- else
- return 0;
- }
- /**
- * @brief write command to SHT3X
- * @param cmd command to send
- * @param addr chip address
- * @param channel chip channel
- */
- void SHT3X_WriteCommand(sht3xCommands cmd, uint8_t addr, uint8_t channel)
- {
- uint8_t cmd_t[2];
- cmd_t[0] = cmd >> 8;
- cmd_t[1] = cmd & 0xFF;
- I2C_Write(addr, cmd_t, 2, channel);
- }
- /**
- * @brief start periodic measurment
- * @param repeatability repeatability
- * @param frequency frequency
- * @param addr chip address
- * @param channel chip channel
- * @note use depending on the required repeatability and frequency,
- * the corresponding command
- */
- void SHT3X_StartPeriodicMeasurment(sht3xRepeatability repeatability, sht3xFrequency frequency, uint8_t addr, uint8_t channel)
- {
- switch(repeatability)
- {
- case REPEATAB_LOW: // low repeatability
- switch(frequency)
- {
- case FREQUENCY_HZ5: // low repeatability, 0.5 Hz
- SHT3X_WriteCommand(CMD_MEAS_PERI_05_L, addr, channel);
- break;
- case FREQUENCY_1HZ: // low repeatability, 1.0 Hz
- SHT3X_WriteCommand(CMD_MEAS_PERI_1_L, addr, channel);
- break;
- case FREQUENCY_2HZ: // low repeatability, 2.0 Hz
- SHT3X_WriteCommand(CMD_MEAS_PERI_2_L, addr, channel);
- break;
- case FREQUENCY_4HZ: // low repeatability, 4.0 Hz
- SHT3X_WriteCommand(CMD_MEAS_PERI_4_L, addr, channel);
- break;
- case FREQUENCY_10HZ: // low repeatability, 10.0 Hz
- SHT3X_WriteCommand(CMD_MEAS_PERI_10_L, addr, channel);
- break;
- default:
- break;
- }
- break;
- case REPEATAB_MEDIUM: // medium repeatability
- switch(frequency)
- {
- case FREQUENCY_HZ5: // medium repeatability, 0.5 Hz
- SHT3X_WriteCommand(CMD_MEAS_PERI_05_M, addr, channel);
- break;
- case FREQUENCY_1HZ: // medium repeatability, 1.0 Hz
- SHT3X_WriteCommand(CMD_MEAS_PERI_1_M, addr, channel);
- break;
- case FREQUENCY_2HZ: // medium repeatability, 2.0 Hz
- SHT3X_WriteCommand(CMD_MEAS_PERI_2_M, addr, channel);
- break;
- case FREQUENCY_4HZ: // medium repeatability, 4.0 Hz
- SHT3X_WriteCommand(CMD_MEAS_PERI_4_M, addr, channel);
- break;
- case FREQUENCY_10HZ: // medium repeatability, 10.0 Hz
- SHT3X_WriteCommand(CMD_MEAS_PERI_10_M, addr, channel);
- break;
- default:
- break;
- }
- break;
- case REPEATAB_HIGH: // high repeatability
- switch(frequency)
- {
- case FREQUENCY_HZ5: // high repeatability, 0.5 Hz
- SHT3X_WriteCommand(CMD_MEAS_PERI_05_H, addr, channel);
- break;
- case FREQUENCY_1HZ: // high repeatability, 1.0 Hz
- SHT3X_WriteCommand(CMD_MEAS_PERI_1_H, addr, channel);
- break;
- case FREQUENCY_2HZ: // high repeatability, 2.0 Hz
- SHT3X_WriteCommand(CMD_MEAS_PERI_2_H, addr, channel);
- break;
- case FREQUENCY_4HZ: // high repeatability, 4.0 Hz
- SHT3X_WriteCommand(CMD_MEAS_PERI_4_H, addr, channel);
- break;
- case FREQUENCY_10HZ: // high repeatability, 10.0 Hz
- SHT3X_WriteCommand(CMD_MEAS_PERI_10_H);
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- }
- /**
- * @brief calc real value from 16 bit data
- * @param temperature temperature 16 bit origin value
- * @param humidity humidity 16 bit origin value
- */
- void SHT3X_ValuePorcess(uint16_t* temperature, uint16_t* humidity)
- {
- temperatureSHT3X = -45 + 175 * (1.0 * (*temperature) / 65535);
- humiditySHT3X = 100 * (1.0 * (*humidity) / 65535);
- warningFlag = 0;
- if(temperatureSHT3X < 0 || temperatureSHT3X>65)
- warningFlag = 1;
- else if(temperatureSHT3X < -40)
- {
- warningFlag = 2;
- temperatureSHT3X = -40;
- }
- else if(temperatureSHT3X > 120)
- {
- warningFlag = 2;
- temperatureSHT3X = 120;
- }
- if(humiditySHT3X < 10 || humiditySHT3X>90)
- warningFlag = 1;
- else if(humiditySHT3X < 0)
- {
- warningFlag = 2;
- humiditySHT3X = 0;
- }
- else if(humiditySHT3X > 100)
- {
- warningFlag = 2;
- humiditySHT3X = 100;
- }
- }
- /**
- * @brief read all data from SHT3X
- * @param temperature temperature 16 bit origin value
- * @param humidity humidity 16 bit origin value
- * @param addr chip address
- * @param channel chip channel
- */
- void SHT3X_ReadDataAndCrc(uint16_t* temperature, uint16_t* humidity, uint8_t addr, uint8_t channel)
- {
- uint8_t bytes[6]; // read 2 data array and 1 checksum byte
- // read two data bytes and one checksum byte
- I2C_Read(addr, bytes, 6, channel);
- // verify checksum then combine the two bytes to a 16-bit value
- if(!SHT3X_CheckCrc(bytes, 2, bytes[2]))
- *temperature = (bytes[0] << 8) | bytes[1];
- // else
- // *temperature = 0;
- if(!SHT3X_CheckCrc(bytes + 3, 2, bytes[5]))
- *humidity = (bytes[3] << 8) | bytes[4];
- // else
- // *humidity = 0;
- SHT3X_ValuePorcess(temperature, humidity);
- }
- /**
- * @brief read data and calc real value
- * @param addr chip address
- * @param channel chip channel
- */
- void SHT3X_ReadMeasurementBuffer(uint8_t addr, uint8_t channel)
- {
- uint16_t hexValueTemp = 0;
- uint16_t hexValueHumi = 0;
- SHT3X_WriteCommand(CMD_FETCH_DATA, addr, channel);
- SHT3X_ReadDataAndCrc(&hexValueTemp, &hexValueHumi, addr, channel);
- }
- /**
- * @brief start measurement in clock stretching mode
- * @param repeatability repeatability
- * @param addr chip address
- * @param channel chip channel
- * @note use depending on the required repeatability, the corresponding command
- */
- void SHT3X_GetTempAndHumiClkStretch(sht3xRepeatability repeatability, uint8_t addr, uint8_t channel)
- {
- uint16_t hexTempValue = 0;
- uint16_t hexHumiValue = 0;
- switch(repeatability)
- {
- case REPEATAB_LOW:
- SHT3X_WriteCommand(CMD_MEAS_CLOCKSTR_L, addr, channel);
- break;
- case REPEATAB_MEDIUM:
- SHT3X_WriteCommand(CMD_MEAS_CLOCKSTR_M, addr, channel);
- break;
- case REPEATAB_HIGH:
- SHT3X_WriteCommand(CMD_MEAS_CLOCKSTR_H, addr, channel);
- break;
- default:
- break;
- }
- SHT3X_ReadDataAndCrc(&hexTempValue, &hexHumiValue, addr, channel);
- }
- /**
- * @brief init SHT3X, check device
- * @param addr chip address
- * @param channel chip channel
- * @note put at main init
- */
- void SHT3X_InitBegin(uint8_t addr, uint8_t channel)
- {
- uint8_t i = 0;
- SHT3X_StartPeriodicMeasurment(REPEATAB_HIGH, FREQUENCY_10HZ, addr, channel);
- for(i = 0; i < 9; i++)
- {
- DelayMs(110);
- SHT3X_ReadMeasurementBuffer(addr, channel);
- // SHT3X_GetTempAndHumiClkStretch(REPEATAB_LOW, addr, channel);
- }
- // SHT3X_StartPeriodicMeasurment(REPEATAB_LOW, FREQUENCY_HZ1, addr, channel);
- SHT3X_StartPeriodicMeasurment(REPEATAB_HIGH, FREQUENCY_10HZ, addr, channel);
- }
- // todo: not tested
- // void main()
- // {
- // SHT3X_InitBegin(addr, channel);
- // while(1)
- // {
- // SHT3X_ReadMeasurementBuffer(addr, channel);
- // UartSendStr("\r\nHT: ");
- // UartSendStr(TemperatureStr);
- // UartSendStr(" - ");
- // UartSendStr(HumidityStr);
- // DelayMs(2000);
- // }
- // }
- // // declare 5byte group, last with '\0' for show
- // uint8_t Temperature[5] = {0, 0, '.', 0};
- // uint8_t Humidity[5] = {0, 0, '.', 0};
- // uint8_t TemperatureStr[5] = {0, 0, '.', 0};
- // uint8_t HumidityStr[5] = {0, 0, '.', 0};
- // uint8_t temperatureHexI = 0; // integer
- // uint8_t temperatureHexD = 0; // decimal
- // uint8_t humidityHexI = 0;
- // uint8_t humidityHexD = 0;
- // temperature = ((uint8_t)decTempValue << 8) + ((uint16_t)(decTempValue * 100) % 100);
- // humidity = ((uint8_t)decHumiValue << 8) + ((uint16_t)(decHumiValue * 100) % 100);
- // temperatureHexI = temperature >> 8;
- // temperatureHexD = temperature;
- // humidityHexI = humidity >> 8;
- // humidityHexD = humidity;
- // // todo higher than 100 or below 0
- // // todo only get origin data, do not change type here
- // // todo AHT20 deal the same, and change I2C function to standard
- // // if()
- // Temperature[0] = temperatureHexI / 10;
- // Temperature[1] = temperatureHexI % 10;
- // Temperature[3] = temperatureHexD / 10;
- // Humidity[0] = humidityHexI / 10;
- // Humidity[1] = humidityHexI % 10;
- // Humidity[3] = humidityHexD / 10;
- // TemperatureStr[0] = Temperature[0] + '0';
- // TemperatureStr[1] = Temperature[1] + '0';
- // TemperatureStr[3] = Temperature[3] + '0';
- // HumidityStr[0] = Humidity[0] + '0';
- // HumidityStr[1] = Humidity[1] + '0';
- // HumidityStr[3] = Humidity[3] + '0';
- #endif /* __SHT3X_ATY_C */
- #endif /* legacy implementation disabled in Dev refactor */
- /******************************** End Of File *********************************/
|