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[0])
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[0] << 8) + data[1]
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[0] << 8) + data[1]
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[0])
sensor2 = sht21.SHT21(tca[1])
sensor3 = sht21.SHT21(tca[2])
# 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.