The SHT30 I2C Temperature and Humidity Sensor
Introduction
The SHT30 is a temperature and humidity sensor that communicates over the I2C bus. Typical accuracy for temperature is +- 0.1 °C and +- 1.5% relative humidity. Sensirion, the company behind the SHT30 supplies a series of documents including the data sheet, several application notes and sample code, written in C for the STM32F10x micro-controller. You can find them at
https://www.sensirion.com/products/catalog/SHT30-DIS-B
There is also
a SHT30 driver written for MicroPython on the ESP8266![](/pub/TWiki/TWikiDocGraphics/external-link.gif)
but unfortunately it did not work on the ESP32 out of the box. Making it work for the ESP32 is not too difficult however. This is the subject of an exercise on the SHT30 (
The I2C bus and the SHT30 Temperature and Humidity Sensor ). Since the SHT30 driver only implements a small subset of the SHT30 functionality, I developed a driver called SHT3X translating the Sensirion code into MicroPython and taking over some of the SHT30 code.
Here is a list of functions, their command codes and if they are implemented in the SHT30 driver:
Function |
Repeatability |
measurement per s |
Clock Stretching |
Command Code |
Implemented in SHT30 driver |
Single shot data acquisition |
High |
|
enabled |
0x2C06 |
no |
Medium |
0x2C0D |
no |
Low |
0x2C10 |
no |
High |
disabled |
0x2400 |
yes |
Medium |
0x240B |
no |
Low |
0x2416 |
no |
Continuous data acquisition |
High |
0.5 |
disabled |
0x2032 |
no |
Medium |
0x2024 |
no |
Low |
0x202F |
no |
High |
1 |
0x2130 |
no |
Medium |
0x2120 |
no |
Low |
0x212D |
no |
High |
2 |
0x2236 |
no |
Medium |
0x2220 |
no |
Low |
0x222B |
no |
High |
4 |
0x2334 |
no |
Medium |
0x2322 |
no |
Low |
0x2329 |
no |
High |
10 |
0x2737 |
no |
Medium |
0x2722 |
no |
Low |
0x272A |
no |
Read serial number |
|
|
|
0x3780 |
no |
Fetch Data |
|
|
|
0xE000 |
no |
Accelerated Response Time |
0x2B32 |
no |
Break continuous acquisition |
0x3093 |
no |
Soft Reset |
0x30A2 |
yes |
Heater enable |
0x306D |
yes |
Heater disable |
0x3066 |
yes |
Read out status register |
0xF32D |
yes |
Clear status register |
0x3041 |
yes |
Read high alert limit |
set |
0xE11F |
no |
clear |
0xE114 |
no |
Read low alert limit |
set |
0xE109 |
no |
clear |
0xE102 |
no |
Write high alert limit |
set |
0x611D |
no |
clear |
0x6116 |
no |
Write low alert limit |
set |
0x610B |
no |
clear |
0x6100 |
no |
The SHT30 command codes
The SHt30 uses 16 bit command codes with a 3-bit CRC (cyclic redundancy check) calculated over the upper 13 bit added on the lowest significant 3 bits.
Let us have a look at the "one time measurement" commands in order to understand the command layout. Here is the table from the data sheet:
If we analyze the codes we get:
Repeatability |
Clock Stretching |
Command code |
bit for clock stretching |
rest of command code |
bits for repeatability |
CRC |
High |
enabled |
0010 |
1 |
100 |
0000 0 |
110 |
Medium |
0010 |
1 |
100 |
0000 1 |
101 |
Low |
0010 |
1 |
100 |
0001 0 |
000 |
High |
disabled |
0010 |
0 |
100 |
0000 0 |
000 |
Medium |
0010 |
0 |
100 |
0000 1 |
011 |
Low |
0010 |
0 |
100 |
0001 0 |
110 |
As you can see, knowing the repeatability and the clock stretching parameter we can easily construct the command code: Starting from a command code 0x2400 we set bit 11 if clock stretching is enabled and we "or" 01 into bits 3 and 4 for medium and 10 for low repeatability to get the command code. This code we use as a key into a dictionary from where we can pick up the 3 bit checksum, which we or to bits 0..2 .
Methods available in the SHT3X class
Here is a list of the available methods of the SHT3Xclass:
__init__(scl_pin=machine.Pin(22),sda_pin=machine.Pin(21),i2c,address=0x45): creates an instance of the SHT3X object. The default values for scl_pin, sda_pin and i2c_address should be ok for the ESP32 and our version of the SHT30 shield. The method raises an SHT3XError.BUS_ERROR if the sht30 chip is not found on the I2C bus
from sht3x import SHT3X
sht30 = SHT3X()
should therefore work and create the SHT3X object.
sht30.isPresent(): returns
True if the sht30 is chip is found on the I2C bus,
False otherwise
sht30.serialNumber(): Returns the 32 bit serial number of the sht30 chip
sht30.readStatus(): Returns the status bits (16 bits) from the status register
sht30.printStatus(): Prints the status bits from the sht30 status register in a humanly readable form
sht30.clearStatus(): Clears the status register
sht30.softReset(): Resets the sht30
sht30.enableHeater(): Switches the heater on
sht30.disableHeater(): Switches the heater off
sht30.getTempAndHumi(clockStretching=!SHT3X.CLOCK_STRETCH, repeatability=!SHT3X.REP_S_LOW, raw=False, timeout=100)
gets temperature and humidity in the selected mode. If clock stretching as been selected the corresponding command 0x2cxx is issued followed by a wait until the measurement has been completed. The wait time used is the maximum measurement time for that mode found in table 4 chapter 2.2 of the data sheet.
If no clock stretching is selected, the method will poll the sht30 every ms for the result data. If within "timeout ms" the sht30 does not return the result an SHT3X.TIMEOUT error is raised.
After the wait, the data are read out and the checksum checked. If the checksum received is wrong an SHT3X.CRC_ERROR is raised.
If raw mode has been selected, the 6 byte result (16 bits for temperature, 16 bits humidity and 2*8 bits checksums) is returned. Otherwise the raw values are converted to physical temperature values (in °C) and relative humidity (in %) which are returned to the caller.
sht30.Celsius2Fahrenheit(tempC): takes a temperature value in °C and converts it to °F
sht30.startPeriodicMeas(mps=0.5,repeatability=self.REP_P_HIGH): starts repetitive measurements in the selected mode. In "continuous mode" clock stretching is not done. Here I wait for the period selected before the data are read out.
sht30.stopPeriodicMeas(): Stops "continuous measurement mode"
sht30.measPeriodic(self,mps=0.5, repeatability=REP_P_HIGH, raw=False, noOfMeas=50, callback=None): Starts continuous measurements using sht30.startPeriodicMeas(), reads out the data after each measurement and stops continuous measurements using stopPeriodicMeas() as soon as "noOfMeas" measurements have been reached. You can specify a callback function which is called with [tempC,humi], the temperature in °C and the humidity value in % as parameter if raw is False or with the raw data [tempRaw,humiRaw,checksum] as parameter if raw is True.
sht30.readAlert(high=True,set=True,raw=False): Reads the alert limits. Returns temperature and humidity limits for alerts in °C and % or the raw data read out if raw == True.
sht30.writeAlert(self,tempC,humi,high=True,set=True): Write the alert limits
Here you find the driver itself:
https://afnog.iotworkshop.africa/pub/IoT_Course_English/SHT30NopI2CTemperatureAndHumiditySensor/sht3x.py.txt
and here some test code exercising the driver:
https://afnog.iotworkshop.africa/pub/IoT_Course_English/SHT30NopI2CTemperatureAndHumiditySensor/sht3xTest.py.txt
And here is the result printed out by the test program:
>>> %Run -c $EDITOR_CONTENT
Serial number: 0x317d411
Measure with clock stretching, the delay between writing the cmd and reading back the result
is calculated from the repeatabilty parameter (see data sheet)
Temperature: 24.26994 °C, Humidity: 61.74011 %
Measure without clock stretching
After sending the command the SHT30 is polled for the result every 1ms
Generates a timeout exception if the SHT30 does not respond in time
Temperature: 24.28329 °C, Humidity: 61.75385 %
Read and print the alert settings: High limit to set the alert
The data sheet says that this should be 60°C and 80%
Temperature limit high: 59.93164 °C Humidity limit high: 79.6875 %
Set accelerated response time
Print the current status register contents
--------------------------------------------------
Status register content: 0x2060
--------------------------------------------------
No alert pending
Heater is enabled
Last command succeeded
Checksum of last write command was correct
Clear the status register, switch on the heater and print the values again
Switch on the heater
--------------------------------------------------
Status register content: 0x20a0
--------------------------------------------------
No alert pending
Heater is enabled
Last command succeeded
Checksum of last write command was correct
Start periodic measurement
We pass the function printContinuousValues as callback routine, printing the temperature and humidity values
read out in each measurement cycle
Period measurement will take 20.0 s
Interval: 2.0
Temperature: 24.21387 °C, Humidity: 61.6684 %
Temperature: 24.26994 °C, Humidity: 61.78131 %
Temperature: 24.28329 °C, Humidity: 61.79504 %
Temperature: 24.24057 °C, Humidity: 61.80878 %
Temperature: 24.25392 °C, Humidity: 61.83167 %
Temperature: 24.24057 °C, Humidity: 61.82861 %
Temperature: 24.22722 °C, Humidity: 61.85608 %
Temperature: 24.24057 °C, Humidity: 61.91101 %
Temperature: 24.22722 °C, Humidity: 61.92932 %
Temperature: 24.21387 °C, Humidity: 61.90643 %
--------------------------------------------------
Status register content: 0x2000
--------------------------------------------------
No alert pending
Heater is enabled
Last command succeeded
Checksum of last write command was correct
>>>
--
Uli Raich - 2020-05-22
Comments