def test_read(self): res = [] res2 = [] res3 = [] bus = SMBus(1) # Read bytes for k in range(2): x = bus.read_byte_data(80, k) res.append(x) self.assertEqual(len(res), 2, msg="Result array of incorrect length.") # Read word x = bus.read_word_data(80, 0) res2.append(x & 255) res2.append(x / 256) self.assertEqual(len(res2), 2, msg="Result array of incorrect length.") self.assertListEqual(res, res2, msg="Byte and word reads differ") # Read block of N bytes n = 2 x = bus.read_i2c_block_data(80, 0, n) res3.extend(x) self.assertEqual(len(res3), n, msg="Result array of incorrect length.") self.assertListEqual(res, res3, msg="Byte and block reads differ") bus.close()
class I2cBus(BaseI2cDriver.I2cBus): def __init__(self, bus_id): super().__init__(bus_id) try: self.bus = SMBus(bus_id) except Exception as e: raise InvalidDriverError( 'Unable to initialize i2c connection with bus {}. Check if i2c bus is avalable.'.format(bus_id), e) def close(self): if self.bus is not None: self.bus.close() def read_byte(self, addr: int, register: int) -> int: return self.bus.read_byte_data(addr, register) def read_word(self, addr: int, register: int) -> int: return self.bus.read_word_data(addr, register) def read_block(self, addr: int, register, length: int) -> List[int]: return self.bus.read_i2c_block_data(addr, register, length) def write_byte_data(self, addr, register, value): self.bus.write_byte_data(addr, register, value) def write_word_data(self, addr, register, value): self.bus.write_word_data(addr, register, value) def write_block_data(self, addr, register, data): self.bus.write_i2c_block_data(addr, register, data)
class InputModule(AbstractInput): """ A sensor support class that measure the MLX90614's ambient and object temperature. """ def __init__(self, input_dev, testing=False): super(InputModule, self).__init__(input_dev, testing=testing, name=__name__) self.MLX90614_RAWIR1=0x04 self.MLX90614_RAWIR2=0x05 self.MLX90614_TA=0x06 self.MLX90614_TOBJ1=0x07 self.MLX90614_TOBJ2=0x08 self.MLX90614_TOMAX=0x20 self.MLX90614_TOMIN=0x21 self.MLX90614_PWMCTRL=0x22 self.MLX90614_TARANGE=0x23 self.MLX90614_EMISS=0x24 self.MLX90614_CONFIG=0x25 self.MLX90614_ADDR=0x0E self.MLX90614_ID1=0x3C self.MLX90614_ID2=0x3D self.MLX90614_ID3=0x3E self.MLX90614_ID4=0x3F if not testing: self.initialize_input() def initialize_input(self): from smbus2 import SMBus self.i2c_address = int(str(self.input_dev.i2c_location), 16) self.bus = SMBus(self.input_dev.i2c_bus) def read_reg(self, reg_addr): return self.bus.read_word_data(self.i2c_address, reg_addr) def data_to_temp(self, data): temp = (data*0.02) - 273.15 return temp def get_amb_temp(self): data = self.read_reg(self.MLX90614_TA) return self.data_to_temp(data) def get_obj_temp(self): data = self.read_reg(self.MLX90614_TOBJ1) return self.data_to_temp(data) def get_measurement(self): """ Gets the ambient (ch0) and object (ch1) temperatures """ self.return_dict = copy.deepcopy(measurements_dict) if self.is_enabled(0): self.value_set(0, self.get_amb_temp()) if self.is_enabled(1): self.value_set(1, self.get_obj_temp()) return self.return_dict
def lm75a(address): if 1 < len(sys.argv): address = int(sys.argv[1], 16) try: bus = SMBus(1) raw = bus.read_word_data(address, 0) & 0xffff raw = ((raw << 8) & 0xffff) + (raw >> 8) temperature = (raw / 32.0) / 8.0 return temperature except Exception as e: print(e) finally: bus.close()
from smbus2 import SMBus ## address of the device from i2cdetect sensorAddr = 0x48 ## initialize smbus object using bus number i2c = SMBus(1) #i2c.write_byte_data(sensorAddr, 1, 0xD) robot = Robot() robot.forward() num = 50 temp = 0 while (temp < num): tempWord = i2c.read_word_data(sensorAddr, 0) byte1 = tempWord & 0xFF byte2 = (tempWord & 0xFF00) >> 12 temperature = ((byte1 << 4) + byte2) * 0.0625 print("Temperature: " + str(temperature)) temp = temp + 1 time.sleep(0.5) robot.stop() GPIO.cleanup()
bus.write_byte_data(ADDRESS, 4, 0x44) b = bus.read_byte_data(ADDRESS, 1) assert b == 0x44 print("Write byte data@4 OK") bus.write_byte_data(ADDRESS, 5, 0x55) b = bus.read_byte_data(ADDRESS, 2) assert b == 0x55 print("Write byte data@5 OK") bus.write_byte_data(ADDRESS, 6, 0x66) b = bus.read_byte_data(ADDRESS, 3) assert b == 0x66 print("Write byte data@6 OK") bus.write_word_data(ADDRESS, 9, 0xabcd) w = bus.read_word_data(ADDRESS, 7) assert w == 0xabcd print("Write word data@9, read word data@7 OK") bus.write_word_data(ADDRESS, 10, 0xef12) w = bus.read_word_data(ADDRESS, 8) assert w == 0xef12 print("Write word data@10, read word data@8 OK") bus.write_block_data( 0x19, 13, [1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2]) block = bus.read_i2c_block_data(0x19, 11, 9) assert block == [8, 1, 2, 3, 4, 5, 6, 7, 8] print("Write/Read block OK")
class InputModule(AbstractInput): """ A sensor support class that monitors the DS18B20's lux """ def __init__(self, input_dev, testing=False): super(InputModule, self).__init__() self.logger = logging.getLogger("mycodo.inputs.bh1750") self._lux = None if not testing: from smbus2 import SMBus self.logger = logging.getLogger("mycodo.bh1750_{id}".format( id=input_dev.unique_id.split('-')[0])) self.i2c_address = int(str(input_dev.i2c_location), 16) self.i2c_bus = input_dev.i2c_bus self.resolution = input_dev.resolution self.sensitivity = input_dev.sensitivity self.convert_to_unit = input_dev.convert_to_unit self.i2c_bus = SMBus(self.i2c_bus) self.power_down() self.set_sensitivity(sensitivity=self.sensitivity) def __repr__(self): """ Representation of object """ return "<{cls}(lux={lux})>".format(cls=type(self).__name__, lux="{0:.2f}".format(self._lux)) def __str__(self): """ Return lux information """ return "Lux: {lux}".format(lux="{0:.2f}".format(self._lux)) def __iter__(self): # must return an iterator """ BH1750Sensor iterates through live lux readings """ return self def next(self): """ Get next lux reading """ if self.read(): # raised an error raise StopIteration # required return dict(lux=float('{0:.2f}'.format(self._lux))) @property def lux(self): """ BH1750 luminosity in lux """ if self._lux is None: # update if needed self.read() return self._lux def get_measurement(self): """ Gets the BH1750's lux """ self._lux = None if self.resolution == 0: lux = self.measure_low_res() elif self.resolution == 1: lux = self.measure_high_res() elif self.resolution == 2: lux = self.measure_high_res2() else: return None lux = convert_units('light', 'lux', self.convert_to_unit, lux) return lux def read(self): """ Takes a reading from the BH1750 and updates the self._lux value :returns: None on success or 1 on error """ try: self._lux = self.get_measurement() if self._lux is not None: return # success - no errors except Exception as e: self.logger.exception( "{cls} raised an exception when taking a reading: " "{err}".format(cls=type(self).__name__, err=e)) return 1 def _set_mode(self, mode): self.mode = mode self.i2c_bus.write_byte(self.i2c_address, self.mode) def power_down(self): self._set_mode(POWER_DOWN) def power_on(self): self._set_mode(POWER_ON) def reset(self): self.power_on() # It has to be powered on before resetting self._set_mode(RESET) def cont_low_res(self): self._set_mode(CONTINUOUS_LOW_RES_MODE) def cont_high_res(self): self._set_mode(CONTINUOUS_HIGH_RES_MODE_1) def cont_high_res2(self): self._set_mode(CONTINUOUS_HIGH_RES_MODE_2) def oneshot_low_res(self): self._set_mode(ONE_TIME_LOW_RES_MODE) def oneshot_high_res(self): self._set_mode(ONE_TIME_HIGH_RES_MODE_1) def oneshot_high_res2(self): self._set_mode(ONE_TIME_HIGH_RES_MODE_2) def set_sensitivity(self, sensitivity=69): """ Set the sensor sensitivity. Valid values are 31 (lowest) to 254 (highest), default is 69. """ if sensitivity < 31: self.mtreg = 31 elif sensitivity > 254: self.mtreg = 254 else: self.mtreg = sensitivity self.power_on() self._set_mode(0x40 | (self.mtreg >> 5)) self._set_mode(0x60 | (self.mtreg & 0x1f)) self.power_down() def get_result(self): """ Return current measurement result in lx. """ data = self.i2c_bus.read_word_data(self.i2c_address, self.mode) count = data >> 8 | (data & 0xff) << 8 mode2coeff = 2 if (self.mode & 0x03) == 0x01 else 1 ratio = 1 / (1.2 * (self.mtreg / 69.0) * mode2coeff) return ratio * count def wait_for_result(self, additional=0): basetime = 0.018 if (self.mode & 0x03) == 0x03 else 0.128 time.sleep(basetime * (self.mtreg / 69.0) + additional) def do_measurement(self, mode, additional_delay=0): """ Perform complete measurement using command specified by parameter mode with additional delay specified in parameter additional_delay. Return output value in Lx. """ self.reset() self._set_mode(mode) self.wait_for_result(additional=additional_delay) return self.get_result() def measure_low_res(self, additional_delay=0): return self.do_measurement(ONE_TIME_LOW_RES_MODE, additional_delay) def measure_high_res(self, additional_delay=0): return self.do_measurement(ONE_TIME_HIGH_RES_MODE_1, additional_delay) def measure_high_res2(self, additional_delay=0): return self.do_measurement(ONE_TIME_HIGH_RES_MODE_2, additional_delay)
class INA233: CLEAR_FAULTS = 0x03 RESTORE_DEFAULT_ALL = 0x12 CAPABILITY = 0x19 IOUT_OC_WARN_LIMIT = 0x4A VIN_OV_WARN_LIMIT = 0x57 VIN_UV_WARN_LIMIT = 0x58 PIN_OP_WARN_LIMIT = 0x6B STATUS_BYTE = 0x78 STATUS_WORD = 0x79 STATUS_IOUT = 0x79 STATUS_IOUT = 0x7B STATUS_INPUT = 0x7C STATUS_CML = 0x7E STATUS_MFR_SPECIFIC = 0x80 READ_EIN = 0x86 READ_VIN = 0x88 READ_IIN = 0x89 READ_VOUT = 0x8B READ_IOUT = 0x8C READ_POUT = 0x96 READ_PIN = 0x97 MFR_ID = 0x99 MFR_MODEL = 0x9A MFR_REVISION = 0x9B MFR_ADC_CONFIG = 0xD0 MFR_READ_VSHUNT = 0xD1 MFR_ALERT_MASK = 0xD2 MFR_CALIBRATION = 0xD4 MFR_DEVICE_CONFIG = 0xD5 CLEAR_EIN = 0xD6 TI_MFR_ID = 0xE0 TI_MFR_MODEL = 0xE1 TI_MFR_REVISION = 0xE2 # from table 1 p 17 of INA233 documentation pdf #SHUNT VOLTAGE TELEMETRY & WARNING COEFFICIENTS _m_vs = 4 _R_vs = 5 _b_vs = 0 _m_c =0 _R_c = 0 _m_p = 0 _R_p = 0 #BUS VOLTAGE TELEMETRY & WARNING COEFFICIENTS _R_vb = 2 _b_vb = 0 _m_vb = 8 # CURRENT & POWER CONSTANT TELEMETRY & WARNING COEFFICIENTS _b_c = 0 _b_p = 0 _BUS_MILLIVOLTS_LSB = 0.00125 _SHUNT_MILLIVOLTS_LSB = 0.0000025 _accumulator_24 = 0 _sample_count = 0 def __init__(self, bus, address): self._bus = SMBus(bus) self._address = address def calibrate(self, R_shunt, I_max): """ Calibration and scaling values per section 7.5.2 of TI INA233 datasheet """ self._R_shunt = R_shunt self._I_max = I_max self._Current_LSB = 0 self._Power_LSB = 0 self._CAL = 0 tmp = 0 round_done = False ERROR = 0 self._Current_LSB=self._I_max/(pow(2,15)) self._Power_LSB=25*self._Current_LSB self._CAL=0.00512/(self._R_shunt*self._Current_LSB) #check if CAL is in the uint16 range if self._CAL>0xFFFF: ERROR=1 else: self._bus.write_word_data(self._address,self.MFR_CALIBRATION,int(self._CAL)) self._m_c=1/self._Current_LSB self._m_p=1/self._Power_LSB #Calculate m and R for maximum accuracy in current measurement tmp=int(self._m_c) while ((tmp > 32768) or (tmp < -32768)): self._m_c=self._m_c/10 self._R_c = self._R_c + 1 tmp=int(self._m_c) while round_done==False: tmp=int(self._m_c) if tmp==self._m_c: round_done=True else: tmp=int(self._m_c*10) #shift decimal to the right if ((tmp>32768) or (tmp<-32768)): #m_c is out of int16 (-32768 to 32768) round_done=True else: self._m_c=self._m_c*10 self._R_c = self._R_c - 1 round_done=False #Calculate m and R for maximum accuracy in power measurement tmp = int(self._m_p) while tmp>32768 or tmp<-32768: self._m_p=self._m_p/10 self._R_p = self._R_p + 1 tmp = int(self._m_p) while round_done == False: tmp = int(self._m_p) if tmp==self._m_p: round_done=True else: tmp = int(self._m_p*10) #shift decimal to the right if tmp>32768 or tmp<-32768: #m_p is out of int16 (-32768 to 32768) round_done=True else: self._m_p = self._m_p*10 self._R_p = self._R_p - 1 self._m_c = int(self._m_c) self._m_p = int(self._m_p) def _getBusVoltageIn_raw(self): raw_read = self._bus.read_word_data(self._address, self.READ_VIN) return int(raw_read) def _getBusVoltageOut_raw(self): raw_read = self._bus.read_word_data(self._address, self.READ_VOUT) return int(raw_read) def _getShuntVoltage_raw(self): raw_read = self._bus.read_word_data(self._address, self.MFR_READ_VSHUNT) return int(raw_read) def _getCurrentOut_raw(self): raw_read = self._bus.read_i2c_block_data(self._address, self.READ_IOUT, 2) return raw_read[0] * 256 + raw_read[1] def _getCurrentIn_raw(self): raw_read = self._bus.read_i2c_block_data(self._address, self.READ_IIN, 2) return raw_read[0] * 256 + raw_read[1] def getShuntVoltage_mV(self): raw_read = self._getShuntVoltage_raw() #return ((raw_read*pow(10,-self._R_vs)-self._b_vs)/self._m_vs) return raw_read * self._SHUNT_MILLIVOLTS_LSB * 1000 def getBusVoltageIn_V(self): raw_read = self._getBusVoltageIn_raw() #return ((raw_read*pow(10,-self._R_vb)-self._b_vb)/self._m_vb) return raw_read * self._BUS_MILLIVOLTS_LSB def getBusVoltageOut_V(self): raw_read = self._getBusVoltageOut_raw() #return ((raw_read*pow(10,-self._R_vb)-self._b_vb)/self._m_vb) return raw_read * self._BUS_MILLIVOLTS_LSB def getCurrentIn_mA(self): word_rdata=self._getCurrentIn_raw() current_twos_compliment = word_rdata current_sign_bit = current_twos_compliment >> 15 if(current_sign_bit == 1): current = float(self._twos_compliment_to_int(current_twos_compliment, 16)) * self._Current_LSB else: #current =(value*(pow(10,-self._R_c))-self._b_c)/self._m_c current = float(current_twos_compliment) * self._Current_LSB return current def getCurrentOut_mA(self): word_rdata=self._getCurrentOut_raw() current_twos_compliment = word_rdata current_sign_bit = current_twos_compliment >> 15 if(current_sign_bit == 1): current = float(self._twos_compliment_to_int(current_twos_compliment, 16)) * self._Current_LSB else: #current =(value*(pow(10,-self._R_c))-self._b_c)/self._m_c current = float(current_twos_compliment) * self._Current_LSB return current def _getPower_raw(self): raw_read = self._bus.read_word_data(self._address, self.READ_PIN) return int(raw_read) def _getEnergy_raw(self): raw_read = self._bus.read_i2c_block_data(self._address,self.READ_EIN,6) self._accumulator=(raw_read[0] << 8) | raw_read[1] self._roll_over=raw_read[2] self._sample_count=raw_read[5]<< 16 self._sample_count=(raw_read[4]<< 8) | self._sample_count self._sample_count=(raw_read[3] | self._sample_count) def getAv_Power_mW(self): raw_av_power=0 av_power=0 # prev_accumulator_24 = self._accumulator_24 # prev_sample_count = self._sample_count self._getEnergy_raw() #Total Accumulated Unscaled Power (Accumulator_24) = (rollover_count × 2^16) + Accumulator self._accumulator_24=int(self._roll_over)*65536+int(self._accumulator) # raw_av_power=(self._accumulator_24-prev_accumulator_24)/(self._sample_count-prev_sample_count) # doing it this way may be less accurate, but it avoids the divide by zero in the first reading raw_av_power=(self._accumulator_24)/(self._sample_count) #av_power=(raw_av_power*pow(10,-self._R_p)-self._b_p)/self._m_p av_power = raw_av_power * self._Power_LSB return av_power * 1000 def getPower_mW(self): raw_read=self._getPower_raw() #power =(raw_read*pow(10,-self._R_p)-self._b_p)/self._m_p power = raw_read * self._Power_LSB return power def _twos_compliment_to_int(self, val, bits): if (val & (1 << (bits - 1))) != 0: val = val - (1 << bits) return val
config_reg = 0x01 config = 0b1100111000000000 ser = serial.Serial('/dev/ttyUSB0', 115200, timeout=1) data_file = open("sensor_data.dat", "w") data_file.write( "YYYY-MM-DD HH:mm:ss.ffffff,lux,b'r,mag/arcsec^2,Hz,idk,idk,Celcius,GPS\n") print(hex(config)) i2c = SMBus(1) #i2c.write_word_data(i2c_addr, config_reg, config) i2c.write_i2c_block_data(i2c_addr, config_reg, [0b11001110, 0b00000000]) for byte in i2c.read_i2c_block_data(i2c_addr, 0x7E, 2): print(hex(byte)) for byte in i2c.read_i2c_block_data(i2c_addr, 0x7F, 2): print(hex(byte)) print(hex(i2c.read_word_data(i2c_addr, config_reg))) while (1): conversion_ready = i2c.read_word_data(i2c_addr, config_reg) if ((conversion_ready & 0x80) == 0x80): reading = i2c.read_word_data(i2c_addr, result_reg) lux = 0.01 * (1 << ((reading & 0xF000) >> 12)) * (reading & 0x0FFF) ser.write(b'rx') sqm = ser.readline() print("Luminance Reading: ", end='') print(lux, end=' ') print("lux") print("SQM Reading: ", end='') print(sqm, end=' ') now = datetime.now() data_file.write(str(now))
def read_word_data(self, *args, **kwargs): """Overridden :method:`read_word_data` from :class:`SMBus` without I2C address parameter.""" return SMBus.read_word_data(self, self.device_addr, *args, **kwargs)
class InputModule(AbstractInput): """ A sensor support class that measures the Chirp's moisture, temperature and light """ def __init__(self, input_dev, testing=False): super(InputModule, self).__init__() self.logger = logging.getLogger("mycodo.inputs.chirp") self._lux = None self._moisture = None self._temperature = None if not testing: self.logger = logging.getLogger( "mycodo.chirp_{id}".format(id=input_dev.unique_id.split('-')[0])) self.i2c_address = int(str(input_dev.i2c_location), 16) self.i2c_bus = input_dev.i2c_bus self.convert_to_unit = input_dev.convert_to_unit self.bus = SMBus(self.i2c_bus) self.filter_average('lux', init_max=3) def __repr__(self): """ Representation of object """ return "<{cls}(lux={lux})(moisture={moist})(temperature={temp})>".format( cls=type(self).__name__, lux="{0}".format(self._lux), moist="{0}".format(self._moisture), temp="{0:.2f}".format(self._temperature)) def __str__(self): """ Return measurement information """ return "Light: {lux}, Moisture: {moist}, Temperature: {temp}".format( lux="{0}".format(self._lux), moist="{0}".format(self._moisture), temp="{0:.2f}".format(self._temperature)) def __iter__(self): # must return an iterator """ ChirpSensor iterates through live measurement readings """ return self def next(self): """ Get next measurement reading """ if self.read(): # raised an error raise StopIteration # required return dict(lux=float('{0}'.format(self._lux)), moisture=float('{0}'.format(self._moisture)), temperature=float('{0:.2f}'.format(self._temperature))) @property def lux(self): """ Chirp light measurement """ if self._lux is None: # update if needed self.read() return self._lux @property def moisture(self): """ Chirp moisture measurement """ if self._moisture is None: # update if needed self.read() return self._moisture @property def temperature(self): """ Chirp temperature in Celsius """ if self._temperature is None: # update if needed self.read() return self._temperature def get_measurement(self): """ Gets the light, moisture, and temperature """ self._lux = None self._moisture = None self._temperature = None lux = self.filter_average('lux', measurement=self.light()) lux = convert_units( 'light', 'lux', self.convert_to_unit, lux) moisture = self.moist() temperature = convert_units( 'temperature', 'C', self.convert_to_unit, self.temp() / 10.0) return lux, moisture, temperature def read(self): """ Takes a reading from the AM2315 and updates the self.dew_point, self._humidity, and self._temperature values :returns: None on success or 1 on error """ try: self._lux, self._moisture, self._temperature = self.get_measurement() if self._lux is not None: return # success - no errors except Exception as e: self.logger.exception( "{cls} raised an exception when taking a reading: " "{err}".format(cls=type(self).__name__, err=e)) return 1 def get_reg(self, reg): # read 2 bytes from register val = self.bus.read_word_data(self.i2c_address, reg) # return swapped bytes (they come in wrong order) return (val >> 8) + ((val & 0xFF) << 8) def reset(self): # To reset the sensor, write 6 to the device I2C address self.bus.write_byte(self.i2c_address, 6) def set_addr(self, new_addr): # To change the I2C address of the sensor, write a new address # (one byte [1..127]) to register 1; the new address will take effect after reset self.bus.write_byte_data(self.i2c_address, 1, new_addr) self.reset() # self.address = new_addr def moist(self): # To read soil moisture, read 2 bytes from register 0 return self.get_reg(0) def temp(self): # To read temperature, read 2 bytes from register 5 return self.get_reg(5) def light(self): # To read light level, start measurement by writing 3 to the # device I2C address, wait for 3 seconds, read 2 bytes from register 4 self.bus.write_byte(self.i2c_address, 3) time.sleep(1.5) lux = self.get_reg(4) if lux == 0: return 65535.0 else: return(1 - (lux / 65535.0)) * 65535.0
class Device(object): """Class for communicating with an I2C device using the smbus library. Allows reading and writing 8-bit, 16-bit, and byte array values to registers on the device.""" def __init__(self, address, busnum): """Create an instance of the I2C device at the specified address on the specified I2C bus number.""" self._address = address self._bus = SMBus(busnum) def writeRaw8(self, value): """Write an 8-bit value on the bus (without register).""" value = value & 0xFF self._bus.write_byte(self._address, value) def write8(self, register, value): """Write an 8-bit value to the specified register.""" value = value & 0xFF self._bus.write_byte_data(self._address, register, value) def write16(self, register, value): """Write a 16-bit value to the specified register.""" value = value & 0xFFFF self._bus.write_word_data(self._address, register, value) def writeList(self, register, data): """Write bytes to the specified register.""" self._bus.write_i2c_block_data(self._address, register, data) def readList(self, register, length): """Read a length number of bytes from the specified register. Results will be returned as a bytearray.""" results = self._bus.read_i2c_block_data(self._address, register, length) return results def readRaw8(self): """Read an 8-bit value on the bus (without register).""" result = self._bus.read_byte(self._address) & 0xFF return result def readU8(self, register): """Read an unsigned byte from the specified register.""" result = self._bus.read_byte_data(self._address, register) & 0xFF return result def readS8(self, register): """Read a signed byte from the specified register.""" result = self.readU8(register) if result > 127: result -= 256 return result def readU16(self, register, little_endian=True): """Read an unsigned 16-bit value from the specified register, with the specified endianness (default little endian, or least significant byte first).""" result = self._bus.read_word_data(self._address, register) & 0xFFFF # Swap bytes if using big endian because read_word_data assumes little # endian on ARM (little endian) systems. if not little_endian: result = ((result << 8) & 0xFF00) + (result >> 8) return result def readS16(self, register, little_endian=True): """Read a signed 16-bit value from the specified register, with the specified endianness (default little endian, or least significant byte first).""" result = self.readU16(register, little_endian) if result > 32767: result -= 65536 return result def readU16LE(self, register): """Read an unsigned 16-bit value from the specified register, in little endian byte order.""" return self.readU16(register, little_endian=True) def readU16BE(self, register): """Read an unsigned 16-bit value from the specified register, in big endian byte order.""" return self.readU16(register, little_endian=False) def readS16LE(self, register): """Read a signed 16-bit value from the specified register, in little endian byte order.""" return self.readS16(register, little_endian=True) def readS16BE(self, register): """Read a signed 16-bit value from the specified register, in big endian byte order.""" return self.readS16(register, little_endian=False)
class BMP280(): BMP280_ADDR = 0x76 t_fine = 0 DIG_T1 = 0x88 DIG_T2 = 0x8A DIG_T3 = 0x8C DIG_P1 = 0x8E DIG_P2 = 0x90 DIG_P3 = 0x92 DIG_P4 = 0x94 DIG_P5 = 0x96 DIG_P6 = 0x98 DIG_P7 = 0x9A DIG_P8 = 0x9C DIG_P9 = 0x9E DEVICE_ID = 0xD0 RESET = 0xE0 STATUS = 0xF3 CTRL_MEAS = 0xF4 CONFIG = 0xF5 PRESSURE = 0xF7 TEMPERATURE = 0xFA RESET_CMD = 0xB6 OVERSAMPLING_P_NONE = 0b000 OVERSAMPLING_P_x1 = 0b001 OVERSAMPLING_P_x2 = 0b010 OVERSAMPLING_P_x4 = 0b011 OVERSAMPLING_P_x8 = 0b100 OVERSAMPLING_P_x16 = 0b101 OVERSAMPLING_T_NONE = 0b000 OVERSAMPLING_T_x1 = 0b001 OVERSAMPLING_T_x2 = 0b010 OVERSAMPLING_T_x4 = 0b011 OVERSAMPLING_T_x8 = 0b100 OVERSAMPLING_T_x16 = 0b101 T_STANDBY_0p5 = 0b000 T_STANDBY_62p5 = 0b001 T_STANDBY_125 = 0b010 T_STANDBY_250 = 0b011 T_STANDBY_500 = 0b100 T_STANDBY_1000 = 0b101 T_STANDBY_2000 = 0b110 T_STANDBY_4000 = 0b111 IIR_FILTER_OFF = 0b000 IIR_FILTER_x2 = 0b001 IIR_FILTER_x4 = 0b010 IIR_FILTER_x8 = 0b011 IIR_FILTER_x16 = 0b100 SLEEP_MODE = 0b00 FORCED_MODE = 0b01 NORMAL_MODE = 0b11 def __init__(self, port=1, mode=FORCED_MODE, oversampling_p=OVERSAMPLING_P_x16, oversampling_t=OVERSAMPLING_T_x1, filter=IIR_FILTER_OFF, standby=T_STANDBY_4000): self.bus = SMBus(port) self.bmp280_init(mode, oversampling_p, oversampling_t, filter, standby) def read_device_id(self): return self.bus.read_byte_data(self.BMP280_ADDR, self.DEVICE_ID) def device_reset(self): self.bus.write_byte_data(self.BMP280_ADDR, self.RESET, self.RESET_CMD) sleep(1) def bmp280_init(self, mode, oversampling_p, oversampling_t, filter, standby): ctrl_meas_reg = mode + (oversampling_p << 2) + (oversampling_t << 5) self.bus.write_byte_data(self.BMP280_ADDR, self.CTRL_MEAS, ctrl_meas_reg) config_reg = 0b000 + (filter << 2) + (standby << 5) self.bus.write_byte_data(self.BMP280_ADDR, self.CONFIG, config_reg) def read_temperature(self): t1 = self.bus.read_word_data(self.BMP280_ADDR, self.DIG_T1) t2 = twos_complement( self.bus.read_word_data(self.BMP280_ADDR, self.DIG_T2)) t3 = twos_complement( self.bus.read_word_data(self.BMP280_ADDR, self.DIG_T3)) raw_data = self.bus.read_i2c_block_data(self.BMP280_ADDR, self.TEMPERATURE, 3) adc_t = (raw_data[0] * pow(2, 16) + raw_data[1] * pow(2, 8) + raw_data[2]) >> 4 var1 = ((adc_t / 16384.0) - (t1 / 1024.0)) * t2 var2 = ((adc_t / 131072.0) - (t1 / 8192.0)) * (((adc_t / 131072.0) - (t1 / 8192.0)) * t3) self.t_fine = var1 + var2 return (var1 + var2) / 5120.0 def read_pressure(self): p1 = self.bus.read_word_data(self.BMP280_ADDR, self.DIG_P1) p2 = twos_complement( self.bus.read_word_data(self.BMP280_ADDR, self.DIG_P2)) p3 = twos_complement( self.bus.read_word_data(self.BMP280_ADDR, self.DIG_P3)) p4 = twos_complement( self.bus.read_word_data(self.BMP280_ADDR, self.DIG_P4)) p5 = twos_complement( self.bus.read_word_data(self.BMP280_ADDR, self.DIG_P5)) p6 = twos_complement( self.bus.read_word_data(self.BMP280_ADDR, self.DIG_P6)) p7 = twos_complement( self.bus.read_word_data(self.BMP280_ADDR, self.DIG_P7)) p8 = twos_complement( self.bus.read_word_data(self.BMP280_ADDR, self.DIG_P8)) p9 = twos_complement( self.bus.read_word_data(self.BMP280_ADDR, self.DIG_P9)) raw_data = self.bus.read_i2c_block_data(self.BMP280_ADDR, self.PRESSURE, 3) adc_p = (raw_data[0] * pow(2, 16) + raw_data[1] * pow(2, 8) + raw_data[2]) >> 4 self.read_temperature() var1 = (self.t_fine / 2.0) - 64000.0 var2 = var1 * var1 * p6 / 32768.0 var2 += var1 * p5 * 2.0 var2 = (var2 / 4.0) + (p4 * 65536.0) var1 = (p3 * var1 * var1 / 524288.0 + (p2 * var1)) / 524288.0 var1 = (1.0 + (var1 / 32768.0)) * p1 p = 1048576.0 - adc_p p = (p - (var2 / 4096.0)) * 6250.0 / var1 var1 = p9 * p * p / 2147483648.0 var2 = p * p8 / 32768.0 p += (var1 + var2 + p7) / 16.0 return p / 100
# ---- Battery SMBUS ---- # bus = SMBus(1) #SMBUS init addr = 0x0b #SMBUS Address serial = "" cycle = "" failedcycles = 0 #Exit when data is not being pulled from smbus while cycle == "": print failedcycles if failedcycles == 13: print "SMBus is broken/diconnected" exit() try: serial = str(bus.read_word_data(addr, 0x1c)) #Serial Number cycle = str(bus.read_word_data(addr, 0x17)) # Cycle Count except IOError: print "Could not connect to bus" time.sleep(1) failedcycles += 1 # ---- MySQL data table init ---- # table = raw_input("Make a new table name: ") addtable = "CREATE TABLE " + str( table ) + "(time DECIMAL(20,2), temperature NUMERIC, voltage NUMERIC, current NUMERIC, relsoc NUMERIC, abssoc NUMERIC, ttoempty NUMERIC,remcap NUMERIC, fullcap NUMERIC, changecurr NUMERIC, changevolt NUMERIC, maxerror NUMERIC);" # ---- Table Management ---- #
class InputModule(AbstractInput): """ A sensor support class that monitors the DS18B20's lux """ def __init__(self, input_dev, testing=False): super(InputModule, self).__init__() self.logger = logging.getLogger("mycodo.inputs.bh1750") if not testing: from smbus2 import SMBus self.logger = logging.getLogger( "mycodo.bh1750_{id}".format(id=input_dev.unique_id.split('-')[0])) self.device_measurements = db_retrieve_table_daemon( DeviceMeasurements).filter( DeviceMeasurements.device_id == input_dev.unique_id) self.i2c_address = int(str(input_dev.i2c_location), 16) self.resolution = input_dev.resolution self.sensitivity = input_dev.sensitivity self.i2c_bus = SMBus(input_dev.i2c_bus) self.power_down() self.set_sensitivity(sensitivity=self.sensitivity) @property def lux(self): """ BH1750 luminosity in lux """ if self._measurements is None: # update if needed self.read() return self._measurements def get_measurement(self): """ Gets the BH1750's lux """ return_dict = measurements_dict.copy() if self.resolution == 0: lux = self.measure_low_res() elif self.resolution == 1: lux = self.measure_high_res() elif self.resolution == 2: lux = self.measure_high_res2() else: return None return_dict[0]['value'] = lux return return_dict def _set_mode(self, mode): self.mode = mode self.i2c_bus.write_byte(self.i2c_address, self.mode) def power_down(self): self._set_mode(POWER_DOWN) def power_on(self): self._set_mode(POWER_ON) def reset(self): self.power_on() # It has to be powered on before resetting self._set_mode(RESET) def cont_low_res(self): self._set_mode(CONTINUOUS_LOW_RES_MODE) def cont_high_res(self): self._set_mode(CONTINUOUS_HIGH_RES_MODE_1) def cont_high_res2(self): self._set_mode(CONTINUOUS_HIGH_RES_MODE_2) def oneshot_low_res(self): self._set_mode(ONE_TIME_LOW_RES_MODE) def oneshot_high_res(self): self._set_mode(ONE_TIME_HIGH_RES_MODE_1) def oneshot_high_res2(self): self._set_mode(ONE_TIME_HIGH_RES_MODE_2) def set_sensitivity(self, sensitivity=69): """ Set the sensor sensitivity. Valid values are 31 (lowest) to 254 (highest), default is 69. """ if sensitivity < 31: self.mtreg = 31 elif sensitivity > 254: self.mtreg = 254 else: self.mtreg = sensitivity self.power_on() self._set_mode(0x40 | (self.mtreg >> 5)) self._set_mode(0x60 | (self.mtreg & 0x1f)) self.power_down() def get_result(self): """ Return current measurement result in lx. """ data = self.i2c_bus.read_word_data(self.i2c_address, self.mode) count = data >> 8 | (data & 0xff) << 8 mode2coeff = 2 if (self.mode & 0x03) == 0x01 else 1 ratio = 1 / (1.2 * (self.mtreg / 69.0) * mode2coeff) return ratio * count def wait_for_result(self, additional=0): basetime = 0.018 if (self.mode & 0x03) == 0x03 else 0.128 time.sleep(basetime * (self.mtreg / 69.0) + additional) def do_measurement(self, mode, additional_delay=0): """ Perform complete measurement using command specified by parameter mode with additional delay specified in parameter additional_delay. Return output value in Lx. """ self.reset() self._set_mode(mode) self.wait_for_result(additional=additional_delay) return self.get_result() def measure_low_res(self, additional_delay=0): return self.do_measurement(ONE_TIME_LOW_RES_MODE, additional_delay) def measure_high_res(self, additional_delay=0): return self.do_measurement(ONE_TIME_HIGH_RES_MODE_1, additional_delay) def measure_high_res2(self, additional_delay=0): return self.do_measurement(ONE_TIME_HIGH_RES_MODE_2, additional_delay)
class i2c_device: # Bit masks. bit0 = 0x01 bit1 = 0x02 bit2 = 0x04 bit3 = 0x08 bit4 = 0x10 bit5 = 0x20 bit6 = 0x40 bit7 = 0x80 def __init__(self, address=None, bus=None): self.address = address # "address" is the device address on the i2c bus. self.bus = bus self.DEBUG = 0 if self.bus == None: self.bus = DEFAULT_I2C_BUS # "bus" is the Raspberry Pi external i2c bus, where the MCP23017 is connected. # This may vary accross different Raspberry Pi models. 0 is used by the # original Raspbery Pi model B (256 MB memory, 26-pin GPIO connector). # 1 is used by recent Raspberry Pi devices. self.device = SMBus(self.bus) return def bus_reset(self): '''Caution: bus reset is a general call operation. It is not device-specific. All devices on the bus are affected. In systems with multiple i2c busses, only one bus (the bus associated with this device) is reset.''' self.device.write_byte(0, 6) return def wbyte_only(self, value): # Write a single byte to device, without any register address. self.device.write_byte(self.address, value) def rbyte_only(self): # Read a single byte from device, without any register address. return self.device.read_byte(self.address) def wbyte(self, reg, value): # Write a single byte <value> to register <reg>. if self.DEBUG >= 32: sys.stdout.write( ' write x{:02X} to chip x{:02X} register {}\n'.format( value, self.address, reg)) sys.flush() self.device.write_byte_data(self.address, reg, value) return def rbyte(self, reg): # Read one byte from register <reg>. return self.device.read_byte_data(self.address, reg) def wword(self, reg, value): '''Write the integer <value> (two bytes) to register <reg>.''' if byte_swap: value = ((value & 0xff) << 8) | ((value >> 8) & 0xff) self.device.write_word_data(self.address, reg, value) return def rword(self, reg): value = self.device.read_word_data(self.address, reg) if byte_swap: value = ((value & 0xff) << 8) | ((value >> 8) & 0xff) return value
class InputModule(AbstractInput): """A sensor support class that monitors the DS18B20's lux.""" def __init__(self, input_dev, testing=False): super().__init__(input_dev, testing=testing, name=__name__) self.i2c_address = None self.i2c_bus = None self.resolution = None if not testing: self.try_initialize() def initialize(self): from smbus2 import SMBus self.i2c_address = int(str(self.input_dev.i2c_location), 16) self.resolution = self.input_dev.resolution self.i2c_bus = SMBus(self.input_dev.i2c_bus) self.power_down() self.set_sensitivity(sensitivity=self.input_dev.sensitivity) @property def lux(self): """BH1750 luminosity in lux.""" if self._measurements is None: # update if needed self.read() return self._measurements def get_measurement(self): """Gets the BH1750's lux.""" self.return_dict = copy.deepcopy(measurements_dict) if self.resolution == 0: lux = self.measure_low_res() elif self.resolution == 1: lux = self.measure_high_res() elif self.resolution == 2: lux = self.measure_high_res2() else: return None self.value_set(0, lux) return self.return_dict def _set_mode(self, mode): self.mode = mode self.i2c_bus.write_byte(self.i2c_address, self.mode) def power_down(self): self._set_mode(POWER_DOWN) def power_on(self): self._set_mode(POWER_ON) def reset(self): self.power_on() # It has to be powered on before resetting self._set_mode(RESET) def cont_low_res(self): self._set_mode(CONTINUOUS_LOW_RES_MODE) def cont_high_res(self): self._set_mode(CONTINUOUS_HIGH_RES_MODE_1) def cont_high_res2(self): self._set_mode(CONTINUOUS_HIGH_RES_MODE_2) def oneshot_low_res(self): self._set_mode(ONE_TIME_LOW_RES_MODE) def oneshot_high_res(self): self._set_mode(ONE_TIME_HIGH_RES_MODE_1) def oneshot_high_res2(self): self._set_mode(ONE_TIME_HIGH_RES_MODE_2) def set_sensitivity(self, sensitivity=69): """ Set the sensor sensitivity. Valid values are 31 (lowest) to 254 (highest), default is 69. """ if sensitivity < 31: self.mtreg = 31 elif sensitivity > 254: self.mtreg = 254 else: self.mtreg = sensitivity self.power_on() self._set_mode(0x40 | (self.mtreg >> 5)) self._set_mode(0x60 | (self.mtreg & 0x1f)) self.power_down() def get_result(self): """Return current measurement result in lux.""" data = self.i2c_bus.read_word_data(self.i2c_address, self.mode) count = data >> 8 | (data & 0xff) << 8 mode2coeff = 2 if (self.mode & 0x03) == 0x01 else 1 ratio = 1 / (1.2 * (self.mtreg / 69.0) * mode2coeff) return ratio * count def wait_for_result(self, additional=0): basetime = 0.018 if (self.mode & 0x03) == 0x03 else 0.128 time.sleep(basetime * (self.mtreg / 69.0) + additional) def do_measurement(self, mode, additional_delay=0): """ Perform complete measurement using command specified by parameter mode with additional delay specified in parameter additional_delay. Return output value in Lx. """ self.reset() self._set_mode(mode) self.wait_for_result(additional=additional_delay) return self.get_result() def measure_low_res(self, additional_delay=0): return self.do_measurement(ONE_TIME_LOW_RES_MODE, additional_delay) def measure_high_res(self, additional_delay=0): return self.do_measurement(ONE_TIME_HIGH_RES_MODE_1, additional_delay) def measure_high_res2(self, additional_delay=0): return self.do_measurement(ONE_TIME_HIGH_RES_MODE_2, additional_delay)
class I2CUnifiedLinux(I2CBase): def __init__(self, bus=None): if bus is None: bus = 1 self.i2c = SMBus(bus) def readfrom_mem(self, addr, memaddr, nbytes, *, addrsize=8): data = [None] * nbytes # initialise empty list self.smbus_i2c_read(addr, memaddr, data, nbytes, addrsize=addrsize) return data def writeto_mem(self, addr, memaddr, buf, *, addrsize=8): self.smbus_i2c_write(addr, memaddr, buf, len(buf), addrsize=addrsize) def smbus_i2c_write(self, address, reg, data_p, length, addrsize=8): ret_val = 0 data = [] for index in range(length): data.append(data_p[index]) if addrsize == 8: msg_w = i2c_msg.write(address, [reg] + data) elif addrsize == 16: msg_w = i2c_msg.write(address, [reg >> 8, reg & 0xff] + data) else: raise Exception("address must be 8 or 16 bits long only") self.i2c.i2c_rdwr(msg_w) return ret_val def smbus_i2c_read(self, address, reg, data_p, length, addrsize=8): ret_val = 0 if addrsize == 8: msg_w = i2c_msg.write( address, [reg]) # warning this is set up for 16-bit addresses elif addrsize == 16: msg_w = i2c_msg.write( address, [reg >> 8, reg & 0xff ]) # warning this is set up for 16-bit addresses else: raise Exception("address must be 8 or 16 bits long only") msg_r = i2c_msg.read(address, length) self.i2c.i2c_rdwr(msg_w, msg_r) if ret_val == 0: for index in range(length): data_p[index] = ord(msg_r.buf[index]) return ret_val def write8(self, addr, reg, data): if reg is None: d = int.from_bytes(data, 'big') self.i2c.write_byte(addr, d) else: r = int.from_bytes(reg, 'big') d = int.from_bytes(data, 'big') self.i2c.write_byte_data(addr, r, d) def read16(self, addr, reg): regInt = int.from_bytes(reg, 'big') return self.i2c.read_word_data(addr, regInt).to_bytes(2, byteorder='little', signed=False)
class PanTilt: """PanTilt HAT Driver Communicates with PanTilt HAT over i2c to control pan, tilt and light functions """ REG_CONFIG = 0x00 REG_SERVO1 = 0x01 REG_SERVO2 = 0x03 REG_WS2812 = 0x05 REG_UPDATE = 0x4E UPDATE_WAIT = 0.03 NUM_LEDS = 24 def __init__(self, enable_lights=True, idle_timeout=2, # Idle timeout in seconds light_mode=WS2812, light_type=RGB, servo1_min=575, servo1_max=2325, servo2_min=575, servo2_max=2325, address=0x15, i2c_bus=None): self._is_setup = False self._idle_timeout = idle_timeout self._servo1_timeout = None self._servo2_timeout = None self._i2c_retries = 10 self._i2c_retry_time = 0.01 self._enable_servo1 = False self._enable_servo2 = False self._enable_lights = enable_lights self._light_on = 0 self._servo_min = [servo1_min, servo2_min] self._servo_max = [servo1_max, servo2_max] self._light_mode = light_mode self._light_type = light_type self._i2c_address = address self._i2c = i2c_bus def setup(self): if self._is_setup: return True if self._i2c is None: try: from smbus2 import SMBus self._i2c = SMBus(1) except ImportError: if version_info[0] < 3: raise ImportError("This library requires python-smbus\nInstall with: sudo apt-get install python-smbus") elif version_info[0] == 3: raise ImportError("This library requires python3-smbus\nInstall with: sudo apt-get install python3-smbus") self.clear() self._set_config() atexit.register(self._atexit) self._is_setup = True def _atexit(self): if self._servo1_timeout is not None: self._servo1_timeout.cancel() if self._servo2_timeout is not None: self._servo2_timeout.cancel() self._enable_servo1 = False self._enable_servo2 = False self._set_config() def idle_timeout(self, value): """Set the idle timeout for the servos Configure the time, in seconds, after which the servos will be automatically disabled. :param value: Timeout in seconds """ self._idle_timeout = value def _set_config(self): """Generate config value for PanTilt HAT and write to device.""" config = 0 config |= self._enable_servo1 config |= self._enable_servo2 << 1 config |= self._enable_lights << 2 config |= self._light_mode << 3 config |= self._light_on << 4 self._i2c_write_byte(self.REG_CONFIG, config) def _check_int_range(self, value, value_min, value_max): """Check the type and bounds check an expected int value.""" if type(value) is not int: raise TypeError("Value should be an integer") if value < value_min or value > value_max: raise ValueError("Value {value} should be between {min} and {max}".format( value=value, min=value_min, max=value_max)) def _check_range(self, value, value_min, value_max): """Check the type and bounds check an expected int value.""" if value < value_min or value > value_max: raise ValueError("Value {value} should be between {min} and {max}".format( value=value, min=value_min, max=value_max)) def _servo_us_to_degrees(self, us, us_min, us_max): """Converts pulse time in microseconds to degrees :param us: Pulse time in microseconds :param us_min: Minimum possible pulse time in microseconds :param us_max: Maximum possible pulse time in microseconds """ self._check_range(us, us_min, us_max) servo_range = us_max - us_min angle = (float(us - us_min) / float(servo_range)) * 180.0 return int(round(angle, 0)) - 90 def _servo_degrees_to_us(self, angle, us_min, us_max): """Converts degrees into a servo pulse time in microseconds :param angle: Angle in degrees from -90 to 90 """ self._check_range(angle, -90, 90) angle += 90 servo_range = us_max - us_min us = (servo_range / 180.0) * angle return us_min + int(us) def _servo_range(self, servo_index): """Get the min and max range values for a servo""" return (self._servo_min[servo_index], self._servo_max[servo_index]) def _i2c_write_block(self, reg, data): if type(data) is list: for x in range(self._i2c_retries): try: self._i2c.write_i2c_block_data(self._i2c_address, reg, data) return except IOError: time.sleep(self._i2c_retry_time) continue raise IOError("Failed to write block") else: raise ValueError("Value must be a list") def _i2c_write_word(self, reg, data): if type(data) is int: for x in range(self._i2c_retries): try: self._i2c.write_word_data(self._i2c_address, reg, data) return except IOError: time.sleep(self._i2c_retry_time) continue raise IOError("Failed to write word") def _i2c_write_byte(self, reg, data): if type(data) is int: for x in range(self._i2c_retries): try: self._i2c.write_byte_data(self._i2c_address, reg, data) return except IOError: time.sleep(self._i2c_retry_time) continue raise IOError("Failed to write byte") def _i2c_read_byte(self, reg): for x in range(self._i2c_retries): try: return self._i2c.read_byte_data(self._i2c_address, reg) except IOError: time.sleep(self._i2c_retry_time) continue raise IOError("Failed to read byte") def _i2c_read_word(self, reg): for x in range(self._i2c_retries): try: return self._i2c.read_word_data(self._i2c_address, reg) except IOError: time.sleep(self._i2c_retry_time) continue raise IOError("Failed to read byte") def clear(self): """Clear the buffer.""" self._pixels = [0] * self.NUM_LEDS * 3 self._pixels += [1] def light_mode(self, mode): """Set the light mode for attached lights. PanTiltHAT can drive either WS2812 or SK6812 pixels, or provide a PWM dimming signal for regular LEDs. * PWM - PWM-dimmable LEDs * WS2812 - 24 WS2812 or 18 SK6812 pixels """ self.setup() self._light_mode = mode self._set_config() def light_type(self, set_type): """Set the light type for attached lights. Set the type of lighting strip connected: * RGB - WS2812 pixels with RGB pixel order * RGB - WS2812 pixels with GRB pixel order * RGBW - SK6812 pixels with RGBW pixel order * GRBW - SK6812 pixels with GRBW pixel order """ self._light_type = set_type def num_pixels(self): """Returns the supported number of pixels depending on light mode. RGBW or GRBW support 18 pixels RGB supports 24 pixels """ if self._light_type in [RGBW, GRBW]: return 18 return 24 def brightness(self, brightness): """Set the brightness of the connected LED ring. This only applies if light_mode has been set to PWM. It will be ignored otherwise. :param brightness: Brightness from 0 to 255 """ self.setup() self._check_int_range(brightness, 0, 255) if self._light_mode == PWM: # The brightness value is taken from the first register of the WS2812 chain self._i2c_write_byte(self.REG_WS2812, brightness) def set_all(self, red, green, blue, white=None): """Set all pixels in the buffer. :param red: Amount of red, from 0 to 255 :param green: Amount of green, from 0 to 255 :param blue: Amount of blue, from 0 to 255 :param white: Optional amount of white for RGBW and GRBW strips """ for index in range(self.num_pixels()): self.set_pixel(index, red, green, blue, white) def set_pixel_rgbw(self, index, red, green, blue, white): """Set a single pixel in the buffer for GRBW lighting stick :param index: Index of pixel from 0 to 17 :param red: Amount of red, from 0 to 255 :param green: Amount of green, from 0 to 255 :param blue: Amount of blue, from 0 to 255 :param white: Amount of white, from 0 to 255 """ self.set_pixel(index, red, green, blue, white) def set_pixel(self, index, red, green, blue, white=None): """Set a single pixel in the buffer. :param index: Index of pixel from 0 to 23 :param red: Amount of red, from 0 to 255 :param green: Amount of green, from 0 to 255 :param blue: Amount of blue, from 0 to 255 :param white: Optional amount of white for RGBW and GRBW strips """ self._check_int_range(index, 0, self.num_pixels() - 1) for color in [red, green, blue]: self._check_int_range(color, 0, 255) if white is not None: self._check_int_range(white, 0, 255) if self._light_type in [RGBW, GRBW]: index *= 4 if self._light_type == RGBW: self._pixels[index] = red self._pixels[index+1] = green self._pixels[index+2] = blue if self._light_type == GRBW: self._pixels[index] = green self._pixels[index+1] = red self._pixels[index+2] = blue if white is not None: self._pixels[index+3] = white else: index *= 3 if self._light_type == RGB: self._pixels[index] = red self._pixels[index+1] = green self._pixels[index+2] = blue if self._light_type == GRB: self._pixels[index] = green self._pixels[index+1] = red self._pixels[index+2] = blue def show(self): """Display the buffer on the connected WS2812 strip.""" self.setup() self._i2c_write_block(self.REG_WS2812, self._pixels[:32]) self._i2c_write_block(self.REG_WS2812 + 32, self._pixels[32:64]) self._i2c_write_block(self.REG_WS2812 + 64, self._pixels[64:]) self._i2c_write_byte(self.REG_UPDATE, 1) def servo_enable(self, index, state): """Enable or disable a servo. Disabling a servo turns off the drive signal. It's good practise to do this if you don't want the Pan/Tilt to point in a certain direction and instead want to save power. :param index: Servo index: either 1 or 2 :param state: Servo state: True = on, False = off """ self.setup() if index not in [1, 2]: raise ValueError("Servo index must be 1 or 2") if state not in [True, False]: raise ValueError("State must be True/False") if index == 1: self._enable_servo1 = state else: self._enable_servo2 = state self._set_config() def servo_pulse_min(self, index, value): """Set the minimum high pulse for a servo in microseconds. :param value: Value in microseconds """ if index not in [1, 2]: raise ValueError("Servo index must be 1 or 2") self._servo_min[index-1] = value def servo_pulse_max(self, index, value): """Set the maximum high pulse for a servo in microseconds. :param value: Value in microseconds """ if index not in [1, 2]: raise ValueError("Servo index must be 1 or 2") self._servo_max[index-1] = value def get_servo_one(self): """Get position of servo 1 in degrees.""" self.setup() us_min, us_max = self._servo_range(0) us = self._i2c_read_word(self.REG_SERVO1) try: return self._servo_us_to_degrees(us, us_min, us_max) except ValueError: return 0 def get_servo_two(self): """Get position of servo 2 in degrees.""" self.setup() us_min, us_max = self._servo_range(1) us = self._i2c_read_word(self.REG_SERVO2) try: return self._servo_us_to_degrees(us, us_min, us_max) except ValueError: return 0 def servo_one(self, angle): """Set position of servo 1 in degrees. :param angle: Angle in degrees from -90 to 90 """ self.setup() if not self._enable_servo1: self._enable_servo1 = True self._set_config() us_min, us_max = self._servo_range(0) us = self._servo_degrees_to_us(angle, us_min, us_max) self._i2c_write_word(self.REG_SERVO1, us) if self._idle_timeout > 0: if self._servo1_timeout is not None: self._servo1_timeout.cancel() self._servo1_timeout = Timer(self._idle_timeout, self._servo1_stop) self._servo1_timeout.daemon = True self._servo1_timeout.start() def _servo1_stop(self): self._servo1_timeout = None self._enable_servo1 = False self._set_config() def servo_two(self, angle): """Set position of servo 2 in degrees. :param angle: Angle in degrees from -90 to 90 """ self.setup() if not self._enable_servo2: self._enable_servo2 = True self._set_config() us_min, us_max = self._servo_range(1) us = self._servo_degrees_to_us(angle, us_min, us_max) self._i2c_write_word(self.REG_SERVO2, us) if self._idle_timeout > 0: if self._servo2_timeout is not None: self._servo2_timeout.cancel() self._servo2_timeout = Timer(self._idle_timeout, self._servo2_stop) self._servo2_timeout.daemon = True self._servo2_timeout.start() def _servo2_stop(self): self._servo2_timeout = None self._enable_servo2 = False self._set_config() pan = servo_one tilt = servo_two get_pan = get_servo_one get_tilt = get_servo_two
class INA233: def __init__(self, bus, addr, max_i=15.0, r_shunt=0.002, debug=False): self.addr = addr self.max_i = max_i self.r_shunt = r_shunt self.debug = debug self.energy_acc = 0 self.last = datetime.utcnow() self.bus = SMBus(bus) self.init() # Set the INA233 to default settings def set_defaults(self): self.bus.write_byte(self.addr, 0x12) self.energy_acc = 0 self.last = datetime.utcnow() # Initialise the INA233 for I and P readings def init(self): # Reset device to defaults self.set_defaults() # Debug if self.debug: print( "INA233 0x%02X Init with max_i: %.1f Amps, r_shunt: %.5f ohms" % (self.addr, self.max_i, self.r_shunt)) # Current LSB is stored as float so we do not need to compute m later self.current_lsb = float(self.max_i) / 2**15 cal = 0.00512 / (self.current_lsb * self.r_shunt) # Round to nearest int for programming cal_r = int(round(cal)) # Debug if self.debug: print( "INA233 0x%02X MFR_CALIBRATION Rounded from %.4f to %d (0x%04X)" % (self.addr, cal, cal_r, cal_r)) print("INA233 0x%02X current_lsb: %.15f" % (self.addr, self.current_lsb)) # Set calibration registers in device self.set_mfr_calibration(cal_r) self.set_mfr_device_config(read_ein=1) self.set_mfr_adc_config(avg=5, vbusct=5, vshct=4, mode=7) # Set the MFR_CALIBRATION register def set_mfr_calibration(self, cal): # Build config value cali = (cal & 0x7FFF) #Write to register self.bus.write_word_data(self.addr, 0xD4, cali) mfr_calibration = self.bus.read_word_data(self.addr, 0xD4) # Debug if self.debug: if (mfr_calibration != cali): print( "INA233 0x%02X MFR_CALIBRATION readback error, write: 0x%04X, read: 0x%04X" % (self.addr, cali, mfr_calibration)) else: print( "INA233 0x%02X MFR_CALIBRATION readback OK, read: 0x%04X" % (self.addr, mfr_calibration)) # Set MFR_ADC_CONFIG register def set_mfr_adc_config(self, avg=0, vbusct=4, vshct=4, mode=7): # Build config value adc_conf = ((0x4 & 0xF) << 12) adc_conf += ((avg & 0x7) << 9) adc_conf += ((vbusct & 0x7) << 6) adc_conf += ((vshct & 0x7) << 3) adc_conf += ((mode & 0x7) << 0) # Write to register self.bus.write_word_data(self.addr, 0xD0, adc_conf) adc_config = self.bus.read_word_data(self.addr, 0xD0) # Debug if self.debug: if (adc_config != adc_conf): print( "INA233 0x%02X MFR_ADC_CONFIG readback error, write: 0x%04X, read: 0x%04X" % (self.addr, adc_conf, adc_config)) else: print( "INA233 0x%02X MFR_ADC_CONFIG readback OK, read: 0x%04X" % (self.addr, adc_config)) #Set MFR_DEVICE_CONFIG register def set_mfr_device_config(self, ein_status=0, ein_accum=0, i2c_filt=0, read_ein=0, alert=1, apol=0): # Build config value dev_conf = ((ein_status & 0x01) << 7) dev_conf += ((ein_accum & 0x03) << 4) dev_conf += ((i2c_filt & 0x01) << 3) dev_conf += ((read_ein & 0x01) << 2) dev_conf += ((alert & 0x01) << 1) dev_conf += ((apol & 0x01) << 0) # Write to register self.bus.write_byte_data(self.addr, 0xD5, dev_conf) device_config = self.bus.read_byte_data(self.addr, 0xD5) # Debug if self.debug: if (device_config != dev_conf): print( "INA233 0x%02X MFR_DEVICE_CONFIG readback error, write: 0x%02X, read: 0x%02X" % (self.addr, dev_conf, device_config)) else: print( "INA233 0x%02X MFR_DEVICE_CONFIG readback OK, read: 0x%02X" % (self.addr, device_config)) # Obtain voltage reading def v_read(self): vin_read = float(self.bus.read_word_data(self.addr, 0x88)) vin = (1.0 / 8) * (vin_read * 10**-2) # Debug if self.debug: print("INA233 0x%02X Voltage : %.2fV" % (self.addr, vin)) return vin # Obtain current reading def i_read(self): iin_read = self.bus.read_word_data(self.addr, 0x89) # Check sign if (iin_read & 0x8000): iin_read = iin_read - 0x10000 iin = self.current_lsb * iin_read # Debug if self.debug: print("INA233 0x%02X Current : %.2fA" % (self.addr, iin)) return iin # Obtain power reading def p_read(self): pin_read = float(self.bus.read_word_data(self.addr, 0x97)) pin = self.current_lsb * 25 * pin_read # Debug if self.debug: print("INA233 0x%02X Power : %.2fW" % (self.addr, pin)) return pin # Read total energy (kWh) since last reset def e_read(self): # Read energy register ein_read = self.bus.read_i2c_block_data(self.addr, 0x86, 7) # Get time of this read t = datetime.utcnow() # Extract sub-values pow_acc = (ein_read[1] & 0xFF) + ((ein_read[2] & 0xFF) << 8) pow_acc_roll = ein_read[3] & 0xFF samples = (ein_read[4] & 0xFF) + ((ein_read[5] & 0xFF) << 8) + ( (ein_read[6] & 0xFF) << 16) # Total energy for this sample period (since self.last) # Assumes autoclear enabled in MFR_DEVICE_CONFIG # Assumes this command is run frequently enough to avoid roll overs (via reset on read) total_e = self.current_lsb * 25 * ((pow_acc_roll * 0xFFFF) + pow_acc) # Energy is total power accumulated * time since measurement start if (samples != 0): dur = (t - self.last).total_seconds() self.last = t self.energy_acc += ( (float(total_e) / samples) * dur) / (3600 * 1000) #Debug if self.debug: print("INA233 0x%02X Energy : %.8fkWh" % (self.addr, self.energy_acc)) return self.energy_acc else: return 0.0 # Print debug information for this INA233 device def print_debug(self): print("\nDebug information for INA233 addr: 0x%02X" % self.addr) # Get MFR_MODEL mfr_model = self.bus.read_i2c_block_data(self.addr, 0x9A, 7) print("MFR_MODEL : " + bytearray(mfr_model).decode('utf-8')) # Get MFR_ID mfr_id = self.bus.read_i2c_block_data(self.addr, 0x99, 3) print("MFR_ID : " + bytearray(mfr_id).decode('utf-8')) # Get MFR_MODEL mfr_revision = self.bus.read_word_data(self.addr, 0x9B) print("MFR_REVISION: 0x%04X" % mfr_revision) # Get MFR_CALIBRATION mfr_calibration = self.bus.read_word_data(self.addr, 0xD4) print("MFR_CALIC : 0x%04X" % mfr_calibration) # Get MFR_DEVICE_CONDIG mfr_dev_config = self.bus.read_byte_data(self.addr, 0xD5) print("MFR_DEV_CONF: 0x%02X" % mfr_dev_config) # Capability capability = self.bus.read_byte_data(self.addr, 0x19) print("Capability : 0x%02X" % capability) # Status byte status_byte = self.bus.read_byte_data(self.addr, 0x78) print("Status byte : 0x%02X" % status_byte) # Status word status_word = self.bus.read_word_data(self.addr, 0x79) print("Status word : 0x%04X" % status_word) # Status iout status_iout = self.bus.read_byte_data(self.addr, 0x7B) print("Status IOUT : 0x%02X" % status_iout) # Status input status_input = self.bus.read_byte_data(self.addr, 0x7C) print("Status INPUT: 0x%02X" % status_input) # Status communications status_cml = self.bus.read_byte_data(self.addr, 0x7E) print("Status CML : 0x%02X" % status_cml) # Status MFR Specific status_mfr = self.bus.read_byte_data(self.addr, 0x80) print("Status MFR : 0x%02X" % status_mfr) # ADC_CONFIG adc_config = self.bus.read_word_data(self.addr, 0xD0) print("ADC_CONFIG : 0x%04X" % adc_config) print("\n")
registers = { 'CONFIG': 0x01, 'TUPPER': 0x02, 'TLOWERL': 0x03, 'TCRIT': 0x04, 'TA': 0x05, 'MANUFACTURER_ID': 0x06, 'DEVICE_ID': 0x07, 'RESOLUTION': 0x08, } bus = SMBus(1) address = 0x18 for k in registers: dat = bus.read_word_data(0x18, registers[k]) print('{} -> {}'.format(k, dat)) # Parse temp v = bus.read_word_data(0x18, 0x05) print('Raw: {}'.format(v)) # Split in 2-complements ub=v & 0xFF lb=(v >> 8) & 0xFF # Clear flags / take lower 13 ub = ub & 0x1F print('1: {}, 2: {}'.format(ub, lb)) # Check for negative values if (ub & 0x10) == 0x10: ub = ub & 0x0F t = 256 - (ub * 16 + lb/16)
class Sfp(): def __init__(self): """Init smbus channel and SFP driver on specified address.""" self.data = { "module_info": { "manufacturer": None, "revision": None, "serial_num": None, "sfp_type": None, "connector": None, "bitrate": None, "wavelength": None }, "diagnostics": { "temp": None, "tx_power_dBm": None, "rx_power_dBm": None, "tx_power": None, "rx_power": None } } try: self.i2c_bus = SMBus(I2C_CHANNEL) self.init() except Exception as e: log.error("An error occured during sfp initializion!") self.i2c_bus = None raise Exception(e) def __del__(self): """Driver destructor.""" self.i2c_bus = None def init(self): """Init and read all info registers""" try: manufacturer = self.i2c_bus.read_i2c_block_data(SFP_I2C_INFO_ADDRESS, SFP_MANUFACTURER_REG, SFP_MANUFACTURER_LENGTH) self.data["module_info"]["manufacturer"] = "".join(chr(x) for x in manufacturer) except Exception as e: raise Exception(f"An error occured during manufacturer data i2c read: {e}") try: revision = self.i2c_bus.read_i2c_block_data(SFP_I2C_INFO_ADDRESS, SFP_REVISION_REG, SFP_REVISION_LENGTH) self.data["module_info"]["revision"] = "".join(chr(x) for x in revision) except Exception as e: raise Exception(f"An error occured during revision i2c read: {e}") try: serial_num = self.i2c_bus.read_i2c_block_data(SFP_I2C_INFO_ADDRESS, SFP_SERIAL_NO_REG, SFP_SERIAL_NO_LENGTH) self.data["module_info"]["serial_num"] = "".join(chr(x) for x in serial_num) except Exception as e: raise Exception(f"An error occured during serial number i2c read: {e}") try: self.data["module_info"]["sfp_type"] = self.i2c_bus.read_byte_data(SFP_I2C_INFO_ADDRESS, SFP_TYPE_REG) except Exception as e: raise Exception(f"An error occured during sfp type i2c read: {e}") try: self.data["module_info"]["connector"] = self.i2c_bus.read_byte_data(SFP_I2C_INFO_ADDRESS, SFP_CONNECTOR_REG) except Exception as e: raise Exception(f"An error occured during connector type i2c read: {e}") try: self.data["module_info"]["bitrate"] = self.i2c_bus.read_byte_data(SFP_I2C_INFO_ADDRESS, SFP_BITRATE_REG) * 100 except Exception as e: raise Exception(f"An error occured during bitrate i2c read: {e}") try: wavelength = self.i2c_bus.read_word_data(SFP_I2C_INFO_ADDRESS, SFP_WAVELENGTH_REG) self.data["module_info"]["wavelength"] = (wavelength & 0xff) * 256 + ((wavelength & 0xff00) >> 8) except Exception as e: raise Exception(f"An error occured during wavelength i2c read: {e}") try: self.diag_settings = self.i2c_bus.read_byte_data(SFP_I2C_INFO_ADDRESS, SFP_DIAG_MONITORING_REG) except Exception as e: raise Exception(f"An error occured during diagnostics settings i2c read: {e}") def convert_to_fp(self, number, num_bits, divisor): """Convert num_bits bit number to a floating point number""" val = 0 for bit in range(0, num_bits): val += (number & (1 << bit)) / divisor return val def convert_to_dB(self, mW): """Convert mW to dB and return value""" if mW == 0.0: return -40.0 # -40.0 is lower limit return 10 * np.log10(mW) def get_diagnostics(self): """Get sfp module diagnostics""" diagnostics_block = self.i2c_bus.read_i2c_block_data(SFP_I2C_DIAG_ADDRESS, SFP_DIAG_REG_START, DIAG_DATA_LENGTH) temp_bytes = diagnostics_block[TEMP_OFFSET: VCC_OFFSET] temp_h = float(np.int8(temp_bytes[0])) # signed int8 temp_l = self.convert_to_fp(temp_bytes[1], 8, 256) temp = temp_h + temp_l self.data["diagnostics"]["temp"] = temp # next is transciever supply voltage - skip this for now # next is tx bias current in uA - skip # next is tx output power in mW tx_bytes = diagnostics_block[TX_POWER_OFFSET:RX_POWER_OFFSET] tx_power = float(np.uint16((tx_bytes[0] << 8) | tx_bytes[1]) / 10000) # LSB is equal to 100 uW, so the range is [0, 6.5535]mW self.data["diagnostics"]["tx_power"] = tx_power tx_power_dbm = round(self.convert_to_dB(tx_power), 3) self.data["diagnostics"]["tx_power_dBm"] = float(tx_power_dbm) # next is rx received power in mW rx_bytes = diagnostics_block[RX_POWER_OFFSET:] rx_power = float(np.uint16((rx_bytes[0] << 8) | rx_bytes[1]) / 10000) # LSB is equal to 100 uW, so the range is [0, 6.5535]mW self.data["diagnostics"]["rx_power"] = rx_power rx_power_dbm = round(self.convert_to_dB(rx_power), 3) self.data["diagnostics"]["rx_power_dBm"] = float(rx_power_dbm) return self.data["diagnostics"] def get_module_info(self): """Get data""" return self.data["module_info"]
class BMSCom: def __init__(self): self._bus = SMBus(1) # indicates /dev/ic2-1 self.address = 0x0B # bus address of the battery status manager self.polynomial = '100000111' # PEC checksum polynomial binary 0x107 (CRC-8) self._bus.pec = 1 # Enable PEC verification # commands read self.reg_cell_voltage = 0x09 # command code to read the voltage of a cell (1mV) self.reg_rsoc100 = 0x0D # command code to read the RSOC value based on a 0−100 scale (1%) self.reg_rsoc1000 = 0x0F # command code to read the RSOC value based on a 0−1000 scale (0.1%) # commands write self.reg_low_rsoc = 0x13 # command code to sets or read the RSOC threshold to generate Alarm signal (1%) self.reg_low_voltage = 0x14 # command code to sets or read the voltage threshold to generate Alarm signal (1mV) # gets voltage for a cell in mV # return int def get_voltage(self): return self._bus.read_word_data(i2c_addr=self.address, register=self.reg_cell_voltage) # gets battery charge in % with a 1% precision # return int def get_charge100(self): return self._bus.read_word_data(i2c_addr=self.address, register=self.reg_rsoc100) # gets battery charge in % with a 0.1% precision # return int def get_charge1000(self): return self._bus.read_word_data(i2c_addr=self.address, register=self.reg_rsoc1000) / 10 # separate a number in two Bytes (data Byte low and data_byte_high) # input int <= 0xFFFF = 65535 # return a list [data_byte_low, data_byte_high] @staticmethod def _separate_bytes(number): list_bytes = [255, 255] if number <= 0xFFFF & number >= 0: data_byte_high1 = number // (16 ** 3) # most significant 4 bits of the most significant Byte data_byte_high2 = (number - data_byte_high1 * 16 ** 3) // (16 ** 2) # less significant 4 bits of the most # significant Byte data_byte_high = data_byte_high1 * 16 + data_byte_high2 # most significant Byte data_byte_low1 = (number - data_byte_high1 * 16 ** 3 - data_byte_high2 * 16 ** 2) // (16 ** 1) # most # significant 4 bits of the less significant Byte data_byte_low2 = ( number - data_byte_high1 * 16 ** 3 - data_byte_high2 * 16 ** 2 - data_byte_low1 * 16) # less # significant 4 bits of the less significant Byte data_byte_low = data_byte_low1 * 16 + data_byte_low2 # less significant Byte list_bytes = [data_byte_low, data_byte_high] elif number < 0: list_bytes = [0, 0] return list_bytes # xor operation with str @staticmethod def _xor(first, second): # initialize result result = [] # Traverse all bits, if bits are # same, then XOR is 0, else 1 for i in range(1, len(second)): if first[i] == second[i]: result.append('0') else: result.append('1') return ''.join(result) # Performs Modulo-2 division def _mod2div(self, divident, divisor): # Number of bits to be XORed at a time. pick = len(divisor) # Slicing the divident to appropriate # length for particular step tmp = divident[0: pick] while pick < len(divident): if tmp[0] == '1': # replace the divident by the result # of XOR and pull 1 bit down tmp = self._xor(divisor, tmp) + divident[pick] else: # If leftmost bit is '0' # If the leftmost bit of the dividend (or the # part used in each step) is 0, the step cannot # use the regular divisor; we need to use an # all-0s divisor. tmp = self._xor('0' * pick, tmp) + divident[pick] # increment pick to move further pick += 1 # For the last n bits, we have to carry it out # normally as increased value of pick will cause # Index Out of Bounds. if tmp[0] == '1': tmp = self._xor(divisor, tmp) else: tmp = self._xor('0' * pick, tmp) checkword = tmp return checkword # Function used at the sender side to encode # calcul checksum CRC-8 for self.polynomial # inputs int # output int def _calculation_checksum(self, register, data_byte_low, data_byte_high): write_adress = self.address * 2 # address for writing data_send = bin(write_adress * 2 ** 24 + register * 2 ** 16 + data_byte_low * 2 ** 8 + data_byte_high) # # transform data in srt binary data_send = data_send[2:len(data_send)] # get rid of the beginning ('0b') l_polynomial = len(self.polynomial) # Appends n-1 zeroes at end of data appended_data = data_send + '0' * (l_polynomial - 1) str_checksum = self._mod2div(appended_data, self.polynomial) n = len(str_checksum) checksum = 0 for i in range(0, len(str_checksum)): n = n - 1 if str_checksum[i] == '1': bit = 1 else: bit = 0 checksum = checksum + bit * 2 ** n return checksum # set low voltage for the alarm in mV # input int <= 0xFFFF = 65535 def set_low_voltage_alarm(self, min_voltage): [data_byte_low, data_byte_high] = self._separate_bytes(min_voltage) checksum = self._calculation_checksum(self.reg_low_voltage, data_byte_low, data_byte_high) self._bus.write_i2c_block_data(i2c_addr=self.address, register=self.reg_low_voltage, data=[data_byte_low, data_byte_high, checksum]) # set low rsoc for the alarm in % # input int <= 0x0064 = 100 def set_low_rsoc_alarm(self, min_rsoc): if min_rsoc > 100: min_rsoc = 100 [data_byte_low, data_byte_high] = self._separate_bytes(min_rsoc) checksum = self._calculation_checksum(self.reg_low_rsoc, data_byte_low, data_byte_high) self._bus.write_i2c_block_data(i2c_addr=self.address, register=self.reg_low_rsoc, data=[data_byte_low, data_byte_high, checksum])
def printHex(data): hexChar = '' for val in data: hexChar += format('0x%02x ' % val) commObj = SMBus(2) if commObj == None: print('Not able to open driver') quit() curList = list() avecurList = list() cur = c_short() for i in range(100): cur = commObj.read_word_data(tgtAddress, SBSCurrent) avecurr = commObj.read_word_data(tgtAddress, SBSAveCurrent) current = c_short(cur).value aveCurrent = c_short(avecurr).value curList.append(current) avecurList.append(aveCurrent) print('Current: ', current, 'Average Current', aveCurrent) time.sleep(1.0) mincur = min(curList) maxcur = max(curList) print('Lowest current: %d Highest Current %d' % (mincur, maxcur)) minaveCurr = min(avecurList) maxaveCurr = max(avecurList) print('Lowest Ave current: %d Highest Ave Current %d' %
class InputModule(AbstractInput): """ A sensor support class that measures the Chirp's moisture, temperature and light """ def __init__(self, input_dev, testing=False): super(InputModule, self).__init__(input_dev, testing=testing, name=__name__) if not testing: self.i2c_address = int(str(input_dev.i2c_location), 16) self.i2c_bus = input_dev.i2c_bus self.bus = SMBus(self.i2c_bus) self.filter_average('lux', init_max=3) def get_measurement(self): """ Gets the light, moisture, and temperature """ self.return_dict = measurements_dict.copy() if self.is_enabled(0): self.value_set(0, self.filter_average('lux', measurement=self.light())) if self.is_enabled(1): self.value_set(1, self.moist()) if self.is_enabled(2): self.value_set(2, self.temp() / 10.0) return self.return_dict def get_reg(self, reg): # read 2 bytes from register val = self.bus.read_word_data(self.i2c_address, reg) # return swapped bytes (they come in wrong order) return (val >> 8) + ((val & 0xFF) << 8) def reset(self): # To reset the sensor, write 6 to the device I2C address self.bus.write_byte(self.i2c_address, 6) def set_addr(self, new_addr): # To change the I2C address of the sensor, write a new address # (one byte [1..127]) to register 1; the new address will take effect after reset self.bus.write_byte_data(self.i2c_address, 1, new_addr) self.reset() # self.address = new_addr def moist(self): # To read soil moisture, read 2 bytes from register 0 return self.get_reg(0) def temp(self): # To read temperature, read 2 bytes from register 5 return self.get_reg(5) def light(self): # To read light level, start measurement by writing 3 to the # device I2C address, wait for 3 seconds, read 2 bytes from register 4 self.bus.write_byte(self.i2c_address, 3) time.sleep(1.5) lux = self.get_reg(4) if lux == 0: return 65535.0 else: return(1 - (lux / 65535.0)) * 65535.0
""" @author: root """ import time from smbus2 import SMBus tgtAddress = 0x0B voltcmd = 0x09 def printHex(data): hexChar = '' for val in data: hexChar += format('0x%02x ' % val) commObj = SMBus(2) if commObj == None: print('Not able to open driver') quit() for i in range(200): b = commObj.read_word_data(tgtAddress, voltcmd) #print('Byte Word: ', b) commObj.write_i2c_block_data(tgtAddress, 0x44, [2,0]) verString = commObj.read_i2c_block_data(tgtAddress, 0x44, 13) print('Result ', verString) commObj.close()