Importing
Once the subdue
is installed, it can be imported and the hardware
directly utilized within your Python program. The packages available are:
subdue.daqmx
subdue.visa
subdue.thermocouple
More packages and functionality may be added as required by the user base.
Searching for Hardware
Each module of Subdue implements a search functionality which consists of two steps: (1) create the searcher object and (2) list the attached objects by reference. For instance, to search for all attached DAQs:
daq_searcher = subdue.NIDAQmxSearch()
references = daq_searcher.list_references() # list the default references available for daqs
models = daq_searcher.list_models() # list the models available for daqs
serial_numbers = daq_searcher.list_serial_numbers() # list the serial numbers available for daqs
devices = daq_searcher.list_devices() # list complete information for daqs (returns list of dicts)
On completion, references
will contain a list of values that correspond to physical devices detected
on that PC.
Currently, there are three searchers available: subdue.NIDAQmxSearch()
, subdue.VisaInstrumentSearch()
,
and subdue.ThermocoupleSearch()
. Each of these implements the list_references()
, list_models()
,
list_serial_numbers()
, and list_devices()
methods.
References
All references may be used for direct device instantiation. For instance:
visa_searcher = subdue.VisaInstrumentSearcher()
# store the first available VISA instrument in reference
reference = visa_searcher.list_references()[0]
psu = PowerSupply(reference)
This method is useful if there is only one VISA instrument that is a power supply attached to your PC.
If more than one power supply is attached, you may wish to use the searcher.list_devices()
method, which
will return a list of dicts, each containing the model number, serial number, and the reference.
>>> references = subdue.VisaInstrumentSearcher().list_references()
>>> print(references)
[{'serial': 'US08E6445J', 'model': 'N5768A', 'reference': 'N5768A'}]
Controlling the Hardware
Unfortunately, due to the differences in operation between instrument types, it is not possible to create a perfectly uniform API through which to program all devices in the same way. Pains have been taken in order to assure as much consistency as possible while still providing access to all functionality available on a particular device.
Each piece of hardware will be allocated by associating it with an object of its type. For instance,
a power supply would be internally represented by an instance of subdue.PowerSupply
.
It is easiest to allocate the hardware object using the reference
field, if possible. Each instrument
has a different 'preferred' reference based on types and drivers. For instance, National Instruments
hardware often populates as DevX
whereas Visa instruments may populate using their serial number
as the preferred.
Data Acquisition (DAQ)
The subdue.NIDAQmx
object encompasses all of the functionality contained within the
DAQ. To create an instance of the DAQ, one needs to specify, either, the serial number or the
device name in the constructor:
daq = subdue.NIDAQmx(device_name='Dev1')
daq = subdue.NIDAQmx(serial_number='123456')
Once the object is created, then its methods may be executed in order to manipulate the DAQ
Digital Output
daq.digital_out_line(port_name, line_name, value)
where port_name
and line_name
correspond to National Instruments conventions and each may be specified
as an integer or as a string. The value
is True
or False
to set or clear the output.
For instance, to set the line labeled "port0 line1" to a high voltage state, either of the following lines may be used to the same effect:
daq.digital_out_line(0, 1, True)
daq.digital_out_line('port0', 'line1', True)
Digital Input
daq.digital_in_line(port_name, line_name)
Similar to digital output, port_name
and line_name
correspond to National Instruments conventions.
The method simply return True
or False
based on the pin state:
if daq.digital_in_line(0, 1):
print('port0, line0 is high!')
else:
print('port0, line0 is low!')
Analog Output
daq.analog_out(analog_output, voltage)
where analog_output
corresponds to NI conventions and voltage
is a floating-point number that
represents the desired voltage.
To set the output of "ao1" to 1.25V, either of the following lines would work:
daq.analog_out('ai1', 1.25)
daq.analog_out(1, 1.25)
Analog Input
daq.sample_analog_in(analog_input, sample_count=1, rate=1000.0, output_format=None)
where:
* analog_input
corresponds to NI conventions
* sample_count
corresponds to the number of samples the programmer wishes to take
* rate
corresponds to the sample rate
* output_format
will allow the user to return a Python-native list
To read one sample of "ai1":
daq.sample_analog_in('ai1')
To read 10 samples of "ai1" at the default 1kHz frequency and return as a numpy array:
daq.sample_analog_in('ai1', 10)
To read 10 samples of "ai1" at 2kHz and return the results as a Python-native list:
daq.sample_analog_in('ai1', 10, 2000, 'list')
Power Supply
The subdue.PowerSupply
object encompasses all of the methods and functionality
applicable to power supplies. To create an instance of the PowerSupply
, one needs to
specify, the instrument object, the model number, or the serial number in the constructor:
psu = subdue.NIDAQmx(instrument=instrument_instance)
psu = subdue.NIDAQmx(device_name='N5768A')
psu = subdue.NIDAQmx(serial_number='123456')
The instrument_instance
is an instance of the pyvisa.ResourceManager.open_resource()
object
and will seldom be utilized.
Read PSU Voltage
psu.read_voltage()
will read and return the output voltage of the power supply.
Read PSU Current
psu.read_current()
will read and return the output voltage of the power supply.
Read PSU Status
psu.read_status()
will return a list of all status messages stored in the instrument.
Reset PSU
psu.reset()
will reset the PSU to its power-on defaults.
Set PSU Voltage
psu.set_voltage(voltage)
where voltage
is a floating-point number representing the output voltage.
Set PSU Current
psu.set_current(current)
where current
is a floating-point number representing the maximum output current.
PSU on/off
The PSU may be turned on using psu.on()
and off using psu.off()
.
PSU Overcurrent Protection
The overcurrent protection may be set or cleared using psu.ocp(True)
or psu.ocp(False)
.
Thermocouple Reader
To utilize the thermocouple reader, first, the thermocouple reader must be allocated as an object and the appropriate channels enabled and setup. Once the channels are functional, then they may be read individually in a sequence.
tc = subdue.ThermocoupleReader()
tc.enable_channel(channel_number=1, tc_type='K')
tc.enable_channel(channel_number=3, tc_type='K')
while True:
print('{} {}'.format(tc.read_one(channel_number=1), tc.read_one(channel_number=3)))
time.sleep(1.0)
This code will print channels 1 and 3 to the console every 1.0s + conversion time for both channels.