Hardware:
- LC Tech STM32 Study Board – a copy (but not a clone) of the MicroPython pyboard. Great Scott has a (great) review of this board
- SHT21 module based on the Sensirion SHT21 I2C temperature and humidity sensor
- LHT00SU1 logic analyser
SHT21 range and resolution:
The sensor’s temperature and humidity ranges are -40…125°C and 0…100%RH respectively, however the normal/useful range is given by the graph below.

The sensor has multiple measurement resolutions for temperature and humidity, the data sheet stating a default resolution of 14bit (temperature) / 12bit (humidity) – we’ll see later how to check this and change it if needed.
Please note the measurement times as a function of measurement resolution – this will be helpful later when we need to decide the wait time between sending the measurement command to the sensor and reading the data.

Wiring:
MicroPython code:
from machine import Pin from machine import SoftI2C import time scl = Pin('X9') sda = Pin('X10') bytes_read = bytearray(2) # Sensor commands: tMeasNoHold = b'\xF3' # b11110011 RHMeasNoHold = b'\xF5' # b11110101 ReadUserRegister = b'\xE7' # b11100111 # I2C Header: # The I2C header consists of the 7bit I2C device address ‘1000000’ and an SDA direction bit (Read R: ‘1’, Write W: ‘0’): I2CHeader_Write = b'\x80' # b10000000 I2CHeader_Read = b'\x81' # b10000001 # Start the I2C comms: I2C = SoftI2C(scl, sda, freq=1000, timeout=50000) def get_temp(): # ####################################################### # Send Write command, trigger a Temp measurement: # Transmission Start condition(S): I2C.start() # write the 2 bytes data frame (header + command). # The sensor indicates the proper reception of a byte by pulling the SDA pin low (ACK bit) # after the falling edge of the 8th SCL clock. noACKw = I2C.write(I2CHeader_Write + tMeasNoHold) print('Write command, No. of ACK bits: ',noACKw) # When using the no hold master mode it is recommended to include a wait period of 20 µs # after the reception of the sensor’s ACK bit and before the Stop condition. time.sleep_us(20) # Transmission Stop condition(P): I2C.stop() # ####################################################### # Wait for the measurement to finish before reading the data: # For a 14bit resolution the max measuring time for temp is 85ms time.sleep_ms(85) # ####################################################### # Read the measurement data: # Transmission Start condition(S): I2C.start() noACKr = I2C.write(I2CHeader_Read) print('Read command , No. of ACK bits: ', noACKr) # Read the data (2 bytes) I2C.readinto(bytes_read) # Transmission Stop condition(P): I2C.stop() # ####################################################### # convert the binary data to something more meaningful using the formula in the SHT21 data sheet: t_SHT21 = (bytes_read[0] << 8) + bytes_read[1] t_SHT21 *= 175.72 t_SHT21 /= pow(2,16) t_SHT21 -= 46.85 # Debug: print ('***************************************************************') print ('bytes_read[0]: ', bin(bytes_read[0])) print ('bytes_read[0] shifted left by 8 bits: ', bin((bytes_read[0] << 8))) print ('bytes_read[1]: ', bin(bytes_read[1])) print ('Measurement data = : ', bin((bytes_read[0] << 8) + bytes_read[1])) print ('***************************************************************') return round (t_SHT21,2)
Logic analyser snapshots:
SCL frequency set to 1000Hz (see line 20):

Write command (see lines 25 … 41):

Wait for the measurement to finish:

Read the measurement data (see lines 49…61):

Quite a hot day:
The above logic analyser snaphots are corelated to the following get_temp() run:
