And the story behind:
Somebody sent to me a nice & tiny temperature/humidity sensor breakout board based on the Si7021 IC:
Si7021 Module - Top View |
On the Top side we have Si7021 Sensor only.
Si7021 Module - Bottom View |
Bottom Side, a 3.3V LDO and a Voltage level shifting circuit that probably makes it 5V tolerant on I2C bus. We will use it at 3.3V so nothing to worry about.
DESCRIPTION
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.
The Si7021 offers an accurate, low-power, factory-calibrated digital solution ideal for measuring humidity, dew-point, and temperature, in applications ranging from HVAC/R and asset tracking to industrial and consumer platforms.
Si7021 - Block Diagram |
Nice. Looks more or less like SHT21 from Sensirion. And we will see that it is quite compatible (at least on the temp/humidity reading procedure side) with small differences for the rest of registers.
FEATURES
- Precision Relative Humidity Sensor - ± 3% RH (max), 0–80% RH
- High Accuracy Temperature Sensor - ±0.4 °C (max), –10 to 85 °C
- 0 to 100% RH operating range
- Up to –40 to +125 °C operating range
- Wide operating voltage (1.9 to 3.6 V) (SHT21 - 2.1V min !)
- Low Power Consumption:
- 150 μA active current
- 60 nA standby current - Factory-calibrated
- I2C Interface
- Integrated on-chip heater
- 3x3 mm DFN Package
- Excellent long term stability
- Optional factory-installed cover
- Low-profile
- Protection during reflow
- Excludes liquids and particulates
Si7021 - Pinout Diagram |
Typical Application Circuit for Relative Humidity and Temperature Measurements
For more details please take a look at the Si7021 Datasheet.
What we will need:
- ESP8266 nEXT EVO Board
- Si7021 Module as the one from above
- For programming and uploading the driver and the software we will continue to use the LuaUploader as before.
Si7021 Board connected with ESP8266 nEXT EVO DevBoard - TOP view |
Si7021 Board connected with ESP8266 nEXT EVO DevBoard - 45 deg view |
Software implementation
The Si7021 communicates with the host controller over a digital I2C interface. The 7-bit base slave address is 0x40
Master I2C devices communicate with the Si7021 using a command structure. The commands are listed below in the I2C command table.
Commands other than those documented below are undefined and should not be sent to the device.
I2C Command Table |
Issuing a Measurement Command
The measurement commands instruct the Si7021 to perform one of two possible measurements: Relative Humidity or Temperature.
The procedure to issue any one of these commands is identical. While the measurement is in progress, the option of either clock stretching (Hold Master Mode) or Not Acknowledging read requests (No Hold Master Mode) is available to indicate to the master that the measurement is in progress. The chosen command code determines which mode is used.
Optionally, a checksum byte can be returned from the slave for use in checking for transmission errors. The checksum byte will follow the least significant measurement byte if it is acknowledged by the master.
The checksum byte is not returned if the master “not acknowledges” the least significant measurement byte. The checksum byte is calculated using a CRC generator polynomial of x^8+ x^5 + x^4 + 1, with an initialization of 0x00.
The checksum byte is optional after initiating an RH or temperature measurement with commands 0xE5, 0xF5,0xE3, and 0xF3. It is required for reading the electronic ID with commands 0xFA 0x0F and 0xFC 0xC9.
For all other commands, the checksum byte is not supported.
1. Init I2C bus/interface
Standard I2C Bus Initialisation function:
function init_I2C()
i2c.setup(bus, sda, scl, i2c.SLOW)
end
2. Write Si7021 Register Function
write_Si_Reg = function (dev_addr, set)
i2c.start(0x0)
i2c.address(0x0, dev_addr ,i2c.TRANSMITTER)
i2c.write(0x0,set)
i2c.stop(0x0)
tmr.delay(5000)
end
3. Read Si7021 Register Function
read_Si_Reg = function (dev_addr)
i2c.start(0x0)
i2c.address(0x0, dev_addr,i2c.RECEIVER)
tmr.delay(5000)
c = i2c.read(0x0,2)
i2c.stop(0x0)
rval = (bit.lshift(string.byte(c, 1), 8) + string.byte(c, 2))
status = bit.band(rval,3) --save status bits
rval = bit.band(rval,65532) --clear status bits
return rval, status
end
4. Measuring Relative Humidity
Once a relative humidity measurement has been made, the results of the measurement
may be converted to percent relative humidity by using the following expression:
hum = -6.0+125.0/65536.0*rval
A humidity measurement will always return XXXXXX10 in the LSB field -> Status bit = 1 ->
marking a Humidity measurement data.
function read_hum()
write_Si_Reg(dev_addr, RHumidityHoldCmd)
tmr.delay(10000)
read_Si_Reg(dev_addr)
hum = -6.0+125.0/65536.0*rval
print("\nStatus : "..status)
print("Humidity : "..string.format("%.2f",hum).."%")
end
5. Measuring Temperature
Each time a relative humidity measurement is made a temperature measurement is also made for the purposes of temperature compensation of the relative humidity measurement. If the temperature value is required, it can be read using command 0xE0; this avoids having to perform a second temperature measurement.
The measure temperature commands 0xE3 and 0xF3 will perform a temperature measurement and return the measurement value, command 0xE0 does not perform a measurement but returns the temperature value measured during the relative humidity measurement.
The checksum output is not available with the 0xE0 command.
The results of the temperature measurement may be converted to temperature in degrees Celsius (°C) using the following expression:
temp = -46.85+175.72/65536.0*rval
A temperature measurement will always return XXXXXX00 in the LSB field - Status bit = 0 -> marking a Temperature measurement data.
function read_temp()
write_Si_Reg(dev_addr, TempHoldCmd)
read_Si_Reg(dev_addr)
temp = -46.85+175.72/65536.0*rval
print("Status : "..status)
print("Temperature : "..string.format("%.2f",temp).."C")
end
6. Main Program
init_I2C()
tmr.alarm( 0, 5000, 1, function()
read_hum()
read_temp()
end)