def test_data_scaling(self): print "Testing setting various scale facotrs and reading." scale_factor = 0x01 scope = Oscilloscope() assert scope.setup() assert scope.open_handle() assert scope.flash_firmware() assert scope.set_ch1_voltage_range(scale_factor) assert scope.set_sample_rate(27) ch1_data, _ = scope.read_data(0x100000) ch1_data = scope.scale_read_data(ch1_data, scale_factor) print "Max:", max(ch1_data), "(V), Min:", min(ch1_data), "(V)" assert ch1_data assert scope.close_handle()
start_time = time.time() print("Clearing FIFO and starting data transfer...") i = 0 scope.start_capture() shutdown_event = scope.read_async(extend_callback, data_points, outstanding_transfers=10, raw=True) while time.time() - start_time < 1: scope.poll() scope.stop_capture() print("Stopping new transfers.") shutdown_event.set() print("Snooze 1") time.sleep(1) print("Closing handle") scope.close_handle() print("Handle closed.") print("Points in buffer:", len(data)) scaled_data = scope.scale_read_data(data, voltage_range) with open('/tmp/continuous_read.out','wt') as ouf: ouf.write(str(scaled_data[:65536])[1:-1].replace(', ',chr(10))) plt.figure(0) plt.plot(scaled_data) plt.figure(1) plt.plot(np.fft.fft(scaled_data).real) #plt.show() stab = build_stability_array(scaled_data, threshold=np.average(scaled_data)) stab_avg, stab_std = np.average(stab), np.std(stab) print("Stability", stab_avg, "+/-", stab_std, "({}% deviance)".format(100.0*stab_std/stab_avg)) bad_pulse_count = len([p for p in stab if abs(stab_avg - p) >= stab_std]) print("Pulses more than 1 std dev out: {}/{} ({} %)".format(bad_pulse_count, len(stab), 100.0*bad_pulse_count/len(stab))) plt.show()
class Plugin(LoggerPlugin): """ Diese Gerät zeichnet die Daten eines Hantek6022 (und möglicherweise anderer) Oszilloskops auf. """ def __init__(self, *args, **kwargs): # Plugin setup super(Plugin, self).__init__(*args, **kwargs) self.setDeviceName(DEVICENAME) self.smallGUI = False self._scope = None self.setPerpetualTimer(self._updateT, samplerate=SAMPLERATE) self._blocksize = 6 * 1024 # should be divisible by 6*1024 self._alternative = 1 # choose ISO 3072 bytes per 125 us self._recordLength = 5000 self._blocksize = self._recordLength self._yData1 = deque(maxlen=self._recordLength) self._yData2 = deque(maxlen=self._recordLength) self._yData1Triggered = deque(maxlen=self._recordLength) self._yData2Triggered = deque(maxlen=self._recordLength) self._singleTriggerFound = False self.__capturer = Thread(target=self.__captureT) self.__capturer.start() # THIS IS YOUR THREAD def _updateT(self): if not self.widget.pauseButton.isChecked(): if self.widget.enableTriggerButton.isChecked(): yData1, yData2, stop = self.__trigger(list(self._yData1), list(self._yData2)) else: yData1 = self._yData1 yData2 = self._yData2 stop = False samplerate = self._str2Samplerate( self.widget.samplerateComboBox.currentText()) xData = [(i - len(yData1)) / samplerate for i in range(len(yData1))] if len(self._yData1) > 1: self.plot(xData, yData1, dname='Hantek', sname='CH1', unit='V') if self.widget.channel2CheckBox.isChecked(): self.plot(xData, yData2, dname='Hantek', sname='CH2', unit='V') if stop: self.widget.pauseButton.setChecked(True) def __captureT(self): #self.last_time = time.time() shutdown_event = self._scope.read_async(self._extend_callback, self._blocksize, outstanding_transfers=10, raw=True) self._scope.start_capture() while self.run: self._scope.poll() # logging.info("Stopping new transfers.") # scope.stop_capture() self._scope.stop_capture() shutdown_event.set() time.sleep(0.1) self._scope.close_handle() def loadGUI(self): self.widget = QtWidgets.QWidget() packagedir = self.getDir(__file__) uic.loadUi(packagedir + "/Hantek6022/hantek.ui", self.widget) # self.setCallbacks() self.widget.reconnectButton.clicked.connect( self.__openConnectionCallback) self.widget.samplerateComboBox.currentTextChanged.connect( self._updateScopeSettings) self.widget.recordLengthSpinBox.valueChanged.connect(self.changeLength) # self.widget.channel1CheckBox.valueChanged.connect(self.enableChannel1) self.widget.channel1CheckBox.setEnabled(False) self.widget.channel1ACDCComboBox.hide() # valueChanged.connect(self.) self.widget.channel1VoltPDivComboBox.currentTextChanged.connect( self._updateScopeSettings) self.widget.channel2VoltPDivComboBox.currentTextChanged.connect( self._updateScopeSettings) self.widget.channel2CheckBox.stateChanged.connect( self._updateScopeSettings) self.widget.channel2ACDCComboBox.hide() # valueChanged.connect(self.) # self.widget.pauseButton.clicked.connect(self.) # self.widget.triggerChannelComboBox.textChanged.connect(self.) # self.widget.triggerLevelSpinBox.valueChanged.connect(self.) # self.widget.enableTriggerButton.clicked.connect(self.) self._recordLength = self.widget.recordLengthSpinBox.value() self.xData = deque(maxlen=self._recordLength) self._yData1 = deque(maxlen=self._recordLength) self._yData2 = deque(maxlen=self._recordLength) self.__openConnectionCallback() return self.widget def __openConnectionCallback(self): self.widget.reconnectButton.setEnabled(False) if self.run: self.cancel() self.widget.reconnectButton.setText("Reconnect") self.__base_address = "" self.widget.reconnectButton.setEnabled(True) else: self._updateScopeSettings() self.widget.reconnectButton.setText("Stop") self.widget.reconnectButton.setEnabled(True) def __trigger(self, data1, data2): if not self._singleTriggerFound: if self.widget.channel2CheckBox.isChecked( ) and self.widget.triggerChannelComboBox.currentText() == 'CH2': triggerSignal = list(data2) else: triggerSignal = list(data1) flanke = self.widget.comboBox.currentText() triggerLevel = self.widget.triggerLevelSpinBox.value() cutoff = 0 mean = self.widget.smoothSpinBox.value() triggerPrepared = False if flanke == 'Rising': if max(triggerSignal) > triggerLevel: for idx in range(len(triggerSignal)): if triggerSignal[ idx] >= triggerLevel - mean and triggerSignal[ idx] <= triggerLevel: triggerPrepared = True elif triggerSignal[ idx] < triggerLevel - mean and triggerPrepared: triggerPrepared = False elif triggerSignal[ idx] > triggerLevel and triggerPrepared == True: cutoff = idx break else: if min(triggerSignal) < triggerLevel: for idx in range(len(triggerSignal)): if triggerSignal[ idx] <= triggerLevel + mean and triggerSignal[ idx] >= triggerLevel: triggerPrepared = True elif triggerSignal[ idx] > triggerLevel + mean and triggerPrepared: triggerPrepared = False elif triggerSignal[ idx] < triggerLevel and triggerPrepared == True: cutoff = idx break stop = False if len(data2) > cutoff: data2 = list(data2)[cutoff:] if len(data1) > cutoff: data1 = list(data1)[cutoff:] if cutoff != 0 and self.widget.checkBox.isChecked( ) and not self._singleTriggerFound: self._singleTriggerFound = True else: self._singleTriggerFound = False if self.widget.checkBox.isChecked(): self._yData1Triggered = deque(list(data1), maxlen=self._recordLength) self._yData2Triggered = deque(list(data2), maxlen=self._recordLength) else: if len(self._yData1Triggered) < self._recordLength: stop = False else: self._singleTriggerFound = False stop = True data1 = self._yData1Triggered data2 = self._yData2Triggered return data1, data2, stop def _updateScopeSettings(self): if self._scope: self.cancel() self._scope = Oscilloscope() self._scope.setup() self._scope.open_handle() if (not self._scope.is_device_firmware_present): self._scope.flash_firmware() else: self._scope.supports_single_channel = True logging.info("Setting up scope!") self._scope.set_interface(self._alternative) logging.info("ISO" if self._scope.is_iso else "BULK", "packet size:", self._scope.packetsize) if self.widget.channel2CheckBox.isChecked(): self._scope.set_num_channels(2) else: self._scope.set_num_channels(1) # set voltage range voltagerange1 = self._strVoltageToID( self.widget.channel1VoltPDivComboBox.currentText()) voltagerange2 = self._strVoltageToID( self.widget.channel2VoltPDivComboBox.currentText()) self._scope.set_ch1_voltage_range(voltagerange1) self._scope.set_ch2_voltage_range(voltagerange2) self._scope.set_sample_rate( self._str2SamplerateID( self.widget.samplerateComboBox.currentText())) self._blocksize = self._recordLength self.start() # self.widget.reconnectButton.setText("Stop") # self.widget.reconnectButton.setEnabled(True) def calibrate(self): if self._scope: self._scope.setup_dso_cal_level() cal_level = self._scope.get_calibration_data() self._scope.set_dso_calibration(cal_level) def _str2SamplerateID(self, strung): if 'MHz' in strung: strung = strung.replace(' MHz', '') return int(strung) else: strung = strung.replace(' kHz', '') return int(int(strung) / 10) def _str2Samplerate(self, strung): if 'MHz' in strung: strung = strung.replace(' MHz', '') return int(strung) * 1000000 else: strung = strung.replace(' kHz', '') return int(strung) * 1000 # def __changeChannel1VoltPDiv(self, strung): # if self._scope: # voltagerange = self._strVoltageToID(strung) # self._scope.set_ch1_voltage_range(voltagerange) # # def __changeChannel2VoltPDiv(self, strung): # if self._scope: # voltagerange = self._strVoltageToID(strung) # self._scope.set_ch2_voltage_range(voltagerange) def _enableChannel2(self, value): if value: self._scope.set_num_channels(2) else: self._scope.set_num_channels(1) def _strVoltageToID(self, strung): voltagerange = 1 if strung == '2.6 V': voltagerange = 2 elif strung == '5 V': voltagerange = 5 elif strung == '10 V': voltagerange = 10 return voltagerange def _extend_callback(self, ch1_data, ch2_data): voltage_data = self._scope.scale_read_data( ch1_data, self._strVoltageToID( self.widget.channel1VoltPDivComboBox.currentText())) if len(voltage_data) > 1: self._yData1.extend(voltage_data) if len(self._yData1Triggered) < self._recordLength: if len(self._yData1Triggered) + len( voltage_data) < self._recordLength: self._yData1Triggered.extend(voltage_data) else: self._yData1Triggered.extend( voltage_data[0:self._recordLength - len(self._yData1Triggered)]) if ch2_data != '': voltage_data = self._scope.scale_read_data( ch2_data, self._strVoltageToID( self.widget.channel1VoltPDivComboBox.currentText())) self._yData2.extend(voltage_data) if len(self._yData2Triggered) < self._recordLength: if len(self._yData2Triggered) + len( voltage_data) < self._recordLength: self._yData2Triggered.extend(voltage_data) else: self._yData2Triggered.extend( voltage_data[0:self._recordLength - len(self._yData2Triggered)]) def changeLength(self, newlen: int = 10000): self._recordLength = newlen self._yData1 = deque(maxlen=self._recordLength) self._yData2 = deque(maxlen=self._recordLength) self._yData1Triggered = deque(maxlen=self._recordLength) self._yData2Triggered = deque(maxlen=self._recordLength) self._updateScopeSettings()
outstanding_transfers=25) print("Clearing FIFO and starting data transfer...") i = 0 scope.start_capture() while time.time() - start_time < 1: scope.poll() scope.stop_capture() print("Stopping new transfers.") shutdown_event.set() print("Snooze 1") time.sleep(1) print("Closing handle") scope.close_handle() print("Handle closed.") print("Points in buffer:", len(data)) scaled_data = scope.scale_read_data(data, voltage_range) with open('/tmp/continuous_read.out', 'wt') as ouf: ouf.write(str(scaled_data[:2 ^ 16])[1:-1].replace(', ', chr(10))) plt.figure(0) plt.plot(scaled_data) plt.figure(1) plt.plot(np.fft.fft(scaled_data).real) #plt.show() stab = build_stability_array(scaled_data, threshold=np.average(scaled_data[:2048])) stab_avg, stab_std = np.average(stab), np.std(stab) print("Stability", stab_avg, "+/-", stab_std, "({}% deviance)".format(100.0 * stab_std / stab_avg)) bad_pulse_count = len([p for p in stab if abs(stab_avg - p) >= stab_std]) print("Pulses more than 1 std dev out: {}/{} ({} %)".format( bad_pulse_count, len(stab), 100.0 * bad_pulse_count / len(stab)))
new_data = data[:window] for i, point in enumerate(data[window:-window]): new_data.append(sum(data[i-window:i+window+1])/(2*window+1)) new_data.extend(data[-window:]) return new_data sample_rate_index = 0x04 voltage_range = 0x01 data_points = 0x2000 scope = Oscilloscope() scope.setup() scope.open_handle() scope.set_sample_rate(sample_rate_index) scope.set_ch1_voltage_range(voltage_range) ch1_data, _ = scope.read_data(data_points) voltage_data = scope.scale_read_data(ch1_data, voltage_range) timing_data, _ = scope.convert_sampling_rate_to_measurement_times(data_points, sample_rate_index) scope.close_handle() pylab.title('Scope Visualization Example') pylab.plot(timing_data, voltage_data, color='#009900', label='Raw Trace') pylab.plot(timing_data, apply_data_smoothing(voltage_data, window=3), color='#0033CC', label='Smoothed Trace') pylab.xlabel('Time (s)') pylab.ylabel('Voltage (V)') pylab.grid() pylab.legend(loc='best') pylab.xticks(rotation=30) pylab.tight_layout() pylab.show()
cal_freq = 10 # skip first samples due to unstable xfer skip = 2 * 0x400 data_points = skip + 20 * 0x400 scope = Oscilloscope() scope.setup() scope.open_handle() scope.set_sample_rate(sample_rate_index) scope.set_ch1_voltage_range(voltage_range) print(scope.set_calibration_frequency(cal_freq)) ch1_data, _ = scope.read_data(data_points) #,raw=True)#timeout=1) voltage_data = scope.scale_read_data(ch1_data[skip:], voltage_range) timing_data, _ = scope.convert_sampling_rate_to_measurement_times( data_points - skip, sample_rate_index) scope.close_handle() if len(timing_data) != len(voltage_data): w = sys.stderr.write w('data lengths differ!\n') w(str([(s, len(eval(s + '_data'))) for s in 'timing voltage'.split()])) w('\n') exit(1) # store the data with open('/tmp/scopevis.dat', 'wt') as ouf: ouf.write('\n'.join('{:8f}'.format(v) for v in voltage_data)) ouf.write('\n')
new_data.extend(data[-window:]) return new_data sample_rate_index = 0x04 voltage_range = 0x01 data_points = 0x2000 scope = Oscilloscope() scope.setup() scope.open_handle() scope.set_sample_rate(sample_rate_index) scope.set_ch1_voltage_range(voltage_range) ch1_data, _ = scope.read_data(data_points)#,raw=True)#timeout=1) voltage_data = scope.scale_read_data(ch1_data, voltage_range) timing_data, _ = scope.convert_sampling_rate_to_measurement_times(data_points, sample_rate_index) scope.close_handle() if len(timing_data) != len(voltage_data): w = sys.stderr.write w('data lengths differ!\n') w(str([(s,len(eval(s+'_data')))for s in 'timing voltage'.split()])) w('\n') exit(1) # store the data with open('/tmp/scopevis.dat', 'wt') as ouf: ouf.write('\n'.join('{:8f}'.format(v) for v in voltage_data)) ouf.write('\n')
def extend_callback(ch1_data, _): data_extend(ch1_data) start_time = time.time() shutdown_event = scope.read_async(extend_callback, data_points, outstanding_transfers=25) print "Clearing FIFO and starting data transfer..." i = 0 scope.start_capture() while time.time() - start_time < 1: time.sleep(0.01) scope.stop_capture() print "Stopping new transfers." shutdown_event.set() print "Snooze 1" time.sleep(1) print "Closing handle" scope.close_handle() print "Handle closed." print "Points in buffer:", len(data) plt.figure(0) plt.plot(scope.scale_read_data(data, voltage_range)) plt.figure(1) plt.plot(np.fft.fft(scope.scale_read_data(data, voltage_range))) stab = build_stability_array(scope.scale_read_data(data, voltage_range), threshold=1.2) stab_avg, stab_std = np.average(stab), np.std(stab) print "Stability", stab_avg, "+/-", stab_std, "({}% deviance)".format(100.0*stab_std/stab_avg) bad_pulse_count = len([p for p in stab if abs(stab_avg - p) >= stab_std]) print "Pulses more than 1 std dev out: {}/{} ({} %)".format(bad_pulse_count, len(stab), 100.0*bad_pulse_count/len(stab)) print stab plt.show()
data_points, outstanding_transfers=25) print "Clearing FIFO and starting data transfer..." i = 0 scope.start_capture() while time.time() - start_time < 1: time.sleep(0.01) scope.stop_capture() print "Stopping new transfers." shutdown_event.set() print "Snooze 1" time.sleep(1) print "Closing handle" scope.close_handle() print "Handle closed." print "Points in buffer:", len(data) plt.figure(0) plt.plot(scope.scale_read_data(data, voltage_range)) plt.figure(1) plt.plot(np.fft.fft(scope.scale_read_data(data, voltage_range))) stab = build_stability_array(scope.scale_read_data(data, voltage_range), threshold=1.2) stab_avg, stab_std = np.average(stab), np.std(stab) print "Stability", stab_avg, "+/-", stab_std, "({}% deviance)".format( 100.0 * stab_std / stab_avg) bad_pulse_count = len([p for p in stab if abs(stab_avg - p) >= stab_std]) print "Pulses more than 1 std dev out: {}/{} ({} %)".format( bad_pulse_count, len(stab), 100.0 * bad_pulse_count / len(stab)) print stab plt.show()