def getPressure(self, oversampling=OVERSAMPLE_0): """ Returns the current pressure in Pascals. The optional parameter 'oversampling' can be given as one of OVERSAMPLE_1, OVERSAMPLE_2, or OVERSAMPLE_3 for averaging of 2, 4 or 8 samples respectively. """ assert self.OVERSAMPLE_0 <= oversampling <= self.OVERSAMPLE_3, \ "unsupported oversample value" temp, b5 = self.getTemp(return_b5_coefficient=True) offset = self.CMD_PRESSURE_OSS_INC * oversampling cmd = self.CMD_PRESSURE + offset self.writeRegister(self.REG_CTRL_MEAS, cmd) bbio.delay(self.PRESSURE_CONVERSION_TIMES[oversampling]) msb, lsb, xlsb = self.readRegister(self.REG_OUT_MSB, 3) val = ((msb<<16) | (lsb<<8) | xlsb) >> (8-oversampling) # Conversions are straight out of the datasheet b6 = b5-4000 x1 = (self.cal_B2 * (b6*b6 / 4096)) / 2048 x2 = self.cal_AC2 * b6 / 2048 x3 = x1+x2 b3 = ((self.cal_AC1*4+x3) << oversampling + 2) / 4 x1 = self.cal_AC3 * b6 / 8192 x2 = (self.cal_B1 * (b6*b6 / 4096)) / 65536 x3 = ((x1 + x2) + 2) / 4 b4 = self.cal_AC4 * (x3 + 32768) / 32768 b7 = (val - b3) * (50000 >> oversampling) if (b7 < 1<<31): p = (b7 * 2) / b4 else: p = (b7 / b4) * 2 x1 = (p / 256)**2 x1 = (x1 * 3038) / 65536 x2 = (-7357 * p) / 65536 p += (x1 + x2 + 3791) / 16 return p
def __init__(self, right_wheel, left_wheel, ir_sensors, speed, potentiometer, start_stop_button): """ Instantiates a robot. :param right_wheel: A dictionary that corresponds to the right wheel of the robot, there are 3 entries: 'motor': The Motor object corresponding to the used motor for that wheel. 'encoder': The Encoder object corresponding the that wheel. 'pi_controller': The PI_controller object corresponding to that wheel. :type right_wheel: dictionary :param left_wheel: A dictionary that corresponds to the left wheel of the robot, the entries are the same. :type left_wheel: dictionary :param ir_sensors: The IR_sensor object used to access to the detected informations. :type ir_sensors: IR_sensor :param speed: The speed that the robot tries to follow. :type speed: float :param potentiometer: The Potentiometer object that the user can use to change the speed that the robot must follow. :type potentiometer: Potentiometer :param start_stop_button: The Button object used for the start and stop button of the robot. :type start_stop_button: Button """ self.__right_wheel = right_wheel self.__right_wheel['pi_controller'].set_limits(cst.LIMITS) self.__left_wheel = left_wheel self.__left_wheel['pi_controller'].set_limits(cst.LIMITS) self.__ir_sensors = ir_sensors self.__speed = speed self.__potentiometer = potentiometer self.__start_stop_button = start_stop_button self.__switch_on = False self.__is_on = False self.__set_wanted_speeds(0, 0) for _ in range(20): self.__get_corrected_speeds() io.delay(cst.PAUSE_MS) io.toggle(cst.START_LED)
def getPressure(self, oversampling=OVERSAMPLE_0): """ Returns the current pressure in Pascals. The optional parameter 'oversampling' can be given as one of OVERSAMPLE_1, OVERSAMPLE_2, or OVERSAMPLE_3 for averaging of 2, 4 or 8 samples respectively. """ assert self.OVERSAMPLE_0 <= oversampling <= self.OVERSAMPLE_3, \ "unsupported oversample value" temp, b5 = self.getTemp(return_b5_coefficient=True) offset = self.CMD_PRESSURE_OSS_INC * oversampling cmd = self.CMD_PRESSURE + offset self.writeRegister(self.REG_CTRL_MEAS, cmd) bbio.delay(self.PRESSURE_CONVERSION_TIMES[oversampling]) msb, lsb, xlsb = self.readRegister(self.REG_OUT_MSB, 3) val = ((msb << 16) | (lsb << 8) | xlsb) >> (8 - oversampling) # Conversions are straight out of the datasheet b6 = b5 - 4000 x1 = (self.cal_B2 * (b6 * b6 / 4096)) / 2048 x2 = self.cal_AC2 * b6 / 2048 x3 = x1 + x2 b3 = ((self.cal_AC1 * 4 + x3) << oversampling + 2) / 4 x1 = self.cal_AC3 * b6 / 8192 x2 = (self.cal_B1 * (b6 * b6 / 4096)) / 65536 x3 = ((x1 + x2) + 2) / 4 b4 = self.cal_AC4 * (x3 + 32768) / 32768 b7 = (val - b3) * (50000 >> oversampling) if (b7 < 1 << 31): p = (b7 * 2) / b4 else: p = (b7 / b4) * 2 x1 = (p / 256)**2 x1 = (x1 * 3038) / 65536 x2 = (-7357 * p) / 65536 p += (x1 + x2 + 3791) / 16 return p
def analogRead(adc_pin): """ Returns voltage read on given analog input pin. If passed one of PyBBIO's AIN0-AIN5 keywords the voltage will be returned in millivolts. May also be passed the path to an AIN file as created by a cape overlay, in which case the value will be returned as found in the file. """ global _ADC_INITIALIZED if not _ADC_INITIALIZED: cape_manager.load(ADC_ENABLE_DTS_OVERLAY, auto_unload=False) # Don't unload the overlay on exit for now because it can # cause kernel panic. bbio.delay(100) _ADC_INITIALIZED = True if adc_pin in ADC: adc_pin = ADC[adc_pin] adc_file = glob.glob(adc_pin[0]) if len(adc_file) == 0: overlay = adc_pin[1] # Overlay not loaded yet cape_manager.load(overlay, auto_unload=False) adc_file = glob.glob(adc_pin[0]) else: adc_file = glob.glob(adc_pin) if len(adc_file) == 0: raise Exception('*Could not load overlay for adc_pin: %s' % adc_pin) adc_file = adc_file[0] # Occasionally the kernel will be writing to the file when you try # to read it, to avoid IOError try up to 5 times: for i in range(5): try: with open(adc_file, 'rb') as f: val = f.read() return int(val) except IOError: continue raise Exception('*Could not open AIN file: %s' % adc_file)
def read(self, addr, reg, size=1): ''' Reads 'size' number of bytes from slave device 'addr' addr : integer between (0-127) - Address of slave device reg : register of the slave device you want to read from size : integer - number of bytes to be read returns an int if size is 1; else list of integers ''' if not self.open: print "I2C bus : %s - not initialized, open before read" % self.config try: if size == 1: return self.bus.read_byte_data(addr, reg) else: read_data = [] for i in range(size): data = self.bus.read_byte_data(addr, reg+i) bbio.delay(4) read_data.append(data) return read_data except IOError as e: print "Bus is active : check if device with address %d is connected/activated" %addr
def write(self, addr, reg, val): ''' Writes value 'val' to address 'addr' addr : integer between (0-127) - Address of slave device reg : register of the slave device you want to write to val : string, integer or list - if list, writes each value in the list returns number of bytes written ''' if not self.open: print "I2C bus : %s - not initialized" % self.config return try: if type(val) == int: self.bus.write_byte_data(addr, reg, val) return 1 else: data = self._format(val) if data: for i, unit in enumerate(data): self.bus.write_byte_data(addr, reg+i, unit) bbio.delay(4) #4 microsecond delay #delay reqd, otherwise loss of data return len(data) else: return 0 except IOError as e: print "Bus is active : check if device with address %d is connected/activated" %addr
def disable(self): self.enabled = False # Wait for PID to stop while self.disabled == False: io.delay(200) # The PID loop has finished self.mosfet.setPower(0.0) self.mosfet.close()
def __init__(self, i2c): self.i2c = i2c if i2c == -1: # Testing mode, don't try to open an I2C interface return i2c.write(self.I2C_ADDRESS, [self.CMD_RESET]) bbio.delay(15) usr_reg = i2c.readTransaction(self.I2C_ADDRESS, self.CMD_USER_REG_READ, 1) assert usr_reg[0] == self.USER_REGISTER_DEFAULT, \ "HTU21D not detected on I2C bus"
def open(self): overlay = 'BB-SPIDEV%i' % (self.bus-1) cape_manager.load(overlay, auto_unload=False) bbio.delay(250) # Give driver time to load assert cape_manager.isLoaded(overlay), "Could not load SPI overlay" super(SPI_Bus, self).open() # Initialize to default parameters: self.setCSActiveLow(0) self.setBitsPerWord(0, 8) self.setMaxFrequency(0, 8000000) self.setClockMode(0, 0)
def begin(self, cols, rows): """ Initializes the LCD driver and sets it to the given number of rows and columns. """ assert cols == 8 or cols == 16 or cols == 20, \ "LiquidCrystal only supports 8, 16 and 20 row displays" assert rows == 1 or rows == 2 or rows == 4, \ "LiquidCrystal only supports 1, 2 and 4 column displays" self.cols = cols self.rows = rows for pin in (self.rs, self.enable) + self.data_pins: bbio.pinMode(pin, bbio.OUTPUT) if self.rw: bbio.pinMode(self.rw, bbio.OUTPUT) bbio.digitalWrite(self.enable, bbio.LOW) # idle state # This is the initialization procedure as defined in the HD44780 datasheet: if self.mode_bits == 8: self.writeCommand(self.COMMAND_FUNCTIONSET | self.FUNCTIONSET_8BIT) else: self._write4bits((self.COMMAND_FUNCTIONSET | self.FUNCTIONSET_8BIT) >> 4) bbio.delay(5) if self.mode_bits == 8: self.writeCommand(self.COMMAND_FUNCTIONSET | self.FUNCTIONSET_8BIT) else: self._write4bits((self.COMMAND_FUNCTIONSET | self.FUNCTIONSET_8BIT) >> 4) bbio.delay(5) if self.mode_bits == 8: self.writeCommand(self.COMMAND_FUNCTIONSET | self.FUNCTIONSET_8BIT) else: self._write4bits((self.COMMAND_FUNCTIONSET | self.FUNCTIONSET_8BIT) >> 4) function_set = 0 if self.mode_bits == 8: function_set = self.FUNCTIONSET_8BIT else: # Must put in 4 bit mode before we can set the rows and cols self._write4bits(self.COMMAND_FUNCTIONSET >> 4) if self.rows > 1: function_set |= self.FUNCTIONSET_2LINE self.writeCommand(self.COMMAND_FUNCTIONSET | function_set) self.setDisplay(self.OFF) self.clear() self._entry_mode = self.ENTRYMODE_SHIFTRIGHT self.writeCommand(self.COMMAND_ENTRYMODE | self._entry_mode) self.setDisplay(self.ON)
def keep_temperature(self): while self.enabled: self.current_temp = self.thermistor.getTemperature() # Read the current temperature error = self.target_temp - self.current_temp # Calculate the error derivative = self._getErrorDerivative(error) # Calculate the error derivative integral = self._getErrorIntegral(error) # Calculate the error integral power = self.P * (error + self.D * derivative + self.I * integral) # The formula for the PID power = max(min(power, 1.0), 0.0) # Normalize to 0,1 self.mosfet.setPower(power) # Update the mosfet if self.debug > 0: # Debug if necessary print self.name + ": Target: %f, Current: %f" % (self.target_temp, self.current_temp), print ", error: %f, power: %f" % (error, power), print ", derivative: %f, integral: %f" % (self.D * derivative, self.I * integral) io.delay(1000) # Wait one second self.disabled = True # Signal the disable that we are done
def pinMux(gpio_pin, mode, preserve_mode_on_exit=False): """ Uses custom device tree overlays to set pin modes. If preserve_mode_on_exit=True the overlay will remain loaded when the program exits, otherwise it will be unloaded before exiting. *This should generally not be called directly from user code. """ gpio_pin = gpio_pin.lower() if not gpio_pin: print "*unknown pinmux pin: %s" % gpio_pin return mux_file_glob = glob.glob("%s/*%s*/state" % (OCP_PATH, gpio_pin)) if len(mux_file_glob) == 0: try: cape_manager.load("PyBBIO-%s" % gpio_pin, not preserve_mode_on_exit) bbio.delay(250) # Give driver time to load except IOError: print "*Could not load %s overlay, resource busy" % gpio_pin return mux_file_glob = glob.glob("%s/*%s*/state" % (OCP_PATH, gpio_pin)) if len(mux_file_glob) == 0: print "*Could not load overlay for pin: %s" % gpio_pin return mux_file = mux_file_glob[0] # Convert mode to ocp mux name: mode = "mode_%s" % format(mode, "#010b") # Possible modes: # mode_0b00100111 # rx active | pull down # mode_0b00110111 # rx active | pull up # mode_0b00101111 # rx active | no pull # mode_0b00000111 # pull down # mode_0b00010111 # pull up # mode_0b00001111 # no pull # See /lib/firmware/PyBBIO-src/*.dts for more info for i in range(3): # If the pin's overlay was just loaded there may not have been enough # time for the driver to get fully initialized, which causes an IOError # when trying to write the mode; try up to 3 times to avoid this: try: with open(mux_file, "wb") as f: f.write(mode) return except IOError: # Wait a bit between attempts bbio.delay(10) # If we get here then it didn't work 3 times in a row; raise the IOError: raise
def pinMux(gpio_pin, mode, preserve_mode_on_exit=False): """ Uses custom device tree overlays to set pin modes. If preserve_mode_on_exit=True the overlay will remain loaded when the program exits, otherwise it will be unloaded before exiting. *This should generally not be called directly from user code. """ gpio_pin = gpio_pin.lower() if not gpio_pin: print "*unknown pinmux pin: %s" % gpio_pin return mux_file_glob = glob.glob('%s/*%s*/state' % (OCP_PATH, gpio_pin)) if len(mux_file_glob) == 0: try: cape_manager.load('PyBBIO-%s' % gpio_pin, not preserve_mode_on_exit) bbio.delay(250) # Give driver time to load except IOError: print "*Could not load %s overlay, resource busy" % gpio_pin return mux_file_glob = glob.glob('%s/*%s*/state' % (OCP_PATH, gpio_pin)) if len(mux_file_glob) == 0: print "*Could not load overlay for pin: %s" % gpio_pin return mux_file = mux_file_glob[0] # Convert mode to ocp mux name: mode = 'mode_%s' % format(mode, '#010b') # Possible modes: # mode_0b00100111 # rx active | pull down # mode_0b00110111 # rx active | pull up # mode_0b00101111 # rx active | no pull # mode_0b00000111 # pull down # mode_0b00010111 # pull up # mode_0b00001111 # no pull # See /lib/firmware/PyBBIO-src/*.dts for more info for i in range(3): # If the pin's overlay was just loaded there may not have been enough # time for the driver to get fully initialized, which causes an IOError # when trying to write the mode; try up to 3 times to avoid this: try: with open(mux_file, 'wb') as f: f.write(mode) return except IOError: # Wait a bit between attempts bbio.delay(10) # If we get here then it didn't work 3 times in a row; raise the IOError: raise
def getHumidity(self): """ Reads and returns the current relative humidity Received value is checked against a CRC and an AssertionError is thrown if it is invalid. """ self.i2c.write(self.I2C_ADDRESS, [self.CMD_RH]) bbio.delay(50) msb, lsb, crc = self.i2c.read(self.I2C_ADDRESS, 3) raw_value = (msb<<8) | lsb assert self.checkCRC(raw_value, crc), "received invalid data" # Should that really throw an error? # Conversion formula from datasheet: return -6.0 + 125.0 * (raw_value/65536.0)
def getTemp(self): """ Reads and returns the current ambient temperature in Celsius Received value is checked against a CRC and an AssertionError is thrown if it is invalid. """ self.i2c.write(self.I2C_ADDRESS, [self.CMD_TEMP]) bbio.delay(50) msb, lsb, crc = self.i2c.read(self.I2C_ADDRESS, 3) raw_value = (msb<<8) | lsb assert self.checkCRC(raw_value, crc), "received invalid data" # Should that really throw an error? # Conversion formula from datasheet: return -46.85 + 175.72 * (raw_value/65536.0)
def __init__(self, eqep_num): assert 0 <= eqep_num <= 3 , "eqep_num must be between 0 and 3" if eqep_num == 3: overlay = "PyBBIO-eqep2b" eqep_num = 2 else: overlay = 'PyBBIO-eqep%i' % eqep_num pwmss_overlay = "PyBBIO-epwmss%i" % eqep_num cape_manager.load(pwmss_overlay, auto_unload=False) delay(10) cape_manager.load(overlay, auto_unload=False) delay(250) # Give driver time to load self.base_dir = self._eqep_dirs[eqep_num] self.enable() addToCleanup(self.disable)
def getHumidity(self): """ Reads and returns the current relative humidity Received value is checked against a CRC and an AssertionError is thrown if it is invalid. """ self.i2c.write(self.I2C_ADDRESS, [self.CMD_RH]) bbio.delay(50) msb, lsb, crc = self.i2c.read(self.I2C_ADDRESS, 3) raw_value = (msb << 8) | lsb assert self.checkCRC(raw_value, crc), "received invalid data" # Should that really throw an error? # Conversion formula from datasheet: return -6.0 + 125.0 * (raw_value / 65536.0)
def getTemp(self, return_b5_coefficient=False): """ Returns current temperature in Celsius. """ self.writeRegister(self.REG_CTRL_MEAS, self.CMD_TEMPERATURE) bbio.delay(self.TEMP_CONVERSION_TIME) msb, lsb = self.readRegister(self.REG_OUT_MSB, 2) val = (msb << 8) | lsb # Conversions are straight out of the datasheet x1 = (val - self.cal_AC6) * self.cal_AC5 / 32768 x2 = self.cal_MC * 2048 / (x1 + self.cal_MD) b5 = x1 + x2 temp_counts = (b5 + 8) / 16 temp = temp_counts * 0.1 # 0.1 degree C resolution if return_b5_coefficient: return (temp, b5) return temp
def __init__(self, eqep_num): assert 0 <= eqep_num <= 3, "eqep_num must be between 0 and 3" if eqep_num == 3: overlay = "PyBBIO-eqep2b" eqep_num = 2 else: overlay = 'PyBBIO-eqep%i' % eqep_num pwmss_overlay = "PyBBIO-epwmss%i" % eqep_num cape_manager.load(pwmss_overlay, auto_unload=False) delay(10) cape_manager.load(overlay, auto_unload=False) delay(250) # Give driver time to load self.base_dir = self._eqep_dirs[eqep_num] self.enable() addToCleanup(self.disable)
def uartInit(uart): """ Enables the given uart by loading its dto. """ port, overlay = UART[uart] if os.path.exists(port): return True # Unloading serial port overlays crashes the current cape manager, # disable until it gets fixed: cape_manager.load(overlay, auto_unload=False) if os.path.exists(port): return True for i in range(5): # Give it some time to load bbio.delay(100) if os.path.exists(port): return True # If we make it here it's pretty safe to say the overlay couldn't load return False
def getTemp(self): """ Reads and returns the current ambient temperature in Celsius Received value is checked against a CRC and an AssertionError is thrown if it is invalid. """ self.i2c.write(self.I2C_ADDRESS, [self.CMD_TEMP]) bbio.delay(50) msb, lsb, crc = self.i2c.read(self.I2C_ADDRESS, 3) raw_value = (msb << 8) | lsb assert self.checkCRC(raw_value, crc), "received invalid data" # Should that really throw an error? # Conversion formula from datasheet: return -46.85 + 175.72 * (raw_value / 65536.0)
def getTemperature(self): Thermistor.mutex.acquire() # Get the mutex try: io.delay(1) adc_val = 0 for i in range(100): # Average 100 times adc_val += io.analogRead(self.pin) # Read the value io.delay(1) # Make sure it has settled adc_val /= 100 finally: Thermistor.mutex.release() # Release the mutex voltage = io.inVolts(adc_val) # Convert to voltage res_val = self.voltage_to_resistance(voltage) # Convert to resistance temperature = self.resistance_to_degrees(res_val) # Convert to degrees if self.debug > 1: print self.name+": ADC: %i - voltage: %f"%(adc_val, voltage), print " - thermistor res: %f - Temperature: %f deg."%(res_val, temperature) return temperature
def i2cInit(bus): ''' Initializes reqd I2C bus i2c0 (/dev/i2c-0) and i2c2 (/dev/i2c-1) are already initialized overlay to be applied for i2c1 (/dev/i2c-2) ''' dev_file, overlay = I2C[bus] if os.path.exists(dev_file): return True cape_manager.load(overlay, auto_unload=False) if os.path.exists(dev_file): return True for i in range(5): bbio.delay(5) if os.path.exists(dev_file): return True return False
def i2cInit(bus): """ Initializes reqd I2C bus i2c0 (/dev/i2c-0) and i2c2 (/dev/i2c-1) are already initialized overlay to be applied for i2c1 (/dev/i2c-2) """ dev_file, overlay = I2C[bus] if os.path.exists(dev_file): return True cape_manager.load(overlay, auto_unload=False) if os.path.exists(dev_file): return True for i in range(5): bbio.delay(5) if os.path.exists(dev_file): return True return False
def start(self): """ Starts the process to follow the line if the status is on, stops the wheels otherwise. """ while True: if self.__start_stop_button.is_activated(): if not self.__switch_on: self.__switch_on = True self.__is_on = not self.__is_on io.toggle(cst.STATUS_LED) else: self.__switch_on = False self.__speed = self.__potentiometer.get_speed() if self.__is_on: self.__analyse_ir() else: self.__set_wanted_speeds(0, 0) right_speed, left_speed = self.__get_corrected_speeds() self.__set_speeds(right_speed, left_speed) io.delay(cst.PAUSE_MS)
def pinMux_dtOverlays(gpio_pin, mode, preserve_mode_on_exit=False): gpio_pin = gpio_pin.lower() mux_file_glob = glob.glob('%s/*%s*/state' % (OCP_PATH, gpio_pin)) if len(mux_file_glob) == 0: try: cape_manager.load('PyBBIO-%s' % gpio_pin, not preserve_mode_on_exit) bbio.delay(250) # Give driver time to load mux_file_glob = glob.glob('%s/*%s*/state' % (OCP_PATH, gpio_pin)) except IOError: print("*Could not load %s overlay, resource busy" % gpio_pin) return False if len(mux_file_glob) == 0: print("*Could not load overlay for pin: %s" % gpio_pin) return False mux_file = mux_file_glob[0] # Convert mode to ocp mux name: mode = 'mode_%s' % format(mode, '#010b') # Possible modes: # mode_0b00100111 # rx active | pull down # mode_0b00110111 # rx active | pull up # mode_0b00101111 # rx active | no pull # mode_0b00000111 # pull down # mode_0b00010111 # pull up # mode_0b00001111 # no pull # See /lib/firmware/PyBBIO-src/*.dts for more info for i in range(3): # If the pin's overlay was just loaded there may not have been enough # time for the driver to get fully initialized, which causes an IOError # when trying to write the mode; try up to 3 times to avoid this: try: with open(mux_file, 'wb') as f: f.write(mode) return True except IOError: # Wait a bit between attempts bbio.delay(10) # If we get here then it didn't work 3 times in a row; raise the IOError: raise
def pinMux_dtOverlays(gpio_pin, mode, preserve_mode_on_exit=False): gpio_pin = gpio_pin.lower() mux_file_glob = glob.glob('%s/*%s*/state' % (OCP_PATH, gpio_pin)) if len(mux_file_glob) == 0: try: cape_manager.load('PyBBIO-%s' % gpio_pin, not preserve_mode_on_exit) bbio.delay(250) # Give driver time to load mux_file_glob = glob.glob('%s/*%s*/state' % (OCP_PATH, gpio_pin)) except IOError: print "*Could not load %s overlay, resource busy" % gpio_pin return False if len(mux_file_glob) == 0: print "*Could not load overlay for pin: %s" % gpio_pin return False mux_file = mux_file_glob[0] # Convert mode to ocp mux name: mode = 'mode_%s' % format(mode, '#010b') # Possible modes: # mode_0b00100111 # rx active | pull down # mode_0b00110111 # rx active | pull up # mode_0b00101111 # rx active | no pull # mode_0b00000111 # pull down # mode_0b00010111 # pull up # mode_0b00001111 # no pull # See /lib/firmware/PyBBIO-src/*.dts for more info for i in range(3): # If the pin's overlay was just loaded there may not have been enough # time for the driver to get fully initialized, which causes an IOError # when trying to write the mode; try up to 3 times to avoid this: try: with open(mux_file, 'wb') as f: f.write(mode) return True except IOError: # Wait a bit between attempts bbio.delay(10) # If we get here then it didn't work 3 times in a row; raise the IOError: raise
def __init__(self, eqep_num): ''' RotaryEncoder(eqep_num) Creates an instance of the class RotaryEncoder. eqep_num determines which eQEP pins are set up. eqep_num can be: EQEP0, EQEP1, EQEP2 or EQEP2b based on which pins \ the rotary encoder is connected to. ''' assert 0 <= eqep_num <= 3 , "eqep_num must be between 0 and 3" if eqep_num == 3: overlay = "PyBBIO-eqep2b" eqep_num = 2 else: overlay = 'PyBBIO-eqep%i' % eqep_num pwmss_overlay = "PyBBIO-epwmss%i" % eqep_num cape_manager.load(pwmss_overlay, auto_unload=False) delay(10) cape_manager.load(overlay, auto_unload=False) delay(250) # Give driver time to load self.base_dir = self._eqep_dirs[eqep_num] self.enable() addToCleanup(self.disable)
def __init__(self, eqep_num): ''' RotaryEncoder(eqep_num) Creates an instance of the class RotaryEncoder. eqep_num determines which eQEP pins are set up. eqep_num can be: EQEP0, EQEP1, EQEP2 or EQEP2b based on which pins \ the rotary encoder is connected to. ''' assert 0 <= eqep_num <= 3, "eqep_num must be between 0 and 3" if eqep_num == 3: overlay = "PyBBIO-eqep2b" eqep_num = 2 else: overlay = 'PyBBIO-eqep%i' % eqep_num pwmss_overlay = "PyBBIO-epwmss%i" % eqep_num cape_manager.load(pwmss_overlay, auto_unload=False) delay(10) cape_manager.load(overlay, auto_unload=False) delay(250) # Give driver time to load self.base_dir = self._eqep_dirs[eqep_num] self.enable() addToCleanup(self.disable)
def pinMux(gpio_pin, mode, preserve_mode_on_exit=False): """ Uses custom device tree overlays to set pin modes. If preserve_mode_on_exit=True the overlay will remain loaded when the program exits, otherwise it will be unloaded before exiting. *This should generally not be called directly from user code. """ gpio_pin = gpio_pin.lower() if not gpio_pin: print "*unknown pinmux pin: %s" % gpio_pin return mux_file_glob = glob.glob('%s/*%s*/state' % (OCP_PATH, gpio_pin)) if len(mux_file_glob) == 0: try: cape_manager.load('PyBBIO-%s' % gpio_pin, not preserve_mode_on_exit) bbio.delay(250) # Give driver time to load except IOError: print "*Could not load %s overlay, resource busy" % gpio_pin return mux_file_glob = glob.glob('%s/*%s*/state' % (OCP_PATH, gpio_pin)) if len(mux_file_glob) == 0: print "*Could not load overlay for pin: %s" % gpio_pin return mux_file = mux_file_glob[0] # Convert mode to ocp mux name: mode = 'mode_%s' % format(mode, '#010b') # Possible modes: # mode_0b00100111 # rx active | pull down # mode_0b00110111 # rx active | pull up # mode_0b00101111 # rx active | no pull # mode_0b00000111 # pull down # mode_0b00010111 # pull up # mode_0b00001111 # no pull # See /lib/firmware/PyBBIO-src/*.dts for more info with open(mux_file, 'wb') as f: f.write(mode)
def run(self): while True: if len(self.epoll_callbacks) == 0: if self.first_interrupt_registered: # At least one interrupt gas been registered in the past # and now all have been unregistered; stop thread: break else: # If we're here then the thread was just created and the # first interrupt hasn't been registered yet; wait for it: bbio.delay(100) events = self.epoll.poll() for fileno, event in events: if fileno in self.epoll_callbacks: if self.first_interrupt: self.first_interrupt = False elapsed = time.time() - self.creation_time if elapsed <= self.CREATION_DEBOUNCE_MS: # Ignore if interrupt fired within CREATION_DEBOUNCE_MS since # the creation of this EpollListener - on 3.8 kernels there is # always one false interrupt when first created, this avoids # that continue self.epoll_callbacks[fileno]()
def run(self): while True: if len(self.epoll_callbacks) == 0: if self.first_interrupt_registered: # At least one interrupt gas been registered in the past # and now all have been unregistered; stop thread: break else: # If we're here then the thread was just created and the # first interrupt hasn't been registered yet; wait for it: bbio.delay(100) events = self.epoll.poll() for fileno, event in events: if fileno in self.epoll_callbacks: if self.first_interrupt: self.first_interrupt = False elapsed = time.time()-self.creation_time if elapsed <= self.CREATION_DEBOUNCE_MS: # Ignore if interrupt fired within CREATION_DEBOUNCE_MS since # the creation of this EpollListener - on 3.8 kernels there is # always one false interrupt when first created, this avoids # that continue self.epoll_callbacks[fileno]()
def spi_init(spi_num): overlay = 'BB-SPIDEV%i' % spi_num assert os.path.exists('/lib/firmware/%s-00A0.dtbo' % overlay), \ "SPI driver not present" cape_manager.load(overlay, auto_unload=False) bbio.delay(250) # Give driver time to load
def clear(self): """ Clears all characters in the dispay's RAM. """ self.writeCommand(self.COMMAND_CLEAR) bbio.delay(2)
def home(self): """ Resets the scroll and puts the cursor at 0,0. """ self.writeCommand(self.COMMAND_HOME) bbio.delay(2)
def __init__(self, i2c_bus, addr=AMG88_ADDR): self.i2c_bus = i2c_bus self.addr = addr self.reset() bbio.delay(100)