API Examples

Device Connection

Create and identify a device:

>>> from pyflind.smx00 import SMx00
>>> sm = SMx00('uart:/dev/ttyUSB0')
>>> ident = sm.get_ident()
>>> for k,v in ident.items():
...   print(f'{k}: {v}')
...
model: SM300
fw_version: v2.0.0
sensor_serial: JP3FYD
electronics_serial: 16068843472820543803

Close the device:

>>> sm.close()

Change the baudrate:

>>> sm.get_baudrate()
921600
>>> sm.set_baudrate(460800)
>>> sm.get_baudrate()
460800

Sensor Operation

Start the sensor in blocking mode:

>>> sm.stream_sync() # must be done at least once per power cycle before start
>>> status, startup_times = sm.start_sensor(120) # wait for up to 120 seconds
>>> status # did the sensor start?
True
>>> for k,v in startup_times.items(): # print the time spent in each state
...   print(f'{k}: {v}')
...
laser_check: 0.0744
warm_up: 3.0
optical_scan: 49.532639999999994
heat_stabilize: 34.836
magnetic_scan: 0.8879999999999999
>>> np.sum(list(startup_times.values())) # total startup time
np.float64(88.33104)

Stop the sensor:

>>> sm.stop_sensor()

Data Streaming

Configure streaming samplerate:

>>> sm.get_samplerate()
1000.0
>>> sm.set_samplerate(2000) # closest supported rate will be chosen
2083.3333333333335

Configure streams:

>>> sm.get_active_streams()
[]
>>> sm.get_stream_map()
SM300StreamMap: {
    6 (0x06): fw_version
    7 (0x07): sensor_serial_lo
    8 (0x08): sensor_serial_hi
   13 (0x0d): electronics_rev
   18 (0x12): larmor_freq
   23 (0x17): mag
   35 (0x23): logic_module_state
   53 (0x35): electronics_2_serial_lo
   54 (0x36): electronics_2_serial_hi
   55 (0x37): electronics_serial_lo
   56 (0x38): electronics_serial_hi
   61 (0x3d): pps_clock_count
   67 (0x43): pps_raw_output
   68 (0x44): pps_raw_input
}
>>> sm.get_max_streams() # how many streams can I enable at the current baudrate/samplerate?
3
>>> sm.configure_stream('larmor_freq', True)
>>> sm.configure_stream('pps_clock_count', True)
>>> sm.get_active_streams()
['larmor_freq', 'pps_clock_count']

Set sample history to buffer the last 60 seconds of data:

>>> fs = sm.get_samplerate()
>>> sm.get_max_history() / fs
0.48
>>> sm.set_max_history(round(fs * 60))
>>> sm.get_max_history() / fs
59.99999999999999

Fetch and plot the magnetic field sample history (requires matplotlib):

>>> data = sm.get_samples()
>>> data.keys()
dict_keys(['n', 'rtt', 'rx_t', 'larmor_freq', 'pps_clock_count'])
>>> len(data['n']) / fs # length of history matches that set above
60.004799999999996
>>> t = data['n'] / fs # compute time from sample index
>>> larmor_freq_raw = data['larmor_freq'] #  measured Larmor frequency in raw units
>>> larmor_freq_hz = larmor_freq_raw * sm.LARMOR_FREQ_RATIO # convert to Hz
>>> mag = larmor_freq_hz / sm.Rb87_GYROMAG_RATIO # convert to field using the Rb87 gyromagnetic ratio
>>> import matplotlib.pyplot as plt
>>> plt.plot(t, mag)
[<matplotlib.lines.Line2D object at 0x7c1e57ac87c0>]
>>> plt.xlabel('Time (s)')
Text(0.5, 0, 'Time (s)')
>>> plt.ylabel('Magnetic Field (T)')
Text(0, 0.5, 'Magnetic Field (T)')
>>> plt.title(f'{sm.get_sensor_serial()} Magnetic Field Measurement')
Text(0.5, 1.0, 'JP3FYD Magnetic Field Measurement')
>>> plt.show()
_images/pyflind_api_ex_mag_plot.png

Register Access

>>> sm.get_register_map()
SM300RegisterMap: {
    0 (0x00): csr
    2 (0x02): pcb_id
    3 (0x03): read_reg
    4 (0x04): scratch
   23 (0x17): schedule_freq
   67 (0x43): checksum_and_state_mon
   68 (0x44): uart_rate
   77 (0x4d): logic_module_ctrl
  101 (0x65): autogain_enable
  110 (0x6e): led_ctrl
  124 (0x7c): sensor_serial_0
  125 (0x7d): sensor_serial_1
  126 (0x7e): sensor_serial_2
  127 (0x7f): sensor_serial_3
  128 (0x80): fw_version_lo
  129 (0x81): fw_version_hi
  130 (0x82): electronics_serial_0
  131 (0x83): electronics_serial_1
  132 (0x84): electronics_serial_2
  133 (0x85): electronics_serial_3
}
>>> sm.get_register('scratch')
0
>>> sm.set_register('scratch', 0xdeaf)
>>> sm.get_register('scratch')
57007

Recording

Record data to a file:

>>> from pyflind.recording import get_fli_recorder
>>> from time import sleep
>>> fs = sm.get_samplerate()
>>> sm.set_max_history(round(fs * 2)) # ensure we have some history overhead to accomodate jitter
>>> rec = get_fli_recorder('smx00_rec_ex.csv', fs) # WAV files also supported
>>> for _ in range(300):
...   sleep(1)
...   data = sm.get_samples()
...   rec.write_data(data)
...
>>> rec.close()

Load data from a recording:

>>> from pyflind.recording import get_fli_recording
>>> rec = get_fli_recording('smx00_rec_ex.csv')
>>> for ch in rec: # list the channels in recording
...   print(ch)
...
larmor_freq
rx_t
rtt
pps_clock_count
>>> t = rec['time'] # time is always available
>>> fs = rec.samplerate()
>>> len(t) / fs
np.float64(307.0507298142522)
>>> larmor_freq = rec['larmor_freq'] # automatically converted to field units on load
>>> import numpy as np
>>> np.mean(larmor_freq)
np.float64(4.520047044447212e-05)