../../_images/monodaq-u-x.png

Synchronized Operation of Multiple MonoDAQ-U-X

To extend number of channels, MonoDAQ-U-X feature a USB Sync Technology, which without any additional wiring synchronizes a number of MonoDAQ’s within 10 ns. This is possible as long all MonoDAQ’s share the same USB Host Controller.

The USB Sync Technology is currently implemented in IDM USB Proxy (idm_usbproxy) software that also provides remote connectivity with the IDM and the Dewesoft X3 MonoDAQ-U-X plugin.

Setup a Connection with IDM USB Proxy

Enable IDM to receive Remote UDP Connections and click [ Apply ] button:

../../_images/idm-udpremote.png

Start the idm_usbproxy with the server name (or IP), in our case the localhost. Note that in this way it’s possible to gather multiple dislocated devices from RaspberryPI’s, or other computers.

$ ./idm_usbproxy --server-host=localhost
[2018-10-17 12:02:15.129] [user] [info] IDM USB proxy starting
[2018-10-17 12:02:15.129] [user] [info] listening on UDP port 8100
[2018-10-17 12:02:15.129] [user] [info] NB! connecting to the remote site localhost:33005
[2018-10-17 12:02:15.136] [user] [info] using firmware path: .
[2018-10-17 12:02:15.183] [user] [info] connected device MonoDAQ-UX-MB-v3 v1.55.0.21, serial: 9900021715170584
[2018-10-17 12:02:15.245] [user] [info] connected device MonoDAQ-UX-MB-v2 v1.55.0.21, serial: 7F000210081A1874
[2018-10-17 12:02:15.246] [user] [info] IDM USB proxy started

and the two MonoDAQ’s appear under Network Devices, ready to be used.

../../_images/idm-udpdev.png

Notebooks typically have multiple USB Host Controllers, often divided to the left and right side connectors. Error is returned when synchronization is not possible. To overcome this issue use USB 3.0 HUBs, which provide multiple transaction translators.

Python and Jupyter Support

The isotel-idm package provides a class monodaq.MonoDAQs_U() which takes as argument the single monodaq.MonoDAQ_U() instances and creates a group. See the example Synchronized Operation

GettingStarted

Getting Started with Multiple MonoDAQs

Here we represent how to fetch samples synchronously from two MonoDAQs one operating at 1 kSa/s and the other at 2 kSa/s.

In [1]:
from isotel.idm import monodaq, signal

Attach the 1st MonoDAQ-U-X

We may randomly pick one, or we may provide a name parameter with it's serial number to always stick at the same one. To be able to distinguish the pin names from the other ones, we assign a prefix to be used in output streams signal names.

In [2]:
mdu1 = monodaq.MonoDAQ_U(prefix='A')
mdu1.print_setup()
pinfunctiontyperangerate [Hz]minmaxoffsetsetvalueunit
V1+ Voltage Input Single LPF ±10V 1000 -10.0 10.0 --- --- 0.006 V
NC --- --- --- --- --- --- --- --- ---
3 Off --- --- --- --- --- --- --- ---
4 Off --- --- --- --- --- --- --- ---
5 Off --- --- --- --- --- --- --- ---
6 Off --- --- --- --- --- --- --- ---
7 Off --- --- --- --- --- --- --- ---
8 Off --- --- --- --- --- --- --- ---
GND OneWire --- --- --- --- --- --- --- ---
IO --- --- --- --- --- --- --- --- ---
CUR+ Off --- --- --- --- --- --- --- ---
CUR- --- --- --- --- --- --- --- --- ---
GND --- --- --- --- --- --- --- --- ---
PWR Off --- --- --- --- --- --- --- ---

Ambient

Tcjc=26.6 ±0.2 oC RH=54 ±2 %

Attach the 2nd MonoDAQ-U-X

Exactly the same procedure as above, just that we assign to it a different prefix.

In [3]:
mdu2 = monodaq.MonoDAQ_U(exclude=[mdu1], prefix='B')
mdu2.print_setup()
pinfunctiontyperangerate [Hz]minmaxoffsetsetvalueunit
V1+ Voltage Input Single LPF ±10V 2000 -10.0 10.0 --- --- 0.054 V
NC --- --- --- --- --- --- --- --- ---
3 Off --- --- --- --- --- --- --- ---
4 Off --- --- --- --- --- --- --- ---
5 Off --- --- --- --- --- --- --- ---
6 Off --- --- --- --- --- --- --- ---
7 Off --- --- --- --- --- --- --- ---
8 Off --- --- --- --- --- --- --- ---
GND OneWire --- --- --- --- --- --- --- ---
IO --- --- --- --- --- --- --- --- ---
CUR+ Off --- --- --- --- --- --- --- ---
CUR- --- --- --- --- --- --- --- --- ---
GND --- --- --- --- --- --- --- --- ---
PWR Off --- --- --- --- --- --- --- ---

Ambient

Tcjc=28.3 ±0.2 oC RH=65 ±3 %

Create a Group

With the helper class MonoDAQs_U() one may combine any number of MonoDAQ-U-X which come from the same USB source and were successfully synchronized.

In [4]:
mdus = monodaq.MonoDAQs_U(mdu1, mdu2)

Fetch Samples

The use of a group fetch() is exactly the same as fetch() for individual device. The output stream uses assigned prefixes to distinguish channels among devices.

In multi-rate environment the number of samples requested is equal to number of samples of the fastest stream, and others are terminated at that point. Here you may see BV1 has 5 samples, while AV1 obtained 3 samples.

In [5]:
list(signal.stream2signal(mdus.fetch(5)))
Out[5]:
[{'AV1+ [V]': {'x': [0.0, 0.001, 0.002], 'y': [0.008, 0.005, 0.0065]},
  'BV1+ [V]': {'x': [0.0, 0.0005, 0.001, 0.0015, 0.002],
   'y': [0.054, 0.0525, 0.053, 0.053, 0.053]}}]

Multi-Rate Math with Scope

You may observe AV1+ is running at a lower rate (1 kSa/s) than BV1+ (2 kSa/s), however math operations will still work well on concurrent samples as seen in this Scope example.

In this example we amplify the difference between the channels by 1000, where both MonoDAQs have left pins open.

In [6]:
N = 20000

signal.scope( 
    signal.stream2signal( 
        signal.addmath( mdus.fetch(N), 'diff [mV]', expr='1000*(AV1-BV1)'),
        split=500)
);
Loading BokehJS ...