mirror of
https://github.com/1991Patrick/I2C_SHT2x.git
synced 2025-03-14 12:27:30 +03:00
257 lines
9.9 KiB
C
257 lines
9.9 KiB
C
/*!
|
||
* \file I2C_SHT2x.c
|
||
* \author Patrick Taling (not the original author from the original code of SENSIRION AG)
|
||
* \date 31/03/2017
|
||
* \version 1.0
|
||
*
|
||
* \brief Simple I2C SHT2x library to measure relative humidity and temperature and write it to an I2C LCD with the ATxmega256a3u.
|
||
*
|
||
* \details The file I2C_SHT2x.c is the library for the SHT2x humidity and temperature sensor
|
||
*
|
||
* The library needs the i2c library from w.e.dolman (<a href="mailto:w.e.dolman@hva.nl">w.e.dolman@hva.nl</a>)
|
||
* For i2c.c use code 21.8 from "de taal C en de Xmega tweede druk" http://dolman-wim.nl/xmega/book/index.php
|
||
* For i2c.h use code 21.9 from "de taal C en de Xmega tweede druk" http://dolman-wim.nl/xmega/book/index.php
|
||
*
|
||
* The libraby needs some parts of the the SHT2x library from SENIRION from https://www.sensirion.com/en/products/humidity-sensors/humidity-temperature-sensor-sht2x-digital-i2c-accurate/
|
||
* The libraby can be download from: https://www.sensirion.com/en/products/all-documents-of-sensirions-humidity-sensors-for-download/
|
||
* Go to SHT2x/ Sample Code SHT21 and download the zip file Sensirion_Humidity_Sensors_SHT21_Sample_Code_C-file
|
||
*
|
||
* \note the following files aren't fully used. Most parts are used in other .c of .h files or disabled.
|
||
* DisplayDip204.C, DisplayDip204.h,
|
||
* I2C_HAL.c, I2C_HAL.h,
|
||
* System.c, System.h and
|
||
* io70f3740.h.
|
||
* \note for the use of two SHT2X you should use different IOs for SDA or additional hardware such as I2C multiplexer.
|
||
* The adress of the SHT2x can’t be changed.
|
||
*
|
||
*
|
||
* \ORIGINAL AUTHOR INFORMATION
|
||
* ==============================================================================
|
||
* S E N S I R I O N AG, Laubisruetistr. 50, CH-8712 Staefa, Switzerland
|
||
* ==============================================================================
|
||
* Project : SHT2x Sample Code (V1.2)
|
||
* File : SHT2x.c
|
||
* Author : MST
|
||
* Controller: NEC V850/SG3 (uPD70F3740)
|
||
* Compiler : IAR compiler for V850 (3.50A)
|
||
* Brief : Sensor layer. Functions for sensor access
|
||
* ==============================================================================
|
||
*
|
||
*
|
||
* \verbatim
|
||
#include <I2C_SHT2x.h>
|
||
#include <i2c.h>
|
||
#include <Typedefs.h>
|
||
\endverbatim
|
||
* \par
|
||
*
|
||
* \note An AVR-project can use multiple I2C's. One shoud take care that
|
||
* in different source files there are no multiple I2C
|
||
* definitions for the same I2C.
|
||
*/
|
||
|
||
#define F_CPU 2000000UL
|
||
#include "I2C_SHT2x.h"
|
||
#include "i2c.h"
|
||
#include "Typedefs.h"
|
||
#include <util/delay.h>
|
||
#include <assert.h>
|
||
#include <math.h>
|
||
|
||
|
||
//==============================================================================
|
||
uint8_t i2c_SHT2x_CheckCrc(uint8_t data[], uint8_t nbrOfBytes, uint8_t checksum)
|
||
//==============================================================================
|
||
{
|
||
uint8_t crc = 0;
|
||
uint8_t byteCtr;
|
||
//calculates 8-Bit checksum with given polynomial
|
||
for (byteCtr = 0; byteCtr < nbrOfBytes; ++byteCtr)
|
||
{ crc ^= (data[byteCtr]);
|
||
for (uint8_t bit = 8; bit > 0; --bit)
|
||
{ if (crc & 0x80) {crc = (crc << 1) ^ POLYNOMIAL;}
|
||
else crc = (crc << 1);
|
||
}
|
||
}
|
||
if (crc != checksum) return CHECKSUM_ERROR;
|
||
else return 0;
|
||
}
|
||
//===========================================================================
|
||
uint8_t i2c_SHT2x_ReadUserRegister(uint8_t *pRegisterValue)
|
||
//===========================================================================
|
||
{
|
||
uint8_t checksum;
|
||
uint8_t error=0;
|
||
error |= i2c_start(&TWIE, I2C_SHT2x_ADR, 0);
|
||
error |= i2c_write(&TWIE, USER_REG_R);
|
||
i2c_stop(&TWIE);
|
||
error |= i2c_start(&TWIE, I2C_SHT2x_ADR, 1);
|
||
*pRegisterValue = i2c_read(&TWIE, I2C_ACK);
|
||
checksum=i2c_read(&TWIE, I2C_NACK);
|
||
error |= i2c_SHT2x_CheckCrc (pRegisterValue,1,checksum);
|
||
i2c_stop(&TWIE);
|
||
return error;
|
||
}
|
||
//===========================================================================
|
||
uint8_t i2c_SHT2x_WriteUserRegister(uint8_t *pRegisterValue)
|
||
//===========================================================================
|
||
{
|
||
uint8_t error=0;
|
||
_delay_ms(2000);
|
||
error |= i2c_start(&TWIE, I2C_SHT2x_ADR, 0);
|
||
error |= i2c_write(&TWIE, USER_REG_W);
|
||
error |= i2c_write(&TWIE, *pRegisterValue);
|
||
i2c_stop(&TWIE);
|
||
return error;
|
||
}
|
||
//===========================================================================
|
||
uint8_t i2c_SHT2x_MeasureHM(etSHT2xMeasureType eSHT2xMeasureType, nt16 *pMeasurand)
|
||
//===========================================================================
|
||
{
|
||
|
||
uint8_t checksum;
|
||
uint8_t data[2];
|
||
uint8_t error=0;
|
||
|
||
//-- write I2C sensor address and command --
|
||
error |= i2c_start(&TWIE, I2C_SHT2x_ADR, 0);
|
||
|
||
switch(eSHT2xMeasureType)
|
||
{ case HUMIDITY: error |= i2c_write(&TWIE, TRIG_RH_MEASUREMENT_HM); break;
|
||
case TEMP: error |= i2c_write(&TWIE, TRIG_T_MEASUREMENT_HM); break;
|
||
default: assert(0);
|
||
}
|
||
i2c_stop(&TWIE);
|
||
|
||
//-- wait until hold master is released --
|
||
error |= i2c_start(&TWIE, I2C_SHT2x_ADR, 1);
|
||
|
||
//-- read two data bytes and one checksum byte --
|
||
pMeasurand->s16.u8H = data[0] = i2c_read(&TWIE, I2C_ACK);
|
||
pMeasurand->s16.u8L = data[1] = i2c_read(&TWIE, I2C_ACK);
|
||
checksum= i2c_read(&TWIE, I2C_NACK);
|
||
|
||
//-- verify checksum --
|
||
error |= i2c_SHT2x_CheckCrc (data,2,checksum);
|
||
i2c_stop(&TWIE);
|
||
return error;
|
||
}
|
||
//===========================================================================
|
||
uint8_t i2c_SHT2x_MeasurePoll(etSHT2xMeasureType eSHT2xMeasureType, nt16 *pMeasurand)
|
||
//--- Disabled due to error in TEMP ---
|
||
//--- measuring TEMP doesn't work after the do while loop ---
|
||
//===========================================================================
|
||
{
|
||
uint8_t checksum;
|
||
uint8_t data[2];
|
||
uint8_t error=0;
|
||
uint16_t i=0;
|
||
|
||
//-- write I2C sensor address and command --
|
||
error |= i2c_start(&TWIE, I2C_SHT2x_ADR, 0); // I2C Adr
|
||
switch(eSHT2xMeasureType)
|
||
{ case HUMIDITY: error |= i2c_write(&TWIE, TRIG_RH_MEASUREMENT_POLL); break;
|
||
case TEMP: error |= i2c_write(&TWIE, TRIG_T_MEASUREMENT_POLL); break;
|
||
default: assert(0);
|
||
}
|
||
_delay_us(20);
|
||
i2c_stop(&TWIE);
|
||
|
||
//-- poll every 10ms for measurement ready. Timeout after 20 retries (200ms)--
|
||
do
|
||
{
|
||
_delay_us(10000); //delay 10ms Max delay is 0.2s (20*10ms = 200ms)
|
||
if(i++ >= 20) break;
|
||
} while(i2c_start(&TWIE, I2C_SHT2x_ADR, 1) == ACK_ERROR);
|
||
if (i>=20) error |= TIME_OUT_ERROR;
|
||
|
||
//-- read two data bytes and one checksum byte --
|
||
pMeasurand->s16.u8H = data[0] = i2c_read(&TWIE, I2C_ACK);
|
||
pMeasurand->s16.u8L = data[1] = i2c_read(&TWIE, I2C_ACK);
|
||
checksum= i2c_read(&TWIE, I2C_NACK);
|
||
|
||
//-- verify checksum --
|
||
error |= i2c_SHT2x_CheckCrc (data,2,checksum);
|
||
i2c_stop(&TWIE);
|
||
return error;
|
||
}
|
||
//===========================================================================
|
||
uint8_t i2c_SHT2x_SoftReset()
|
||
//===========================================================================
|
||
{
|
||
uint8_t error=0;
|
||
error |= i2c_start(&TWIE, I2C_SHT2x_ADR, 0);
|
||
error |= i2c_write(&TWIE, SOFT_RESET);
|
||
i2c_stop(&TWIE);
|
||
_delay_ms(15);
|
||
return error;
|
||
}
|
||
//==============================================================================
|
||
float i2c_SHT2x_CalcRH(uint16_t sRH)
|
||
// --- The original formula from SENSIRION is wrong! ---
|
||
//==============================================================================
|
||
{
|
||
float humidityRH;
|
||
sRH &= ~0x0003;
|
||
|
||
//-- calculate relative humidity [%RH] --
|
||
humidityRH = (float)sRH / RESOLUTION_16; //RH = -6 + 125 * sRH/2^16;
|
||
humidityRH = humidityRH * CONSTANT_125;
|
||
humidityRH = humidityRH - CONSTANT_6;
|
||
|
||
return humidityRH;
|
||
}
|
||
//==============================================================================
|
||
float i2c_SHT2x_CalcTemperatureC(uint16_t sT)
|
||
// --- The original formula from SENSIRION is wrong! ---
|
||
//==============================================================================
|
||
{
|
||
float temperatureC;
|
||
sT &= ~0x0003;
|
||
|
||
//-- calculate temperature [°C] --
|
||
temperatureC = (float)sT / RESOLUTION_16; //T= -46.85 + 175.72 * ST/2^16
|
||
temperatureC = temperatureC * CONSTANT_175_72;
|
||
temperatureC = temperatureC - CONSTANT_46_85;
|
||
|
||
return temperatureC;
|
||
}
|
||
|
||
//==============================================================================
|
||
uint8_t i2c_SHT2x_GetSerialNumber(uint8_t SerialNumber[])
|
||
//==============================================================================
|
||
{
|
||
uint8_t error=0; //error variable
|
||
//Read from memory location 1
|
||
error |= i2c_start(&TWIE, I2C_SHT2x_ADR, 0); //I2C address
|
||
error |= i2c_write(&TWIE, CMD_CHIP_MEMORY_LOC_1); //Command for readout on-chip memory
|
||
error |= i2c_write(&TWIE, ADR_CHIP_MEMORY_LOC_1); //on-chip memory address
|
||
i2c_stop(&TWIE);
|
||
|
||
error |= i2c_start(&TWIE, I2C_SHT2x_ADR, 1); //I2C read address
|
||
SerialNumber[5] = i2c_read(&TWIE, I2C_ACK); //Read SNB_3
|
||
i2c_read(&TWIE, I2C_ACK); //Read CRC SNB_3 (CRC is not analyzed)
|
||
SerialNumber[4] = i2c_read(&TWIE, I2C_ACK); //Read SNB_2
|
||
i2c_read(&TWIE, I2C_ACK); //Read CRC SNB_2 (CRC is not analyzed)
|
||
SerialNumber[3] = i2c_read(&TWIE, I2C_ACK); //Read SNB_1
|
||
i2c_read(&TWIE, I2C_ACK);; //Read CRC SNB_1 (CRC is not analyzed)
|
||
SerialNumber[2] = i2c_read(&TWIE, I2C_ACK); //Read SNB_0
|
||
i2c_read(&TWIE, I2C_NACK); //Read CRC SNB_0 (CRC is not analyzed)
|
||
i2c_stop(&TWIE);
|
||
|
||
//Read from memory location 2
|
||
error |= i2c_start(&TWIE, I2C_SHT2x_ADR, 0); //I2C address
|
||
error |= i2c_write(&TWIE, CMD_CHIP_MEMORY_LOC_2); //Command for readout on-chip memory
|
||
error |= i2c_write(&TWIE, ADR_CHIP_MEMORY_LOC_2); //on-chip memory address
|
||
i2c_stop(&TWIE);
|
||
|
||
error |= i2c_start(&TWIE, I2C_SHT2x_ADR, 1); //I2C address
|
||
SerialNumber[1] = i2c_read(&TWIE, I2C_ACK); //Read SNC_1
|
||
SerialNumber[0] = i2c_read(&TWIE, I2C_ACK); //Read SNC_0
|
||
i2c_read(&TWIE, I2C_ACK); //Read CRC SNC0/1 (CRC is not analyzed)
|
||
SerialNumber[7] = i2c_read(&TWIE, I2C_ACK); //Read SNA_1
|
||
SerialNumber[6] = i2c_read(&TWIE, I2C_ACK); //Read SNA_0
|
||
i2c_read(&TWIE, I2C_NACK); //Read CRC SNA0/1 (CRC is not analyzed)
|
||
i2c_stop(&TWIE);
|
||
return error;
|
||
} |