|
| void | clearDark () |
| | Clears the stored dark from all spectrometers.
|
| |
| void | clearReference () |
| | Clears the stored reference from all spectrometers.
|
| |
| void | close () |
| | Release all resources at end of application session.
|
| |
| async Task< List< ChannelSpectrum > > | getSpectraAsync (bool sendTrigger=true) |
| | Get one spectrum from each populated position.
|
| |
| Spectrometer | getSpectrometer (int pos) |
| | Get a handle to the spectrometer at a given position.
|
| |
| async Task< ChannelSpectrum > | getSpectrumAsync (int pos, bool computeTimeout=true) |
| | Get a spectrum from one spectrometer. Does not call startAcquisition, and assumes that EITHER a hardware trigger has been initiated through other means, or that the system is in software triggered mode.
|
| |
| async Task< bool > | openAsync () |
| | Initialize all connected spectrometers, determine positions in the multi-channel system, find out which are configured to provide the external hardware trigger and fan control, etc.
|
| |
| List< int > | positionsByIntegTime () |
| | Provide a list of spectrometer positions, sorted in ascending order by integration time.
|
| |
| async Task< bool > | sendHWTrigger () |
| | Sends a hardware trigger using the configured spectrometer.
|
| |
| bool | setIntegrationTimeMS (uint ms) |
| | A convenience method to set all spectrometers in the system to a common integration time.
|
| |
| async Task< bool > | startAcquisitionAsync () |
| | Use the configured spectrometer's laserEnable output to raise a brief HW trigger pulse.
|
| |
| async Task< List< ChannelSpectrum > > | takeDarkAsync (bool sendTrigger=true) |
| | Takes a spectrum from each spectrometer, and stores it internally as a new dark reference.
|
| |
| async Task< List< ChannelSpectrum > > | takeReferenceAsync (bool sendTrigger=true) |
| | Takes a spectrum from each spectrometer, and stores it internally as a new reference.
|
| |
|
| bool | fanEnabled [get, set] |
| | Use the configured spectrometer's laserEnable output to turn the system fans on or off.
|
| |
| int | fanPos [get] |
| | The position of the spectrometer configured to control the fans.
|
| |
| bool | hardwareTriggeringEnabled [get, set] |
| | Whether external hardware triggering is currently enabled.
|
| |
| bool | integrationThrowaways [get, set] |
| | Whether spectrometers in the system should automatically take "throwaway" acquisitions after changing integration time (default).
|
| |
| SortedSet< int > | positions = new SortedSet<int>() [get, private set] |
| | A convenience accessor to iterate over populated positions (channels).
|
| |
| bool | reflectanceEnabled [get, set] |
| | If enabled, and if reference measurements have been recorded, calls to getSpectraAsync() and getSpectrumAsync() will populate ChannelSpectrum intensities with computed reflectance rather than raw counts.
|
| |
| uint | scanAveraging [get, set] |
| | At the moment, we have no validated way to encapsulate scan averaging within WasatchNET when using HW drivers. Therefore, we're doing the looping and averaging in getSpectraAsync, controlled by this field.
|
| |
| int | spectrometerCount [get] |
| | How many spectrometers (channels) were found.
|
| |
| int | triggerPos [get] |
| | The position of the spectrometer configured to generate the external hardware trigger.
|
| |
| int | triggerPulseWidthMS = 5 [get, set] |
| | How long the triggerSpec's laserEnable signal is raised high to generate an acquisition trigger to all spectrometers.
|
| |
WasatchNET has always provided support to control multiple spectrometers in parallel. However, such control is inherently manual, with all operations and timing left to the user. Other than basic synchronization of the USB bus, no automated timing or coordination is provided across multiple devices.
MultiChannelWrapper simplifies operation for customers creating multi-channel spectroscopic applications in which multiple spectrometers are expected to start acquisitions at the same time (simultaneous measurements of a single event), typically via hardware triggering.
- "Position" and "Channel" are used interchangeably.
- all testing was done with 8-channel system of WP-OEM (ARM) spectrometers, but should apply to other configurations
- Position is 1-indexed, given typical customer tendencies and user labeling requirements.
As WP-OEM spectrometers do not currently expose an accessory connector with an obvious GPIO output useable as a trigger source, and as the immediate customer is using non-laser models excited via external light sources, the laserEnable output is being used as a quasi-GPIO, both for raising trigger signals and to control connected fans.
| async Task< List< ChannelSpectrum > > WasatchNET.MultiChannelWrapper.getSpectraAsync |
( |
bool |
sendTrigger = true | ) |
|
|
inline |
Get one spectrum from each populated position.
This reads one spectrum from each selected device. The reads are performed in serial for two reasons. First, the USB bus is itself physically serial, so truely parallel communication isn't technically possible. Secondly, the attempt to interleave spectral packets over bulk endpoints, and the randomized inter-packet timing and buffer sizing thus introduced, has been observed to confuse some hardware USB controllers.
Sorting by integration time should ensure total read-out time is close to minimal.
At present, all scan averaging (SW and HW triggered) is provided by this method.
- Parameters
-
| sendTrigger | whether to automatically send trigger(s) to start the acquisitions |
- Returns
- a list of ChannelSpectra in position order
| async Task< ChannelSpectrum > WasatchNET.MultiChannelWrapper.getSpectrumAsync |
( |
int |
pos, |
|
|
bool |
computeTimeout = true |
|
) |
| |
|
inline |
Get a spectrum from one spectrometer. Does not call startAcquisition, and assumes that EITHER a hardware trigger has been initiated through other means, or that the system is in software triggered mode.
The intended use-case for "computeTimeout" is to ensure that, when the higher-level getSpectraAsync() is called and generates a startAcquisition trigger, we don't completely throw the notion of "reasonable timeouts" out the window. That is, even though getSpectraAsync is reading spectra in serial, and therefore spectrometers further down the line will actually have had more time to complete their acquisitions, we don't unfairly "penalize" earlier spectrometers by holding them to strict timeouts, to which later spectrometers avoided by happenstance. Partially this is so we can continue to use timeouts as for their intended purpose, to correctly alert the user and system developers when a component is failing to meet specified tolerances and expectations of performance. Timeouts are there to tell us when a component is failing to perform as intended, and we don't want to lose that important feedback even when measurements are artificially slowed by having to read back spectra from numerous devices.
- Parameters
-
| pos | spectrometer position to acquire |
| computeTimeout | compute a dynamic timeout from lastTriggerSent |
| async Task< bool > WasatchNET.MultiChannelWrapper.openAsync |
( |
| ) |
|
|
inline |
Initialize all connected spectrometers, determine positions in the multi-channel system, find out which are configured to provide the external hardware trigger and fan control, etc.
<todo> could provide some "filter" options to let the caller determine which connected spectrometers should be considered valid channels, e.g. regex patterns for model, serial and/or userData. </todo>
- Returns
- true on success
| bool WasatchNET.MultiChannelWrapper.hardwareTriggeringEnabled |
|
getset |
Whether external hardware triggering is currently enabled.
Note that with ARM spectrometers, whether hardware triggering is enabled or not may seem somewhat philosophical; after all, ARM spectrometers ALWAYS respond to both HW and SW triggers, so this value doesn't actually change anything inside the spectrometer.
What it does is change behavior within WasatchNET, as normally a spectrometer with TriggerSource.INTERNAL (and autoTrigger) will automatically generate a SW /trigger whenever Spectrometer.getSpectrum() is called. Likewise, timeout behavior changes depending on this setting, as a HW-triggered acquisition should generally continue to block until a HW trigger is detected.
Of course, things are actually more complicated than that, as Spectrometer.autoTrigger also feeds into whether the spectrometer will internally generate a SW trigger, and there are various explicit timeouts which can be applied even to HW-triggered spectrometers.