I can't reach my sht21 sensor throughout the Multiplexer tca9548a (adafruit). When I run it with python3 in the raspberry pi's terminal, I get this error report:
Traceback (most recent call last): File "sensormeasurement.py", line 15, in <module> sensor1 = sht21.SHT21(tca) File "/home/pi/programming_stuff/sht21.py", line 20, in __init__ self.bus.write_byte(self._I2C_ADDRESS, self._SOFTRESET) AttributeError: 'TCA9548A_Channel' object has no attribute 'write_byte'
I think, this is because I mixed the code from adafruit blinka: Github repository Adafruit_CircuitPython_TCA9548A
# The MIT License (MIT) # # Copyright (c) 2018 Carter Nelson for Adafruit Industries # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. """ ``Adafruit_TCA9548A`` ==================================================== CircuitPython driver for the TCA9548A I2C Multiplexer. * Author(s): Carter Nelson Implementation Notes -------------------- **Hardware:** * TCA9548A I2C Multiplexer: https://www.adafruit.com/product/2717 **Software and Dependencies:** * Adafruit CircuitPython firmware for the supported boards: https://github.com/adafruit/circuitpython/releases * Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice """ # imports from micropython import const _DEFAULT_ADDRESS = const(0x70) __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_TCA9548A.git" class TCA9548A_Channel(): """Helper class to represent an output channel on the TCA9548A and take care of the necessary I2C commands for channel switching. This class needs to behave like an I2CDevice.""" def __init__(self, tca, channel): self.tca = tca self.channel_switch = bytearray([1 << channel]) def try_lock(self): """Pass thru for try_lock.""" while not self.tca.i2c.try_lock(): pass self.tca.i2c.writeto(self.tca.address, self.channel_switch) return True def unlock(self): """Pass thru for unlock.""" return self.tca.i2c.unlock() def readfrom_into(self, address, buffer, **kwargs): """Pass thru for readfrom_into.""" if address == self.tca.address: raise ValueError("Device address must be different than TCA9548A address.") return self.tca.i2c.readfrom_into(address, buffer, **kwargs) def writeto(self, address, buffer, **kwargs): """Pass thru for writeto.""" if address == self.tca.address: raise ValueError("Device address must be different than TCA9548A address.") return self.tca.i2c.writeto(address, buffer, **kwargs) class TCA9548A(): """Class which provides interface to TCA9548A I2C multiplexer.""" def __init__(self, i2c, address=_DEFAULT_ADDRESS): self.i2c = i2c self.address = address self.channels = [None]*8 def __len__(self): return 8 def __getitem__(self, key): if not 0 <= key <= 7: raise IndexError("Channel must be an integer in the range: 0-7") if self.channels[key] is None: self.channels[key] = TCA9548A_Channel(self, key) return self.channels[key]
with a program for the i2c triggered sht21 sensor from this repository modified for python3:
import smbus import time class SHT21: """Class to read temperature and humidity from SHT21. Ressources: http://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/Humidity/Sensirion_Humidity_SHT21_Datasheet_V3.pdf https://github.com/jaques/sht21_python/blob/master/sht21.py Martin Steppuhn's code from http://www.emsystech.de/raspi-sht21""" #control constants _SOFTRESET = 0xFE _I2C_ADDRESS = 0x40 _TRIGGER_TEMPERATURE_NO_HOLD = 0xF3 _TRIGGER_HUMIDITY_NO_HOLD = 0xF5 def __init__(self, bus): """According to the datasheet the soft reset takes less than 15 ms.""" self.bus = bus self.bus.write_byte(self._I2C_ADDRESS, self._SOFTRESET) time.sleep(0.015) def read_temperature(self): """Reads the temperature from the sensor. Not that this call blocks for 250ms to allow the sensor to return the data""" data =  self.bus.write_byte(self._I2C_ADDRESS, self._TRIGGER_TEMPERATURE_NO_HOLD) time.sleep(0.250) data.append(self.bus.read_byte(self._I2C_ADDRESS)) data.append(self.bus.read_byte(self._I2C_ADDRESS)) return self._get_temperature_from_buffer(data) def read_humidity(self): """Reads the humidity from the sensor. Not that this call blocks for 250ms to allow the sensor to return the data""" data =  self.bus.write_byte(self._I2C_ADDRESS, self._TRIGGER_HUMIDITY_NO_HOLD) time.sleep(0.250) data.append(self.bus.read_byte(self._I2C_ADDRESS)) data.append(self.bus.read_byte(self._I2C_ADDRESS)) return self._get_humidity_from_buffer(data) def _get_temperature_from_buffer(self, data): """This function reads the first two bytes of data and returns the temperature in C by using the following function: T = =46.82 + (172.72 * (ST/2^16)) where ST is the value from the sensor """ unadjusted = (data << 8) + data unadjusted *= 175.72 unadjusted /= 1 << 16 # divide by 2^16 unadjusted -= 46.85 return unadjusted def _get_humidity_from_buffer(self, data): """This function reads the first two bytes of data and returns the relative humidity in percent by using the following function: RH = -6 + (125 * (SRH / 2 ^16)) where SRH is the value read from the sensor """ unadjusted = (data << 8) + data unadjusted *= 125 unadjusted /= 1 << 16 # divide by 2^16 unadjusted -= 6 return unadjusted def close(self): """Closes the i2c connection""" self.bus.close() def __enter__(self): """used to enable python's with statement support""" return self def __exit__(self, type, value, traceback): """with support""" self.close() if __name__ == "__main__": try: bus = smbus.SMBus(1) with SHT21(bus) as sht21: print "Temperature: %s"%sht21.read_temperature() print "Humidity: %s"%sht21.read_humidity() except IOError, e: print e print 'Error creating connection to i2c.'
in the modified document (which is also from Github repository Adafruit_CircuitPython_TCA9548A) which I named sensormeasurement.py:
# This program is using Senirion SHT21 sensors for humidity and temperature measurement which is attached to TCA9548A Multiplexer through channels 0 and 1. This is like the example in https://github.com/adafruit/Adafruit_CircuitPython_TCA9548A import time import board import busio import adafruit_tca9548a import sht21 # Create I2C bus as normal i2c = busio.I2C(board.SCL, board.SDA) # Create the TCA9548A object and give it the I2C bus tca = adafruit_tca9548a.TCA9548A(i2c) # For each sensor, create it using the TCA9548A channel instead of the I2C object sensor1 = sht21.SHT21(tca) sensor2 = sht21.SHT21(tca) sensor3 = sht21.SHT21(tca) # Loop and profit! while True: print ("Temperature: %s" % sensor1.read_temperature()) print ("Humidity: %s" % sensor1.read_humidity()) time.sleep(0.1)
I installed CiruitPython, and when I rewire my circuit, so that the sensor is directly plugged in the i2c port of the raspberry pi, then the sht21.py runs perfectly. But since I what to use more than one sensor, I want to use the multiplexer. Maybe the problem is that I use smbus in sht21.py and in sensormeasurement.py I used busio instead. So, how should I modify sht21.py? I am new at this subject, so please explain it in detail. Thanks.