I2C Communication with a temperature/humidity sensor : SI7021
tags: flipper, arduino, si7021, I2C
This is an example code of I2C communication between a temperature/humidity sensor and the flipper board.
The temperature/humidity sensor in the example is a SI7021 .
The sensor is wired on I2C1 communication bus so we will use Wire1 instance (if we were using I2C0 it would have been Wire instance, see flipper arduino bus references ). The i2C address of the SI7021 is 0x40 (see datasheet ).
Following code has been modified from this source.
1. Arduino Code
- flipper_si7021.ino
/* Si7021 sensor reading <strong>without</strong> library * Datasheet: https://www.silabs.com/documents/public/data-sheets/Si7021-A20.pdf */ /******************************I2C COMMAND TABLE***************************** * Measure Relative Humidity, Hold Master Mode 0xE5 * Measure Relative Humidity, No Hold Master Mode 0xF5 * Measure Temperature, Hold Master Mode 0xE3 * Measure Temperature, No Hold Master Mode 0xF3 * Read Temperature Value from Previous RH Measurement 0xE0 * Reset 0xFE * Write RH/T User Register 1 0xE6 * Read RH/T User Register 1 0xE7 * Write Heater Control Register 0x51 * Read Heater Control Register 0x11 * Read Electronic ID 1st Byte 0xFA 0x0F * Read Electronic ID 2nd Byte 0xFC 0xC9 * Read Firmware Revision 0x84 0xB8 * * source datasheet */ // This library allows you to communicate with I2C / TWI devices. # include <Wire.h> // SI7021 I2C address is 0x40(64) # define si7021Addr 0x40 // function for reading values into a array of unsigned int data[2] // from the Si7021 with a specific i2c address si7021Addr=0x40 // with one of the commands listed above. Function body at the end of this sketch void getSiData(unsigned int *_ret_data, byte _i2c_command); void setup() { //enabling VDD_SW power rail to give 5V source to the daughter board pinMode(SW_VDD_EN, OUTPUT); digitalWrite(SW_VDD_EN,HIGH); //enabling 5V_sensor power rail to switch on the sensor pinMode(EXP_36, OUTPUT); digitalWrite(EXP_36,HIGH); //enabling 3V3_SW power rail to pull the I2C bus up via the 10K resistors pinMode(SW_3V3_EN, OUTPUT); digitalWrite(SW_3V3_EN,HIGH); //wait for the power sources to be turned on delay(1000); // Initiate Wire1 and join the I2C1 bus Wire1.begin(); Serial.begin(115200); //reset sensor by sending 0xFE command to the Si7021 address Wire1.beginTransmission(si7021Addr); Wire1.write(0xFE); // Write reset command Wire1.endTransmission(); delay(15); // Default = 15ms } void loop(){ //sensor returns 2 bytes via I2C. It will be converted to temperature or humidity later unsigned int data[2]; //Send humidity measurement command and get response into the array 'data' getSiData(data, 0xE5); // Convert the data float humidity = ((data[0] * 256.0) + data[1]); humidity = ((125 * humidity) / 65536.0) - 6; // Send temperature measurement command getSiData(data, 0xE3); /* re-use temperature already measured by humidity measurement some milliseconds before command -> E0 *getSiData(data, 0xE0); * *However, does not report valid results * *Datasheet: *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. */ // Convert the data float temp = ((data[0] * 256.0) + data[1]); float celsTemp = ((175.72 * temp) / 65536.0) - 46.85; float fahrTemp = celsTemp * 1.8 + 32; // Output data to serial monitor Serial.print("Humidity : "); Serial.print(humidity); Serial.println(" % RH"); Serial.print("Celsius : "); Serial.print(celsTemp); Serial.println(" C"); delay(10000); } void getSiData(unsigned int *_ret_data, byte _i2c_command) { // start i2c communication Wire1.beginTransmission(si7021Addr); //send i2c command to sensor Wire1.write(_i2c_command); // we are done with our transmission...close i2c communication Wire1.endTransmission(); delay(85); // Request 2 bytes of data Wire1.requestFrom(si7021Addr, 2); // Read 2 bytes of data and save it to _ret_data which points to 'data[2]' if(Wire1.available() == 2) { _ret_data[0] = Wire1.read(); _ret_data[1] = Wire1.read(); }