class ICAHSensor: ping_dur = 0.00015 # s, same as measured for gpiozero speed_of_sound = 343 # m/s at 101325 Pa, 293 K def __init__(self, trig, echo): self.trig = DigitalOutputDevice(trig) self.echo = DigitalInputDevice(echo) self.hist = [] def get_distance(self): ''' This could be made non-blocking by using a background thread that continually updates the current distance. We should also reject outliers in the distance measurements using the filter() function or similar. ''' del (self.hist[:]) for i in range(10): self.trig.on() sleep(self.ping_dur) self.trig.off() self.echo.wait_for_active() t0 = time() self.echo.wait_for_inactive() dt = time() - t0 dist = dt * ICAHSensor.speed_of_sound / 2 self.hist.append(dist) return sum(self.hist) / len(self.hist)
def setup(): encoder_a = DigitalInputDevice(12) while True: encoder_a.wait_for_active() print('ON!') encoder_a.wait_for_inactive() print('OFF!')
class Bumper(): ''' Bumper Task: reacts to bumper sensors. Parameters: pin: the GPIO pin used as an input label: the label used in logging level: the logging Level activated_callback: a callback function called when the sensor is activated deactivated_callback: a callback function called when the sensor is deactivated Returns: true for 1 second duration after a positive sensor reading. Usage: PIN = 25 LABEL = 'center' LEVEL = Level.INFO _activated_callback = self.activated_callback _deactivated_callback = self.deactivated_callback _bumper = Bumper(PIN, LABEL, LEVEL, _activated_callback, _deactivated_callback) _bumper.enable() value = _bumper.get() ''' def __init__(self, pin, label, level, activated_callback, deactivated_callback): ''' The parameters include two optional callback functions, one when the bumper is activated, another when deactivated. ''' self._log = Logger("bumper:" + label, level) self._log.debug('initialising bumper:{} on pin {}...'.format( label, pin)) self._enabled = False if activated_callback is None: self._log.error("no activated_callback argument provided.") if deactivated_callback is None: self._log.error("no deactivated_callback argument provided.") self._pin = pin self._label = label self._sensor = DigitalInputDevice(pin, bounce_time=BOUNCE_TIME_SEC, pull_up=True) self._activated_callback = activated_callback self._deactivated_callback = deactivated_callback self._sensor.when_activated = self._activated self._sensor.when_deactivated = self._deactivated self._wait_for_inactive = True self._log.info('bumper on pin {} ready.'.format(label, pin)) # .......................................................................... def set_wait_for_inactive(self, state): self._log.info('set wait for inactive for bumper:{} to: {}'.format( self._label, state)) self._wait_for_inactive = state # .......................................................................... def enable(self): self._enabled = True self._log.info('enabled.') # .......................................................................... def disable(self): self._enabled = False self._log.info('disabled.') # .......................................................................... def poll(self): _active = self._sensor.is_active self._log.info('poll {} bumper: {}'.format(self._label, _active)) return _active # .......................................................................... def _activated(self): ''' The default function called when the sensor is activated. ''' self._log.info('>> activated bumper:{} on pin {}...'.format( self._label, self._pin)) if self._enabled: if self._activated_callback != None: self._log.info('calling activated_callback...') # Pause the script until the device is deactivated, or the timeout is reached. # Parameters: timeout (float or None) – Number of seconds to wait before proceeding. # If this is None (the default), then wait indefinitely until the device is inactive. # self._log.info('wait for inactive: bumper:{} on pin {}.'.format(self._label,self._pin)) if self._wait_for_inactive: self._sensor.wait_for_inactive( timeout=ACTIVATE_TIMEOUT_SEC) # self._sensor.wait_for_inactive(timeout=None) self._activated_callback() else: self._log.warning('activated_callback is None!') else: self._log.warning( '[DISABLED] activated bumper:{} on pin {}...'.format( self._label, self._pin)) # .......................................................................... def _deactivated(self): ''' The default function called when the sensor is deactivated. ''' self._log.debug('>> deactivated bumper:{} on pin {}...'.format( self._label, self._pin)) if self._enabled: if self._deactivated_callback != None: self._log.debug('calling deactivated_callback...') # Pause the script until the device is activated, or the timeout is reached. # Parameters: timeout (float or None) – Number of seconds to wait before proceeding. # If this is None (the default), then wait indefinitely until the device is active. # self._log.info('wait for active: bumper:{} on pin {}.'.format(self._label,self._pin)) self._sensor.wait_for_active(timeout=DEACTIVATE_TIMEOUT_SEC) # self._sensor.wait_for_active(timeout=None) self._deactivated_callback() else: self._log.warning('deactivated_callback is None!') else: self._log.warning( '[DISABLED] deactivated bumper:{} on pin {}...'.format( self._label, self._pin)) # .......................................................................... def close(self): self._log.info('closed.')
class ADCBoard: def __init__(self): self.adc = spidev.SpiDev() self.pin_reset = DigitalOutputDevice(18, active_high=False) self.pin_drdy = DigitalInputDevice(17) self.pin_cs = DigitalOutputDevice(22, active_high=False) self.exit_event = Event() def _pause(self, delay_ms: int): self.exit_event.wait(delay_ms / 1000) def reset(self): self.pin_reset.off() self._pause(200) self.pin_reset.on() self._pause(200) self.pin_reset.off() def command(self, cmd): self.pin_cs.on() # cs 0 self.adc.writebytes([cmd]) self.pin_cs.off() # cs 1 def write_reg(self, reg, data): self.pin_cs.on() # cs 0 self.adc.writebytes([CMD['CMD_WREG'] | reg, 0x00, data]) self.pin_cs.off() # cs 1 def read_reg(self, reg): self.pin_cs.on() # cs 0 self.adc.writebytes([CMD['CMD_RREG'] | reg, 0x00]) response = self.adc.readbytes(1) self.pin_cs.off() # cs 1 return response def wait_for_drdy(self, timeout_ms: int = 1000): self.pin_drdy.wait_for_inactive(timeout_ms) if self.pin_drdy.is_active: raise TimeoutError() def config(self, gain, drate): self.wait_for_drdy() buf = [0, 0, 0, 0, 0, 0, 0, 0] buf[0] = (0 << 3) | (1 << 2) | (0 << 1) buf[1] = 0x08 buf[2] = (0 << 5) | (0 << 3) | (gain << 0) buf[3] = drate self.pin_cs.on() # cs 0 self.adc.writebytes([CMD['CMD_WREG'] | 0, 0x03]) self.adc.writebytes(buf) self.pin_cs.off() # cs 1 self._pause(1) def get_chip_id(self) -> int: self.wait_for_drdy() id = self.read_reg(REG_E['REG_STATUS']) return id[0] >> 4 def set_channel(self, ch: int): self.write_reg(REG_E['REG_MUX'], (ch << 4) | (1 << 3)) def init(self) -> int: """ Initializes the device and returns chip-id :return: """ self.adc.open(0, 0) self.adc.max_speed_hz = 20000 self.adc.mode = 0b01 self.reset() chip_id = self.get_chip_id() print(f'Chip-id: {chip_id}') self.config(ADS1256_GAIN_E['ADS1256_GAIN_1'], ADS1256_DRATE_E['ADS1256_30000SPS']) return chip_id def read_adc(self, ch): self.set_channel(ch) self.command(CMD['CMD_SYNC']) self.command(CMD['CMD_WAKEUP']) self.wait_for_drdy() self.pin_cs.on() # cs 0 self.adc.writebytes([CMD['CMD_RDATA']]) buf = self.adc.readbytes(3) self.pin_cs.off() # cs 0 read = (buf[0] << 16) & 0xff0000 read |= (buf[1] << 8) & 0xff00 read |= (buf[2]) & 0xff if read & 0x800000: read &= 0xF000000 return read