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()
def __init__(self, input_dev, testing=False): super(InputModule, self).__init__() self.logger = logging.getLogger("mycodo.inputs.sht2x") if not testing: from smbus2 import SMBus self.logger = logging.getLogger( "mycodo.sht2x_{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.i2c_bus = input_dev.i2c_bus self.sht2x = SMBus(self.i2c_bus)
def __init__(self, bus=0): """ Initialize the AXP209 object :param bus: i2c bus number or a SMBus object :type bus: Integer or SMBus object """ if isinstance(bus, int): self.bus = SMBus(bus, force=True) self.autocleanup = True else: self.bus = bus self.autocleanup = False # force ADC enable for battery voltage and current self.adc_enable1 = 0xc3
def __init__(self, input_dev, testing=False): super(InputModule, self).__init__() self.logger = logging.getLogger("mycodo.inputs.mh_z16") if not testing: self.logger = logging.getLogger( "mycodo.mh_z16_{id}".format(id=input_dev.unique_id.split('-')[0])) self.interface = input_dev.interface self.uart_location = input_dev.uart_location if self.interface == 'UART': import serial # Check if device is valid self.serial_device = is_device(self.uart_location) if self.serial_device: try: self.ser = serial.Serial(self.serial_device, timeout=1) except serial.SerialException: self.logger.exception('Opening serial') else: self.logger.error( 'Could not open "{dev}". ' 'Check the device location is correct.'.format( dev=self.uart_location)) elif self.interface == 'I2C': from smbus2 import SMBus self.i2c_address = int(str(input_dev.i2c_location), 16) self.i2c_bus = input_dev.i2c_bus self.cmd_measure = [0xFF, 0x01, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63] self.IOCONTROL = 0X0E << 3 self.FCR = 0X02 << 3 self.LCR = 0X03 << 3 self.DLL = 0x00 << 3 self.DLH = 0X01 << 3 self.THR = 0X00 << 3 self.RHR = 0x00 << 3 self.TXLVL = 0X08 << 3 self.RXLVL = 0X09 << 3 self.i2c = SMBus(self.i2c_bus) self.begin()
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)
def __init__(self, input_dev, testing=False): super(InputModule, self).__init__() self.logger = logging.getLogger('mycodo.inputs.am2320') self.powered = False self.sensor = None self.i2c_address = 0x5C if not testing: from smbus2 import SMBus self.logger = logging.getLogger( 'mycodo.am2320_{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_bus = input_dev.i2c_bus self.power_output_id = input_dev.power_output_id self.start_sensor() self.sensor = SMBus(self.i2c_bus)
def __init__(self): self.sensor = Si7021(SMBus(1))
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 BNO080_I2C: # I2C packet read delay in microseconds I2CDELAY = 400 # Packets can be up to 32k. MAX_PACKET_SIZE = 32762 # This is in words, we only care about the first 9 (Qs, range, etc) MAX_METADATA_SIZE = 9 # SHTP cmd channel: byte-0=command, byte-1=parameter, byte-n=parameter CHANNEL_COMMAND = 0 # SHTP exec channel: write 1=reset, 2=on, 3=sleep, read 1=reset complete CHANNEL_EXECUTABLE = 1 # Sensor Hub control channel for sensor config commands and responses CHANNEL_CONTROL = 2 # Input Sensor reports only sends data from sensor to host CHANNEL_REPORTS = 3 # Wake Input Sensor reports sends data from wake sensors to host CHANNEL_WAKE_REPORTS = 4 # Gyro rotation vector in extra channel to allow prioritization CHANNEL_GYRO = 5 # Control channel commands (BNO8X datasheet figure 1-30) COMMAND_RESPONSE = 0xF1 COMMAND_REQUEST = 0xF2 FRS_READ_RESPONSE = 0xF3 # Flash Record System read response FRS_READ_REQUEST = 0xF4 # Flash Record System read request FRS_WRITE_RESPONSE = 0xF5 # Flash Record System write response FRS__WRITE_DATA = 0xF6 # Flash Record System write data FRS__WRITE_REQUEST = 0xF7 # Flash Record System write request PRODUCT_ID_RESPONSE = 0xF8 PRODUCT_ID_REQUEST = 0xF9 GET_TIME_REFERENCE = 0xFB GET_TIMESTAMP_REBASE = 0xFA GET_FEATURE_RESPONSE = 0xFC SET_FEATURE_COMMAND = 0xFD GET_FEATURE_REQUEST = 0xFE #All the different sensors and features we can get reports from #These are used when enabling a given sensor SENSOR_REPORTID_ACC = 0x01 # Accelerometer SENSOR_REPORTID_GYR = 0x02 # Gyroscope SENSOR_REPORTID_MAG = 0x03 # Magnetometer SENSOR_REPORTID_LIN = 0x04 # Linear Acceleration SENSOR_REPORTID_ROT = 0x05 # Rotation Vector SENSOR_REPORTID_GRA = 0x06 # Gravity SENSOR_REPORTID_GAM = 0x08 # Game Rotation Vector SENSOR_REPORTID_GEO = 0x09 # Geomagnetic Rotation SENSOR_REPORTID_TAP = 0x10 # Tap Detector SENSOR_REPORTID_STP = 0x11 # Step Counter SENSOR_REPORTID_STA = 0x13 # Stability Classifier SENSOR_REPORTID_PER = 0x1E # Personal Activity Classifier REPORT_SIZES = { SENSOR_REPORTID_ACC: 10, SENSOR_REPORTID_GYR: 10, SENSOR_REPORTID_MAG: 10, SENSOR_REPORTID_LIN: 10, SENSOR_REPORTID_ROT: 14, SENSOR_REPORTID_GRA: 10, SENSOR_REPORTID_GAM: 12, SENSOR_REPORTID_GEO: 14, SENSOR_REPORTID_TAP: 5, SENSOR_REPORTID_STP: 12, SENSOR_REPORTID_STA: 6, SENSOR_REPORTID_PER: 4, GET_TIME_REFERENCE: 5, GET_TIMESTAMP_REBASE: 5 } def __init__(self, addr, port): self.addr = addr self.bus = SMBus(port) self.sequence = [0] * 5 self.get_ad() @classmethod def _i2c_delay(cls): time.sleep(cls.I2CDELAY / 1000000) def start_calib(self): me_calib = [ self.COMMAND_REQUEST, self.sequence[self.CHANNEL_CONTROL], 0x07, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ] self.send_shtp(self.CHANNEL_CONTROL, me_calib) res_head, res_data = self.receive_shtp_until(self.CHANNEL_CONTROL, [self.COMMAND_RESPONSE]) count = 0 while res_data[2] != 0x07 and count < 3: res_head, res_data = self.receive_shtp_until( self.CHANNEL_COMMAND, [self.COMMAND_RESPONSE]) count += 1 if res_data[2] == 0x07 and res_data[5] != 0: print(f"ERROR: ME calibration set command failed: {res_data}") self.start_game_rot(10) self.start_mag(50) report_dict = self.get_report([self.SENSOR_REPORTID_MAG]) mag_rep = report_dict.get( self.SENSOR_REPORTID_MAG, [[0x00, 0x00, 0x00]])[-1] # most recent mag report while mag_rep[2] & 0x03 != 0x03: print(mag_rep[2] & 0x03) time.sleep(1 / 50) delete_last_lines(1) report_dict = self.get_report([self.SENSOR_REPORTID_MAG]) mag_rep = report_dict.get( self.SENSOR_REPORTID_MAG, [[0x00, 0x00, 0x00]])[-1] # most recent mag report print("Calibration Success!") self.save_dcd() return True def set_feature(self, sensor, features, sensitivity, rate, batch, sensor_spec): feat_cmd = [ self.SET_FEATURE_COMMAND, sensor, features, sensitivity & 0xff, # sensitvity LSB sensitivity >> 8, # sensitivty MSB rate & 0xff, # rate LSB (rate & 0xff00) >> 8, # rate (rate & 0xff0000) >> 16, # rate (rate) >> 24, # rate MSB (batch & 0xff), # batch rate LSB (batch & 0xff00) >> 8, # batch rate (batch & 0xff0000) >> 16, # batch rate (batch >> 24), # batch rate MSB (sensor_spec & 0xff), (sensor_spec & 0xff00) >> 8, (sensor_spec & 0xff0000) >> 16, (sensor_spec >> 24) ] self.send_shtp(self.CHANNEL_CONTROL, feat_cmd) time.sleep(0.1) # letting sensor catch up self.send_shtp(self.CHANNEL_CONTROL, [self.GET_FEATURE_REQUEST, sensor]) self._i2c_delay() res_head, res_data = self.receive_shtp_until( self.CHANNEL_CONTROL, [self.GET_FEATURE_RESPONSE]) # TODO: Log this on debug and check the values # print(f"Sensor: {res_data[1]}"); # print(f"Feature Flags: {res_data[2]}"); # print(f"Sensitivity byte: {res_data[4]}, {res_data[3]}"); # print(f"Report Interval word: {res_data[8]} {res_data[7]} {res_data[6]} {res_data[5]}"); # print(f"Sensor Specific Config word: {res_data[13]}, {res_data[14]}, {res_data[15]}, {res_data[16]}"); return True def save_dcd(self): ''' saves the current dynamic calibration data, should be done after a calibration ''' dcd_cmd = [ self.COMMAND_REQUEST, self.sequence[self.CHANNEL_CONTROL], 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ] self.send_shtp(self.CHANNEL_CONTROL, dcd_cmd) count = 0 res_head, res_data = self.receive_shtp_until(self.CHANNEL_CONTROL, [self.COMMAND_RESPONSE]) while res_data[2] != 0x06 and count < 3: count += 1 if res_data[2] == 0x06 and res_data[5] != 0: print( f"ERROR: DCD Save failed after calibration: {self.print_hex(res_data)}" ) return False else: return True def start_acc(self, rate): return self.set_feature(self.SENSOR_REPORTID_ACC, 0, 0, rate, 0, 0) def start_rot(self, rate): return self.set_feature(self.SENSOR_REPORTID_ROT, 0, 0, rate, 0, 0) def start_game_rot(self, rate): return self.set_feature(self.SENSOR_REPORTID_GAM, 0, 0, rate, 0, 0) def start_mag(self, rate): return self.set_feature(self.SENSOR_REPORTID_MAG, 0, 0, rate, 0, 0) def get_report(self, report_types): report_types.append(self.GET_TIME_REFERENCE) res_head, res_data = self.receive_shtp_until(self.CHANNEL_REPORTS, report_types, 20) report_ind = 0 reports = {} while report_ind < len(res_data): inc = self.REPORT_SIZES.get(res_data[report_ind], None) if inc is None: print(f"WARNING: unrecognized input report: {res_data[0]}") return None else: if not reports.get(res_data[report_ind], False): reports[res_data[report_ind]] = [ res_data[report_ind:report_ind + inc] ] else: reports[res_data[report_ind]].append( res_data[report_ind:report_ind + inc]) report_ind += inc return reports def get_report_cont(self, report_types, rate, reports): while True: report_types.append(self.GET_TIME_REFERENCE) res_head, res_data = self.receive_shtp_until( self.CHANNEL_REPORTS, report_types, 20) report_ind = 0 while report_ind < len(res_data): inc = self.REPORT_SIZES.get(res_data[report_ind], None) if inc is None: print(f"WARNING: unrecognized input report: {res_data[0]}") return None else: reports[res_data[report_ind]] = [ res_data[report_ind:report_ind + inc] ] report_ind += inc time.sleep(rate) def get_shtp_errors(self): self.send_shtp(self.CHANNEL_COMMAND, [0x01]) res_head, res_data = self.receive_shtp_until(self.CHANNEL_COMMAND, [0x01], 5) def get_prod_inf(self): self.send_shtp(self.CHANNEL_CONTROL, [self.PRODUCT_ID_REQUEST]) _res_head1, res_data1 = self.receive_shtp_until( self.CHANNEL_CONTROL, [self.PRODUCT_ID_RESPONSE]) _res_head2, res_data2 = self.receive_shtp_until( self.CHANNEL_CONTROL, [self.PRODUCT_ID_RESPONSE]) return [res_data1, res_data2] def send_shtp(self, channel, data): ''' sends a single SHTP message to the IMU ''' self.sequence[channel] += 1 packetlen = len(data) + 4 packet = [ packetlen & 0xFF, (packetlen >> 8) & 0xFF, channel, self.sequence[channel], *data ] # TODO: add to debug log # print("Sending: ") # print(print_hex(packet)) write = i2c_msg.write(self.addr, packet) write.flags = 0x0000 self.bus.i2c_rdwr(write) def receive_shtp_until(self, chan_type, res_types, max_count=3): ''' asks IMU for I2C SHTP messages until the one with the correct channel and report type(s) shows up ''' count = 0 res_head, res_data = self.receive_shtp() while (res_head[2] != chan_type or res_data[0] not in res_types) and count < max_count: self._i2c_delay() res_head, res_data = self.receive_shtp() count += 1 return [ res_head, res_data ] if res_head[2] == chan_type and res_data[0] in res_types else [ None, [] ] def receive_shtp(self): ''' reads a single SHTP message from the IMU ''' read_head = i2c_msg.read(self.addr, 4) self.bus.i2c_rdwr(read_head) header = list(read_head) packetlen = ( header[1] << 8) | header[0] # stitch the two length bytes together packetlen &= ~(1 << 15) # clear MSB datalen = packetlen - 4 # subtract header subtransfer = header[ 1] & 0x80 != 0x00 # see if the data is not all ready at once read = i2c_msg.read(self.addr, packetlen) time.sleep(1000 / 1000000) # sleep 1000 us between reads self.bus.i2c_rdwr(read) msg = list(read) if len(msg) != packetlen or len(msg) == 0: # print ("Packet Error") return [[0] * 4, [0] * 4] if msg[2] == 0 and msg[0 + 4] == 0x01: self.print_shtp_errs(msg[4:]) self.sequence[msg[2]] = msg[3] # sync the sequence with the IMU # print("Received: ") # print(print_hex(msg)) return [msg[0:4], msg[4:]] @staticmethod def print_shtp_errs(err_data): if len(err_data) == 1: return None err_dict = [ "No Error", "Hub application attempted to exceed maximum read cargo length", "Hub application attempted to exceed maximum read cargo length", "Host wrote a header with length greater than maximum write cargo length", "Host wrote a header with length <= header length (invalid or no payload)", "Host tried to fragment cargo (transfer length < full cargo length)", "Host wrote continuation of fragmented cargo (continuation bit set)", "Unrecognized command on control channel (2)", "Unrecognized parameter to get-advertisement command", "Host wrote to unrecognized channel", "Advertisement request received while Advertisement Response was pending", "Host write before the hub finished sending advertisement response", "Error list too long to send, truncated" ] print("ERROR: the following errors were reported from the IMU:") for err in err_data[1:]: print(f"\t{err_dict[err]}") def get_ad(self): res_head, res_data = self.receive_shtp() if res_head[2] == self.CHANNEL_COMMAND and res_data[0] == 0x00: # TODO: log not print, and get something out of this ad print("Got advertisement") else: print("Did not get advertisement, moving on") @classmethod def parse_rep(cls, rep): rep_methods = { -1: cls._print_missing, cls.SENSOR_REPORTID_ACC: cls._print_acc, cls.SENSOR_REPORTID_GYR: cls._print_gyr, cls.SENSOR_REPORTID_MAG: cls._print_mag, cls.SENSOR_REPORTID_LIN: cls._print_lin, cls.SENSOR_REPORTID_ROT: cls._print_rot, cls.SENSOR_REPORTID_GRA: cls._print_gra, cls.SENSOR_REPORTID_GAM: cls._print_gam, cls.SENSOR_REPORTID_GEO: cls._print_geo, cls.SENSOR_REPORTID_TAP: cls._print_tap, cls.SENSOR_REPORTID_STP: cls._print_stp, cls.SENSOR_REPORTID_STA: cls._print_sta, cls.SENSOR_REPORTID_PER: cls._print_per } return rep_methods[rep[0]](rep) @classmethod def _print_missing(cls, rep): return {"name": "err", "message": "no report available"} @classmethod def _print_acc(cls, rep): return { "name": "acc", "stat": hex(rep[2]), "delay": hex(rep[3]), "x": cls.print_hex(rep[5:3:-1]), "y": cls.print_hex(rep[7:5:-1]), "z": cls.print_hex(rep[9:7:-1]) } @classmethod def _print_gyr(cls, rep): pass @classmethod def _print_mag(cls, rep): pass @classmethod def _print_lin(cls, rep): pass @classmethod def _print_rot(cls, rep): return { "name": "rot", "stat": hex(rep[2]), "delay": hex(rep[3]), "i": cls.print_hex(rep[5:3:-1]), "j": cls.print_hex(rep[7:5:-1]), "k": cls.print_hex(rep[9:7:-1]), "r": cls.print_hex(rep[11:9:-1]), "accuracy": cls.print_hex(rep[13:11:-1]) } @classmethod def _print_gra(cls, rep): pass @classmethod def _print_gam(cls, rep): pass @classmethod def _print_geo(cls, rep): pass @classmethod def _print_tap(cls, rep): pass @classmethod def _print_stp(cls, rep): pass @classmethod def _print_sta(cls, rep): pass @classmethod def _print_per(cls, rep): pass @classmethod def print_hex(cls, hexs): return '0x' + ''.join([hex(h).strip('0x').zfill(2) for h in hexs])
def __init__(self, bus): self.smbus = SMBus(bus=bus) self.write_seq_num = 0 sleep(1) # give the bus a chance to settle
class InputModule(AbstractInput): """ A sensor support class that measures the SHT2x's humidity and temperature and calculates the dew point """ def __init__(self, input_dev, testing=False): super(InputModule, self).__init__() self.logger = logging.getLogger("mycodo.inputs.sht2x") if not testing: from smbus2 import SMBus self.logger = logging.getLogger( "mycodo.sht2x_{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.i2c_bus = input_dev.i2c_bus self.sht2x = SMBus(self.i2c_bus) def get_measurement(self): """ Gets the humidity and temperature """ return_dict = measurements_dict.copy() for _ in range(2): try: # Send temperature measurement command # 0xF3(243) NO HOLD master self.sht2x.write_byte(self.i2c_address, 0xF3) time.sleep(0.5) # Read data back, 2 bytes # Temp MSB, Temp LSB data0 = self.sht2x.read_byte(self.i2c_address) data1 = self.sht2x.read_byte(self.i2c_address) temperature = -46.85 + (((data0 * 256 + data1) * 175.72) / 65536.0) # Send humidity measurement command # 0xF5(245) NO HOLD master self.sht2x.write_byte(self.i2c_address, 0xF5) time.sleep(0.5) # Read data back, 2 bytes # Humidity MSB, Humidity LSB data0 = self.sht2x.read_byte(self.i2c_address) data1 = self.sht2x.read_byte(self.i2c_address) humidity = -6 + (((data0 * 256 + data1) * 125.0) / 65536.0) if self.is_enabled(0): return_dict[0]['value'] = temperature if self.is_enabled(1): return_dict[1]['value'] = humidity if (self.is_enabled(2) and self.is_enabled(0) and self.is_enabled(1)): return_dict[2]['value'] = calculate_dewpoint( return_dict[0]['value'], return_dict[1]['value']) if (self.is_enabled(3) and self.is_enabled(0) and self.is_enabled(1)): return_dict[3]['value'] = calculate_vapor_pressure_deficit( return_dict[0]['value'], return_dict[1]['value']) return return_dict except Exception as e: self.logger.exception( "Exception when taking a reading: {err}".format(err=e)) # Send soft reset and try a second read self.sht2x.write_byte(self.i2c_address, 0xFE) time.sleep(0.1)
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. """ from smbus2 import SMBus import time bus_number = 1 i2c_address = 0x76 bus = SMBus(bus_number) dig_temp = [] dig_pres = [] dig_hum = [] t_fine = 0.0 def writeReg(reg_address, data): bus.write_byte_data(i2c_address, reg_address, data) def get_calib_param(): calib = []
self.vinReg[1]) adinVal = self.bus.read_word_data(self.addr, self.adinReg[0]) adinVal = adinVal << 4 adinVal = adinVal | self.bus.read_word_data( self.addr, self.adinReg[1]) self.post([('vin', vinVal), ('adin', adinVal)]) def post(self, vals): if self.debug: print('[+] Recv post vals of:', vals) cols = vals[0][0] values = vals[0][1] if len(vals) > 1: for val in vals[1:]: cols += ', ' + val[0] values += ', ' + str(val[1]) insertString = 'INSERT INTO {table} ({columns}) VALUES ({vals})'.format( columns=cols, table=self.table, vals=values) self.execute(insertString) def execute(self, string): if self.debug: print('[+] Executing:', string) self.curs.execute(string) if __name__ == '__main__': bus = SMBus(1) ip = raw_input('ip address of brix?') print('ip is set to:', ip) poller = LtcPoll.__init__(bus, ip) poller.start()
def __init__(self, addr=0x8): self.arduino_i2c_addr = addr self.i2c_bus = SMBus(1)
class MQ(): ######################### Hardware Related Macros ######################### MQ_PIN = 0 # define which analog input channel you are going to use (MCP3008) RL_VALUE = 5 # define the load resistance on the board, in kilo ohms RO_CLEAN_AIR_FACTOR = 9.83 # RO_CLEAR_AIR_FACTOR=(Sensor resistance in clean air)/RO, # which is derived from the chart in datasheet ######################### Software Related Macros ######################### CALIBARAION_SAMPLE_TIMES = 50 # define how many samples you are going to take in the calibration phase CALIBRATION_SAMPLE_INTERVAL = 500 # define the time interal(in milisecond) between each samples in the # cablibration phase READ_SAMPLE_INTERVAL = 50 # define how many samples you are going to take in normal operation READ_SAMPLE_TIMES = 5 # define the time interal(in milisecond) between each samples in # normal operation ######################### Application Related Macros ###################### GAS_LPG = 0 GAS_CO = 1 GAS_SMOKE = 2 def __init__(self, Ro=10, analogPin=1): self.Ro = Ro self.MQ_PIN = analogPin self.adc = SMBus(1) self.LPGCurve = [2.3, 0.21, -0.47] # two points are taken from the curve. # with these two points, a line is formed which is "approximately equivalent" # to the original curve. # data format:{ x, y, slope}; point1: (lg200, 0.21), point2: (lg10000, -0.59) self.COCurve = [2.3, 0.72, -0.34] # two points are taken from the curve. # with these two points, a line is formed which is "approximately equivalent" # to the original curve. # data format:[ x, y, slope]; point1: (lg200, 0.72), point2: (lg10000, 0.15) self.SmokeCurve = [2.3, 0.53, -0.44] # two points are taken from the curve. # with these two points, a line is formed which is "approximately equivalent" # to the original curve. # data format:[ x, y, slope]; point1: (lg200, 0.53), point2: (lg10000, -0.22) print("Calibrating...") self.Ro = self.MQCalibration(self.MQ_PIN) print("Calibration is done...\n") print("Ro=%f kohm" % self.Ro) def MQPercentage(self): val = {} read = self.MQRead(self.MQ_PIN) val["GAS_LPG"] = self.MQGetGasPercentage(read / self.Ro, self.GAS_LPG) val["CO"] = self.MQGetGasPercentage(read / self.Ro, self.GAS_CO) val["SMOKE"] = self.MQGetGasPercentage(read / self.Ro, self.GAS_SMOKE) return val ######################### MQResistanceCalculation ######################### # Input: raw_adc - raw value read from adc, which represents the voltage # Output: the calculated sensor resistance # Remarks: The sensor and the load resistor forms a voltage divider. Given the voltage # across the load resistor and its resistance, the resistance of the sensor # could be derived. ############################################################################ def MQResistanceCalculation(self, raw_adc): return float(self.RL_VALUE * (1023.0 - raw_adc) / float(raw_adc)) ######################### MQCalibration #################################### # Input: mq_pin - analog channel # Output: Ro of the sensor # Remarks: This function assumes that the sensor is in clean air. It use # MQResistanceCalculation to calculates the sensor resistance in clean air # and then divides it with RO_CLEAN_AIR_FACTOR. RO_CLEAN_AIR_FACTOR is about # 10, which differs slightly between different sensors. ############################################################################ def MQCalibration(self, mq_pin): val = 0.0 for i in range(self.CALIBARAION_SAMPLE_TIMES): # take multiple samples self.adc.write_byte(0x48, 0) val += self.MQResistanceCalculation(self.adc.read_byte(0x48)) time.sleep(self.CALIBRATION_SAMPLE_INTERVAL / 1000.0) val = val / self.CALIBARAION_SAMPLE_TIMES # calculate the average value val = val / self.RO_CLEAN_AIR_FACTOR # divided by RO_CLEAN_AIR_FACTOR yields the Ro # according to the chart in the datasheet return val ######################### MQRead ########################################## # Input: mq_pin - analog channel # Output: Rs of the sensor # Remarks: This function use MQResistanceCalculation to caculate the sensor resistenc (Rs). # The Rs changes as the sensor is in the different consentration of the target # gas. The sample times and the time interval between samples could be configured # by changing the definition of the macros. ############################################################################ def MQRead(self, mq_pin): rs = 0.0 for i in range(self.READ_SAMPLE_TIMES): self.adc.write_byte(0x48, 0) rs += self.MQResistanceCalculation(self.adc.read_byte(0x48)) time.sleep(self.READ_SAMPLE_INTERVAL / 1000.0) rs = rs / self.READ_SAMPLE_TIMES return rs ######################### MQGetGasPercentage ############################## # Input: rs_ro_ratio - Rs divided by Ro # gas_id - target gas type # Output: ppm of the target gas # Remarks: This function passes different curves to the MQGetPercentage function which # calculates the ppm (parts per million) of the target gas. ############################################################################ def MQGetGasPercentage(self, rs_ro_ratio, gas_id): if (gas_id == self.GAS_LPG): return self.MQGetPercentage(rs_ro_ratio, self.LPGCurve) elif (gas_id == self.GAS_CO): return self.MQGetPercentage(rs_ro_ratio, self.COCurve) elif (gas_id == self.GAS_SMOKE): return self.MQGetPercentage(rs_ro_ratio, self.SmokeCurve) return 0 ######################### MQGetPercentage ################################# # Input: rs_ro_ratio - Rs divided by Ro # pcurve - pointer to the curve of the target gas # Output: ppm of the target gas # Remarks: By using the slope and a point of the line. The x(logarithmic value of ppm) # of the line could be derived if y(rs_ro_ratio) is provided. As it is a # logarithmic coordinate, power of 10 is used to convert the result to non-logarithmic # value. ############################################################################ def MQGetPercentage(self, rs_ro_ratio, pcurve): return (math.pow( 10, (((math.log(rs_ro_ratio) - pcurve[1]) / pcurve[2]) + pcurve[0])))
def smbus_init(): # Initialise the bme280 bus = SMBus(1) bme280 = BME280(i2c_dev=bus) print("smbus_init Init ...") return bme280
class IOE(): def __init__(self, i2c_addr=I2C_ADDR, interrupt_timeout=1.0, interrupt_pin=None, gpio=None, skip_chip_id_check=False): self._i2c_addr = i2c_addr self._i2c_dev = SMBus(1) self._debug = False self._vref = 3.3 self._timeout = interrupt_timeout self._interrupt_pin = interrupt_pin self._gpio = gpio self._encoder_offset = [0, 0, 0, 0] self._encoder_last = [0, 0, 0, 0] if self._interrupt_pin is not None: if self._gpio is None: import RPi.GPIO as GPIO self._gpio = GPIO self._gpio.setwarnings(False) self._gpio.setmode(GPIO.BCM) self._gpio.setup(self._interrupt_pin, GPIO.IN, pull_up_down=GPIO.PUD_OFF) self.enable_interrupt_out() self._pins = [ PWM_PIN(1, 5, 5, REG_PIOCON1), PWM_PIN(1, 0, 2, REG_PIOCON0), PWM_PIN(1, 2, 0, REG_PIOCON0), PWM_PIN(1, 4, 1, REG_PIOCON0), PWM_PIN(0, 0, 3, REG_PIOCON0), PWM_PIN(0, 1, 4, REG_PIOCON0), ADC_OR_PWM_PIN(1, 1, 7, 1, REG_PIOCON0), ADC_OR_PWM_PIN(0, 3, 6, 5, REG_PIOCON0), ADC_OR_PWM_PIN(0, 4, 5, 3, REG_PIOCON1), ADC_PIN(3, 0, 1), ADC_PIN(0, 6, 3), ADC_OR_PWM_PIN(0, 5, 4, 2, REG_PIOCON1), ADC_PIN(0, 7, 2), ADC_PIN(1, 7, 0) ] if not skip_chip_id_check: chip_id = (self.i2c_read8(REG_CHIP_ID_H) << 8) | self.i2c_read8(REG_CHIP_ID_L) if chip_id != CHIP_ID: raise RuntimeError("Chip ID invalid: {:04x} expected: {:04x}.".format(chip_id, CHIP_ID)) def i2c_read8(self, reg): """Read a single (8bit) register from the device.""" msg_w = i2c_msg.write(self._i2c_addr, [reg]) self._i2c_dev.i2c_rdwr(msg_w) msg_r = i2c_msg.read(self._i2c_addr, 1) self._i2c_dev.i2c_rdwr(msg_r) return list(msg_r)[0] def i2c_write8(self, reg, value): """Write a single (8bit) register to the device.""" msg_w = i2c_msg.write(self._i2c_addr, [reg, value]) self._i2c_dev.i2c_rdwr(msg_w) def setup_rotary_encoder(self, channel, pin_a, pin_b, pin_c=None, count_microsteps=False): """Set up a rotary encoder.""" channel -= 1 self.set_mode(pin_a, PIN_MODE_PU, schmitt_trigger=True) self.set_mode(pin_b, PIN_MODE_PU, schmitt_trigger=True) if pin_c is not None: self.set_mode(pin_c, PIN_MODE_OD) self.output(pin_c, 0) self.i2c_write8([REG_ENC_1_CFG, REG_ENC_2_CFG, REG_ENC_3_CFG, REG_ENC_4_CFG][channel], pin_a | (pin_b << 4)) self.change_bit(REG_ENC_EN, channel * 2 + 1, count_microsteps) self.set_bit(REG_ENC_EN, channel * 2) def read_rotary_encoder(self, channel): """Read the step count from a rotary encoder.""" channel -= 1 last = self._encoder_last[channel] reg = [REG_ENC_1_COUNT, REG_ENC_2_COUNT, REG_ENC_3_COUNT, REG_ENC_4_COUNT][channel] value = self.i2c_read8(reg) if value & 0b10000000: value -= 256 if last > 64 and value < -64: self._encoder_offset[channel] += 256 if last < -64 and value > 64: self._encoder_offset[channel] -= 256 self._encoder_last[channel] = value return self._encoder_offset[channel] + value def set_rotary_encoder(self, channel,number): """set the step count from a rotary encoder.""" channel -= 1 last = self._encoder_last[channel] offset = self._encoder_offset[channel] #print("lastdiff_rotary_encoder layst: " + str(last)) #print("diff_rotary_encoder offset: " + str(offset)) reg = [REG_ENC_1_COUNT, REG_ENC_2_COUNT, REG_ENC_3_COUNT, REG_ENC_4_COUNT][channel] #print("read before write : " + str(self.i2c_read8(reg))) self.i2c_write8(reg,number) #print("read after write REG: " + str(self.i2c_read8(reg))) def diff_rotary_encoder(self, channel): """Read the step count from a rotary encoder and return diff.""" channel -= 1 last = self._encoder_last[channel] offset = self._encoder_offset[channel] #print("lastdiff_rotary_encoder layst: " + str(last)) #print("diff_rotary_encoder offset: " + str(offset)) reg = [REG_ENC_1_COUNT, REG_ENC_2_COUNT, REG_ENC_3_COUNT, REG_ENC_4_COUNT][channel] value = self.i2c_read8(reg) #print("readREG: " + str(self.i2c_read8(reg))) if value & 0b10000000: value -= 256 if last > 64 and value < -64: self._encoder_offset[channel] += 256 if last < -64 and value > 64: self._encoder_offset[channel] -= 256 self._encoder_last[channel] = value #print("new value diff_rotary_encoder: " + str(value)) diff=offset + value - last #print("new value diff_rotary_encoder: " + str(diff)) return diff def set_bits(self, reg, bits): """Set the specified bits (using a mask) in a register.""" if reg in BIT_ADDRESSED_REGS: for bit in range(8): if bits & (1 << bit): self.i2c_write8(reg, 0b1000 | (bit & 0b111)) else: value = self.i2c_read8(reg) time.sleep(0.001) self.i2c_write8(reg, value | bits) def set_bit(self, reg, bit): """Set the specified bit (nth position from right) in a register.""" self.set_bits(reg, (1 << bit)) def clr_bits(self, reg, bits): """Clear the specified bits (using a mask) in a register.""" if reg in BIT_ADDRESSED_REGS: for bit in range(8): if bits & (1 << bit): self.i2c_write8(reg, 0b0000 | (bit & 0b111)) else: value = self.i2c_read8(reg) time.sleep(0.001) self.i2c_write8(reg, value & ~bits) def clr_bit(self, reg, bit): """Clear the specified bit (nth position from right) in a register.""" self.clr_bits(reg, (1 << bit)) def get_bit(self, reg, bit): """Returns the specified bit (nth position from right) from a register.""" return self.i2c_read8(reg) & (1 << bit) def change_bit(self, reg, bit, state): """Toggle one register bit on/off.""" if state: self.set_bit(reg, bit) else: self.clr_bit(reg, bit) def enable_interrupt_out(self, pin_swap=False): """Enable the IOE interrupts.""" self.set_bit(REG_INT, BIT_INT_OUT_EN) self.change_bit(REG_INT, BIT_INT_PIN_SWAP, pin_swap) def disable_interrupt_out(self): """Disable the IOE interrupt output.""" self.clr_bit(REG_INT, BIT_INT_OUT_EN) def get_interrupt(self): """Get the IOE interrupt state.""" if self._interrupt_pin is not None: return self._gpio.input(self._interrupt_pin) == 0 else: return self.get_bit(REG_INT, BIT_INT_TRIGD) def clear_interrupt(self): """Clear the interrupt flag.""" self.clr_bit(REG_INT, BIT_INT_TRIGD) def set_pin_interrupt(self, pin, enabled): """Enable/disable the input interrupt on a specific pin. :param pin: Pin from 1-14 :param enabled: True/False for enabled/disabled """ if pin < 1 or pin > len(self._pins): raise ValueError("Pin should be in range 1-14.") io_pin = self._pins[pin - 1] self.change_bit(io_pin.reg_int_mask_p, io_pin.pin, enabled) def on_interrupt(self, callback): """Attach an event handler to be run on interrupt. :param callback: Callback function to run: callback(pin) """ if self._interrupt_pin is not None: print("set Callbackfunction to run : " + str(callback) + " and enable event detect for Pin: " str(self._interrupt_pin)) try: self._gpio.add_event_detect(self._interrupt_pin, self._gpio.FALLING, callback=callback, bouncetime=1) except Exception as e: print("add event_detect failed_: self._gpio.add_event_detect(self._interrupt_pin, self._gpio.FALLING, callback=callback, bouncetime=1)") print("Oops Problem within rgb_Volume(self)! ", e.__class__, "occurred.") def _wait_for_flash(self): """Wait for the IOE to finish writing non-volatile memory.""" t_start = time.time() while self.get_interrupt(): if time.time() - t_start > self._timeout: raise RuntimeError("Timed out waiting for interrupt!") time.sleep(0.001) t_start = time.time() while not self.get_interrupt(): if time.time() - t_start > self._timeout: raise RuntimeError("Timed out waiting for interrupt!") time.sleep(0.001) def set_i2c_addr(self, i2c_addr): """Set the IOE i2c address.""" self.set_bit(REG_CTRL, 4) self.i2c_write8(REG_ADDR, i2c_addr) self._i2c_addr = i2c_addr time.sleep(0.25) # TODO Handle addr change IOError better # self._wait_for_flash() self.clr_bit(REG_CTRL, 4) def set_adc_vref(self, vref): """Set the ADC voltage reference.""" self._vref = vref def get_adc_vref(self): """Get the ADC voltage reference.""" return self._vref def get_chip_id(self): """Get the IOE chip ID.""" return (self.i2c_read8(REG_CHIP_ID_H) << 8) | self.i2c_read8(REG_CHIP_ID_L) def _pwm_load(self): # Load new period and duty registers into buffer t_start = time.time() self.set_bit(REG_PWMCON0, 6) # Set the "LOAD" bit of PWMCON0 while self.get_bit(REG_PWMCON0, 6): time.sleep(0.001) # Wait for "LOAD" to complete if time.time() - t_start >= self._timeout: raise RuntimeError("Timed out waiting for PWM load!") def set_pwm_control(self, divider): """Set PWM settings. PWM is driven by the 24MHz FSYS clock by default. :param divider: Clock divider, one of 1, 2, 4, 8, 16, 32, 64 or 128 """ try: pwmdiv2 = { 1: 0b000, 2: 0b001, 4: 0b010, 8: 0b011, 16: 0b100, 32: 0b101, 64: 0b110, 128: 0b111}[divider] except KeyError: raise ValueError("A clock divider of {}".format(divider)) # TODO: This currently sets GP, PWMTYP and FBINEN to 0 # It might be desirable to make these available to the user # GP - Group mode enable (changes first three pairs of pAM to PWM01H and PWM01L) # PWMTYP - PWM type select: 0 edge-aligned, 1 center-aligned # FBINEN - Fault-break input enable self.i2c_write8(REG_PWMCON1, pwmdiv2) def set_pwm_period(self, value): """Set the PWM period. The period is the point at which the PWM counter is reset to zero. The PWM clock runs at FSYS with a divider of 1/1. Also specifies the maximum value that can be set in the PWM duty cycle. """ value &= 0xffff self.i2c_write8(REG_PWMPL, value & 0xff) self.i2c_write8(REG_PWMPH, value >> 8) self._pwm_load() def get_mode(self, pin): """Get the current mode of a pin.""" return self._pins[pin - 1].mode def set_mode(self, pin, mode, schmitt_trigger=False, invert=False): """Set a pin output mode. :param mode: one of the supplied IN, OUT, PWM or ADC constants """ if pin < 1 or pin > len(self._pins): raise ValueError("Pin should be in range 1-14.") io_pin = self._pins[pin - 1] if io_pin.mode == mode: return gpio_mode = mode & 0b11 io_mode = (mode >> 2) & 0b11 initial_state = mode >> 4 if io_mode != PIN_MODE_IO and mode not in io_pin.type: raise ValueError("Pin {} does not support {}!".format(pin, MODE_NAMES[io_mode])) io_pin.mode = mode if self._debug: print("Setting pin {pin} to mode {mode} {name}, state: {state}".format(pin=pin, mode=MODE_NAMES[io_mode], name=GPIO_NAMES[gpio_mode], state=STATE_NAMES[initial_state])) if mode == PIN_MODE_PWM: self.set_bit(io_pin.reg_iopwm, io_pin.pwm_channel) self.change_bit(REG_PNP, io_pin.pwm_channel, invert) self.set_bit(REG_PWMCON0, 7) # Set PWMRUN bit else: if PIN_MODE_PWM in io_pin.type: self.clr_bit(io_pin.reg_iopwm, io_pin.pwm_channel) pm1 = self.i2c_read8(io_pin.reg_m1) pm2 = self.i2c_read8(io_pin.reg_m2) # Clear the pm1 and pm2 bits pm1 &= 255 - (1 << io_pin.pin) pm2 &= 255 - (1 << io_pin.pin) # Set the new pm1 and pm2 bits according to our gpio_mode pm1 |= (gpio_mode >> 1) << io_pin.pin pm2 |= (gpio_mode & 0b1) << io_pin.pin self.i2c_write8(io_pin.reg_m1, pm1) self.i2c_write8(io_pin.reg_m2, pm2) # Set up Schmitt trigger mode on inputs if mode in [PIN_MODE_PU, PIN_MODE_IN]: self.change_bit(io_pin.reg_ps, io_pin.pin, schmitt_trigger) # 5th bit of mode encodes default output pin state self.i2c_write8(io_pin.reg_p, (initial_state << 3) | io_pin.pin) def input(self, pin, adc_timeout=1): """Read the IO pin state. Returns a 12-bit ADC reading if the pin is in ADC mode Returns True/False if the pin is in any other input mode Returns None if the pin is in PWM mode :param adc_timeout: Timeout (in seconds) for an ADC read (default 1.0) """ if pin < 1 or pin > len(self._pins): raise ValueError("Pin should be in range 1-14.") io_pin = self._pins[pin - 1] if io_pin.mode == PIN_MODE_ADC: if self._debug: print("Reading ADC from pin {}".format(pin)) self.clr_bits(REG_ADCCON0, 0x0f) self.set_bits(REG_ADCCON0, io_pin.adc_channel) self.i2c_write8(REG_AINDIDS, 0) self.set_bit(REG_AINDIDS, io_pin.adc_channel) self.set_bit(REG_ADCCON1, 0) self.clr_bit(REG_ADCCON0, 7) # ADCF - Clear the conversion complete flag self.set_bit(REG_ADCCON0, 6) # ADCS - Set the ADC conversion start flag # Wait for the ADCF conversion complete flag to be set t_start = time.time() while not self.get_bit(REG_ADCCON0, 7): time.sleep(0.01) if time.time() - t_start >= adc_timeout: raise RuntimeError("Timeout waiting for ADC conversion!") hi = self.i2c_read8(REG_ADCRH) lo = self.i2c_read8(REG_ADCRL) return ((hi << 4) | lo) / 4095.0 * self._vref else: if self._debug: print("Reading IO from pin {}".format(pin)) pv = self.get_bit(io_pin.reg_p, io_pin.pin) return HIGH if pv else LOW def output(self, pin, value): """Write an IO pin state or PWM duty cycle. :param value: Either True/False for OUT, or a number between 0 and PWM period for PWM. """ if pin < 1 or pin > len(self._pins): raise ValueError("Pin should be in range 1-14.") io_pin = self._pins[pin - 1] if io_pin.mode == PIN_MODE_PWM: if self._debug: print("Outputting PWM to pin: {pin}".format(pin=pin)) self.i2c_write8(io_pin.reg_pwml, value & 0xff) self.i2c_write8(io_pin.reg_pwmh, value >> 8) self._pwm_load() else: if value == LOW: if self._debug: print("Outputting LOW to pin: {pin}".format(pin=pin, value=value)) self.clr_bit(io_pin.reg_p, io_pin.pin) elif value == HIGH: if self._debug: print("Outputting HIGH to pin: {pin}".format(pin=pin, value=value)) self.set_bit(io_pin.reg_p, io_pin.pin)
if array[i]: retVal |= 0x1 << (5 - i) # get list and convert to boolean return retVal def read(self, n=None) -> List[bool]: return [x > self.THRESHOLD for x in self.read_raw(n)] def __getitem__(self, item): if isinstance(item, slice): data = self.read() return data.__getitem__(item) elif isinstance(item, int): return self.read(item) else: logger.error( 'Bad type (not int or slice) passed to receptors.__getitem__()' ) return [] if __name__ == '__main__': master = SMBus(1) read = ReceptorControl(master) while True: print("Raw Data: {}".format(read.read_raw())) print("Integer: {}".format(read.read_int())) print("Bit Array: {}".format(read.read())) print(''.join(['1' if x else '0' for x in read[:]])) sleep(1)
class VL53L1X: """VL53L1X ToF.""" def __init__(self, i2c_bus=1): """Initialize the VL53L1X ToF Sensor from ST""" self._i2c_bus = i2c_bus self._i2c = SMBus(1) self._default_dev = None self._dev_list = None self._ok = True self._distance = 0 # Resgiter Address self.ADDR_UNIT_ID_HIGH = 0x16 # Serial number high byte self.ADDR_UNIT_ID_LOW = 0x17 # Serial number low byte self.ADDR_I2C_ID_HIGH = 0x18 # Write serial number high byte for I2C address unlock self.ADDR_I2C_ID_LOW = 0x19 # Write serial number low byte for I2C address unlock self.ADDR_I2C_SEC_ADDR = 0x8a # Write new I2C address after unlock def open(self): self._i2c.open(bus=self._i2c_bus) self._configure_i2c_library_functions() self._default_dev = _TOF_LIBRARY.initialise() self._dev_list = dict() def add_sensor(self, sensor_id, address): self._dev_list[sensor_id] = _TOF_LIBRARY.copy_dev(self._default_dev) _TOF_LIBRARY.init_dev(self._dev_list[sensor_id], c_uint8(address)) def close(self): self._i2c.close() self._default_dev = None self._dev_list = None def _configure_i2c_library_functions(self): # I2C bus read callback for low level library. def _i2c_read(address, reg, data_p, length): ret_val = 0 msg_w = i2c_msg.write(address, [reg >> 8, reg & 0xff]) msg_r = i2c_msg.read(address, length) # print("R: a: %x\tr:%d" % (address,reg)) try: self._i2c.i2c_rdwr(msg_w, msg_r) except: print("Cannot read on 0x%x I2C bus, reg: %d" % (address, reg)) if ret_val == 0: for index in range(length): data_p[index] = ord(msg_r.buf[index]) return ret_val # I2C bus write callback for low level library. def _i2c_write(address, reg, data_p, length): ret_val = 0 data = [] for index in range(length): data.append(data_p[index]) msg_w = i2c_msg.write(address, [reg >> 8, reg & 0xff] + data) # print("W: a: %x\tr:%d" % (address,reg)) try: self._i2c.i2c_rdwr(msg_w) except: print("Cannot write on 0x%x I2C bus, reg: %d" % (address, reg)) return ret_val # Pass i2c read/write function pointers to VL53L1X library. self._i2c_read_func = _I2C_READ_FUNC(_i2c_read) self._i2c_write_func = _I2C_WRITE_FUNC(_i2c_write) _TOF_LIBRARY.VL53L1_set_i2c(self._i2c_read_func, self._i2c_write_func) def start_ranging(self, sensor_id, mode=VL53L1xDistanceMode.LONG): """Start VL53L1X ToF Sensor Ranging""" dev = self._dev_list[sensor_id] _TOF_LIBRARY.startRanging(dev, mode) def stop_ranging(self, sensor_id): """Stop VL53L1X ToF Sensor Ranging""" dev = self._dev_list[sensor_id] _TOF_LIBRARY.stopRanging(dev) def get_distance(self, sensor_id): dev = self._dev_list[sensor_id] return _TOF_LIBRARY.getDistance(dev) def get_address(self, sensor_id): dev = self._dev_list[sensor_id] return _TOF_LIBRARY.get_address(dev) def change_address(self, sensor_id, new_address): dev = self._dev_list[sensor_id] _TOF_LIBRARY.setDeviceAddress(dev, new_address) def update(self, sensor_id): """Read raw distance for homeassistant""" self._distance = self.get_distance(sensor_id) @property def sample_ok(self): """Return True for a valid measurement data.""" return self._ok and self._distance >= 0 @property def distance(self): """Distance in mm""" return self._distance
def __init__(self, addr, port): self.addr = addr self.bus = SMBus(port) self.sequence = [0] * 5 self.get_ad()
def __init__(self, bus, addr, alt): self.addr = addr self.alt = alt self.bus = SMBus(bus) self.init()
def __init__(self): self._device = SMBus(2) self.led_current = 20 self.frequency = FREQUENCY_390K625 self._write_u8(_VCNL4010_INTCONTROL, 0x08)
def set_eon_fan(val): global LEON, last_eon_fan_val if last_eon_fan_val is None or last_eon_fan_val != val: bus = SMBus(7, force=True) if LEON: try: i = [0x1, 0x3 | 0, 0x3 | 0x08, 0x3 | 0x10][val] bus.write_i2c_block_data(0x3d, 0, [i]) except IOError: # tusb320 if val == 0: bus.write_i2c_block_data(0x67, 0xa, [0]) #bus.write_i2c_block_data(0x67, 0x45, [1<<2]) else: #bus.write_i2c_block_data(0x67, 0x45, [0]) bus.write_i2c_block_data(0x67, 0xa, [0x20]) bus.write_i2c_block_data(0x67, 0x8, [(val - 1) << 6]) else: bus.write_byte_data(0x21, 0x04, 0x2) bus.write_byte_data(0x21, 0x03, (val*2)+1) bus.write_byte_data(0x21, 0x04, 0x4) bus.close() last_eon_fan_val = val
def _read_u8(self, address): # Read an 8-bit unsigned value from the specified 8-bit address. with SMBus(2) as self._device: read = self._device.read_byte_data(_VCNL4010_I2CADDR_DEFAULT, address) return read
from evdev import InputDevice, list_devices, ecodes from smbus2 import SMBus from pi_wars import Controller, Stick, drive_from_vector from yrk_oo.motors import Motors, MotorDriver if __name__ == "__main__": device = InputDevice(list_devices()[0]) stick = Stick(ecodes.ABS_X, ecodes.ABS_Y, deadzone=0.1) controller = Controller(device, [stick]) bus = SMBus(13) m1 = MotorDriver(Motors.MOTOR1, bus, 0.1) m2 = MotorDriver(Motors.MOTOR4, bus, 0.1) m11 = MotorDriver(Motors.MOTOR2, bus, 0.1) m22 = MotorDriver(Motors.MOTOR3, bus, 0.1) for _ in controller.read_loop(): m1_v, m2_v = drive_from_vector(*stick.value) print(stick.value, m1_v, m2_v) m1.set(m1_v) m11.set(m1_v) m22.set(m2_v) m2.set(m2_v)
def _write_u8(self, address, val): # Write an 8-bit unsigned value to the specified 8-bit address. with SMBus(2) as self._device: self._device.write_byte_data(_VCNL4010_I2CADDR_DEFAULT, address, val)
class I2C_Comm: def __init__(self, bus): self.smbus = SMBus(bus=bus) self.write_seq_num = 0 sleep(1) # give the bus a chance to settle def get_device_info(self, adr): board_info = { "inventoryVersion": 0, "i2cAddress": 0, "boardType": 0, "boardDescription": "unknown", "boardVersion": 0, "i2cCommSwVersion": "unknown", "inventorySwVersion": "unknown", "applicationSwVersion": "unknown" } reg, dev_info = self.read_register( adr, tcc.I2C_REG_INVENTORY_VERSION, tcc.I2C_REG_ID_LEN + tcc.I2C_INVENTORY_VERSION_LEN) if reg == tcc.I2C_REG_INVENTORY_VERSION and dev_info[0] == 1: # #################################### # inventory structure version 1 # #################################### board_info["inventoryVersion"] = dev_info[0] # reg, dev_info = self.read_register( adr, tcc.I2C_REG_I2C_ADR, tcc.I2C_REG_ID_LEN + tcc.I2C_I2C_ADR_LEN) if reg > 0: board_info["i2cAddress"] = dev_info[0] # reg, dev_info = self.read_register( adr, tcc.I2C_REG_BOARD_TYPE, tcc.I2C_REG_ID_LEN + tcc.I2C_BOARD_TYPE_LEN) if reg > 0: board_info["boardType"] = dev_info[0] # reg, dev_info = self.read_register( adr, tcc.I2C_REG_BOARD_DESCRIPTION, tcc.I2C_REG_ID_LEN + tcc.I2C_BOARD_DESCRIPTION_LEN) if reg > 0: board_info["boardDescription"] = self.char_list_to_string( dev_info) reg, dev_info = self.read_register( adr, tcc.I2C_REG_BOARD_VERSION, tcc.I2C_REG_ID_LEN + tcc.I2C_BOARD_VERSION_LEN) if reg > 0: board_info["boardVersion"] = dev_info[0] reg, dev_info = self.read_register( adr, tcc.I2C_REG_I2C_COMM_SW_VERSION, tcc.I2C_REG_ID_LEN + tcc.I2C_I2C_COMM_SW_VERSION_LEN) if reg > 0: board_info["i2cCommSwVersion"] = self.char_list_to_string( dev_info) reg, dev_info = self.read_register( adr, tcc.I2C_REG_INVENTORY_SW_VERSION, tcc.I2C_REG_ID_LEN + tcc.I2C_INVENTORY_SW_VERSION_LEN) if reg > 0: board_info["inventorySwVersion"] = self.char_list_to_string( dev_info) reg, dev_info = self.read_register( adr, tcc.I2C_REG_APP_SW_VERSION, tcc.I2C_REG_ID_LEN + tcc.I2C_APP_SW_VERSION_LEN) if reg > 0: board_info["applicationSwVersion"] = self.char_list_to_string( dev_info) return board_info @staticmethod def char_list_to_string(char_list): return ''.join([chr(c) for c in char_list if 31 < c and c < 128]) def read_register(self, adr, reg, data_length): """ :param adr: I2C Bus address :param reg: board register :param data_length: of data to read (not counting the checksum) :return: reg or -1 (on error), reg_data (remaining bytes read) """ cmd = -1 # Assume error return reg_data = [] length = data_length + tcc.I2C_CHECKSUM_LEN for retry in range(0, 4): try: reg_data = self.smbus.read_i2c_block_data(adr, reg, length) if len(reg_data) == length: if self.validate_checksum(reg_data) == 0: cmd = reg_data.pop( 0) # todo - checksum is still attached ! reg_data.pop(-1) # remove the checksum if cmd == reg: break else: print("read_register checksum error {}".format( self.validate_checksum(reg_data))) else: print("read_register length error {}".format(length)) except IOError: print("IOError read_register at adr {} / reg {}".format( adr, reg)) return cmd, reg_data """ def set_register(self, adr, reg, send_data): try: self.smbus.write_i2c_block_data(adr, reg, send_data) except IOError: print("Error setRegister at adr {} / reg {}".format(adr, reg)) def get_byte_reg(self, adr, reg): Read one byte of data from the specified register at the specified address. This would be a useful function for collecting inventory data except the Arduino code would need to be rewritten. The Arduino code sends multiple bytes back, starting with the regId. It would need to send only the requested data. To make use of this method, the Arduino code would need to send a single byte back in response to a request. Maybe later there will be registers where I need to do this. This method would be appropriate where higher performance is required. :param adr: :param reg: :return: reg or -1 on error reg_data for retry in range(0, 4): try: reg_data = self.smbus.read_byte_data(adr, reg) return_reg = reg break except IOError: print("Error get_byte_reg at adr {} / reg {}".format(adr, reg)) # Note the following values may be overwritten by a successful retry return_reg = -1 # assume error reg_data = 0 return return_reg, reg_data """ @staticmethod def get_controller_list(): """ Find all active I2C devices on the bus :return: list of I2C addresses of all active devices """ arduino_list = [] run_cmd = "i2cdetect -y 1" try: i2c_detect_output = subprocess.run(run_cmd, shell=True, check=True, stdout=subprocess.PIPE, universal_newlines=True) i2c_detect_output.check_returncode() i2c_rows = i2c_detect_output.stdout.splitlines() del i2c_rows[0] # delete top row, its the heading for row in i2c_rows: adr_list = row.split() # delete the row identifier del adr_list[0] for adr in adr_list: if adr != '--': arduino_list.append(adr) except subprocess.CalledProcessError: print("CallProcessError encountered") return arduino_list def block_read_test(self, adr): """Execute a block read test on the given address. A loopback test consists of the following message sent 256 times to the given adr: block data read to - register : I2C_REG_UP_COUNTER The data read is expected to increment on each read. The return value is a tuple (messagesSent, readExceptions, data_mismatches). data_mismatches = length_failures + Checksum fail + regId fail + data (up_counter) fail """ messages_to_send = 256 read_exception = 0 data_mismatch = 0 length = 3 # reg, count, cs reg = tcc.I2C_REG_UP_COUNTER # Reset the upCounter uncorrected_error, re, we, dm = self.write_register_verify( adr, reg, [0]) if uncorrected_error > 0: print( "An attempt to reset the UP_COUNTER at adr {} resulted in an uncorrectable error: {}" .format(adr, uncorrected_error)) # now do the reads expected_data = 0 for i in range(messages_to_send): try: read_data = self.smbus.read_i2c_block_data(adr, reg, length) if len(read_data) == length: if self.validate_checksum(read_data) == 0: read_data.pop(-1) # remove the checksum if read_data[0] != reg or read_data[1] != expected_data: data_mismatch += 1 print("Read error. S/B {} Is {}".format( expected_data, read_data[1])) else: data_mismatch += 1 # todo - verify the following byte assignments print("Checksum error: {} {} ".format( read_data[1], read_data[2])) else: data_mismatch += 1 print("Length read error") expected_data += 1 except IOError: read_exception += 1 print("Read IOerror at adr {}".format(adr)) #sleep(0.00001) return messages_to_send, read_exception, data_mismatch def block_write_test(self, adr): """Execute a loopback test on the given address A loopback test consists of the following message sent 256 times to the given adr: write_register_verify to write_test reg - data [d1, d2, d3] - read back the seqNum to verify The return value is a tuple ( messages_sent, read_exception, write_exception, data_mismatch, uncorrectable_errors """ messages_to_send = 256 write_exception = 0 read_exception = 0 data_mismatch = 0 uncorrectable_err = 0 reg = tcc.I2C_REG_WRITE_TEST for i in range(messages_to_send): # generate the data data = [i % 256, (i + 1) % 256, (i + 2) % 256] # do the write ue, re, we, dm = self.write_register_verify(adr, reg, data) # update the results uncorrectable_err += ue read_exception += re write_exception += we data_mismatch += dm return messages_to_send, read_exception, write_exception, \ data_mismatch, uncorrectable_err def write_register_verify(self, adr, reg, data): """Do a single write / verify test with retries on the write and read back return - uncorrected_errors read_exception write_exception data_mismatch """ #print("Adr: {}, reg {}, data {}".format(adr, reg,data)); write_exception = 0 read_exception = 0 data_mismatch = 0 uncorrected_errors = 0 read_result = -1 for attempt in range(1, 5): write_result, we = self.write_func(adr, reg, data) write_exception += we if write_result == 0: # todo - .5 slows things down enough to print in the main Arduino loop if necessary # I also used .1 to process buffers in the main loop prior to changing verify # from reading data back to reading sequence number back. # sleep(.001) read_result, re, dm = self.read_verify(adr, 19, [self.write_seq_num]) read_exception += re data_mismatch += dm if read_result == 0: break if read_result != 0: uncorrected_errors = 1 """ errors = write_exception + read_exception + data_mismatch + uncorrected_errors if errors > 0: print("we {}, re {}, dm {}, unerr {}".format(write_exception, read_exception, data_mismatch, uncorrected_error)) """ return uncorrected_errors, read_exception, write_exception, data_mismatch def write_func(self, adr, reg, data): """Write given data to the given address / register Inputs adr - I2C bus adr reg - register to write to data - list of bytes to write Generate a checksum and append it to the data. Make n attempts to write the data to adr/register. If an IOError occurs during the write, count it and retry. If a retry is required, use a new write_seq_num. return result 0 : success, data was written, (may have taken retries) -1 : failure, unable to write data write_exception - number of IOErrors encountered """ write_exception = 0 result = -1 # assume failure for attempt in range(1, 5): try: self.write_seq_num = (self.write_seq_num + 1) % 256 cs = self.gen_checksum(reg, [self.write_seq_num] + data) self.smbus.write_i2c_block_data(adr, reg, [self.write_seq_num] + data + [cs], force=True) result = 0 break except IOError: print("Write exception {}".format(self.write_seq_num)) write_exception += 1 return result, write_exception def read_verify(self, adr, reg, data): """Read from the given address/register and verify the expected_data Inputs adr - I2C bus adr reg - register to read from data - list of bytes expected Make n attempts to read from the given adr/register and verify the expected_data. If an IOError occurs during the read, count it and retry. If a checksum error occurs during the read, count it and retry. return result 0 : success, data was verified (may have taken retries) -1 : failure, unable to verify data read_exception - number of IOErrors encountered data_mismatch - number of read failures """ read_exception = 0 data_mismatch = 0 result = -1 # assume failure expected_data = [ reg ] + data # Put the reg in the data list. Its part of the return data for attempt in range(1, 5): # 4 retries for now try: # do the read/verify read_data = self.smbus.read_i2c_block_data( adr, reg, len(expected_data) + 1) # +1 for checksum if self.validate_checksum(read_data) == 0: read_data.pop(-1) # removed the trailing checksum if read_data == expected_data: result = 0 else: data_mismatch += 1 break # OK, we were able to successfully read the register - we're done trying else: data_mismatch += 1 print("Read Verify Checksum error") except IOError: read_exception += 1 return result, read_exception, data_mismatch def loopback_test(self, adr): """Execute a loopback test on the given address A loopback test consists of the following message sent 256 times to the given adr block data read to - register 99 - seq number The return value is a tuple (messagesSent, resendCount). """ messages_to_send = 256 errors = 0 for i in range(messages_to_send): try: self.smbus.read_i2c_block_data(adr, 99, 2) # 2=length except IOError: errors += 1 print("Oops - error at adr {}".format(adr)) sleep(0.001) return messages_to_send, errors @staticmethod def validate_checksum(data): """Return zero is the checksum is valid""" checksum = 0 for element in data: checksum += element return checksum % 256 @staticmethod def gen_checksum(reg, buffer): check_sum = reg for element in buffer: check_sum += element return -(check_sum % 256)
def _read_u16BE(self, address): with SMBus(2) as self._device: read_block = self._device.read_i2c_block_data(_VCNL4010_I2CADDR_DEFAULT, address, 2) return (read_block[0] << 8) | read_block[1]
class SGP30: def __init__(self, i2c_dev=None, i2c_msg=None, i2c_addr=SGP30_I2C_ADDR): """Mapping table of SGP30 commands. Friendly-name, followed by 16-bit command, then the number of parameter and response words. Each word is two bytes followed by a third CRC checksum byte. So a response length of 2 would result in the transmission of 6 bytes total. """ self.commands = { 'init_air_quality': (0x2003, 0, 0), 'measure_air_quality': (0x2008, 0, 2), 'get_baseline': (0x2015, 0, 2), 'set_baseline': (0x201e, 2, 0), 'set_humidity': (0x2061, 1, 0), # 'measure_test': (0x2032, 0, 1), # Production verification only 'get_feature_set_version': (0x202f, 0, 1), 'measure_raw_signals': (0x2050, 0, 2), 'get_serial_id': (0x3682, 0, 3) } self._i2c_addr = i2c_addr self._i2c_dev = i2c_dev self._i2c_msg = i2c_msg if self._i2c_dev is None: from smbus2 import SMBus, i2c_msg self._i2c_msg = i2c_msg self._i2c_dev = SMBus(1) def command(self, command_name, parameters=None): if parameters is None: parameters = [] parameters = list(parameters) cmd, param_len, response_len = self.commands[command_name] if len(parameters) != param_len: raise ValueError("{} requires {} parameters. {} supplied!".format( command_name, param_len, len(parameters))) parameters_out = [cmd] for i in range(len(parameters)): parameters_out.append(parameters[i]) parameters_out.append(self.calculate_crc(parameters[i])) data_out = struct.pack('>H' + ('HB' * param_len), *parameters_out) msg_w = self._i2c_msg.write(self._i2c_addr, data_out) self._i2c_dev.i2c_rdwr(msg_w) time.sleep(0.025) # Suitable for all commands except 'measure_test' if response_len > 0: # Each parameter is a word (2 bytes) followed by a CRC (1 byte) msg_r = self._i2c_msg.read(self._i2c_addr, response_len * 3) self._i2c_dev.i2c_rdwr(msg_r) buf = msg_r.buf[0:response_len * 3] response = struct.unpack('>' + ('HB' * response_len), buf) verified = [] for i in range(response_len): offset = i * 2 value, crc = response[offset:offset + 2] if crc != self.calculate_crc(value): raise RuntimeError( "Invalid CRC in response from SGP30: {:02x} != {:02x}", crc, self.calculate_crc(value), buf) verified.append(value) return verified def calculate_crc(self, data): """Calculate an 8-bit CRC from a 16-bit word Defined in section 6.6 of the SGP30 datasheet. Polynominal: 0x31 (x8 + x5 + x4 + x1) Initialization: 0xFF Reflect input/output: False Final XOR: 0x00 """ crc = 0xff # Initialization value # calculates 8-Bit checksum with given polynomial for byte in [(data & 0xff00) >> 8, data & 0x00ff]: crc ^= byte for _ in range(8): if crc & 0x80: crc = (crc << 1) ^ 0x31 # XOR with polynominal else: crc <<= 1 return crc & 0xff def get_unique_id(self): result = self.command('get_serial_id') return result[0] << 32 | result[1] << 16 | result[0] def get_feature_set_version(self): result = self.command('get_feature_set_version')[0] return (result & 0xf000) >> 12, result & 0x00ff def start_measurement(self, run_while_waiting=None): """Start air quality measurement on the SGP30. The first 15 readings are discarded so this command will block for 15s. :param run_while_waiting: Function to call for every discarded reading. """ self.command('init_air_quality') testsamples = 0 while True: # Discard the initialisation readings as per page 8/15 of the datasheet eco2, tvoc = self.command('measure_air_quality') # The first 15 readings should return as 400, 0 so abort when they change # Break after 20 test samples to avoid a potential infinite loop if eco2 != 400 or tvoc != 0 or testsamples >= 20: break if callable(run_while_waiting): run_while_waiting() time.sleep(1.0) testsamples += 1 def get_air_quality(self): """Get an air quality measurement. Returns an instance of SGP30Reading with the properties equivalent_co2 and total_voc. This should be called at 1s intervals to ensure the dynamic baseline compensation on the SGP30 operates correctly. """ eco2, tvoc = self.command('measure_air_quality') return SGP30Reading(eco2, tvoc) def get_baseline(self): """Get the current baseline setting. Returns an instance of SGP30Reading with the properties equivalent_co2 and total_voc. """ eco2, tvoc = self.command('get_baseline') return SGP30Reading(eco2, tvoc) def set_baseline(self, eco2, tvoc): self.command('set_baseline', [tvoc, eco2]) def __del__(self): self._i2c_dev.close()
class InputModule(AbstractInput): """ A sensor support class that measures the AM2320's humidity and temperature and calculates the dew point """ def __init__(self, input_dev, testing=False): super(InputModule, self).__init__() self.logger = logging.getLogger('mycodo.inputs.am2320') self.powered = False self.sensor = None self.i2c_address = 0x5C if not testing: from smbus2 import SMBus self.logger = logging.getLogger( 'mycodo.am2320_{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_bus = input_dev.i2c_bus self.power_output_id = input_dev.power_output_id self.start_sensor() self.sensor = SMBus(self.i2c_bus) def get_measurement(self): """ Gets the humidity and temperature """ return_dict = measurements_dict.copy() temperature, humidity = self.read() if self.is_enabled(0): return_dict[0]['value'] = temperature if self.is_enabled(1): return_dict[1]['value'] = humidity if (self.is_enabled(2) and self.is_enabled(0) and self.is_enabled(1)): return_dict[2]['value'] = calculate_dewpoint( return_dict[0]['value'], return_dict[1]['value']) if (self.is_enabled(3) and self.is_enabled(0) and self.is_enabled(1)): return_dict[3]['value'] = calculate_vapor_pressure_deficit( return_dict[0]['value'], return_dict[1]['value']) return return_dict def read(self): try: self.sensor.write_i2c_block_data( self.i2c_address, 0x03, [0x00, 0x04]) except OSError as e: self.logger.error(e) time.sleep(0.02) blocks = self.sensor.read_i2c_block_data(self.i2c_address, 0, 6) humidity = ((blocks[2] << 8) + blocks[3]) / 10.0 temperature = ((blocks[4] << 8) + blocks[5]) / 10.0 return temperature, humidity def setup(self): try: self.sensor.write_i2c_block_data(self.i2c_address, 0x00, []) except OSError as e: self.logger.error(e) time.sleep(0.1)
class LCD_Grove_LCD_RGB: """Output to a Grove I2C LCD RGB display (16x2 LCD with RGB or monochrome backlight)""" def __init__(self, lcd_dev): self.logger = logging.getLogger( "{}_{}".format(__name__, lcd_dev.unique_id.split('-')[0])) self.lcd_initialized = False self.lcd_is_on = False self.red = 255 self.green = 255 self.blue = 255 self.i2c_address = int(lcd_dev.location, 16) self.i2c_address_backlight = int(lcd_dev.location_backlight, 16) # self.i2c_address_backlight = 0x62 self.i2c_bus = lcd_dev.i2c_bus self.lcd_x_characters = lcd_dev.x_characters self.lcd_y_lines = lcd_dev.y_lines self.LCD_WIDTH = self.lcd_x_characters # Max characters per line self.I2C_ADDR = self.i2c_address # Commands, etc self.LCD_CLEARDISPLAY = 0x01 self.LCD_RETURNHOME = 0x02 self.LCD_ENTRYMODESET = 0x04 self.LCD_DISPLAYCONTROL = 0x08 self.LCD_CURSORSHIFT = 0x10 self.LCD_FUNCTIONSET = 0x20 self.LCD_SETCGRAMADDR = 0x40 self.LCD_SETDDRAMADDR = 0x80 # flags for function set self.LCD_8BITMODE = 0x10 self.LCD_4BITMODE = 0x00 self.LCD_2LINE = 0x08 self.LCD_1LINE = 0x00 self.LCD_5x10DOTS = 0x04 self.LCD_5x8DOTS = 0x00 # flags for display on/off control self.LCD_DISPLAYON = 0x04 self.LCD_DISPLAYOFF = 0x00 self.LCD_CURSORON = 0x02 self.LCD_CURSOROFF = 0x00 self.LCD_BLINKON = 0x01 self.LCD_BLINKOFF = 0x00 # flags for display entry mode self.LCD_ENTRYRIGHT = 0x00 self.LCD_ENTRYLEFT = 0x02 self.LCD_ENTRYSHIFTINCREMENT = 0x01 self.LCD_ENTRYSHIFTDECREMENT = 0x00 # RGB backlight registers self.REG_MODE1 = 0x00 self.REG_MODE2 = 0x01 self.REG_OUTPUT = 0x08 # Setup I2C bus try: self.bus = SMBus(self.i2c_bus) except Exception as except_msg: self.logger.exception( "Could not initialize I2C bus: {err}".format( err=except_msg)) # set configuration displayConfig = self.LCD_FUNCTIONSET if self.lcd_y_lines == 2: displayConfig = displayConfig | self.LCD_2LINE self.writeCommand(displayConfig) time.sleep(0.005) self.writeCommand(displayConfig) time.sleep(0.001) self.writeCommand(displayConfig) self.writeCommand(displayConfig) # set state displayState = self.LCD_DISPLAYCONTROL | self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF self.writeCommand(displayState) self.clearDisplay() # set the entry mode entryMode = self.LCD_ENTRYMODESET | self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT self.writeCommand(entryMode) # Initialize the backlight self.bus.write_byte_data(self.i2c_address_backlight, self.REG_MODE1, 0) # set LEDs controllable by both PWM and GRPPWM registers self.bus.write_byte_data(self.i2c_address_backlight, self.REG_OUTPUT, 0xff) # set MODE2 values # 0010 0000 -> 0x20 (DMBLNK to 1, ie blinky mode) self.bus.write_byte_data(self.i2c_address_backlight, self.REG_MODE2, 0x20) self.setRGB(self.red, self.green, self.blue) def writeCommand(self, cmd): self.bus.write_byte_data(self.i2c_address,0x80,cmd) def writeData(self, data): self.bus.write_byte_data(self.i2c_address,0x40,data) def setRGB(self, r, g, b): self.bus.write_byte_data(self.i2c_address_backlight, 4, r) self.bus.write_byte_data(self.i2c_address_backlight, 3, g) self.bus.write_byte_data(self.i2c_address_backlight, 2, b) def clearDisplay(self): self.writeCommand(self.LCD_CLEARDISPLAY) # clear display time.sleep(0.002) def setCursor(self, col, row): if row == 0: location = col | 0x80 else: location = col | 0xc0 self.writeCommand(location) time.sleep(0.001) def setText(self, text): self.clearDisplay() self.setCursor(0, 0) count = 0 row = 0 for c in text: if c == '\n' or count == 16: count = 0 row += 1 if row == 2: break self.writeCommand(0xc0) if c == '\n': continue count += 1 self.writeData(ord(c)) def lcd_init(self): """ Clear LCD display """ self.clearDisplay() def lcd_backlight(self, state): """ Turn the backlight on or off """ if state: self.setRGB(self.red, self.green, self.blue) else: self.setRGB(0,0,0) def lcd_backlight_color(self, color_tuple): try: tuple_colors = color_tuple.split(",") self.red = int(tuple_colors[0]) self.green = int(tuple_colors[1]) self.blue = int(tuple_colors[2]) self.setRGB(self.red, self.green, self.blue) except: self.logger.error("Could not set color. Invalid color string: '{}'".format(color_tuple)) def lcd_byte(self, bits, mode, backlight=None): """ Send byte to data pins """ # bits = the data # mode = 1 for data # 0 for command if mode == 0: self.writeCommand(bits) else: self.writeData(bits) def lcd_toggle_enable(self, bits): """ Toggle enable """ pass def lcd_string_write(self, message, line): """ Send strings to display """ self.setCursor(0, line) for c in message: self.writeData(ord(c)) def lcd_write_lines(self, line_1, line_2, line_3, line_4): msg = "" if line_1: msg += line_1 msg += "\n" if line_2: msg += line_2 msg += "\n" if line_3: msg += line_3 msg += "\n" if line_4: msg += line_4 self.setText(msg)
class InputModule(AbstractInput): """ A sensor support class that monitors the MH-Z16's CO2 concentration """ def __init__(self, input_dev, testing=False): super(InputModule, self).__init__() self.logger = logging.getLogger("mycodo.inputs.mh_z16") if not testing: self.logger = logging.getLogger( "mycodo.mh_z16_{id}".format(id=input_dev.unique_id.split('-')[0])) self.interface = input_dev.interface self.uart_location = input_dev.uart_location if self.interface == 'UART': import serial # Check if device is valid self.serial_device = is_device(self.uart_location) if self.serial_device: try: self.ser = serial.Serial(self.serial_device, timeout=1) except serial.SerialException: self.logger.exception('Opening serial') else: self.logger.error( 'Could not open "{dev}". ' 'Check the device location is correct.'.format( dev=self.uart_location)) elif self.interface == 'I2C': from smbus2 import SMBus self.i2c_address = int(str(input_dev.i2c_location), 16) self.i2c_bus = input_dev.i2c_bus self.cmd_measure = [0xFF, 0x01, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63] self.IOCONTROL = 0X0E << 3 self.FCR = 0X02 << 3 self.LCR = 0X03 << 3 self.DLL = 0x00 << 3 self.DLH = 0X01 << 3 self.THR = 0X00 << 3 self.RHR = 0x00 << 3 self.TXLVL = 0X08 << 3 self.RXLVL = 0X09 << 3 self.i2c = SMBus(self.i2c_bus) self.begin() def get_measurement(self): """ Gets the MH-Z16's CO2 concentration in ppmv via UART""" return_dict = measurements_dict.copy() co2 = None if self.interface == 'UART': if not self.serial_device: # Don't measure if device isn't validated return None self.ser.flushInput() time.sleep(1) self.ser.write(bytearray([0xff, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79])) time.sleep(.01) resp = self.ser.read(9) if len(resp) != 0: high = resp[2] low = resp[3] co2 = (high * 256) + low elif self.interface == 'I2C': self.write_register(self.FCR, 0x07) self.send(self.cmd_measure) try: co2 = self.parse(self.receive()) except Exception: co2 = None return_dict[0]['value'] = co2 return return_dict def begin(self): try: self.write_register(self.IOCONTROL, 0x08) except IOError: pass self.write_register(self.FCR, 0x07) self.write_register(self.LCR, 0x83) self.write_register(self.DLL, 0x60) self.write_register(self.DLH, 0x00) self.write_register(self.LCR, 0x03) @staticmethod def parse(response): checksum = 0 if len(response) < 9: return None for i in range(0, 9): checksum += response[i] if response[0] == 0xFF: if response[1] == 0x9C: if checksum % 256 == 0xFF: return (response[2] << 24) + (response[3] << 16) + (response[4] << 8) + response[5] return None def read_register(self, reg_addr): time.sleep(0.01) return self.i2c.read_byte_data(self.i2c_address, reg_addr) def write_register(self, reg_addr, val): time.sleep(0.01) self.i2c.write_byte_data(self.i2c_address, reg_addr, val) def send(self, command): if self.read_register(self.TXLVL) >= len(command): self.i2c.write_i2c_block_data(self.i2c_address, self.THR, command) def receive(self): n = 9 buf = [] start = time.clock() while n > 0: rx_level = self.read_register(self.RXLVL) if rx_level > n: rx_level = n buf.extend(self.i2c.read_i2c_block_data(self.i2c_address, self.RHR, rx_level)) n = n - rx_level if time.clock() - start > 0.2: break return buf
def __init__(self, lcd_dev): self.logger = logging.getLogger( "{}_{}".format(__name__, lcd_dev.unique_id.split('-')[0])) self.lcd_initialized = False self.lcd_is_on = False self.red = 255 self.green = 255 self.blue = 255 self.i2c_address = int(lcd_dev.location, 16) self.i2c_address_backlight = int(lcd_dev.location_backlight, 16) # self.i2c_address_backlight = 0x62 self.i2c_bus = lcd_dev.i2c_bus self.lcd_x_characters = lcd_dev.x_characters self.lcd_y_lines = lcd_dev.y_lines self.LCD_WIDTH = self.lcd_x_characters # Max characters per line self.I2C_ADDR = self.i2c_address # Commands, etc self.LCD_CLEARDISPLAY = 0x01 self.LCD_RETURNHOME = 0x02 self.LCD_ENTRYMODESET = 0x04 self.LCD_DISPLAYCONTROL = 0x08 self.LCD_CURSORSHIFT = 0x10 self.LCD_FUNCTIONSET = 0x20 self.LCD_SETCGRAMADDR = 0x40 self.LCD_SETDDRAMADDR = 0x80 # flags for function set self.LCD_8BITMODE = 0x10 self.LCD_4BITMODE = 0x00 self.LCD_2LINE = 0x08 self.LCD_1LINE = 0x00 self.LCD_5x10DOTS = 0x04 self.LCD_5x8DOTS = 0x00 # flags for display on/off control self.LCD_DISPLAYON = 0x04 self.LCD_DISPLAYOFF = 0x00 self.LCD_CURSORON = 0x02 self.LCD_CURSOROFF = 0x00 self.LCD_BLINKON = 0x01 self.LCD_BLINKOFF = 0x00 # flags for display entry mode self.LCD_ENTRYRIGHT = 0x00 self.LCD_ENTRYLEFT = 0x02 self.LCD_ENTRYSHIFTINCREMENT = 0x01 self.LCD_ENTRYSHIFTDECREMENT = 0x00 # RGB backlight registers self.REG_MODE1 = 0x00 self.REG_MODE2 = 0x01 self.REG_OUTPUT = 0x08 # Setup I2C bus try: self.bus = SMBus(self.i2c_bus) except Exception as except_msg: self.logger.exception( "Could not initialize I2C bus: {err}".format( err=except_msg)) # set configuration displayConfig = self.LCD_FUNCTIONSET if self.lcd_y_lines == 2: displayConfig = displayConfig | self.LCD_2LINE self.writeCommand(displayConfig) time.sleep(0.005) self.writeCommand(displayConfig) time.sleep(0.001) self.writeCommand(displayConfig) self.writeCommand(displayConfig) # set state displayState = self.LCD_DISPLAYCONTROL | self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF self.writeCommand(displayState) self.clearDisplay() # set the entry mode entryMode = self.LCD_ENTRYMODESET | self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT self.writeCommand(entryMode) # Initialize the backlight self.bus.write_byte_data(self.i2c_address_backlight, self.REG_MODE1, 0) # set LEDs controllable by both PWM and GRPPWM registers self.bus.write_byte_data(self.i2c_address_backlight, self.REG_OUTPUT, 0xff) # set MODE2 values # 0010 0000 -> 0x20 (DMBLNK to 1, ie blinky mode) self.bus.write_byte_data(self.i2c_address_backlight, self.REG_MODE2, 0x20) self.setRGB(self.red, self.green, self.blue)
class Sonar: __units = {"mm":0, "cm":1} __dist_reg = 0 __RGB_MODE = 2 __RGB1_R = 3 __RGB1_G = 4 __RGB1_B = 5 __RGB2_R = 6 __RGB2_G = 7 __RGB2_B = 8 __RGB1_R_BREATHING_CYCLE = 9 __RGB1_G_BREATHING_CYCLE = 10 __RGB1_B_BREATHING_CYCLE = 11 __RGB2_R_BREATHING_CYCLE = 12 __RGB2_G_BREATHING_CYCLE = 13 __RGB2_B_BREATHING_CYCLE = 14 def __init__(self): self.i2c_addr = 0x77 self.i2c = 1 self.R1 = 0 self.G1 = 0 self.B1 = 0 self.R2 = 0 self.G2 = 0 self.B2 = 0 self.RGBMode = 0 self.bus = SMBus(self.i2c) def __getattr(self, attr): if attr in self.__units: return self.__units[attr] if attr == "Distance": return self.getDistance() else: raise AttributeError('Unknow attribute : %s'%attr) #设置灯的模式,0为彩灯模式,1为呼吸灯模式 def setRGBMode(self, mode): try: self.bus.write_byte_data(self.i2c_addr, self.__RGB_MODE, mode) except: print('Sensor not connected!') #设置灯的颜色 #参数1:0表示左边的灯,1表示右边 #参数2:颜色的rgb比例值,以元组形式传入,范围0-255, 依次为r,g,b def setRGB(self, index, rgb): start_reg = 3 if index == 1 else 6 try: self.bus.write_byte_data(self.i2c_addr, start_reg, rgb[0]) self.bus.write_byte_data(self.i2c_addr, start_reg+1, rgb[1]) self.bus.write_byte_data(self.i2c_addr, start_reg+2, rgb[2]) except: print('Sensor not connected!') #呼吸灯模式 #参数1:0表示左边的灯,1表示右边 #参数2:颜色通道, 0表示然,1表示g, 2表示b #参数3:颜色变化周期,单位ms def setBreathCycle(self, index, rgb, cycle): start_reg = 9 if index == 1 else 12 cycle = int(cycle / 100) try: self.bus.write_byte_data(self.i2c_addr, start_reg + rgb, cycle) except: print('Sensor not connected!') def startSymphony(self): self.setRGBMode(1) self.setBreathCycle(1, 0, 2000) self.setBreathCycle(1, 1, 3300) self.setBreathCycle(1, 2, 4700) self.setBreathCycle(0, 0, 4600) self.setBreathCycle(0, 1, 2000) self.setBreathCycle(0, 2, 3400) #获取距离, 单位mm def getDistance(self): dist = 5000 try: msg = i2c_msg.write(self.i2c_addr, [0,]) self.bus.i2c_rdwr(msg) read = i2c_msg.read(self.i2c_addr, 2) self.bus.i2c_rdwr(read) dist = int.from_bytes(bytes(list(read)), byteorder='little', signed=False) if dist > 5000: dist = 5000 except BaseException as e: print('Sensor not connected!', e) return dist
class AXP209(object): def __init__(self, bus=0): """ Initialize the AXP209 object :param bus: i2c bus number or a SMBus object :type bus: Integer or SMBus object """ if isinstance(bus, int): self.bus = SMBus(bus, force=True) self.autocleanup = True else: self.bus = bus self.autocleanup = False # force ADC enable for battery voltage and current self.adc_enable1 = 0xc3 def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): if self.autocleanup: self.close() def close(self): self.bus.close() @property def gpio2_output(self): pass @gpio2_output.setter def gpio2_output(self, val): flags = GPIO012_FEATURE_SET_FLAGS() if bool(val): flags.gpio_function = 0b111 else: flags.gpio_function = 0b000 self.bus.write_byte_data(AXP209_ADDRESS, GPIO2_FEATURE_SET_REG, flags.asbyte) @property def adc_enable1(self): flags = ADC_ENABLE1_FLAGS() flags.asbyte = self.bus.read_byte_data(AXP209_ADDRESS, ADC_ENABLE1_REG) return flags @adc_enable1.setter def adc_enable1(self, flags): if hasattr(flags, "asbyte"): flags = flags.asbyte self.bus.write_byte_data(AXP209_ADDRESS, ADC_ENABLE1_REG, flags) @property def power_input_status(self): flags = POWER_INPUT_STATUS_FLAGS() flags.asbyte = self.bus.read_byte_data(AXP209_ADDRESS, POWER_INPUT_STATUS_REG) return flags @property def battery_current_direction(self): return bool(self.power_input_status.battery_current_direction) @property def power_operating_mode(self): flags = POWER_OPERATING_STATUS_FLAGS() flags.asbyte = self.bus.read_byte_data(AXP209_ADDRESS, POWER_OPERATING_MODE_REG) return flags @property def battery_exists(self): return bool(self.power_operating_mode.battery_exists) @property def battery_charging(self): return bool(self.power_operating_mode.battery_charging) @property def battery_voltage(self): """ Returns voltage in mV """ msb = self.bus.read_byte_data(AXP209_ADDRESS, BATTERY_VOLTAGE_MSB_REG) lsb = self.bus.read_byte_data(AXP209_ADDRESS, BATTERY_VOLTAGE_LSB_REG) voltage_bin = msb << 4 | lsb & 0x0f return voltage_bin * 1.1 @property def battery_charge_current(self): """ Returns current in mA """ msb = self.bus.read_byte_data(AXP209_ADDRESS, BATTERY_CHARGE_CURRENT_MSB_REG) lsb = self.bus.read_byte_data(AXP209_ADDRESS, BATTERY_CHARGE_CURRENT_LSB_REG) # (12 bits) charge_bin = msb << 4 | lsb & 0x0f # 0 mV -> 000h, 0.5 mA/bit FFFh -> 1800 mA return charge_bin * 0.5 @property def battery_discharge_current(self): """ Returns current in mA """ msb = self.bus.read_byte_data(AXP209_ADDRESS, BATTERY_DISCHARGE_CURRENT_MSB_REG) lsb = self.bus.read_byte_data(AXP209_ADDRESS, BATTERY_DISCHARGE_CURRENT_LSB_REG) # 13bits discharge_bin = msb << 5 | lsb & 0x1f # 0 mV -> 000h, 0.5 mA/bit 1FFFh -> 1800 mA return discharge_bin * 0.5 @property def internal_temperature(self): """ Returns temperature in celsius C """ temp_msb = self.bus.read_byte_data(AXP209_ADDRESS, INTERNAL_TEMPERATURE_MSB_REG) temp_lsb = self.bus.read_byte_data(AXP209_ADDRESS, INTERNAL_TEMPERATURE_LSB_REG) # MSB is 8 bits, LSB is lower 4 bits temp = temp_msb << 4 | temp_lsb & 0x0f # -144.7c -> 000h, 0.1c/bit FFFh -> 264.8c return temp*0.1-144.7 @property def battery_gauge(self): gauge_bin = self.bus.read_byte_data(AXP209_ADDRESS, BATTERY_GAUGE_REG) gauge = gauge_bin & 0x7f if gauge > 100: return -1 return gauge
class InputModule(AbstractInput): """ A sensor support class that measures the SHT2x's humidity and temperature and calculates the dew point """ def __init__(self, input_dev, testing=False): super(InputModule, self).__init__() self.logger = logging.getLogger("mycodo.inputs.sht2x") self._dew_point = None self._humidity = None self._temperature = None if not testing: from smbus2 import SMBus self.logger = logging.getLogger( "mycodo.sht2x_{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.sht2x = SMBus(self.i2c_bus) def __repr__(self): """ Representation of object """ return "<{cls}(dewpoint={dpt})(humidity={hum})(temperature={temp})>".format( cls=type(self).__name__, dpt="{0:.2f}".format(self._dew_point), hum="{0:.2f}".format(self._humidity), temp="{0:.2f}".format(self._temperature)) def __str__(self): """ Return measurement information """ return "Dew Point: {dpt}, Humidity: {hum}, Temperature: {temp}".format( dpt="{0:.2f}".format(self._dew_point), hum="{0:.2f}".format(self._humidity), temp="{0:.2f}".format(self._temperature)) def __iter__(self): # must return an iterator """ SHT2xSensor 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(dewpoint=float('{0:.2f}'.format(self._dew_point)), humidity=float('{0:.2f}'.format(self._humidity)), temperature=float('{0:.2f}'.format(self._temperature))) @property def dew_point(self): """ SHT2x dew point in Celsius """ if self._dew_point is None: # update if needed self.read() return self._dew_point @property def humidity(self): """ SHT2x relative humidity in percent """ if self._humidity is None: # update if needed self.read() return self._humidity @property def temperature(self): """ SHT2x temperature in Celsius """ if self._temperature is None: # update if needed self.read() return self._temperature def get_measurement(self): """ Gets the humidity and temperature """ self._dew_point = None self._humidity = None self._temperature = None dew_point = None humidity = None temperature = None for _ in range(2): try: # Send temperature measurement command # 0xF3(243) NO HOLD master self.sht2x.write_byte(self.i2c_address, 0xF3) time.sleep(0.5) # Read data back, 2 bytes # Temp MSB, Temp LSB data0 = self.sht2x.read_byte(self.i2c_address) data1 = self.sht2x.read_byte(self.i2c_address) temperature = -46.85 + (((data0 * 256 + data1) * 175.72) / 65536.0) # Send humidity measurement command # 0xF5(245) NO HOLD master self.sht2x.write_byte(self.i2c_address, 0xF5) time.sleep(0.5) # Read data back, 2 bytes # Humidity MSB, Humidity LSB data0 = self.sht2x.read_byte(self.i2c_address) data1 = self.sht2x.read_byte(self.i2c_address) humidity = -6 + (((data0 * 256 + data1) * 125.0) / 65536.0) dew_point = calculate_dewpoint(temperature, humidity) return dew_point, humidity, temperature except Exception as e: self.logger.exception( "Exception when taking a reading: {err}".format(err=e)) # Send soft reset and try a second read self.sht2x.write_byte(self.i2c_address, 0xFE) time.sleep(0.1) dew_point = convert_units( 'dewpoint', 'C', self.convert_to_unit, dew_point) temperature = convert_units( 'temperature', 'C', self.convert_to_unit, temperature) humidity = convert_units( 'humidity', 'percent', self.convert_to_unit, humidity) return dew_point, humidity, temperature def read(self): """ Takes a reading from the SHT2x and updates the self.dew_point, self._humidity, and self._temperature values :returns: None on success or 1 on error """ try: (self._dew_point, self._humidity, self._temperature) = self.get_measurement() if self._dew_point 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
""" @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()
def __init__(self, motorsList): self.motors = motorsList self.motorCount = 0 self.bus = SMBus(1)
def test_func(self): bus = SMBus(1) print("\nSupported I2C functionality: %x" % bus.funcs) bus.close()
def set_eon_fan(val): global last_eon_fan_val if last_eon_fan_val is None or last_eon_fan_val != val: bus = SMBus(7, force=True) try: i = [0x1, 0x3 | 0, 0x3 | 0x08, 0x3 | 0x10][val] bus.write_i2c_block_data(0x3d, 0, [i]) except IOError: # tusb320 if val == 0: bus.write_i2c_block_data(0x67, 0xa, [0]) else: bus.write_i2c_block_data(0x67, 0xa, [0x20]) bus.write_i2c_block_data(0x67, 0x8, [(val - 1) << 6]) bus.close() last_eon_fan_val = val
class MPL3115A2: def __init__(self, bus, addr, alt): self.addr = addr self.alt = alt self.bus = SMBus(bus) self.init() # Initialise the MPL3115A2 def init(self): self.reset() self.w_pt_data_cfg(drem=1, pdefe=0, tdefe=0) self.w_ctrl_reg1(alt=self.alt, os=1, sbyb=1) self.r_ctrl_reg1() self.r_ctrl_reg2() # Reset device def reset(self): # Reset by writing to CTRL2 try: self.bus.write_byte_data(self.addr, 0x26, 0x04) except: print("MPL3115A2 SMBus reset on device reset, please wait...") time.sleep(1) self.r_ctrl_reg1() self.r_ctrl_reg2() # Write data config register def w_pt_data_cfg(self, drem=0, pdefe=0, tdefe=0): # Parse data = ((drem & 0x1) << 2) + ((pdefe & 0x1) << 1) + ( (tdefe & 0x1) << 0) # Debug print("MPL3115A2 PT_DATA_CFG: 0x%02X" % data) # Write to device self.bus.write_byte_data(self.addr, 0x13, data) # Write control register 1 def w_ctrl_reg1(self, alt=0, os=0, ost=0, sbyb=0): # Parse data = ((alt & 0x1) << 7) + ((os & 0x7) << 3) + ((ost & 0x1) << 1) + ( (sbyb & 0x1) << 0) # Debug print("MPL3115A2 CTRL1: 0x%02X" % data) # Write to device self.bus.write_byte_data(self.addr, 0x26, data) # Write control register 2 def w_ctrl_reg2(self, load=0, alarm=0, st=0): # Parse data = ((load & 0x1) << 5) + ((alarm & 0x1) << 4) + ((st & 0xF) << 0) # Debug print("MPL3115A2 CTRL2: 0x%02X" % data) # Write to device self.bus.write_byte_data(self.addr, 0x27, data) # Read pressure from device def p_read(self): # Read data from device data = self.bus.read_i2c_block_data(self.addr, 0x01, 3) # Is alt mode or pressure if (self.alt): print("MPL3115A2 Compute altitude") # Parse aint = ((data[0] & 0x7F) << 8) + ((data[1] & 0xFF) << 0) sign = (data[0] & 0x80) afrc = ((data[2] & 0xF0) >> 4) alt = 0.0 if (sign): alt -= 2**16 alt += aint alt += (afrc * 0.0625) print("MPL3115A2 Altitude: %.4f" % alt) # Return return "{:.2f}".format(round(alt, 2)) else: print("MPL3115A2 Compute pressure") # Parse pint = ((data[0] & 0xFF) << 10) + ((data[1] & 0xFF) << 2) + ( (data[2] & 0xC0) >> 6) pfrc = ((data[2] & 0x30) >> 4) p = pint + (pfrc * 0.25) hPa = p / 100 print("MPL3115A2 Pressure: %.2f" % p) # Return return "{:.2f}".format(round(hPa, 2)) # Read temperature data def t_read(self): self.r_ctrl_reg1() self.r_ctrl_reg2() self.r_dr_status() # Read data from device data = self.bus.read_i2c_block_data(self.addr, 0x04, 2) # Parse temp = 0.0 tint = ((data[0] & 0x7F) << 0) tfrc = ((data[1] & 0xF0) >> 4) sign = (data[0] & 0x80) # Compute if (sign): temp -= 128 temp += tint temp += (tfrc * 0.0625) print("MPL3115A2 Temp: %.4f" % temp) # Return return "{:.2f}".format(round(temp, 2)) # Read data config register def r_pt_data_cfg(self): # Read byte from device data = self.bus.read_byte_data(self.addr, 0x13) # Parse drem = ((data & 0x04) >> 2) pdefe = ((data & 0x02) >> 1) tdefe = ((data & 0x01) >> 0) # Debug print("MPL3115A2 DREM: 0x%02X, PDEFE: 0x%02X, TDEFE: 0x%02X" % (drem, pdefe, tdefe)) # Return return drem, pdefe, tdefe # Read sensor status register def r_dr_status(self): # Read byte from device data = self.bus.read_byte_data(self.addr, 0x07) # Parse ptow = ((data & 0x80) >> 7) poww = ((data & 0x40) >> 6) tow = ((data & 0x20) >> 5) ptdr = ((data & 0x08) >> 3) pdr = ((data & 0x04) >> 2) tdr = ((data & 0x02) >> 1) # Debug print( "MPL3115A2 PTOW: 0x%02X, POW: 0x%02X, TOW: 0x%02X, PTDR: 0x%02X, PDR: 0x%02X, TDR: 0x%02X" % (ptow, poww, tow, ptdr, pdr, tdr)) # Return return ptow, poww, tow, ptdr, pdr, tdr # Read control register 1 def r_ctrl_reg1(self): # Read byte from device data = self.bus.read_byte_data(self.addr, 0x26) # Parse alt = ((data & 0x80) >> 7) os = ((data & 0x38) >> 3) rst = ((data & 0x04) >> 2) ost = ((data & 0x02) >> 1) sbyb = ((data & 0x01) >> 0) # Debug print( "MPL3115A2 ALT: 0x%02X, OS: 0x%02X, RST: 0x%02X, OST: 0x%02X, SBYB: 0x%02X" % (alt, os, rst, ost, sbyb)) # Return return alt, os, rst, ost, sbyb # Read control register 2 def r_ctrl_reg2(self): # Read byte from device data = self.bus.read_byte_data(self.addr, 0x27) # Parse load = ((data & 0x20) >> 5) alarm = ((data & 0x10) >> 4) st = ((data & 0x0F) >> 0) # Debug print("MPL3115A2 LOAD: 0x%02X, ALARM: 0x%02X, ST: 0x%02X" % (load, alarm, st)) # Return return load, alarm, st
class InputModule(AbstractInput): """ A sensor support class that monitors the DS18B20's lux """ def __init__(self, input_dev, testing=False): super(InputModule, self).__init__(input_dev, testing=testing, name=__name__) self.i2c_address = None self.i2c_bus = None self.resolution = None 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.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 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)