class ADXL372(object): def __init__(self, address=0x53, i2c=None): self.address = address self.bus = Bus(i2c) print('ID: {}'.format(self.id)) self.reset() self._timing_control = 0 self._power_control = 0 self._measurement_control = 0 self._sample_rate = 400 self._bandwidth = 200 self._mode = STANDBY_MODE def read(self): raw = self.bus.read_i2c_block_data(self.address, ADXL372_X_DATA_H, 6) return self.xyz(raw) def read_fifo(self, size): data = [] while size > 32: data.extend( self.bus.read_i2c_block_data(self.address, ADXL372_FIFO_DATA, 32)) size -= 32 if size: data.extend( self.bus.read_i2c_block_data(self.address, ADXL372_FIFO_DATA, size)) return data def reset(self): self.write_register(ADXL372_SRESET, 0x52) def timing_control(self, sample_rate=400, wakeup_ms=52): try: sample_bits = ADXL372_SAMPLE_RATE.index(sample_rate) wakeup_bits = ADXL372_WAKEUP_TIME.index(wakeup_ms) except ValueError: print('Supported sample rates: {}'.format(ADXL372_SAMPLE_RATE)) print('Supported wakeup time: {}'.format(ADXL372_WAKEUP_TIME)) raise ValueError('Invalid sample rate or wakeup time') self._timing_control = (sample_bits << TIMING_ODR_POS) | ( wakeup_bits << TIMING_WUR_POS) self._sample_rate = sample_rate self.write_register(ADXL372_TIMING, self._timing_control) def power_control(self, mode=0, low_pass_filter=0, high_pass_filter=0): if mode not in ADXL372_OP_MODE: raise ValueError('Invalid operating mode') value = mode if not low_pass_filter: value |= 1 << 3 if not high_pass_filter: value |= 1 << 2 self._mode = mode self._power_control = value self.write_register(ADXL372_POWER_CTL, value) def measurement_control(self, bandwidth=200, low_noise=0, linkloop=0, autosleep=0): try: value = ADXL372_BANDWIDTH.index(bandwidth) except ValueError: print('Supported bandwidth: {}'.format(ADXL372_BANDWIDTH)) raise ValueError('Invalid bandwidth') if low_noise: value |= 1 << 3 if linkloop: value |= linkloop << 4 if autosleep: value |= 1 << 6 self._measurement_control = value self.write_register(ADXL372_MEASURE, value) def fifo_control(self, mode=FIFO_STREAMED, format=FIFO_XYZ, samples=0x80): self.write_register(ADXL372_FIFO_SAMPLES, samples & 0xFF) self.write_register(ADXL372_FIFO_CTL, ((samples >> 8) & 0x1) | (mode << 1) | (format << 3)) @property def sample_rate(self): return self._sample_rate @sample_rate.setter def sample_rate(self, value): self._sample_rate = value try: simple_bits = ADXL372_SAMPLE_RATE.index(value) except ValueError: print('Supported sample rates: {}'.format(ADXL372_SAMPLE_RATE)) raise ValueError('Invalid sample rate') self._timing_control = (self._timing_control & TIMING_ODR_MASK) | ( simple_bits << TIMING_ODR_POS) self.write_register(ADXL372_TIMING, self._timing_control) @property def bandwidth(self): return self._bandwidth @bandwidth.setter def bandwidth(self, value): if value in ADXL372_BANDWIDTH: self._bandwidth = value bandwidth_bits = ADXL372_BANDWIDTH.index(value) self._measurement_control = ( self._measurement_control & MEASURE_BANDWIDTH_MASK) | bandwidth_bits else: print('Supported bandwidth: {}'.format(ADXL372_BANDWIDTH)) raise ValueError('Invalid bandwidth') @property def mode(self): return self._mode @mode.setter def mode(self, value): if value in ADXL372_OP_MODE: self._mode = value self._power_control = (self._power_control & PWRCTRL_OPMODE_MASK) | value self.write_register(ADXL372_POWER_CTL, value) else: raise ValueError('Invalid operating mode') @property def samples_in_fifo(self): data = self.bus.read_word_data(self.address, ADXL372_FIFO_ENTRIES_2) return ((data & 0x3) << 8) | ((data >> 8) & 0xFF) @property def status(self): return self.bus.read_word_data(self.address, ADXL372_STATUS_1) @property def id(self): return self.bus.read_i2c_block_data(self.address, ADXL372_ADI_DEVID, 4) def read_register(self, register): return self.bus.read_byte_data(self.address, register) def write_register(self, register, value): self.bus.write_byte_data(self.address, register, value) def update_register(self, register, mask, shift, value): data = self.read_register(register) data = (data & mask) | ((value << shift) & ~mask) self.write_register(register, data) def dump_registers(self): registers = self.bus.read_i2c_block_data(self.address, 0x39, 0x43 - 0x39) for register in registers: print(hex(register)) def xyz(self, raw): value = [0] * 3 for i in range(3): value[i] = (raw[2 * i] << 4) | (raw[2 * i + 1] >> 4) if value[i] & 0xF00: value[i] = -((~value[i] & 0xFFF) + 1) return value
class GroveOledDisplay128x64(object): HORIZONTAL = 0x00 VERTICAL = 0x01 PAGE = 0x02 def __init__(self, bus=None, address=0x3C): self.bus = Bus(bus) self.address = address self.off() self.inverse = False self.mode = self.HORIZONTAL self.clear() self.on() def on(self): self.send_command(_DISPLAY_ON) def off(self): self.send_command(_DISPLAY_OFF) def send_command(self, command): self.bus.write_byte_data(self.address, _COMMAND_MODE, command) def send_data(self, data): self.bus.write_byte_data(self.address, _DATA_MODE, data) def send_commands(self, commands): for c in commands: self.send_command(c) def clear(self): self.off() for i in range(8): self.set_cursor(i, 0) self.puts(' ' * 16) self.on() self.set_cursor(0, 0) @property def inverse(self): return self._inverse @inverse.setter def inverse(self, enable): self.send_command(_INVERSE_DISPLAY if enable else _NORMAL_DISPLAY) self._inverse = enable @property def mode(self): return self._mode @mode.setter def mode(self, mode): self.send_command(0x20) self.send_command(mode) self._mode = mode def set_cursor(self, row, column): self.send_command(0xB0 + row) self.send_command(0x00 + (8 * column & 0x0F)) self.send_command(0x10 + ((8 * column >> 4) & 0x0F)) def putc(self, c): C_add = ord(c) if C_add < 32 or C_add > 127: # Ignore non-printable ASCII characters c = ' ' C_add = ord(c) for i in range(0, 8): self.send_data(BasicFont[C_add - 32][i]) def puts(self, text): for c in text: self.putc(c) def show_image(self, image): from PIL import Image import numpy as np im = Image.open(image) bw = im.convert('1') pixels = np.array(bw.getdata()) page_size = 128 * 8 self.set_cursor(0, 0) for page in range(8): start = page_size * page end = start + page_size for i in range(start, start + 1280): data = np.packbits(pixels[i:end:128][::-1])[0] self.send_data(data)
class GroveThermocoupleAmpMCP9600(object): def __init__(self, address = 0x60): self._addr = address self._bus = Bus() self._therm = THER_TYPE_K self._junc = HOT_JUNCTION_REG_ADDR self._junc_res = COLD_JUNC_RESOLUTION_0_625 def _read_version(self): version = self._bus.read_i2c_block_data(self._addr,VERSION_ID_REG_ADDR,2) return version def _set_filt_coefficients(self,coefficients): data = self._bus.read_byte_data(self._addr,THERM_SENS_CFG_REG_ADDR) data = (data & 0xF8) | coefficients self._bus.write_byte_data(self._addr,THERM_SENS_CFG_REG_ADDR,data) def _set_cold_junc_resolution(self,junc_res): data = self._bus.read_byte_data(self._addr,DEVICE_CFG_REG_ADDR) data = (data & 0x7F) | junc_res self._bus.write_byte_data(self._addr,DEVICE_CFG_REG_ADDR,data) self._junc_res = junc_res def _set_ADC_meas_resolution(self,res): data = self._bus.read_byte_data(self._addr,DEVICE_CFG_REG_ADDR) data = (data & 0x9F) | res self._bus.write_byte_data(self._addr,DEVICE_CFG_REG_ADDR,data) def _set_burst_mode_samp(self,samp): data = self._bus.read_byte_data(self._addr,DEVICE_CFG_REG_ADDR) data = (data & 0xE3) | samp self._bus.write_byte_data(self._addr,DEVICE_CFG_REG_ADDR,data) def _set_sensor_mode(self,mode): data = self._bus.read_byte_data(self._addr,DEVICE_CFG_REG_ADDR) data = (data & 0xFC) | mode self._bus.write_byte_data(self._addr,DEVICE_CFG_REG_ADDR,data) def get_config(self): config1 = self._bus.read_byte_data(self._addr,DEVICE_CFG_REG_ADDR) config2 = self._bus.read_byte_data(self._addr,THERM_SENS_CFG_REG_ADDR) return config1, config2 def set_therm_type(self,therm_type): therm_cfg_data = self._bus.read_byte_data(self._addr,THERM_SENS_CFG_REG_ADDR) therm_cfg_data = (therm_cfg_data & 0x8F) | therm_type self._bus.write_byte_data(self._addr,THERM_SENS_CFG_REG_ADDR,therm_cfg_data) self._therm = therm_type def set_junc_type(self, junc): if not junc is None: self._junc = junc return self._junc def set_config(self, filter = FILT_OFF, junc_res = COLD_JUNC_RESOLUTION_0_625, adc_res = ADC_14BIT_RESOLUTION, burst_smps = BURST_1_SAMPLE, oper_mode = NORMAL_OPERATION ): self._set_filt_coefficients(filter) self._set_cold_junc_resolution(junc_res) self._set_ADC_meas_resolution(adc_res) self._set_burst_mode_samp(burst_smps) self._set_sensor_mode(oper_mode) return None def read(self): data = self._bus.read_word_data(self._addr, self._junc) # Big endian -> little endian data = socket.ntohs(data) # print("RAW = 0x%X" % data) # It's 16-bit 2's complement code temperature = ctypes.c_short(data).value / 16.0 return temperature
class grove_si114x(object): def __init__(self, address=SI114X_ADDR): self.bus = Bus() self.addr = address self._logger = logging.getLogger('grove_si114x') assert self.Begin( ), "Please check if the I2C device insert in I2C of Base Hat" def __del__(self): self._WriteByte(SI114X_COMMAND, SI114X_RESET) time.sleep(0.1) self.bus.close() def __exit__(self): self.bus.close() #Init the si114x and begin to collect data def Begin(self): if self._ReadByte(SI114X_PART_ID) != 0X45: return False self.Reset() #INIT self.DeInit() return True #reset the si114x #inclue IRQ reg, command regs... def Reset(self): self._WriteByte(SI114X_MEAS_RATE0, 0) self._WriteByte(SI114X_MEAS_RATE1, 0) self._WriteByte(SI114X_IRQ_ENABLE, 0) self._WriteByte(SI114X_IRQ_MODE1, 0) self._WriteByte(SI114X_IRQ_MODE2, 0) self._WriteByte(SI114X_INT_CFG, 0) self._WriteByte(SI114X_IRQ_STATUS, 0xFF) self._WriteByte(SI114X_COMMAND, SI114X_RESET) time.sleep(0.1) self._WriteByte(SI114X_HW_KEY, 0x17) time.sleep(0.1) #default init def DeInit(self): #ENABLE UV reading #these reg must be set to the fixed value self._WriteByte(SI114X_UCOEFF0, 0x29) self._WriteByte(SI114X_UCOEFF1, 0x89) self._WriteByte(SI114X_UCOEFF2, 0x02) self._WriteByte(SI114X_UCOEFF3, 0x00) self.WriteParamData( SI114X_CHLIST, SI114X_CHLIST_ENUV | SI114X_CHLIST_ENALSIR | SI114X_CHLIST_ENALSVIS | SI114X_CHLIST_ENPS1) # #set LED1 CURRENT(22.4mA)(It is a normal value for many LED) # self.WriteParamData(SI114X_PS1_ADCMUX, SI114X_ADCMUX_LARGE_IR) self._WriteByte(SI114X_PS_LED21, SI114X_LED_CURRENT_22MA) self.WriteParamData(SI114X_PSLED12_SELECT, SI114X_PSLED12_SELECT_PS1_LED1) # # #PS ADC SETTING # self.WriteParamData(SI114X_PS_ADC_GAIN, SI114X_ADC_GAIN_DIV1) self.WriteParamData(SI114X_PS_ADC_COUNTER, SI114X_ADC_COUNTER_511ADCCLK) self.WriteParamData( SI114X_PS_ADC_MISC, SI114X_ADC_MISC_HIGHRANGE | SI114X_ADC_MISC_ADC_RAWADC) # #VIS ADC SETTING # self.WriteParamData(SI114X_ALS_VIS_ADC_GAIN, SI114X_ADC_GAIN_DIV1) self.WriteParamData(SI114X_ALS_VIS_ADC_COUNTER, SI114X_ADC_COUNTER_511ADCCLK) self.WriteParamData(SI114X_ALS_VIS_ADC_MISC, SI114X_ADC_MISC_HIGHRANGE) # #IR ADC SETTING # self.WriteParamData(SI114X_ALS_IR_ADC_GAIN, SI114X_ADC_GAIN_DIV1) self.WriteParamData(SI114X_ALS_IR_ADC_COUNTER, SI114X_ADC_COUNTER_511ADCCLK) self.WriteParamData(SI114X_ALS_IR_ADC_MISC, SI114X_ADC_MISC_HIGHRANGE) # #interrupt enable # self._WriteByte(SI114X_INT_CFG, SI114X_INT_CFG_INTOE) self._WriteByte(SI114X_IRQ_ENABLE, SI114X_IRQEN_ALS) # #AUTO RUN # self._WriteByte(SI114X_MEAS_RATE0, 0xFF) self._WriteByte(SI114X_COMMAND, SI114X_PSALS_AUTO) #read param data def ReadParamData(self, Reg): self._WriteByte(SI114X_COMMAND, Reg | SI114X_QUERY) return self._ReadByte(SI114X_RD) #writ param data def WriteParamData(self, Reg, Value): #write Value into PARAMWR reg first self._WriteByte(SI114X_WR, Value) self._WriteByte(SI114X_COMMAND, Reg | SI114X_SET) #SI114X writes value out to PARAM_RD,read and confirm its right return self._ReadByte(SI114X_RD) #Read Visible Value @property def ReadVisible(self): return self._ReadHalfWord(SI114X_ALS_VIS_DATA0) #Read IR Value @property def ReadIR(self): return self._ReadHalfWord(SI114X_ALS_IR_DATA0) #Read UV Value #this function is a int value ,but the real value must be div 100 @property def ReadUV(self): return self._ReadHalfWord(SI114X_AUX_DATA0_UVINDEX0) #Read Proximity Value def ReadProximity(self, PSn): return self._ReadHalfWord(PSn) # read 8 bit data from Reg def _ReadByte(self, Reg): try: read_data = self.bus.read_byte_data(self.addr, Reg) except OSError: raise OSError( "Please check if the I2C device insert in I2C of Base Hat") return read_data # Write 8 bit data to Reg def _WriteByte(self, Reg, Value): try: self.bus.write_byte_data(self.addr, Reg, Value) except OSError: raise OSError( "Please check if the I2C device insert in I2C of Base Hat") # read 16 bit data from Reg def _ReadHalfWord(self, Reg): try: block = self.bus.read_i2c_block_data(self.addr, Reg, 2) except OSError: raise OSError( "Please check if the I2C device insert in I2C of Base Hat") read_data = (block[0] & 0xff) | (block[1] << 8) return read_data
class Grove12KeyCapTouchMpr121(): def __init__(self,bus_num = 1,addr = TOUCH_SENSOR_DEFAULT_ADDR): self.bus = Bus(bus_num) self.addr = addr self.threshold = 0 self.touch_flag = [0]*CHANNEL_NUM def sensor_init(self): self._set_mode(STOP_MODE) data = [0x23,0x10] self._set_global_param(data) self._set_debounce(0x22) self._set_mode(NORMAL_MODE) def set_threshold(self,threshold): self.threshold = threshold def wait_for_ready(self): time.sleep(.2) def _set_mode(self,mode): self.bus.write_byte_data(self.addr,MODE_CONFIG_REG_ADDR,mode) def _set_global_param(self,data): self.bus.write_i2c_block_data(self.addr,GLOBAL_PARAM_REG_ADDR_L,data) def _set_debounce(self,data): self.bus.write_byte_data(self.addr,SET_DEBOUNCE_REG_ADDR,data) def _check_status_register(self): data_status = self.bus.read_i2c_block_data(self.addr,TOUCH_STATUS_REG_ADDR_L,2) return data_status def get_filtered_touch_data(self,sensor_status): result_value = [] for i in range(CHANNEL_NUM): time.sleep(.01) if(sensor_status & (1<<i)): channel_data = self.bus.read_i2c_block_data(self.addr,FILTERED_DATA_REG_START_ADDR_L+2*i,2) result_value.append(channel_data[0] | channel_data[1]<<8 ) else: result_value.append(0) return result_value def listen_sensor_status(self): data = self._check_status_register() touch_status = data[0] | (data[1]<<8) touch_result_value = self.get_filtered_touch_data(touch_status) for i in range(CHANNEL_NUM): if(touch_result_value[i] < self.threshold ): touch_result_value[i] = 0 return touch_result_value def parse_and_print_result(self,result): for i in range(CHANNEL_NUM): if(result[i] != 0): if(0 == self.touch_flag[i]): self.touch_flag[i] = 1 print("Channel %d is pressed,value is %d" %(i,result[i])) else: if(1 == self.touch_flag[i]): self.touch_flag[i] = 0 print("Channel %d is released,value is %d" %(i,result[i]))
class Tsl2561: i2c = None def __init__(self, bus=I2C_SMBUS, address=I2C_ADDRESS, debug=1, pause=0.8): # assert(bus is not None) # assert(address > 0b000111 and address < 0b1111000) self.address = address self.bus = Bus(bus) self.pause = pause self.debug = debug self.gain = 0 self._bus = bus self._addr = address ambient = None IR = None self._ambient = 0 self._IR = 0 self._LUX = None self._control(_POWER_UP) self._partno_revision() def _reverseByteOrder(self, data): """Reverses the byte order of an int (16-bit) or long (32-bit) value""" # Courtesy Vishal Sapre byteCount = len(hex(data)[2:].replace('L','')[::2]) val = 0 for i in range(byteCount): val = (val << 8) | (data & 0xff) data >>= 8 return val def _read_byte(self, address): command = _CMD | address self.bus.read_byte_data(self.address, command) def _read_word(self, address,little_endian=True): try: command = _CMD | address result = self.bus.read_word_data(self.address, command) if not little_endian: result = ((result << 8) & 0xFF00) + (result >> 8) if (self.debug): print ("I2C: Device 0x{} returned 0x{} from reg 0x{}".format(self.address, result & 0xFFFF, reg)) return result except IOError, err: return self.errMsg() def _write_byte(self, address, data): command = _CMD | address self.bus.write_byte_data(self.address, command, data) def _write_word(self, address, data): command = _CMD | _AUTO | address data = [(data >> 8) & 0xFF, data & 0xFF] self.bus.write_i2c_block_data(self.address, command, data) def setGain(self, gain = 1): """ Set the gain """ if (gain != self.gain): if (gain==1): cmd = _CMD | _REG_TIMING value = 0x02 self._write_byte(cmd, value) if (self.debug): print ("Setting low gain") else: cmd = _CMD | _REG_TIMING value = 0x12 self._write_byte(cmd, value) if (self.debug): print ("Setting high gain") self.gain = gain # Safe gain for calculation print('setGain...gian=',gain) time.sleep(self.pause) # Pause for integration (self.pause must be bigger than integration time) def readWord(self, reg): """ Reads a word from the TSL2561 I2C device """ try: wordval = self._read_word(reg) print ('wordval=',wordval) newval = self._reverseByteOrder(wordval) print ('newval=',newval) if (self.debug): print("I2C: Device 0x{}: returned 0x{} from reg 0x{}".format(self._addr, wordval & 0xFFFF, reg)) return newval except IOError: print("Error accessing 0x{}: Chcekcyour I2C address".format(self._addr)) return -1 def readFull(self, reg = 0x8C): """ Read visible + IR diode from the TSL2561 I2C device """ return self.readWord(reg) def readIR(self, reg = 0x8E): """ Reads only IR diode from the TSL2561 I2C device """ return self.readWord(reg) def readLux(self, gain = 0): """ Grabs a lux reading either with autoranging (gain=0) or with specific gain (1, 16) """ if (self.debug): print ("gain=",gain) if (gain == 1 or gain == 16): self.setGain(gain) # Low/High Gain ambient = self.readFull() IR = self.readIR() elif (gain == 0): # Auto gain self.setGain(16) # First try highGain ambient = self.readFull() if (ambient < 65535): IR = slef.readIR() if (ambient >= 65535 or IR >= 65535): # Value(s) exeed(s) datarange self.setGain(1) # Set low Gain ambient = self.readFull() IR = self.readIR() # If either sensor is saturated, no acculate lux value can be achieved. if (ambient == 0xffff or IR == 0xffff): self._LUX = None self._ambient = None self._IR = None return (self.ambient, self.IR, self._ambient, self._IR, self._LUX) if (self.gain == 1): self._ambient = 16 * ambient # Scale 1x to 16x self._IR = 16 * IR else: self._ambient = 1 * ambient if (self.debug): print ("IR Result without scaling: ",IR) print ("IR Result: ", self._IR) print ("Ambient Result without scaling: ", ambient) print ("Ambient Result: ", self._ambient) if (self._ambient == 0): # Sometimes, the channel 0 returns 0 when dark ... self._LUX = 0.0 return (ambient, IR, self._ambient, self._IR, self._LUX) ratio = (self._IR / float(self._ambient)) if (self.debug): print ("ratio: ", ratio) if ((ratio >= 0) and (ratio <= 0.52)): self._LUX = (0.0315 * self._ambient) - (0.0593 * self._ambient * (ratio ** 1.4)) elif (ratio <= 0.65): self._LUX = (0.0229 * self._ambient) - (0.0291 * self._IR) elif (ratio <= 0.80): self._LUX = (0.0157 * self._ambient) - (0.018 * self._IR) elif (ratio <= 1.3): self._LUX = (0.00338 * self._ambient) - (0.0026 * self._IR) elif (ratio > 1.3): self._LUX = 0 return (ambient, IR, self._ambient, self._IR, self._LUX) def _control(self, params): if (params == _POWER_UP): print ("Power ON") elif (params == _POWER_DOWN): print ("Power OFF") cmd = _CMD | _REG_CONTROL | params self._write_byte(self._addr, cmd) # select command register and power on time.sleep(0.4) # Wait for 400ms to power up or power down. def _partno_revision(self): """ Read Partnumber and revision of the sensor """ cmd = _CMD | _REG_ID value = self._read_byte(cmd) print ("value=",value) part = str(value)[7:4] if (part == "0000"): PartNo = "TSL2560CS" elif (part == "0001"): PartNo = "TSL2561CS" elif (part == "0100"): PartNo = "TSL2560T/FN/CL" else: PartNo = "not TSL2560 or TSL2561" RevNo = str(value)[3:0] if (self.debug): print ("response: ", value) print ("PartNo = ", PartNo) print ("RevNo = ", RevNo) return (PartNo, RevNo)
class GroveI2cColorSensorV2: """Driver for Grove I2C Color Sensor (TCS34725)""" def __init__(self, bus=None, address=0x29): self.address = address self.bus = Bus(bus) self.awake = False if self.id not in (0x44, 0x4D): raise ValueError('Not find a Grove I2C Color Sensor V2') self.set_integration_time(24) self.set_gain(4) def wakeup(self): enable = self._read_byte(_ENABLE) self._write_byte(_ENABLE, enable | _PON | _AEN) time.sleep(0.0024) self.awake = True def sleep(self): enable = self._read_byte(_ENABLE) self._write_byte(_ENABLE, enable & ~_PON) self.awake = False def is_awake(self): return self._read_byte(_ENABLE) & _PON def set_wait_time(self, t): pass @property def id(self): return self._read_byte(_ID) @property def integration_time(self): steps = 256 - self._read_byte(_ATIME) return steps * 2.4 def set_integration_time(self, t): """Set the integration time of the sensor""" if t < 2.4: t = 2.4 elif t > 614.4: t = 614.4 steps = int(t / 2.4) self._integration_time = steps * 2.4 self._write_byte(_ATIME, 256 - steps) @property def gain(self): """The gain control. Should be 1, 4, 16, or 60. """ return _GAINS[self._read_byte(_CONTROL)] def set_gain(self, gain): if gain in _GAINS: self._write_byte(_CONTROL, _GAINS.index(gain)) @property def raw(self): """Read RGBC registers return 16 bits red, green, blue and clear data """ if not self.awake: self.wakeup() while not self._valid(): time.sleep(0.0024) data = tuple( self._read_word(reg) for reg in (_RDATA, _GDATA, _BDATA, _CDATA)) return data @property def rgb(self): """Read the RGB color detected by the sensor. Returns a 3-tuple of red, green, blue component values as bytes (0-255). """ r, g, b, clear = self.raw if clear: r = int(255 * r / clear) g = int(255 * g / clear) b = int(255 * b / clear) else: r, g, b = 0, 0, 0 return r, g, b def _valid(self): """Check if RGBC is valid""" return self._read_byte(_STATUS) & 0x01 def _read_byte(self, address): command = _CMD | address return self.bus.read_byte_data(self.address, command) def _read_word(self, address): command = _CMD | _AUTO | address return self.bus.read_word_data(self.address, command) def _write_byte(self, address, data): command = _CMD | address self.bus.write_byte_data(self.address, command, data) def _write_word(self, address, data): command = _CMD | _AUTO | address data = [(data >> 8) & 0xFF, data & 0xFF] self.bus.write_i2c_block_data(self.address, command, data)
class GroveOledDisplay128x64(object): HORIZONTAL = 0x00 VERTICAL = 0x01 PAGE = 0x02 def __init__(self, bus=None, address=0x3C): self.bus = Bus(bus) self.address = address self.off() self.inverse = False self.mode = self.HORIZONTAL self.width = 128 # test self.height = 64 # test self._pages = self.height//8 # test self._buffer = [0]*(self.width*self._pages) # test self.clear() self.on() def on(self): self.send_command(_DISPLAY_ON) def off(self): self.send_command(_DISPLAY_OFF) def send_command(self, command): self.bus.write_byte_data(self.address, _COMMAND_MODE, command) def send_data(self, data): self.bus.write_byte_data(self.address, _DATA_MODE, data) def send_commands(self, commands): for c in commands: self.send_command(c) def clear(self): self.off() self._buffer = [0]*(self.width*self._pages) self.adf_display() self.on() self.set_cursor(0, 0) @property def inverse(self): return self._inverse @inverse.setter def inverse(self, enable): self.send_command(_INVERSE_DISPLAY if enable else _NORMAL_DISPLAY) self._inverse = enable @property def mode(self): return self._mode @mode.setter def mode(self, mode): self.send_command(0x20) self.send_command(mode) self._mode = mode def set_cursor(self, row, column): self.send_command(0xB0 + row) self.send_command(0x00 + (8*column & 0x0F)) self.send_command(0x10 + ((8*column>>4)&0x0F)) def putc(self, c): C_add = ord(c) if C_add < 32 or C_add > 127: # Ignore non-printable ASCII characters c = ' ' C_add = ord(c) for i in range(0, 8): self.send_data(BasicFont[C_add-32][i]) def puts(self, text): for c in text: self.putc(c) def adf_image(self, image): """Set buffer to value of Python Imaging Library image. The image should be in 1 bit mode and a size equal to the display size. """ if image.mode != '1': raise ValueError('Image must be in mode 1.') imwidth, imheight = image.size if imwidth != 128 or imheight != 64: raise ValueError('Image must be same dimensions as display (128x64).') # Grab all the pixels from the image, faster than getpixel. pix = image.load() # Iterate through the memory pages index = 0 for page in range(self._pages): # Iterate through all x axis columns. for x in range(self.width): # Set the bits for the column of pixels at the current position. bits = 0 # Don't use range here as it's a bit slow for bit in [0, 1, 2, 3, 4, 5, 6, 7]: bits = bits << 1 bits |= 0 if pix[(x, page*8+7-bit)] == 0 else 1 # Update buffer byte and increment to next byte. self._buffer[index] = bits index += 1 def adf_display(self): """Write display buffer to physical display.""" # self.command(SSD1306_COLUMNADDR) # self.command(0) # Column start address. (0 = reset) # self.command(self.width-1) # Column end address. # self.command(SSD1306_PAGEADDR) # self.command(0) # Page start address. (0 = reset) # self.command(self._pages-1) # Page end address. # Write buffer data. for i in range(0, len(self._buffer), 16): control = 0x40 # Co = 0, DC = 0 #self._i2c.writeList(control, self._buffer[i:i+16]) #self._bus.write_i2c_block_data(self._address, register, data) #self.bus.write_byte_data(self.address, _DATA_MODE, data) self.bus.write_i2c_block_data(self.address, _DATA_MODE, self._buffer[i:i+16]) def show_image(self, image): #im = image #Image.open(image) #bw = im.convert('1') pixels = np.array(image.getdata()) #pixels = image.load() page_size = 128 * 8 self.set_cursor(0, 0) # iterate through pages for page in range(8): start = page_size * page end = start + page_size # iterate through x-axis columns for i in range(start, start + 128): data = np.packbits(pixels[i:end:128][::-1])[0] self.send_data(data)
class ButtonTypedI2c(Button): def __init__(self, address=0x03): self.bus = Bus() self.addr = address self.dev_id = 0 self.val = 0 self.probeDevID() self.get_val() self.send_Byte(0x02) app1 = self.status_read() while 1: self.status_read() time.sleep(1.0) continue def set_devID(self, reg, size): self.bus.write_byte_data(self.addr, reg, size) def send_Byte(self, reg): self.bus.write_byte(self.addr, reg) def get_devID(self, data): return self.bus.read_byte(self.addr, data) def get_data(self, reg, len): return self.bus.read_i2c_block_data(self.addr, reg, len) def probeDevID(self): for i in range(4): id = self.get_data(0x00, 4) did = 0 for j in range(4): did = (did >> 8) | (int(id[j]) << 24) #print("DEV_ID = {:8X}".format(did)) if (did >> 16) == 0x2886: self.dev_id = did return self.dev_id self.get_devID(True) def get_val(self): if (self.dev_id & 0xFFFF) == 0x0002: self.val = 5 print("Grove 5_way tactile Switch Insert") self.key_names = grove_5way_tactile_keys return self.val elif (self.dev_id & 0xFFFF) == 0x0003: self.val = 6 print("Grove 6_pos dip Switch Insert") self.key_names = grove_6pos_dip_switch_keys return self.val def status_read(self): app = self.get_data(0x01, 4 + self.val) #print("get event ={}".format(app)) for i in range(0, self.val): print("{} : RAW- ".format(self.key_names[i]), end='') print("{} ".format(app[i + 4] & 1 and "HIGH" or "LOW")) if (self.dev_id & 0xFFFF) == 0x0002: print("{} ".format(app[i + 4] & 1 and "RELEASEND" or "PRESSED")) elif (self.dev_id & 0xFFFF) == 0x0003: print("{} ".format(app[i + 4] & 1 and "OFF" or "ON")) for i in range(0, self.val): if app[i + 4] & ~1: print("{} ".format(self.key_names[i])) print(": EVENT - ") if app[i + 4] & (1 << 1): print("SINGLE-CLICK") if app[i + 4] & (1 << 2): print("DOUBLE-CLICL") if app[i + 4] & (1 << 3): print("LONG-PRESS") if app[i + 4] & (1 << 4): print("LEVEL-CHANGED") print("") return app