Source code for lantz.drivers.tektronix.tds1012

# -*- coding: utf-8 -*-
"""
    lantz.drivers.tektronix.tds1012
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Implements the drivers to control an oscilloscope.

    :copyright: 2015 by Lantz Authors, see AUTHORS for more details.
    :license: BSD, see LICENSE for more details.
    
    Source: Tektronix Manual
"""

import numpy as np

from lantz.feat import Feat
from lantz.action import Action
from lantz.messagebased import MessageBasedDriver
from lantz.errors import InvalidCommand


[docs]class TDS1012(MessageBasedDriver): """Tektronix TDS1012 100MHz 2 Channel Digital Storage Oscilloscope """ MANUFACTURER_ID = '0x699' @Action() def initiate(self): """ Initiates the acquisition in the osciloscope. """ self.send(':ACQ:STATE ON') @Action() def idn(self): """ Identify the Osciloscope """ return self.query('*IDN?') @Action() def autoset(self): """ Adjust the vertical, horizontal and trigger controls to display a stable waveform. """ self.send('AUTOS EXEC') @Action() def autocal(self): """ Autocalibration of osciloscope. It may take several minutes to complete """ return self.send('*CAL') @Feat(limits=(1,2)) def datasource(self): """ Retrieves the data source from which data is going to be taken. TDS1012 has 2 channels """ return self.query('DAT:SOU?') @datasource.setter def datasource(self,value): """ Sets the data source for the acquisition of data. """ self.send('DAT:SOU CH{}'.format(value)) @Action() def acquire_parameters(self): """ Acquire parameters of the osciloscope. It is intended for adjusting the values obtained in acquire_curve """ values = 'XZE?;XIN?;PT_OF?;YZE?;YMU?;YOF?;' answer = self.query('WFMP:{}'.format(values)) parameters = {} for v, j in zip(values.split('?;'),answer.split(';')): parameters[v] = float(j) return parameters @Action() def data_setup(self): """ Sets the way data is going to be encoded for sending. """ self.send('DAT:ENC ASCI;WID 2') #ASCII is the least efficient way, but # couldn't make the binary mode to work @Action() def acquire_curve(self,start=1,stop=2500): """ Gets data from the oscilloscope. It accepts setting the start and stop points of the acquisition (by default the entire range). """ parameters = self.acquire_parameters() self.data_setup() self.send('DAT:STAR {}'.format(start)) self.send('DAT:STOP {}'.format(stop)) data = self.query('CURV?') data = data.split(',') data = np.array(list(map(float,data))) ydata = (data - parameters['YOF']) * parameters['YMU']\ + parameters['YZE'] xdata = np.arange(len(data))*parameters['XIN'] + parameters['XZE'] return list(xdata), list(ydata) @Action() def forcetrigger(self): """ Creates a trigger event. """ self.send('TRIG:FORC') return @Action() def triggerlevel(self): """ Sets the trigger level to 50% of the minimum and maximum values of the signal. """ self.send('TRIG:MAI SETL') @Feat(values={'AUTO', 'NORMAL'}) def trigger(self): """ Retrieves trigger state. """ return self.query('TRIG:MAIN:MODE?') @trigger.setter def trigger(self,state): """ Sets the trigger state. """ self.send('TRIG:MAI:MOD {}'.format(state)) return @Feat() def horizontal_division(self): """ Horizontal time base division. """ return float(self.query('HOR:MAI:SCA?')) @horizontal_division.setter def horizontal_division(self,value): """ Sets the horizontal time base division. """ self.send('HOR:MAI:SCA {}'.format(value)) return @Feat(values={0, 4, 16, 64, 128}) def number_averages(self): """ Number of averages """ answer = self.query('ACQ?') answer = answer.split(';') if answer[0] == 'SAMPLE': return 0 elif answer[0] == 'AVERAGE': return int(self.query('ACQ:NUMAV?')) else: raise InvalidCommand @number_averages.setter def number_averages(self,value): """ Sets the number of averages. If 0, the it is a continous sample. """ if value == 0: self.send('ACQ:MOD SAMPLE') else: self.send('ACQ:MOD AVE;NUMAV {}'.format(value)) @Action(values={'FREQ', 'MINI', 'MAXI', 'MEAN'}) def _measure(self, mode): """ Measures the Frequency, Minimum, Maximum or Mean of a signal. """ self.send('MEASU:IMM:TYP {}'.format(mode)) return float(self.query('MEASU:IMM:VAL?'))
[docs] def measure_mean(self): """ Gets the mean of the signal. """ answer = self._measure('MEAN') return answer
[docs] def measure_frequency(self): """ Gets the frequency of the signal. """ answer = self._measure('FREQ') return answer
[docs] def measure_minimum(self): """ Gets the minimum of the signal. """ answer = self._measure('MINI') return answer
[docs] def measure_maximum(self): """ Gets the mean of the signal. """ answer = self._measure('MAXI') return answer
if __name__ == '__main__': import argparse parser = argparse.ArgumentParser(description='Measure using TDS1012 and dump to screen') parser.add_argument('-p', '--port', default='/dev/ttyS0', help='Serial port') parser.add_argument('-v', '--view', action='store_true', default=True, help='View ') parser.add_argument('-c', '--channel', default=1, type=int, help='Channel to use') args = parser.parse_args() osc = TDS1012(args.port) osc.initiate() print('Osciloscope Identification: {}'.format(osc.idn)) print(osc.trigger) osc.forcetrigger() osc.triggerlevel() osc.trigger = "AUTO" print(osc.trigger) params = osc.acquire_parameters() if args.view: import matplotlib.pyplot as plt import numpy as np if args.view: osc.datasource = args.channel x, y = osc.acquire_curve() x = np.array(x) x = x - x.min() y = np.array(y) plt.plot(x, y) plt.show()