Commands

Send commands to the dev-kit.

Example

>>> import microspec
>>> kit = microspec.Devkit()

If status=='TIMEOUT' it means the command timed out before a response was received.

For applications that run a long time, such as data loggers and free-running plot GUIs, there are occasional timeouts when calling captureFrame(). These applications should check the status attribute of responses to captureFrame() and ignore the data if the status is ‘TIMEOUT’.

A UserWarning is also issued when a timeout occurs, identifying which command timed out. This is not an exception, so it does not cause the application to terminate.

Notes

The Devkit attribute timeout defaults to 2 seconds, which is usually long enough to send a command, execute it on the dev-kit, and receive a response back on the host computer running the application. It is rare to observe a timeout when sending commands at the REPL or executing a script that runs a few commands and exits. Users can observe a timeout condition by setting a very short timeout such as 1ms.

class microspec.commands.Devkit

Interface for dev-kit communication.

Every communication with the dev-kit consists of:

  • a command sent to the dev-kit
  • a response received from the dev-kit

Calling a Devkit method sends the command. The method’s return value is the response.

Example

Command getBridgeLED returns getBridgeLED_response:

>>> import microspec
>>> kit = microspec.Devkit()
>>> kit.getBridgeLED()
getBridgeLED_response(status='OK', led_setting='GREEN')

Assign the response to variable reply:

>>> reply = kit.getBridgeLED()

Access each part of the response as attributes status and led_setting:

>>> reply.status
'OK'
>>> reply.led_setting
'GREEN'
autoExposure()

Auto-expose the spectrometer.

Tell dev-kit firmware to adjust spectrometer exposure time until peak signal strength hits the auto-expose target.

Returns:
  • status
  • success
  • iterations
Return type:autoExposure_response

See also

setAutoExposeConfig()
configure auto-expose parameters
getExposure()
get the new exposure time after the auto-expose

Examples

>>> kit.autoExposure() # doctest: +SKIP
autoExposure_response(status='OK', success='GAVE_UP', iterations=4)
captureFrame()

One-liner

Returns:
  • status (str) – Serial communication status, either ‘OK’, ‘ERROR’, or ‘TIMEOUT’.
  • num_pixels (int) – The number of pixels in the frame (either 392 or 784 depending on pixel binning).
  • pixels (list) – The 16-bit ADC counts at each pixel, starting with pixel 1 and ending with pixel 392 or 784 (depending on pixel binning).
  • frame (dict) – Python dictionary where the key is the pixel number and the value is the 16-bit ADC counts at that pixel.

Examples

Setup:

>>> import microspec as usp
>>> kit = usp.Devkit()

Capture a frame:

>>> reply = kit.captureFrame()

The frame is stored as a Python list of numbers. Each number is the signal strength at that pixel in units of counts.

The list starts with pixel 1. With pixel binning on, the frame has 392 pixels, so the list ends with pixel 392:

>>> print(reply)
captureFrame_response(status='OK', num_pixels=392,
                      pixels=[...], frame={...})

The list pixels is hard to read on its own (index 0 is pixel 1, index 1 is pixel 2, etc.):

>>> print(reply.pixels)
[..., ..., ...]

It is usually more convenient for applications to use the dict frame because it tags each pixel with its pixel number:

>>> print(reply.frame)
{1: ..., 2: ..., ..., 391: ..., 392: ...}

This is still hard to read in the REPL. Put each pixel on its own line:

>>> import pprint
>>> pprint.pprint(reply.frame)
{1: ...,
 2: ...,
 ...
 391: ...,
 392: ...}

Alternatively, turn the (pixel number, pixel value) pairs into a list of tuples:

>>> frame = list(zip(range(1,reply.num_pixels+1), reply.pixels))
>>> pprint.pprint(frame)
[(1, ...),
 (2, ...),
 ...,
 (391, ...),
 (392,...)]

Notes

If there is a timeout, captureFrame() returns status='TIMEOUT', and fills the reply with obviously bad data:

  • num_pixels=0
  • pixels=[]
  • frame={}

Applications are protected from accidentally setting a Devkit.timeout that is shorter than the exposure time (because this guarantees that captureFrame() timeouts before a response is received).

If the timeout is less than the exposure time, captureFrame() uses a Devkit.timeout that is one second longer than the exposure time.

If an application loops captureFrame() for a long time (such as the data logging and plotting GUI examples above), there will likely be a timeout.

In this case, captureFrame() issues a UserWarning describing which command caused the timeout.

This is only a warning because the timeout is hardware-dependent. It does not indicate a bug in the application code.

The timeout UserWarning prints to the console and can safely be ignored. If the timeouts are a frequent event, it indicates a problem with the host computer, its USB port, or the USB cable.

getAutoExposeConfig()

One-liner

Examples

Setup:

>>> import microspec as usp
>>> kit = usp.Devkit()
getBridgeLED(led_num: int = 0)

Read the state of the indicator LED on the Bridge PCB.

Examples

Setup – set the LED to a known state:

>>> import microspec as usp
>>> kit = usp.Devkit()
>>> kit.setBridgeLED(led_num=0, led_setting=usp.GREEN)
setBridgeLED_response(status='OK')

Call getBridgeLED:

>>> kit.getBridgeLED()
getBridgeLED_response(status='OK', led_setting='GREEN')

See also

setBridgeLED()

getExposure()

One-liner

Examples

Setup:

>>> import microspec as usp
>>> kit = usp.Devkit()

getExposure reports exposure time in both units:

>>> # Setup: set exposure time to 5ms
>>> kit.setExposure(ms=5)
setExposure_response(status='OK')
>>> # Test: expect 5.0ms and 250 cycles
>>> kit.getExposure()
getExposure_response(status='OK', ms=5.0, cycles=250)
getSensorConfig()

One-liner

Examples

Setup:

>>> import microspec as usp
>>> kit = usp.Devkit()
>>> kit.setSensorConfig() # restore default config
setSensorConfig_response(status='OK')

Read the spectrometer’s pixel configuration:

>>> kit.getSensorConfig()
getSensorConfig_response(status='OK', binning='BINNING_ON',
                         gain='GAIN1X', row_bitmap='ALL_ROWS')
getSensorLED(led_num: int)

Read the state of an indicator LED on the Sensor PCB.

There are two indicator LEDS: led0 and led1.

Note

Application code should never call this method:

Examples

Setup – set the LEDs to a known state:

>>> import microspec as usp
>>> kit = usp.Devkit()
>>> kit.setSensorLED(usp.GREEN, led_num=0)
setSensorLED_response(status='OK')
>>> kit.setSensorLED(usp.GREEN, led_num=1)
setSensorLED_response(status='OK')

Call getSensorLED:

>>> kit.getSensorLED(0) # Expect OFF
getSensorLED_response(status='OK', led_setting='OFF')
>>> kit.getSensorLED(1) # Expect GREEN
getSensorLED_response(status='OK', led_setting='GREEN')

See also

setSensorLED()

setAutoExposeConfig(max_tries: int = 12, start_pixel: int = 7, stop_pixel: int = 392, target: int = 46420, target_tolerance: int = 3277, max_exposure: int = 10000)

One-liner

Examples

Setup:

>>> import microspec as usp
>>> kit = usp.Devkit()

Configure auto-expose with …:

>>> kit.setAutoExposeConfig()
setAutoExposeConfig_response(status='OK')
>>> kit.getAutoExposeConfig()
getAutoExposeConfig_response(status='OK', max_tries=12,
                             start_pixel=7, stop_pixel=392,
                             target=46420, target_tolerance=3277,
                             max_exposure=10000)

Configure the dev-kit with the default auto-expose parameters:

>>> kit.setAutoExposeConfig()
setAutoExposeConfig_response(status='OK')
>>> kit.getAutoExposeConfig()
getAutoExposeConfig_response(status='OK', max_tries=12,
                            start_pixel=7, stop_pixel=392,
                            target=46420, target_tolerance=3277,
                            max_exposure=10000)
setBridgeLED(led_setting: int, led_num: int = 0)

Set the LED on the Bridge PCB to OFF, GREEN, or RED.

Examples

Setup:

>>> import microspec as usp
>>> kit = usp.Devkit()

Call setBridgeLED with optional parameter led_num:

>>> kit.setBridgeLED(led_num=0, led_setting=usp.GREEN)
setBridgeLED_response(status='OK')

Call setBridgeLED without optional parameter led_num:

>>> kit.setBridgeLED(led_setting=usp.GREEN)
setBridgeLED_response(status='OK')

Call setBridgeLED with an invalid parameter value:

>>> kit.setBridgeLED(led_num=1, led_setting=usp.GREEN)
setBridgeLED_response(status='ERROR')

See also

getBridgeLED()

setExposure(ms: float = None, cycles: int = None)

One-liner

Examples

Setup:

>>> import microspec as usp
>>> kit = usp.Devkit()

setExposure accepts time in units of ms:

>>> kit.setExposure(ms=5.0)
setExposure_response(status='OK')

setExposure accepts time in units of cycles:

>>> kit.setExposure(cycles=250)
setExposure_response(status='OK')

setExposure requires an exposure time input

>>> kit.setExposure()
Traceback (most recent call last):
    ...
TypeError: setExposure() missing 1 required argument: 'ms' or 'cycles'

Calling setExposure with both ms and cycles is not allowed:

>>> kit.setExposure(ms=5.0, cycles=250)
Traceback (most recent call last):
    ...
TypeError: setExposure() got an unexpected keyword 'cycles'
(requires 'ms' or 'cycles' but received both)

Exposure time must be within the allowed range:

>>> # Min exposure time in milliseconds:
>>> usp.to_ms(usp.MIN_CYCLES)
0.02
>>> # Max exposure time in milliseconds:
>>> usp.to_ms(usp.MAX_CYCLES)
1310.0
>>> # Try exceeding maximum exposure:
>>> kit.setExposure(cycles=usp.MAX_CYCLES+1)
Traceback (most recent call last):
...
TypeError: Exposure time cannot be more than 65500 cycles.
>>> # Try exposure time below the minimum:
>>> kit.setExposure(cycles=usp.MIN_CYCLES-1)
Traceback (most recent call last):
...
TypeError: Exposure time cannot be less than 1 cycles.
setSensorConfig(binning: int = 1, gain: int = 1, row_bitmap: int = 31)

One-liner

Examples

Setup:

>>> import microspec as usp
>>> kit = usp.Devkit() #doctest: +SKIP

Configure the spectrometer with pixel binning off:

>>> kit.setSensorConfig(binning=usp.BINNING_OFF) #doctest: +SKIP
setSensorConfig_response(status='OK')
>>> kit.getSensorConfig() #doctest: +SKIP
getSensorConfig_response(status='OK', binning='BINNING_OFF',
                         gain='GAIN1X', row_bitmap='ALL_ROWS')

Configure the spectrometer with the default pixel configuration:

>>> kit.setSensorConfig() #doctest: +SKIP
setSensorConfig_response(status='OK')
>>> kit.getSensorConfig() #doctest: +SKIP
getSensorConfig_response(status='OK', binning='BINNING_ON',
                         gain='GAIN1X', row_bitmap='ALL_ROWS')
setSensorLED(led_setting: int, led_num: int)

Set the LEDs on the Sensor PCB to OFF, GREEN, or RED.

There are two indicator LEDS:

  • led0

    • usually appears GREEN
    • is OFF while a command is being executed
    • only turns RED if there is a serious error in serial communication (this should never happen)
  • led1

    • usually appears GREEN
    • turns RED during auto-expose
    • stays RED if auto-expose fails
    • turns GREEN if auto-expose succeeds

Note

Application code should never call this method. The LEDs are controlled by firmware to indicate status. Controlling the LEDs from the application undermines the LEDs purpose as status indicators.

Examples

Setup:

>>> import microspec as usp
>>> kit = usp.Devkit() #doctest: +SKIP

Turn led0 and led1 OFF:

>>> kit.setSensorLED(usp.OFF, 0) #doctest: +SKIP
setSensorLED_response(status='OK')
>>> kit.setSensorLED(usp.OFF, 1) #doctest: +SKIP
setSensorLED_response(status='OK')

Turn led0 and led1 RED:

>>> kit.setSensorLED(usp.RED, 0) #doctest: +SKIP
setSensorLED_response(status='OK')
>>> kit.setSensorLED(usp.RED, 1) #doctest: +SKIP
setSensorLED_response(status='OK')

Turn led0 and led1 GREEN:

>>> kit.setSensorLED(usp.GREEN, 0) #doctest: +SKIP
setSensorLED_response(status='OK')
>>> kit.setSensorLED(usp.GREEN, 1) #doctest: +SKIP
setSensorLED_response(status='OK')