/**
* @file SHT3X_ATY.c
*
* @param Project DEVICE_GENERAL_ATY_LIB
*
* @author ATY
*
* @copyright
* - Copyright 2017 - 2025 MZ-ATY
* - This code follows:
* - MZ-ATY Various Contents Joint Statement -
*
* https://mengze.top/MZ-ATY_VCJS
* - CC 4.0 BY-NC-SA -
*
* https://creativecommons.org/licenses/by-nc-sa/4.0/
* - Your use will be deemed to have accepted the terms of this statement.
*
* @brief Familiar 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"
/******************************* For user *************************************/
/******************************************************************************/
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 */
/******************************** End Of File *********************************/