In this example we connect a Si7021 I2C Humidity and Temperature Sensor to an ESP32 running Micropython
The Si7021 I2C Humidity and Temperature Sensor is a monolithic CMOS IC integrating humidity and temperature sensor elements, an analog-to-digital converter, signal processing, calibration data, and an I2C Interface. The patented
use of industry-standard, low-K polymeric dielectrics for sensing humidity enables the construction of low-power, monolithic CMOS Sensor ICs with low drift and hysteresis, and excellent long term stability.
The humidity and temperature sensors are factory-calibrated and the calibration data is stored in the on-chip non-volatile memory. This ensures that the sensors are fully interchangeable, with no recalibration or software changes required.
Parts List
I actually used a GY-21P which is a combined BMP280 and Si7021 sensor in one module. We only deal with the Si7021 module here
Connection
An easy module to connect to an ESP32, SCL is 22 and SDA is 21 on the Wemos board I used, you can see this is the schematic below
Code
You can use any method to upload files or an IDE for development.
The following is based on a github library – . The first part of this is the library which I upload to my ESP32
This is the library called si7021.py
[codesyntax lang=”python”]
'''This module implements a driver for the Si7021 humidity and temperature sensor. Datasheet: https://www.silabs.com/Support%20Documents%2FTechnicalDocs%2FSi7021-A20.pdf ''' from time import sleep class CRCError(Exception): 'Data failed a CRC check.' pass class Si7021(object): 'Driver for the Si7021 temperature sensor.' SI7021_DEFAULT_ADDRESS = 0x40 SI7021_MEASTEMP_NOHOLD_CMD = bytearray([0xF3]) SI7021_MEASRH_NOHOLD_CMD = bytearray([0xF5]) SI7021_RESET_CMD = bytearray([0xFE]) SI7021_ID1_CMD = bytearray([0xFA, 0x0F]) SI7021_ID2_CMD = bytearray([0xFC, 0xC9]) I2C_WAIT_TIME = 0.025 def __init__(self, i2c, address=SI7021_DEFAULT_ADDRESS): 'Initialize an Si7021 sensor object.' self.i2c = i2c self.address = address self.serial, self.identifier = self._get_device_info() @property def temperature(self): 'Return the temperature in Celcius.' temperature = self._get_data(self.SI7021_MEASTEMP_NOHOLD_CMD) celcius = temperature * 175.72 / 65536 - 46.85 return celcius @temperature.setter def temperature(self, value): raise AttributeError('can\'t set attribute') @property def relative_humidity(self): 'Return the relative humidity as a percentage. i.e. 35.59927' relative_humidity = self._get_data(self.SI7021_MEASRH_NOHOLD_CMD) relative_humidity = relative_humidity * 125 / 65536 - 6 return relative_humidity @relative_humidity.setter def relative_humidity(self, value): raise AttributeError('can\'t set attribute') def reset(self): 'Reset the sensor.' self.i2c.writeto(self.address, self.SI7021_RESET_CMD) sleep(self.I2C_WAIT_TIME) def _get_data(self, command): 'Retrieve data from the sensor and verify it with a CRC check.' data = bytearray(3) self.i2c.writeto(self.address, command) sleep(self.I2C_WAIT_TIME) self.i2c.readfrom_into(self.address, data) value = self._convert_to_integer(data[:2]) verified = self._verify_checksum(data) if not verified: raise CRCError('Data read off i2c bus failed CRC check.', data[:2], data[-1]) return value def _get_device_info(self): '''Get the serial number and the sensor identifier. The identifier is part of the bytes returned for the serial number. ''' # Serial 1st half self.i2c.writeto(self.address, self.SI7021_ID1_CMD) id1 = bytearray(8) sleep(self.I2C_WAIT_TIME) self.i2c.readfrom_into(self.address, id1) # Serial 2nd half self.i2c.writeto(self.address, self.SI7021_ID2_CMD) id2 = bytearray(6) sleep(self.I2C_WAIT_TIME) self.i2c.readfrom_into(self.address, id2) combined_id = bytearray([id1[0], id1[2], id1[4], id1[6], id2[0], id2[1], id2[3], id2[4]]) serial = self._convert_to_integer(combined_id) identifier = self._get_device_identifier(id2[0]) return serial, identifier def _convert_to_integer(self, bytes_to_convert): 'Use bitwise operators to convert the bytes into integers.' integer = None for chunk in bytes_to_convert: if not integer: integer = chunk else: integer = integer << 8 integer = integer | chunk return integer def _get_device_identifier(self, identifier_byte): '''Convert the identifier byte to a device identifier. Values are based on the information from page 24 of the datasheet. ''' if identifier_byte == 0x00 or identifier_byte == 0xFF: return 'engineering sample' elif identifier_byte == 0x0D: return 'Si7013' elif identifier_byte == 0x14: return 'Si7020' elif identifier_byte == 0x15: return 'Si7021' else: return 'unknown' def _verify_checksum(self, data): ''''Verify the checksum using the polynomial from page 19 of the datasheet. x8 + x5 + x4 + 1 = 0x131 = 0b100110001 Valid Example: byte1: 0x67 [01100111] byte2: 0x8c [10001100] byte3: 0xfc [11111100] (CRC byte) ''' crc = 0 values = data[:2] checksum = int(data[-1]) for value in values: crc = crc ^ value for _ in range(8, 0, -1): if crc & 0x80: #10000000 crc <<= 1 crc ^= 0x131 #100110001 else: crc <<= 1 if crc != checksum: return False else: return True def convert_celcius_to_fahrenheit(celcius): 'Convert a Celcius measurement into a Fahrenheit measurement.' return celcius * 1.8 + 32
[/codesyntax]
Now you upload this library and then you can create or modify the main.py with this example code
[codesyntax lang=”python”]
import si7021 import machine i2c = machine.I2C(sda=machine.Pin(21),scl=machine.Pin(22)) temp_sensor = si7021.Si7021(i2c) print('Serial: {value}'.format(value=temp_sensor.serial)) print('Identifier: {value}'.format(value=temp_sensor.identifier)) print('Temperature: {value}'.format(value=temp_sensor.temperature)) print('Relative Humidity: {value}'.format(value=temp_sensor.relative_humidity))
[/codesyntax]
Testing
Open up the REPL window. Here is what I saw in uPyCraft
Ready to download this file,please wait!
….
download ok
exec(open(‘./main.py’).read(),globals())
Serial: 9108027469264322559
Identifier: Si7021
Temperature: 23.03474
Relative Humidity: 36.35458
>>>
Links
https://www.silabs.com/documents/public/data-sheets/Si7021-A20.pdf
1 comment
Looks good, D
did you try 2 and more sensors on one esp32 ?