====== 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 [[https://www.silabs.com/documents/public/data-sheets/Si7021-A20.pdf|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 [[products:flipper:arduino_bus_references|flipper arduino bus references]] ). The i2C address of the SI7021 is 0x40 (see {{ :products:flipper:si7021-a20.pdf |datasheet}} ). Following code has been modified from this [[https://github.com/ThomasBarris/Si7021/blob/master/example.ino|source]]. ===== - Arduino Code ===== /* Si7021 sensor reading without 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 // 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(); }