SI7021 I2C pin setup (SOLVED)



  • @robert-hh Well I formatted the flash, then restarted the device.
    Than uploded SI7021.py, an empyt boot file, and a main.py with 6 line of code. But still no luck...

    Uploading project (main folder)...
    Not safe booting, disabled in settings
    Reading file status
    Failed to read project status, uploading all files
    Creating dir lib
    [1/3] Writing file boot.py
    [2/3] Writing file lib/SI7021.py
    [3/3] Writing file main.py
    Upload done, resetting board...
    OKets Jun  8 2016 00:22:57
    
    rst:0x7 (TG0WDT_SYS_RESET),boot:0x33 (SPI_FAST_FLASH_BOOT)
    configsip: 0, SPIWP:0xee
    clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    mode:DIO, clock div:1
    load:0x3fff8028,len:8
    load:0x3fff8030,len:1728
    load:0x4009fa00,len:0
    load:0x4009fa00,len:14584
    entry 0x400a059c
    [64]
    Traceback (most recent call last):
      File "main.py", line 6, in <module>
      File "/flash/lib/SI7021.py", line 32, in readTemp
    OSError: I2C bus error
    Pycom MicroPython 1.18.1.r1 [v1.8.6-849-b0520f1] on 2018-08-29; LoPy4 with ESP32
    Type "help()" for more information.
    

    my main.py:

    from machine import I2C
    from SI7021 import SI7021
    i2c=I2C(0, I2C.MASTER)
    print(i2c.scan())
    m = SI7021(i2c)
    print(m.readRH(), m.readTemp())
    

    my boot.py, is just comment

    and my SI7021 is like this:

    from time import sleep_ms
    from machine import Pin, I2C
    
    # Default Address
    SI7021_I2C_DEFAULT_ADDR = 0x40
    
    # Commands
    CMD_MEASURE_RELATIVE_HUMIDITY_HOLD_MASTER_MODE = 0xE5
    CMD_MEASURE_RELATIVE_HUMIDITY = 0xF5
    CMD_MEASURE_TEMPERATURE_HOLD_MASTER_MODE = 0xE3
    CMD_MEASURE_TEMPERATURE = 0xF3
    CMD_READ_TEMPERATURE_VALUE_FROM_PREVIOUS_RH_MEASUREMENT = 0xE0
    CMD_RESET = 0xFE
    CMD_WRITE_RH_T_USER_REGISTER_1 = 0xE6
    CMD_READ_RH_T_USER_REGISTER_1 = 0xE7
    CMD_WRITE_HEATER_CONTROL_REGISTER = 0x51
    CMD_READ_HEATER_CONTROL_REGISTER = 0x11
    
    class SI7021(object):
      def __init__(self, i2c=None):
        self.i2c = i2c
        self.addr = SI7021_I2C_DEFAULT_ADDR
        self.cbuffer = bytearray(2)
        self.cbuffer[1] = 0x00
        
      def write_command(self, command_byte):
        self.i2c.writeto(self.addr, command_byte)
    
      def readTemp(self):
        self.write_command(CMD_MEASURE_TEMPERATURE)
        sleep_ms(25)
        temp = self.i2c.readfrom(self.addr,3)
        temp2 = temp[0] << 8
        temp2 = temp2 | temp[1]
        return (175.72 * temp2 / 65536) - 46.85
    
      def readRH(self):
        self.write_command(CMD_MEASURE_RELATIVE_HUMIDITY)
        sleep_ms(25)
        rh = self.i2c.readfrom(self.addr, 3)
        rh2 = rh[0] << 8
        rh2 = rh2 | rh[1]
        return (125 * rh2 / 65536) - 6
    


  • @tttadam When you update the firmware, then you have in the advanced section the option to erase the file system. Other method from the REPL prompt:

    import uos
    uos.mkfs("/flash")
    

    And then reboot.



  • @robert-hh Can I do a factory reset somehow? Delete everything from the device.



  • @tttadam Please check that there is only one copy of SI7021.py installed on your device. When working with pymakr, that may happen. Please use simple tools like ftp for the check. And yes, the version I posted works. No, I do not think that your device is defect. And it is well protected. Ans since it responds well to scan(), the wiring is also fine. So the code or code set-up is most probably the problem.



  • @robert-hh

    Traceback (most recent call last):
      File "main.py", line 6, in <module>
      File "/flash/lib/SI7021.py", line 32, in readTemp
    OSError: I2C bus error
    

    still the same. If it's working on your side, than my sensor must be dead.



  • @tttadam Don't care about the baud rate. Here is works well at the default baud rate (I purchased I device for testing). This is the class code which works:

    from time import sleep_ms
    from machine import Pin, I2C
    
    # Default Address
    SI7021_I2C_DEFAULT_ADDR = 0x40
    
    # Commands
    CMD_MEASURE_RELATIVE_HUMIDITY_HOLD_MASTER_MODE = 0xE5
    CMD_MEASURE_RELATIVE_HUMIDITY = 0xF5
    CMD_MEASURE_TEMPERATURE_HOLD_MASTER_MODE = 0xE3
    CMD_MEASURE_TEMPERATURE = 0xF3
    CMD_READ_TEMPERATURE_VALUE_FROM_PREVIOUS_RH_MEASUREMENT = 0xE0
    CMD_RESET = 0xFE
    CMD_WRITE_RH_T_USER_REGISTER_1 = 0xE6
    CMD_READ_RH_T_USER_REGISTER_1 = 0xE7
    CMD_WRITE_HEATER_CONTROL_REGISTER = 0x51
    CMD_READ_HEATER_CONTROL_REGISTER = 0x11
    
    class SI7021(object):
      def __init__(self, i2c=None):
        self.i2c = i2c
        self.addr = SI7021_I2C_DEFAULT_ADDR
        self.cbuffer = bytearray(2)
        self.cbuffer[1] = 0x00
        
      def write_command(self, command_byte):
        self.i2c.writeto(self.addr, command_byte)
    
      def readTemp(self):
        self.write_command(CMD_MEASURE_TEMPERATURE)
        sleep_ms(25)
        temp = self.i2c.readfrom(self.addr,3)
        temp2 = temp[0] << 8
        temp2 = temp2 | temp[1]
        return (175.72 * temp2 / 65536) - 46.85
    
      def readRH(self):
        self.write_command(CMD_MEASURE_RELATIVE_HUMIDITY)
        sleep_ms(25)
        rh = self.i2c.readfrom(self.addr, 3)
        rh2 = rh[0] << 8
        rh2 = rh2 | rh[1]
        return (125 * rh2 / 65536) - 6
    

    It is called with:

    from machine import I2C
    i2c=I2C(0, I2C.MASTER)
    
    from SI7021 import SI7021
    m = SI7021(i2c)
    print(m.readRH(), m.readTemp())
    

    Device connected at P9 = SDA and P10 = SCL, Vin at 3.3V



  • @robert-hh well I ran my little baudrate finder again with modflyed write_command method.
    But I got tha same result, exept it frozed at 2964 baud.

    I am not sure what am I missing.



  • @tttadam The board looks fine. Not additional resistors required. In the SI7021 class there is a function call write_command. Change that function into:

    def write_command(self, command_byte):
        self.i2c.writeto(self.addr, command_byte)
    


  • @robert-hh Sorry But it is not clear for me. What sould I change in SI7021.py file?
    Thnak you



  • @robert-hh 1sorry for the delay.
    I took pictures of the sensors.
    https://photos.app.goo.gl/d1p1NSwZaXU41QbK8



  • @nespressif @tttadam I just verified that change to write_command(), and it works.
    Setting: Vin of the SI7021 module at 3.3V, not external pull-up resistors.



  • This post is deleted!


  • @robert-hh I'm sorry, but I don't understand what you want me to do. I've already tried creating a SI7021(i2c) class object and I get that error. Maybe that's how it works, I'll try it:

    def write_command(self, command_byte):
        #self.cbuffer[0] = command_byte
        self.i2c.writeto(self.addr, command_byte)
    


  • @nespressif The difference is in writing the command. In your example, you are writing a single int value,
    i2c.writeto(0x40, 0xf3) #read temp no hold
    wheras in the class it is two bytes, where the first byte contains the command, and the second a zero.

      def write_command(self, command_byte):
        self.cbuffer[0] = command_byte
        self.i2c.writeto(self.addr, self.cbuffer)
    

    Since you have a suitable device at hand, could you try to change the class accordingly. e.g. like below:

      def readTemp(self):
        self.i2c.writeto(self.addr, CMD_MEASURE_TEMPERATURE)
        sleep_ms(25)
        temp = self.i2c.readfrom(self.addr,3)
        temp2 = temp[0] << 8
        temp2 = temp2 | temp[1]
        return (175.72 * temp2 / 65536) - 46.85
    


  • Hello everyone, I have tested with an HTU21d sensor that is very similar to the SI7021 and with the SI7021 class I also get the "I2C bus error". However with the code in the main.py, it works perfectly, and without external resistances, I do not understand why I get the error with the class, if everything seems to be fine.
    I use this one:

    from machine import I2C
    import time
    
    i2c = I2C(0, I2C.MASTER)
    print(i2c.scan()) #I get [64] is 0x40
    
    i2c.writeto(0x40, 0xf3) #read temp no hold
    time.sleep_ms(25) 
    temp = i2c.readfrom(0x40, 3)
    temp2 = temp[0] << 8
    temp2 = temp2 | temp[1]
    print((175.72 * temp2 / 65536) - 46.85) 
    

    I hope it helps you, Regards



  • @eric73 said in SI7021 I2C pin setup:

    Single transistor level shifter ?

    Yes. there is a standard circuit doing this with single MosFET transistor, used by all cheap level shifter. Principle below. LV is low voltage, HV is high voltage, Lx and Hx are the low & high voltage logic. And you see the pull-up resistors on both sides:
    0_1539239103613_shifter.jpg
    P.S.: You could make a picture of the back side of the sensor, just to clarify @Eric73 's question.



  • @tttadam Single transistor level shifter ? A single transistor is an inverter gate, your SDA and SCL signal will be inverted. Please note that i2c is an opendrain bus with pull up. Your SI7021 can be powered by +5V (if its identical to the one showed by robert-hh) but have you checked is your board have 5V-3.3V regulator and have you checked what is SDA and SCL voltage level when you just power SI7021? In SI7021 datasheet absolute maximum rating for SDA and SCL is 3.3V, i have doubts that a SI7021 board have +5V pull-up on SDA and SCL....without power any of the two board, please check your wire continuity with multimeter if you can.



  • @robert-hh Well I just ran the code again(from 5V without resistors), but I got OS error for every baud rate from 1 to 10000. So I think something most be wrong with this sensor.



  • @tttadam I searched a little bit for a module that looks like yours. I found one, and in the backside pictures I see some resistors, which most likely are 10k pull-up resistors, and a three terminal device, which is according to the print-out a LM6206N3 3.3V voltage regulator. The pull-up resistors seem to be connected to 5V. Being 10k, that should not hurt the pycom device, and you do not need external pull-up resistors. And the 5V were OK for your device.
    0_1539111519069_SI7021.jpg
    Edit: I see also a dual level shifter, which is intended to connect a 5V side at the micro to the 3.3 V side of the sensor. It is a single FET transistor level shifter.



  • @robert-hh Okay, I will get bigger resistors, and replace the sensor.
    Thank you for the help.


 

Pycom on Twitter