Skip to content
Snippets Groups Projects
Commit 94baaaff authored by Daniele Nicolodi's avatar Daniele Nicolodi
Browse files

hp34970a: Add option to specify channel list and configuration

parent ddd46917
No related branches found
No related tags found
No related merge requests found
import dataclasses
import datetime
import re
import signal
import time
import click
import serial
from ptblab import datalogger, utils, win32time
from ptblab import datalogger, utils, win32time, terminal
class HP34970A:
......@@ -104,16 +106,64 @@ class HP34970A:
self.send(b'ABORT')
UNITS = {
'FRES': 'Ohm',
'RES': 'Ohm',
'TEMP': 'K',
}
@dataclasses.dataclass
class Channel:
number: int
func: str
spec: str
nplc: int
units: str
@classmethod
def parse(cls, s):
m = re.match(r'^(\d+):([A-Z]+):([^:]+):(\d+)$', s)
if not m:
raise ValueError(s)
return cls(int(m.group(1)), m.group(2), m.group(3), int(m.group(4)), UNITS[m.group(2)])
@click.command()
@click.argument('filename', required=False)
@click.option('--device', '-d', metavar='DEV', default='COM4')
@click.option('--datadir', type=click.Path(), help='Data folder for datalogger mode.')
@click.option('--dataname', default='temp2', metavar='STRING', help='Data name in datalogger mode.')
@click.option('--channel', '-c', default=('102:FRES:1000:20',), metavar='SPEC', help='Channel specification.', multiple=True)
@utils.config_option(section='hp34970a')
def main(filename, device, datadir, dataname):
def main(filename, device, channel, datadir, dataname):
"""Acquire readings from Agilent 34970A data acquisition unit.
Channel configuration is specified with the --channel option followed by a
string in the form N:FUNC:SPEC:NPLC where N is the channel number, FUNC is
the function, SPEC are furhter qualifications passed to the "CONF:FUNC"
SCPI command, and NPLC is the integration time in number of power line
cycles. See the instrument manual for details.
Channels are always read in ascending channel number.
Examples:
- 101:FRES:1000:20 : channel 101, 4-wire resistance measurement, 1000 Ohm
range, 20 power line cycles integration time.
- 102:TEMP:FRTD,85:10 : channel 102, 4-wire RTD measurement, calibration
with alpha = 0.00385, 10 power line cycles integration time.
"""
win32time.set_resolution(win32time.get_resolution().max)
data = datalogger.open_data_file(datadir, dataname, filename)
terminal.setup()
spec = sorted((Channel.parse(c) for c in channel), key=lambda c: c.number)
frmt = '{:.3f} {:s} ' + ' '.join(f'{{:.4f}} {c.units}' for c in spec)
instr = HP34970A(device)
......@@ -130,14 +180,16 @@ def main(filename, device, datadir, dataname):
# Wait for operation to complete.
instr.query(b'*OPC?')
# Setup 4-wire Pt100 temperature measuremet for channel 101.
instr.send(b'CONF:TEMP FRTD,85,1,1E-6,(@101)')
# Set units to K.
instr.send(b'UNIT:TEMP K,(@101)')
for c in spec:
instr.send(f'CONF:{c.func:s} {c.spec},(@{c.number:d})'.encode('ascii'))
instr.send(f'SENS:{c.func:s}:NPLC {c.nplc:d},(@{c.number:d})'.encode('ascii'))
# Set units to K for temperature readings.
if c.func == 'FTEMP' or c.func == 'TEMP':
instr.send(f'UNIT:TEMP K,(@{c.number:d})'.encode('ascii'))
# Set integration time in units of number of power line cycles (PLCs).
instr.send(b'SENS:TEMP:NPLC 20,(@101)')
# Set scan list.
channels = ','.join(str(c.number) for c in spec)
instr.send(f'ROUTE:SCAN (@{channels})'.encode('ascii'))
# Set scan interval to 1 second.
instr.send(b'TRIG:SOURCE TIMER')
......@@ -147,10 +199,11 @@ def main(filename, device, datadir, dataname):
instr.send(b'TRIG:COUNT INFINITY')
# Acquire data.
for timestamp, temp, v in instr.scan():
for timestamp, *values in instr.scan():
t = datetime.datetime.fromtimestamp(timestamp).isoformat(' ', 'milliseconds')
print(f'{timestamp:.3f} {t} {temp:.4f} K', end='\r')
data.write(timestamp, temp)
print(frmt.format(timestamp, t, *values), end='\033[0K\r')
data.write(timestamp, *values)
print()
if __name__ == '__main__':
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment