Guten Tag,
Mit Python ist das so eine Sache mit diesen Multiplexern. Bis jetzt habe ich dafür noch keine Lösung gefunden. Dennoch einen Lösungsvorschlag würde ich dir mit auf den Weg geben.
from smbus import SMBus
'''
A simple Python 3.x code with SMBUS ( I²C / 2Wire Bus by Philips / NXP ) to read
the sensor with the circuit HTU21A.
MIT-Lizenz Copyright (c) 2022
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.
Datasheet at http://web.sensor-ic.com:8000/ZLXIAZAI/MEAS20140716/HTU21A.pdf
'''
class HTU21D(object):
CMD_TRIG_TEMP_HM = 0xE3
CMD_TRIG_HUMID_HM = 0xE5
CMD_TRIG_TEMP_NHM = 0xF3
CMD_TRIG_HUMID_NHM = 0xF5
CMD_WRITE_USER_REG = 0xE6
CMD_READ_USER_REG = 0xE7
CMD_RESET = 0xFE
def __init__(self, busno=1, address=0x40):
self.bus = SMBus(busno)
self.i2c_address = address
self.__check_bus__(self.bus, self.i2c_address)
def read_temperature(self):
self.__reset__()
msb, lsb, crc = self.bus.read_i2c_block_data(\
self.i2c_address, self.CMD_TRIG_TEMP_HM, 3)
return ((-46.85 + 175.72 * (msb * 256 + lsb) / 65536)\
if self.__crc_check___(msb, lsb, crc) else -1)
def read_humidity(self):
self.__reset__()
msb, lsb, crc = self.bus.read_i2c_block_data(\
self.i2c_address, self.CMD_TRIG_HUMID_HM, 3)
return (((-6 + 125 * (msb * 256 + lsb) / 65536.0) / 100.0)\
if self.__crc_check___(msb, lsb, crc) else -1)
def __reset__(self):
self.bus.write_byte(self.i2c_address, self.CMD_RESET)
def __check_bus__(self, bus, address):
try:
value = bus.read_i2c_block_data(self.i2c_address, \
self.CMD_READ_USER_REG,3)
except :
print('Sensor GY21_HTU21 not found at', hex(address))
exit()
print(('Sensor GY21_HTU21 found.' if value == [2, 0 , 0] else \
'is not a sensorGY21_HTU21 at this bus address'))
def __crc_check___(self, msb, lsb, crc):
remainder = ((msb << 8) | lsb) << 8
remainder |= crc
divsor = 0x988000
for i in range(0, 16):
if remainder & 1 << (23 - i):
remainder ^= divsor
divsor >>= 1
return (True if remainder == 0 else False)
Display More
Zum Ersten - ich würde auf diesen Adafruit Code verzichten. Dafür gibt es auch schnellere Alternativen (siehe Code-Listing).
Dann würde ich einfach, so habe ich mir zumindest in einer ähnlichen Situation beholfen, weil es wirklich keine wirklich vernünftige PYTHON Lösung für diese Bus-Multiplexer gibt, ich habe die Vc Leitungen über einen Portexpander geschaltet. Somit nacheinander die Sensoren angeschaltet, die Sensorwerte ausgelesen, diesen einen Sensor wieder Stromlos gemacht, und dann den nächsten Sensor aktiviert.
Wenn es keine zeitkritischen Vorgänge sind, kann man hier z.B. den 8 BIt Portexpander PCF8574 nutzen. Dazu integriert man diesen PCF8574 in den Bus, und nutzt die Output GPIOs als Spannungsversorgung für den jeweiligen Sensor. Funktioniert absolut Problemlos, denn auch der PCF8574 ist via Python sehr einfach zu steuern. Du musst nur beachten, nach der Power-ON Schaltung über einen der GPIO Output Ports des Portexpanders, noch eine Verweilzeit einzubauen, bis der Sensor abgefragt werden kann. Auch so kann man recht einfach, mehrere I2C Bus Komponenten mit gleicher Adresse abfragen, solange diese nicht immer und wirklich zeitgleich an sein sollen.