def get_encoder(self): """Get current encoder relative position Returns: Position: The actual encoder value. """ return self.send_command(mkcmd(52, ''), 'H')[0]
def get_info(self): """Read device configuration Returns: [hardware version, firmware version, device ID number] """ return self.send_command(mkcmd(39, ''), 'BBI')
def read_adc(self): """Read data from ADC and return the raw value Returns: Raw ADC value """ return self.send_command(mkcmd(1, ''), 'h')[0]
def start(self): """ Start all available experiments """ for s in self.experiments: if s.__class__ is DAQBurst: self.__create_burst(s.period) elif s.__class__ is DAQStream: self.__create_stream(s.number, s.period) else: # External self.__create_external(s.number, s.edge) self.__setup_channel(s.number, s.npoints, s.continuous) self.__conf_channel(s.number, s.mode, s.pinput, s.ninput, s.gain, s.nsamples) if (s.get_mode() == ANALOG_OUTPUT): pr_data, pr_offset = s.get_preload_data() for i in range(len(pr_offset)): self.__load_signal(pr_offset[i], pr_data[i]) break self.send_command(mkcmd(64, ''), '') if not self.__running: threading.Thread.start(self) self.__running = True self.__measuring = True
def spi_write(self, value, word=False): """Bit-bang SPI transfer (send+receive) a byte or a word Args: value: Data to send (byte/word to transmit) word: send a 2-byte word, instead of a byte Raises: ValueError: Value out of range """ if not 0 <= value <= 65535: raise ValueError("value out of range") if word: ret = self.send_command(mkcmd(29, 'H', value), 'H')[0] else: ret = self.send_command(mkcmd(29, 'B', value), 'B')[0] return ret
def enable_crc(self, on): """Enable/Disable the cyclic redundancy check Args: on: Enable CRC Raises: ValueError: on value out of range """ if on not in [0, 1]: raise ValueError("on value out of range") return self.send_command(mkcmd(55, 'B', on), 'B')[0]
def init_encoder(self, resolution): """Start Encoder function Args: resolution: Maximum number of ticks per round [0:65535] Raises: ValueError: resolution value out of range """ if not 0 <= resolution <= 65535: raise ValueError("resolution value out of range") return self.send_command(mkcmd(50, 'B', resolution), 'B')[0]
def get_counter(self, reset): """Get the counter value Args: reset: reset the counter after perform reading (>0: reset) Raises: ValueError: reset value out of range """ if not 0 <= reset <= 255: raise ValueError("reset value out of range") return self.send_command(mkcmd(42, 'B', reset), 'H')[0]
def init_capture(self, period): """Start Capture mode around a given period Args: period: estimated period of the wave (in microseconds) Raises: ValueError: period out of range """ if not 0 <= period <= 65535: raise ValueError("period out of range") return self.send_command(mkcmd(14, 'H', period), 'H')[0]
def spi_config(self, cpol, cpha): """Bit-Bang SPI configure (clock properties) Args: cpol: Clock polarity (clock pin state when inactive) cpha: Clock phase (leading 0, or trailing 1 edges read) Raises: ValueError: Invalid spisw_config values """ if not 0 <= cpol <= 1 or not 0 <= cpha <= 1: raise ValueError('Invalid spisw_config values') return self.send_command(mkcmd(26, 'BB', cpol, cpha), 'BB')
def read_analog(self): """Read data from ADC in volts Returns: Voltage value """ value = self.send_command(mkcmd(1, ''), 'h')[0] # Raw value to voltage-> index = self.gain + 1 if self.__hw_ver == 'm' else self.pinput value *= self.gains[index] value = -value/1e5 if self.__hw_ver == 'm' else value/1e4 value = (value + self.offsets[index])/1e3 return value
def set_led(self, color): """Choose LED status. LED switch on (green, red or orange) or switch off. Args: color: LED color (0:off, 1:green, 2:red, 3:orange) Raises: ValueError: Invalid color number """ if not 0 <= color <= 3: raise ValueError('Invalid color number') return self.send_command(mkcmd(18, 'B', color), 'B')[0]
def set_id(self, id): """ Identify openDAQ device Args: id: id number of the device [000:999] Raises: ValueError: id out of range """ if not 0 <= id < 1000: raise ValueError('id out of range') return self.send_command(mkcmd(39, 'I', id), 'bbI')
def set_port_dir(self, output): """Configure all PIOs directions. Set the direction of all D1-D6 terminals. Args: output: Port directions byte (bits: 0:input, 1:output) Raises: ValueError: output value out of range """ if not 0 <= output < 64: raise ValueError("output value out of range") return self.send_command(mkcmd(9, 'B', output), 'B')[0]
def read_analog(self): """Read data from ADC in volts Returns: Voltage value """ value = self.send_command(mkcmd(1, ''), 'h')[0] # Raw value to voltage-> index = self.gain + 1 if self.__hw_ver == 'm' else self.pinput value *= self.gains[index] value = -value / 1e5 if self.__hw_ver == 'm' else value / 1e4 value = (value + self.offsets[index]) / 1e3 return value
def init_counter(self, edge): """Initialize the edge Counter Configure which edge increments the count: Low-to-High (1) or High-to-Low (0). Args: edge: high-to-low (0) or low-to-high (1) Raises: ValueError: edge value out of range """ if edge not in [0, 1]: raise ValueError("edge value out of range") return self.send_command(mkcmd(41, 'B', edge), 'B')[0]
def __destroy_channel(self, number): """ Command firmware to clear a Datachannel structure Args: number: Number of DataChannel structure to clear [0:4] (0: reset all DataChannels) Raises: ValueError: Invalid number """ if not 1 <= number <= 4: raise ValueError('Invalid number') return self.send_command(mkcmd(57, 'B', number), 'B')[0]
def __create_burst(self, period): """ Send a command to the firmware to create Burst experiment Args: period: Period of the burst experiment (microseconds) [100:65535] Raises: ValueError: Invalid period """ if not 100 <= period <= 65535: raise ValueError('Invalid period') return self.send_command(mkcmd(21, 'H', period), 'H')
def set_port(self, value): """Write all PIO values Set the value of all D1-D6 terminals. Args: value: Port output byte (bits: 0:low, 1:high) Returns: Real value of the port. Output pin as fixed in value\ input pin refresh with current state. Raises: ValueError: port output byte out of range """ if not 0 <= value < 64: raise ValueError("port output byte out of range") return self.send_command(mkcmd(7, 'B', value), 'B')[0]
def conf_adc(self, pinput=8, ninput=0, gain=0, nsamples=20): """ Configure the analog-to-digital converter. Get the parameters for configure the analog-to-digital converter. Args: pinput: Positive input [1:8] ninput: Negative input openDAQ[M]= [0, 5, 6, 7, 8, 25] openDAQ[S]= [0,1:8] (must be 0 or pinput-1) gain: Analog gain openDAQ[M]= [0:4] (x1/3, x1, x2, x10, x100) openDAQ[S]= [0:7] (x1,x2,x4,x5,x8,x10,x16,x20) nsamples: Number of samples per data point [0-255) Raises: ValueError: Values out of range """ if not 1 <= pinput <= 8: raise ValueError("positive input out of range") if self.__hw_ver == 'm' and ninput not in [0, 5, 6, 7, 8, 25]: raise ValueError("negative input out of range") if self.__hw_ver == 's' and ninput != 0 and ( pinput % 2 == 0 and ninput != pinput - 1 or pinput % 2 != 0 and ninput != pinput + 1): raise ValueError("negative input out of range") if self.__hw_ver == 'm' and not 0 <= gain <= 4: raise ValueError("gain out of range") if self.__hw_ver == 's' and not 0 <= gain <= 7: raise ValueError("gain out of range") if not 0 <= nsamples < 255: raise ValueError("samples number out of range") self.gain = gain if self.__hw_ver == 's' and ninput != 0: self.pinput = (pinput - 1)/2 + 9 else: self.pinput = pinput return self.send_command(mkcmd(2, 'BBBB', pinput, ninput, gain, nsamples), 'hBBBB')
def conf_adc(self, pinput=8, ninput=0, gain=0, nsamples=20): """ Configure the analog-to-digital converter. Get the parameters for configure the analog-to-digital converter. Args: pinput: Positive input [1:8] ninput: Negative input openDAQ[M]= [0, 5, 6, 7, 8, 25] openDAQ[S]= [0,1:8] (must be 0 or pinput-1) gain: Analog gain openDAQ[M]= [0:4] (x1/3, x1, x2, x10, x100) openDAQ[S]= [0:7] (x1,x2,x4,x5,x8,x10,x16,x20) nsamples: Number of samples per data point [0-255) Raises: ValueError: Values out of range """ if not 1 <= pinput <= 8: raise ValueError("positive input out of range") if self.__hw_ver == 'm' and ninput not in [0, 5, 6, 7, 8, 25]: raise ValueError("negative input out of range") if self.__hw_ver == 's' and ninput != 0 and ( pinput % 2 == 0 and ninput != pinput - 1 or pinput % 2 != 0 and ninput != pinput + 1): raise ValueError("negative input out of range") if self.__hw_ver == 'm' and not 0 <= gain <= 4: raise ValueError("gain out of range") if self.__hw_ver == 's' and not 0 <= gain <= 7: raise ValueError("gain out of range") if not 0 <= nsamples < 255: raise ValueError("samples number out of range") self.gain = gain if self.__hw_ver == 's' and ninput != 0: self.pinput = (pinput - 1) / 2 + 9 else: self.pinput = pinput return self.send_command( mkcmd(2, 'BBBB', pinput, ninput, gain, nsamples), 'hBBBB')
def set_dac(self, raw): """Set DAC output (binary value) Set the raw value into DAC without data conversion. Args: raw: RAW binary ADC data value. Raises: ValueError: DAC voltage out of range """ value = int(round(raw)) if (self. __hw_ver == 'm' and not 0 <= value < 16384) or ( self. __hw_ver == 's' and not 0 <= value < 65536): raise ValueError('DAC value out of range') return self.send_command(mkcmd(24, 'H', value), 'h')[0]
def init_pwm(self, duty, period): """Start PWM output with a given period and duty cycle Args: duty: High time of the signal [0:1023](0 always low,\ 1023 always high) period: Period of the signal (microseconds) [0:65535] Raises: ValueError: Values out of range """ if not 0 <= duty < 1024: raise ValueError("duty value out of range") if not 0 <= period <= 65535: raise ValueError("period value out of range") return self.send_command(mkcmd(10, 'HH', duty, period), 'HH')
def set_dac(self, raw): """Set DAC output (binary value) Set the raw value into DAC without data conversion. Args: raw: RAW binary ADC data value. Raises: ValueError: DAC voltage out of range """ value = int(round(raw)) if (self.__hw_ver == 'm' and not 0 <= value < 16384) or (self.__hw_ver == 's' and not 0 <= value < 65536): raise ValueError('DAC value out of range') return self.send_command(mkcmd(24, 'H', value), 'h')[0]
def spi_setup(self, nbytes, sck=1, mosi=2, miso=3): """Bit-Bang SPI setup (PIO numbers to use) Args: nbytes: Number of bytes sck: Clock pin mosi: MOSI pin (master out / slave in) miso: MISO pin (master in / slave out) Raises: ValueError: Invalid values """ if not 0 <= nbytes <= 3: raise ValueError('Invalid number of bytes') if not 1 <= sck <= 6 or not 1 <= mosi <= 6 or not 1 <= miso <= 6: raise ValueError('Invalid spisw_setup values') return self.send_command(mkcmd(28, 'BBB', sck, mosi, miso), 'BBB')
def __create_stream(self, number, period): """ Send a command to the firmware to create Stream experiment Args: number: Assign a DataChannel number for this experiment [1:4] period: Period of the stream experiment (milliseconds) [1:65536] Raises: ValueError: Invalid values """ if not 1 <= number <= 4: raise ValueError('Invalid number') if not 1 <= period <= 65535: raise ValueError('Invalid period') return self.send_command(mkcmd(19, 'BH', number, period), 'BH')
def __create_external(self, number, edge): """ Send a command to the firmware to create External experiment Args: number: Assign a DataChannel number for this experiment [1:4] edge: New data on rising (1) or falling (0) edges [0:1] Raises: ValueError: Invalid values """ if not 1 <= number <= 4: raise ValueError('Invalid number') if edge not in [0, 1]: raise ValueError('Invalid edge') return self.send_command(mkcmd(20, 'BB', number, edge), 'BB')
def stop(self): """ Stop all running experiments and exit threads. Experiments will no longer be available. Call just before quitting program! Clears experiment list """ self.__measuring = False self.__running = False self.__stopping = True while True: try: self.send_command(mkcmd(80, ''), '') self.clear_experiments() break except CRCError: time.sleep(0.2) self.flush()
def halt(self, clear=False): """ Stop running experiments but keep threads active to start new experiments Args: clear - Clear experiment list """ self.__measuring = False while True: try: self.send_command(mkcmd(80, ''), '') time.sleep(1) break except CRCError: time.sleep(0.2) self.flush() if clear: self.clear_experiments()
def set_pio_dir(self, number, output): """Configure PIO direction Set the direction of a specific PIO terminal (D1-D6). Args: number: PIO number [1:6] output: PIO direction (0 input, 1 output) Raises: ValueError: Invalid PIO number """ if not 1 <= number <= 6: raise ValueError('Invalid PIO number') if output not in [0, 1]: raise ValueError("PIO direction out of range") return self.send_command(mkcmd(5, 'BB', number, int(bool(output))), 'BB')
def set_pio(self, number, value): """Write PIO output value Set the value of the PIO terminal (0: low, 1: high). Args: number: PIO number (1-6) value: digital value (0: low, 1: high) Raises: ValueError: Invalid PIO number """ if not 1 <= number <= 6: raise ValueError('Invalid PIO number') if value not in [0, 1]: raise ValueError("digital value out of range") return self.send_command(mkcmd(3, 'BB', number, int(bool(value))), 'BB')
def get_capture(self, mode): """Get Capture reading for the period length Low cycle, High cycle or Full period. Args: mode: Period length 0: Low cycle 1: High cycle 2: Full period Returns: mode Period: The period length in microseconds Raises: ValueError: mode value out of range """ if mode not in [0, 1, 2]: raise ValueError("mode value out of range") return self.send_command(mkcmd(16, 'B', mode), 'BH')
def __load_signal(self, pr_of, pr_data): """ Load an array of values in volts to preload DAC output Raises: LengthError: Invalid dada length """ if not 1 <= len(pr_data) <= 400: raise LengthError('Invalid data length') values = [] self.set_analog(pr_data[0]) for volts in pr_data: raw = self.__volts_to_raw(volts) ''' if self.__hw_ver == "s": raw *= 2 ''' values.append(raw) return self.send_command(mkcmd(23, 'h%dH' % len(values), pr_of, *values), 'Bh')
def __load_signal(self, pr_of, pr_data): """ Load an array of values in volts to preload DAC output Raises: LengthError: Invalid dada length """ if not 1 <= len(pr_data) <= 400: raise LengthError('Invalid data length') values = [] self.set_analog(pr_data[0]) for volts in pr_data: raw = self.__volts_to_raw(volts) ''' if self.__hw_ver == "s": raw *= 2 ''' values.append(raw) return self.send_command( mkcmd(23, 'h%dH' % len(values), pr_of, *values), 'Bh')