sampazzer
Posts: 30
Joined: Wed Nov 13, 2013 7:57 pm

SI7021 Temp Humid sensor and SMbus

Wed Aug 23, 2017 1:29 pm

Hi all.

I bought an SI7021 adafruit sensor which I have been struggling to get to work since it arrived!

I've wired it up using the 3.3v line for power so to match the logic for the Pi. I have carried out the i2cdetect command to check the bus and I can see it on address 40 as you should!

I've imported the smbus library which I'm trying to use to read the bytes from the sensor with following the datasheet https://cdn-learn.adafruit.com/assets/a ... 21-A20.pdf

The humidity read i2c transaction is:

S, Slave add, W, [A], Measure command, [A], Sr, Slave add, r, [NA*], Sr, Slave address, r, [A], [MS Byte], a, [LS Byte], NA, P

*Note: Device will NACK the slave address byte until conversion is complete.
[ ] = slave

I've attempted a number of different smbus commands to try and get the sensor to give back a relative humidity value. Somewhere on the internet it said to:

Code: Select all

import smbus
import time

bus = smbus.SMBus(1) #set the bus up e.g./dev/i2c-1
address = 0x40

bus.write_byte(address,0xF5)
data0 = bus.read_byte(address) #MSB
data1 = bus.read_byte(address) #LSB the sensor sends the reading back in a 16bit word.
This doesnt work because when I print out the data0, data1 then I always get two values the same, like its just reading the MSB twice. (it looks like a lot of people are running this code without realising this is happening!)

I've also tried to use the i2c_smbus_write_byte_data() and i2c_smbus_read_word_data() commands which return some errors which I can't remember at the time of writing this. I'll add them on later.

I have however successfully read the user1 register. The output I get seems to match up to what it should be against the data sheet with the RSVD showing 1's in the correct places! This was using the code:

Code: Select all

import smbus
import time

bus = smbus.SMBus(1) #set the bus up e.g./dev/i2c-1
address = 0x40

read_user_register = bus.read_byte_data(address,0xE7) & 0xFF
time.sleep(0.1)

print("{:08b}".format(read_user_register))
I understand that I can use pigpio library to help but I cant see why a sensor using a standard I2C bus cant be communicated to using the smbus library!!!

It would be greatly appreciated if someone could shed some light on this as I've been tearing my hear out trying to sort it and scouring the internet! I'm thinking that maybethe read word smbus command doesnt put the bits in the correct place as per what the datasheet shows the device is expecting.

Thanks all, Sam.

sampazzer
Posts: 30
Joined: Wed Nov 13, 2013 7:57 pm

Re: SI7021 Temp Humid sensor and SMbus

Sun Aug 27, 2017 4:26 pm

Any techs available to shed any light on this?

Is it potentially to do with the repeated starts? I understand that this has been a problem for the i2c driver for the Pi in the past?

User avatar
joan
Posts: 14196
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: SI7021 Temp Humid sensor and SMbus

Sun Aug 27, 2017 4:43 pm

I've just had a look at the pigpio Si7021 code. It only uses I2C commands, no SMBus commands.

http://abyz.co.uk/rpi/pigpio/examples.h ... _Si7021_py

The device may require I2C rather than the restricted subset imposed by SMBus.

sampazzer
Posts: 30
Joined: Wed Nov 13, 2013 7:57 pm

Re: SI7021 Temp Humid sensor and SMbus

Mon Aug 28, 2017 11:34 am

Hi Joan thanks for your reply.

I've actually got a version of it up and running using your library which is brilliant by the way!

I'm just baffled as to why theres not an easy option in a full python library that covers the whole spectrum of i2c sensor communication. Maybe I'm being a bit naive there, I understand theres a lot of C conversion to do?

I have just found a smbus2 library which might do what I want it to do with a write/read function with repeated starts

User avatar
joan
Posts: 14196
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: SI7021 Temp Humid sensor and SMbus

Mon Aug 28, 2017 12:26 pm

I2C itself is almost too simple for a library. All you need is functions to write one or more bytes and read one or more bytes (from user land). Everything else would normally be handled by the hardware driver. SMBus imposes a restrictive order over this simplicity, and to my mind adds nothing of use with the possible exception of a time-out on bus transactions.

I don't remember repeated starts being an issue for the Si 7021. If you need that level of control you could just bit bang the protocol. However I think the current Pi Linux driver automatically adds repeated starts when needed.

sampazzer
Posts: 30
Joined: Wed Nov 13, 2013 7:57 pm

Re: SI7021 Temp Humid sensor and SMbus

Mon Aug 28, 2017 8:23 pm

How would I go about writing my own functions for the given transaction? That would be perfect but I'm not entirely sure how to go about it.

Glad I can put the repeated start to bed. I think the problem is as you've said the SMbus transactions just don't fit the sequence that the SI7021 is looking for and I cant shoehorn them in to work.

Would be brilliant if I could make my own function for the transaction.

Have you got any recommendations?

I need to include fcntl and IOCtl and talk to the driver directly?!

User avatar
joan
Posts: 14196
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: SI7021 Temp Humid sensor and SMbus

Mon Aug 28, 2017 8:25 pm

Do you want to use pure Python? If so I have some code which will be a start which I'll dig out.

sampazzer
Posts: 30
Joined: Wed Nov 13, 2013 7:57 pm

Re: SI7021 Temp Humid sensor and SMbus

Tue Aug 29, 2017 2:06 am

That would be amazing.

My only experience of C is a bit of C# in the past so having a go in pure Python would be cool.

User avatar
joan
Posts: 14196
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: SI7021 Temp Humid sensor and SMbus

Tue Aug 29, 2017 8:37 am

The following code has an i2c class which is all you need. The read/write functions are the equivalent of pigpio's i2c_read_device/i2c_write_device. The extraneous SMBus code was simply used to test performance.

Code: Select all

#!/usr/bin/env python

import io
import fcntl

# i2c.py
# 2014-09-21
# Public Domain

# Also see https://www.raspberrypi.org/forums/viewtopic.php?p=547441#p547441

I2C_SLAVE=0x0703

class i2c:

   def __init__(self, device, bus):

      self.fr = io.open("/dev/i2c-"+str(bus), "rb", buffering=0)
      self.fw = io.open("/dev/i2c-"+str(bus), "wb", buffering=0)

      # set device address

      fcntl.ioctl(self.fr, I2C_SLAVE, device)
      fcntl.ioctl(self.fw, I2C_SLAVE, device)

   def write(self, bytes):
      self.fw.write(bytes)

   def read(self, bytes):
      return self.fr.read(bytes)

   def close(self):
      self.fw.close()
      self.fr.close()

if __name__ == "__main__":

   import time

   import struct

   import i2c

   import smbus

   dev = i2c.i2c(0x53, 0) # device 0x53, bus 0

   dev.write("\x2D\x00") # POWER_CTL reset
   dev.write("\x2D\x08") # POWER_CTL measure
   dev.write("\x31\x00") # DATA_FORMAT reset
   dev.write("\x31\x0B") # DATA_FORMAT full res +/- 16g

   num_samples=5000

   sample=[(0,0,0)]*num_samples

   start1 = time.time()

   for s in xrange(num_samples):

      dev.write("\x32")
      sample[s] = struct.unpack('3h', dev.read(6))
      # print("x={} y={} z={}".format(buf[0], buf[1], buf[2]))

   end1 = time.time()

   bus = smbus.SMBus(0)
   sensor_address = 0x53

   start2 = time.time()

   for s in xrange(num_samples):

      buf = bus.read_i2c_block_data(sensor_address, 0x32, 6)
      tup=(buf[0]|buf[1]<<8, buf[2]|buf[3]<<8, buf[4]|buf[5]<<8)
      sample[s] = tup

   end2 = time.time()

   print(end1-start1)

   print(end2-start2)

   dev.close()

sampazzer
Posts: 30
Joined: Wed Nov 13, 2013 7:57 pm

Re: SI7021 Temp Humid sensor and SMbus

Tue Aug 29, 2017 11:45 pm

This looks brilliant thank you. I'm delving in and trying to understand whats going on with it. It uses librarys I've never used before with regards to io and fcntl.

Does this code work in python 3 do you know or is it for python 2?

Again thank you very much.

User avatar
joan
Posts: 14196
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: SI7021 Temp Humid sensor and SMbus

Wed Aug 30, 2017 9:42 am

I don't remember using the code with Python 3 but neither can I think of a reason why it wouldn't work. You'll have to try and see.

Return to “Troubleshooting”