Skip to content

Commit

Permalink
make scopevis.py example program really useful
Browse files Browse the repository at this point in the history
Signed-off-by: Martin <[email protected]>
  • Loading branch information
Ho-Ro committed May 6, 2024
1 parent ac44d00 commit ea05828
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 41 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
2024-05-03: upversion 2.10.8; update examples and doc [ac44d00]
2024-05-02: more documentation for example programs [fb8e531]
2024-05-01: fix set_cal_out_freq_6022.py; some minor updates [3560cbd]
2024-02-25: add fx2lib lib files [852f574]
Expand Down
4 changes: 3 additions & 1 deletion PyHT6022/LibUsbScope.py
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ def read_data(self, data_size=0x400, raw=False, timeout=0):
if self.num_channels == 2:
chdata = data[::2], data[1::2]
else:
chdata = data, ''
chdata = data, b''
if raw:
return chdata
else:
Expand Down Expand Up @@ -799,10 +799,12 @@ def set_sample_rate(self, rate_index, timeout=0):
:param rate_index: The rate_index. These are the keys for the SAMPLE_RATES dict for the Oscilloscope object.
Common rate_index values and actual sample rate per channel:
102 <-> 20 kS/s
103 <-> 32 kS/s
104 <-> 40 kS/s
105 <-> 50 kS/s
106 <-> 64 kS/s
110 <-> 100 kS/s
113 <-> 128 kS/s
120 <-> 200 kS/s
140 <-> 400 kS/s
150 <-> 500 kS/s
Expand Down
10 changes: 5 additions & 5 deletions examples/capture_6022.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ def pcb( ch1_data, ch2_data ):
pcb.av1 /= downsample
pcb.av2 /= downsample
if pcb.timestep < sample_time:
line = "{:>10.6f}, {:>10.5f}, {:>10.5f}\n".format( pcb.timestep, pcb.av1, pcb.av2 )
line = f"{pcb.timestep:>10.6f}, {pcb.av1:>10.5f}, {pcb.av2:>10.5f}\n"
if german:
line=line.replace( ',', ';' ).replace( '.', ',' )
outfile.write( line )
Expand All @@ -187,7 +187,7 @@ def pcb( ch1_data, ch2_data ):
else: # write out every sample
for ch1_value, ch2_value in zip( ch1_scaled, ch2_scaled ): # merge CH1 & CH2
if pcb.timestep < sample_time:
line = "{:>10.6f}, {:>10.5f}, {:>10.5f}\n".format( pcb.timestep, ch1_value, ch2_value )
line = f"{pcb.timestep:>10.6f}, {ch1_value:>10.5f}, {ch2_value:>10.5f}\n"
if german:
line=line.replace( ',', ';' ).replace( '.', ',' )
outfile.write( line )
Expand Down Expand Up @@ -227,7 +227,7 @@ def pcb( ch1_data, ch2_data ):

if downsample: # calculate the effective sample rate
sample_rate = sample_rate / 256 / downsample
line = "\rCaptured data for {} second(s) @ {} S/s\n".format( sample_time, sample_rate)
line = f"\rCaptured data for {sample_time} second(s) @ {sample_rate} S/s\n"
if german:
line=line.replace( ',', ';' ).replace( '.', ',' )
sys.stderr.write( line )
Expand All @@ -245,11 +245,11 @@ def pcb( ch1_data, ch2_data ):
rms1 = math.sqrt( rms1 )
rms2 = math.sqrt( rms2 )

line = "CH1: DC = {:8.4f} V, AC = {:8.4f} V, RMS = {:8.4f} V\n".format( dc1, ac1, rms1 )
line = f"CH1: DC = {dc1:8.4f} V, AC = {ac1:8.4f} V, RMS = {rms1:8.4f} V\n"
if german:
line=line.replace( ',', ';' ).replace( '.', ',' )
sys.stderr.write( line )
line = "CH2: DC = {:8.4f} V, AC = {:8.4f} V, RMS = {:8.4f} V\n".format( dc2, ac2, rms2 )
line = f"CH2: DC = {dc2:8.4f} V, AC = {ac2:8.4f} V, RMS = {rms2:8.4f} V\n"
if german:
line=line.replace( ',', ';' ).replace( '.', ',' )
sys.stderr.write( line )
Expand Down
126 changes: 91 additions & 35 deletions examples/scopevis.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,54 +6,110 @@
import pylab
import time
import sys
import argparse

def apply_data_smoothing(data, window=1):
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
samplerates = ( 20, 32, 50, 64, 100, 128, 200, 500, 1000, 2000, 4000, 8000, 10000 )
samplerate_help = "sample rate in kS/s ("
for samplerate in samplerates:
samplerate_help += str( samplerate ) + ", "
samplerate_help += f"default: {samplerates[0]})"

gains = ( 1, 2, 5, 10 )
gain_help = "channel gain ("
for gain in gains:
gain_help += str( gain ) + ", "
gain_help += f"default: {gains[0]})"

sample_rate_index = 1
voltage_range = 0x01
cal_freq = 10
# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser(
prog='scopevis.py',
description='Capture data from Hantek6022' )
ap.add_argument( "--ac1", action = "store_true", default = False, help = "AC coupling for CH1" )
ap.add_argument( "--ac2", action = "store_true", default = False, help = "AC coupling for CH2" )
ap.add_argument( "-b", "--blocks", type = int, default = 20, help="number of 1K sample blocks, default: 20" )
ap.add_argument( "--ch1", type = int, default = gains[0], help=f"select gain for ch1 (1, 2, 5, 10, default: {gains[0]})" )
ap.add_argument( "--ch2", type = int, default = 0, help="sample also ch2 with gain 1, 2, 5, 10" )
ap.add_argument( "-f", "--frequency", type = int, default = 0, help="set cal out frequency in Hz" )
ap.add_argument( "-s", "--samplerate", type = int, default = samplerates[0], help=samplerate_help )

# skip first samples due to unstable xfer
skip = 2 * 0x400
data_points = skip + 20 * 0x400
options = ap.parse_args()
argerr = False
if options.ch1 and options.ch1 not in gains:
print( "error, ch1 gain must be one of:", gains )
argerr = True
if options.ch2 and options.ch2 not in gains:
print( "error, ch2 gain must be one of:", gains )
argerr = True
if options.samplerate not in samplerates:
print( "error, rate must be one of:", samplerates )
argerr = True
if argerr:
sys.exit()

data_points = options.blocks * 1024

# skip first 2K samples due to unstable xfer
skip = 2 * 1024
data_points += skip

scope = Oscilloscope()
scope.setup()
scope.open_handle()
scope.set_sample_rate(sample_rate_index)
scope.set_ch1_voltage_range(voltage_range)
scope.set_ch1_ac_dc( scope.DC )
scope.set_calibration_frequency( cal_freq )

time.sleep( 1 )
# upload correct firmware into device's RAM
if (not scope.is_device_firmware_present):
scope.flash_firmware()

# calculate and set the sample rate ID from real sample rate value
if options.samplerate < 1e3:
sample_id = int( round( 100 + options.samplerate / 10 ) ) # 20k..500k -> 102..150
else:
sample_id = int( round( options.samplerate / 1e3 ) ) # 1000k -> 1

scope.set_sample_rate( sample_id )

if options.ch1:
scope.set_ch1_voltage_range( options.ch1 )
if options.ac1:
scope.set_ch1_ac_dc( scope.AC )
else:
scope.set_ch1_ac_dc( scope.DC )

if options.ch2:
scope.set_num_channels( 2 )
scope.set_ch2_voltage_range( options.ch2 )
if options.ac2:
scope.set_ch2_ac_dc( scope.AC )
else:
scope.set_ch2_ac_dc( scope.DC )
else:
scope.set_ch2_voltage_range( 1 )

ch1_data, _ = scope.read_data(data_points)#,raw=True)#timeout=1)
# read and apply calibration values from EEPROM
calibration = scope.get_calibration_values()

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)
if options.frequency:
scope.set_calibration_frequency( options.frequency )

time.sleep( 0.1 )


ch1_data, ch2_data = scope.read_data(data_points)#,raw=True)#timeout=1)

if options.ch1:
voltage_data1 = scope.scale_read_data(ch1_data[skip:], options.ch1, channel=1 )
if options.ch2:
voltage_data2 = scope.scale_read_data(ch2_data[skip:], options.ch2, channel=2 )
timing_data, rate_label = scope.convert_sampling_rate_to_measurement_times(data_points-skip, sample_id)
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')

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.title( f'{options.blocks}K samples @ {rate_label}')
if options.ch1:
pylab.plot(timing_data, voltage_data1, color='#C00000', label='CH1')
if options.ch2:
pylab.plot(timing_data, voltage_data2, color='#0000C0', label='CH2')

pylab.xlabel('Time (s)')
pylab.ylabel('Voltage (V)')
pylab.grid()
Expand Down

0 comments on commit ea05828

Please sign in to comment.