LabVIEW support?

We have now received two requests for Joulescope to support LabVIEW. Would you want to use your Joulescope with LabVIEW? If you want LabVIEW, please :heart: this post.

We are also not LabVIEW experts. If you have recommendations for how to integrate Joulescope with LabVIEW quickly and inexpensively, please post and let us know!

2 Likes

As a LabVIEW user, I think it would a nice capability to have, but I’d have to say that other software integration features would be more useful to me, such as being able to integrate the Joulescope output with embedded debugger trace information. Being able to display Joulescope output synchronized with ARM ITM output, for example, would be IMO the most bang for the buck, and much more useful than having one or two GPIO lines displayed.

I can’t think of a use case where I would apply the LabVIEW integration in a development environment. Perhaps as part of an ATE application, though. I foresee Joulescope being used more in the early development environment than in the production environment. This is why I would strongly urge you to focus on integration into IDE debugging environments. However, when you eventually do make your 2- or 4-quadrant model of the Joulescope, I think there are more use cases geared toward acceptance testing that would present themselves (one of which you and I have already discussed related to isolated medical signals).

Example use case with LabVIEW might be collection of long term charge/discharge profile on a device containing wireless charge capability, such as a medical implantable. The two-quadrant device would be ideal for this, although the current device can work depending on the charging specifications.

Estimating battery life under various operating conditions can always be done with modelling, but having real data as evidentiary documentation will always be accepted.

As far as integrating Joulescope with LabVIEW, a dll with a documented API that exposes the desired Joulescope control and data is all that is really needed for a LabVIEW user to integrate into their application. I have not looked at the Joulescope software - maybe you already have this. If so, it would be a fairly trivial matter to create a LabVIEW driver. You also have a USB interface, so a VISA-compliant driver could also be made. That would be the preferable solution, as National Instruments has many VISA instrument drivers on their website, and yours could be one of them :slight_smile:

1 Like

We received another request for Joulescope LabVIEW integration, so I took a quick look. The quickest path is likely a VISA/VXI-11/TCP/IP socket server. We recently created a simple socket server to enable integration into other programming languages. We could potentially build upon that example.

Here are some interesting code repos:

Specs:

Note that HiSLIP is the successor to VXI-11, but VXI-11 still appears to be well-supported. Here are some (partial?) HiSLIP python implementations:

Hello, I am interested in using LabVIEW with our Joulescope. Has there been any progress on integrating a LabVIEW driver and command set for this?
Thanks!

Hi @mclark10 and welcome to the forum! Thanks for posting about your interest in using LabVIEW with your Joulescope. We have not made any progress on this.

What does Joulescope LabVIEW support mean to you? Are you just looking to use Joulescope’s 2 Hz multimeter data? Like what you can do with SCPI?

Do you plan on needing the full-rate 2 MSPS oscilloscope-style waveform in LabVIEW?

Hi Matt,

Thanks for the reply. My goal is to monitor and log current on multiple devices (a Joulescope per device) at preferably 2-5k samples/sec. Our group in Olathe, KS has a setup to perform this but they are using Python. I was hoping to be able to do something similar using LabVIEW. The device I want to log has a current profile that draws several hundred milliamps on startup, then around 5-15 in full power mode, with 100mA or so spikes during communication, and draws about 15uA in sleep mode, but pulses to about 50mA every 40 seconds or so. Because of its auto ranging capability it looks like the Joulescope is the perfect tool for logging current data for this application. Was hoping there was a LabVIEW VISA driver and SCPI commands I could use. Hopefully someday, if you guys receive enough interest.

Thanks again,

Mark

Python with the pyjoulescope library is perfect for this application. Do you want LabVIEW to control or coordinate with other equipment? If not and python is acceptable, I can put together an example that captures from multiple Joulescope simultaneously.

Since you mentioned multiple devices, please note that the downsampling is performed on the host. The Joulescope instrument always sends the full 2 MSPS data to the host over USB, which limits a single USB 2.0 high-speed root hub to about 3 Joulescopes max. You can add more root hubs to desktop PCs using a PCI-E to USB adapter card.

If you can get by with 2 Hz data, Joulescopes have a mode where that is computed on instrument, which cuts the USB bandwidth to almost nothing. We have many customers using the downsample_logging.py script for long-term data collection for this case.

I will be using LabVIEW to control other equipment. If you can put together something to get me started that would be awesome.

Hi @mclark10 - I just added a capture_all.py example. You will first need to install python and pyjoulescope. See the documentation for instructions. The latest Python 3.9.0 works, but make sure it’s the 64-bit version. You can then either clone the entire pyjoulescope_examples repo or just download the single capture_all.py. Run the script using:

python capture_all --help

To capture from all connected Joulescopes at 2 kHz:

python capture_all -f 2000

Hope this helps, and please post again if you run into issues!

Hi Matt,

I think I can make this work by calling the python script from LabVIEW.

Thanks for your help.

Mark

1 Like

Hello! Late to the thread but I figured best to continue here than start a new one on the same topic. I’ve got a simple implementation of Joulescope Python APIs in LabVIEW using the Python Node blocks. However, right now I run a python function in a loop which searches for a joulescope device and then takes a measurement. I want to seperate this into two steps where I search for a joulescope device once at the beginning and then take measurements in a loop, to increase execution speed (no need to search for the same jouelscope device each time). The problem I have is the Device.search function returns a device class. I’m not sure how to receive this class in LabVIEW and pass it to the following Python Node running in a loop which makes measurements using this Device Class as an input. Any example LabVIEW VI’s like this available? Thanks!

Hi @ap340528 and welcome to the Joulescope forum!

Unfortunately, I don’t have any experience using LabView with Python, but hopefully I can help you figure this out. Passing python objects between different LabView Python Nodes sounds like it could be challenging.

Why not stay within a single Python Node? I suspect that LabView performs python initialization once and should allow you to store data in Python between invocations. If so, you can perform joulescope.scan_require_one at the first invocation and store the resulting joulescope.Device instance. Then on that invocation and all future ones you can call Device.read or whatever you want to do.

My search for the LabView Python documentation only found this which I guess is something. If this is true, you should be able to write a function like this:

myfunction_call_count = 0


def my_function(parameter1):
    global myfunction_call_count
    if myfunction_call_count == 0:
        print('joulescope.scan_require_one')
    myfunction_call_count += 1
    print('joulescope.read %s' % (parameter1, ))


# test as python script
my_function('a')
my_function('b')
my_function('c')

This outputs:

joulescope.scan_require_one
joulescope.read a
joulescope.read b
joulescope.read c

In your script, you would store both myfunction_call_count and the Joulescope.Device instance as global variables.

Note that this approach will not get blocks of samples with gaps. If you want to get the full, continuous waveform, you will need to use the Joulescope streaming API with Device.start rather than Device.read.

Does this help?

Thanks for the feedback Matt.

The reason I don’t have all of this in one node/function is I need to provide feedback to other equipment that I control via LabVIEW. When the current increases above a level, I want to enable another piece of equipment. If I use 1 Node/function, I cant provide feedback to other equipment b/c I’m stuck inside the python node/function measuring. I’m trying to run in a non-blocking manner.

Also, as I mentioned, I was hoping to increase update rate by only calling device discovery once, therefore I need two separate Nodes - one for finding the device, one for measuring.

I’ve ended up …

  1. Declaring a Global object to store the found device, this is done in the python file but outside any function. Here you can see my lack of Python experience …
  2. Creating an initialization function which searches for and store the Joulescope device
  3. Creating a function which takes measurements with Device.read, I call this function using a Python node in a loop to take measurements.

This does seem to work!
However, even with the changes above, the update rate is still pretty slow.

So here’s a follow up question: I know how to capture High resolution .JLS data but I don’t believe I can view it at the same time. I need to view Current data in real time to know when to stop capturing to .JLS - that is, when the current falls back to sleep mode levels. How would you recommend doing this? Monitor current as I do Right now, and start .JLS data capture when current rises? Can I continue to use device.read while .JLS is capturing so I know when to stop capturing or would this interrupt .JLS data? Could I do the same with Reduced Data to CSV?

Also, should I be calling Start() before I use .Read? Thanks!

Making progress!

When you use start, you do not use read. Instead, you register as many stream callbacks as you want using stream_process_register. Check out the read_by_callback example. JLS recording is just a different callback that you register. See the capture_jls_v1 (existing JLS file format) and capture_jls_v2 example (upcoming V2 format, and the Joulescope UI already supports viewing).

You can also checkout the trigger example, which is more complicated but may also be closer to what you envision.

These callbacks are all invoked from the Joulescope thread, so your code may need to resynchronize the data to the LabView calling thread.

Hello,

I am not a Python user and I am trying to use Labview to analyse 2 MSPS raw data from Joulescope.
To do this I am trying to use Joulescope server as you suggest. All is OK untill I’m using the Start command with data={‘fields’: [‘current’, ‘voltage’]} as indicated in “joulescope_server/client.py” client_test_01 example : by return I receive Statistics data but no Raw 2MSPS data as I hoped.
Is it possible to receive these raw data by means of joulescope server ? If so, coud you explain me how to do it ?
Thanks !

Hi @Tverc2 and welcome to the Joulescope forum!

The provided client is just an example. If you want to go with this approach, you will run the provided server, but you would need a corresponding socket client written in LabVIEW. If anyone has already done this, hopefully they can post here!

Now, I did just update the client_test_01 to provide more sensible defaults. It now has the current range set to auto. The example client also now prints every time it receives streaming data. In a real application, your program would need to do something with this data in joulescope_server.client.Client._on_streaming_data.

Does this help?

We have a few LabView users that really just want to capture a JLS file. If this applies to your use case, you can launch a command to do this for you, such as joulescope capture ....

Hi Matt,

thanks for the feedback !

I see you have updated client_test_01 but unfortunately I don’t know how to “translate” this in Labview : I have written the Labview socket client but when I send from Labview the equivalent of " client.transact(‘start’, device=device, data={‘fields’: [‘current’, ‘voltage’]}) " I only receive Stats from server every 0.5 sec.
Should I send an other command ?
I’m currently in JSON format, should I use Binary ?

Hi @Tverc2

I recommend making sure that the server is working well on your machine, first. Start by git pull the latest from pyjoulescope_server. Connect a Joulescope to your machine. Open two terminals. In the first, type:

cd {path/to/pyjoulescope_server}}
python -m joulescope_server server

In the second, type:

cd {path/to/pyjoulescope_server}}
python -m joulescope_server client

Here is what I see in the first:

c:\repos\Jetperch\pyjoulescope_server>python -m joulescope_server server
Serving on ('127.0.0.1', 23423)
INFO:2021-09-22 12:29:38,780:win32_device_notify.py:80:joulescope.usb.winusb.win32_device_notify:open
INFO:2021-09-22 12:29:48,987:server.py:350:joulescope_server.server:ClientManager.run start
INFO:2021-09-22 12:29:48,987:server.py:232:joulescope_server.server:_async_task start
INFO:2021-09-22 12:29:48,990:driver.py:1393:joulescope.driver:scan_for_changes 1 devices: 1 added, 0 removed
INFO:2021-09-22 12:29:48,990:device_thread.py:208:joulescope.usb.device_thread:close
INFO:2021-09-22 12:29:48,991:device_thread.py:139:joulescope.usb.device_thread:DeviceThread.post(close) when thread not running
INFO:2021-09-22 12:29:48,991:device_thread.py:197:joulescope.usb.device_thread:open
INFO:2021-09-22 12:29:48,991:device_thread.py:125:joulescope.usb.device_thread:DeviceThread.run start
INFO:2021-09-22 12:29:48,991:device.py:697:joulescope.usb.winusb.device:WinUsbDevice.close
INFO:2021-09-22 12:29:48,991:device.py:653:joulescope.usb.winusb.device:WinUsbDevice.open
INFO:2021-09-22 12:29:48,991:device.py:682:joulescope.usb.winusb.device:is_high_speed = True
INFO:2021-09-22 12:29:48,991:device.py:683:joulescope.usb.winusb.device:interface_settings = InterfaceDescriptor(
    length=9,
    descriptor_type=4,
    interface_number=0,
    alternate_setting=0,
    num_endpoints=2,
    interface_class=255,
    interface_sub_class=0,
    interface_protocol=0,
    interface=0)
INFO:2021-09-22 12:29:48,991:driver.py:525:joulescope.driver:Create StreamBuffer
INFO:2021-09-22 12:29:49,103:driver.py:556:joulescope.driver:info:
{
  "type": "info",
  "ver": 1,
  "ctl": {
    "mfg": {
      "country": "USA",
      "location": "MD_01",
      "lot": "201927_00"
    },
    "hw": {
      "rev": "H",
      "sn_mcu": "E10230201E078CAAADDCD9854091005F",
      "sn_mfg": "000147"
    },
    "fw": {
      "ver": "1.3.2"
    },
    "fpga": {
      "ver": "0.2.0",
      "prod_id": "0x9314acf2"
    }
  },
  "sensor": {
    "fw": {
      "ver": "1.3.2"
    },
    "fpga": {
      "ver": "1.2.1"
    }
  }
}
INFO:2021-09-22 12:29:49,103:driver.py:503:joulescope.driver:serial number = 1e200302e170c8aadacd9d58041900f5
INFO:2021-09-22 12:29:49,162:device.py:776:joulescope.usb.winusb.device:read_stream_start 2
INFO:2021-09-22 12:29:49,162:device.py:406:joulescope.usb.winusb.device:endpoint start 0x82 transfer size = 131072 bytes
INFO:2021-09-22 12:29:50,188:server.py:258:joulescope_server.server:_statistics_fn Joulescope:000147
INFO:2021-09-22 12:29:50,688:server.py:258:joulescope_server.server:_statistics_fn Joulescope:000147
INFO:2021-09-22 12:29:51,188:server.py:258:joulescope_server.server:_statistics_fn Joulescope:000147
INFO:2021-09-22 12:29:51,688:server.py:258:joulescope_server.server:_statistics_fn Joulescope:000147
INFO:2021-09-22 12:29:52,158:driver.py:880:joulescope.driver:stop : streaming=True
INFO:2021-09-22 12:29:52,158:device.py:789:joulescope.usb.winusb.device:read_stream_stop 2
INFO:2021-09-22 12:29:52,159:device.py:415:joulescope.usb.winusb.device:endpoint stop
INFO:2021-09-22 12:29:52,159:driver.py:810:joulescope.driver:streaming done(0, )
INFO:2021-09-22 12:29:52,159:server.py:314:joulescope_server.server:_stop_fn Joulescope:000147
INFO:2021-09-22 12:29:52,185:driver.py:880:joulescope.driver:stop : streaming=False
INFO:2021-09-22 12:29:52,185:device_thread.py:208:joulescope.usb.device_thread:close
INFO:2021-09-22 12:29:52,185:device.py:697:joulescope.usb.winusb.device:WinUsbDevice.close
INFO:2021-09-22 12:29:52,185:device_thread.py:102:joulescope.usb.device_thread:DeviceThread._cmd_process_all close
INFO:2021-09-22 12:29:52,185:device_thread.py:132:joulescope.usb.device_thread:DeviceThread.run flush
INFO:2021-09-22 12:29:52,186:device_thread.py:134:joulescope.usb.device_thread:DeviceThread.run done
INFO:2021-09-22 12:29:52,186:server.py:373:joulescope_server.server:Client closed socket
INFO:2021-09-22 12:29:52,187:server.py:249:joulescope_server.server:_async_task done
INFO:2021-09-22 12:29:52,187:server.py:382:joulescope_server.server:ClientManager.run done

and the second:

c:\repos\Jetperch\pyjoulescope_server>python -m joulescope_server client
INFO:2021-09-22 12:29:48,987:client.py:73:joulescope_server.client:req: {'id': 0, 'type': 'hello', 'phase': 'req'}
INFO:2021-09-22 12:29:48,987:client.py:84:joulescope_server.client:rsp: {'id': 0, 'type': 'hello', 'phase': 'rsp', 'status': 200, 'status_msg': 'Success', 'data': {'protocol_version': 1, 'server_version': '0.1.1', 'joulescope_version': '0.9.7'}}
INFO:2021-09-22 12:29:48,987:client.py:73:joulescope_server.client:req: {'id': 1, 'type': 'scan', 'phase': 'req', 'config': 'auto'}
INFO:2021-09-22 12:29:48,990:client.py:84:joulescope_server.client:rsp: {'id': 1, 'type': 'scan', 'phase': 'rsp', 'config': 'auto', 'status': 200, 'status_msg': 'Success', 'data': ['Joulescope:000147']}
INFO:2021-09-22 12:29:48,990:client.py:73:joulescope_server.client:req: {'id': 2, 'type': 'open', 'phase': 'req', 'device': 'Joulescope:000147'}
INFO:2021-09-22 12:29:49,155:client.py:84:joulescope_server.client:rsp: {'id': 2, 'type': 'open', 'phase': 'rsp', 'device': 'Joulescope:000147', 'status': 200, 'status_msg': 'Success'}
INFO:2021-09-22 12:29:49,156:client.py:73:joulescope_server.client:req: {'id': 3, 'type': 'parameters', 'phase': 'req', 'device': 'Joulescope:000147'}
INFO:2021-09-22 12:29:49,157:client.py:84:joulescope_server.client:rsp: {'id': 3, 'type': 'parameters', 'phase': 'rsp', 'device': 'Joulescope:000147', 'status': 200, 'status_msg': 'Success', 'data': {'sensor_power': {'name': 'sensor_power', 'default': 'on', 'path': 'setting', 'options': [['off', 0, []], ['on', 1, []]], 'units': None, 'brief': 'Force the sensor power on or off.', 'detail': 'Altering this parameter during operation may cause errors.', 'flags': ['developer']}, 'source': {'name': 'source', 'default': 'off', 'path': 'setting', 'options': [['off', 0, []], ['raw', 192, ['on']], ['pattern_usb', 9, []], ['pattern_control', 10, []], ['pattern_sensor', 175, []]], 'units': None, 'brief': 'Select the streaming data source.', 'detail': None, 'flags': ['developer']}, 'i_range': {'name': 'i_range', 'default': 'off', 'path': 'setting', 'options': [['auto', 128, ['on']], ['10 A', 1, ['0', 0]], ['2 A', 2, ['1', 1]], ['180 mA', 4, ['2', 2]], ['18 mA', 8, ['3', 3]], ['1.8 mA', 16, ['4', 4]], ['180 µA', 32, ['5', 5]], ['18 µA', 64, ['6', 6]], ['off', 0, []]], 'units': None, 'brief': 'Select the current measurement range (shunt resistor)', 'detail': None, 'flags': []}, 'v_range': {'name': 'v_range', 'default': '15V', 'path': 'setting', 'options': [['15V', 0, ['low', 0]], ['5V', 1, ['high', 1]]], 'units': None, 'brief': 'Select the voltage measurement range (gain)', 'detail': None, 'flags': []}, 'ovr_to_lsb': {'name': 'ovr_to_lsb', 'default': 'off', 'path': 'setting', 'options': [['off', 0, []], ['on', 1, []]], 'units': None, 'brief': 'Map overflow flags to the LSBs', 'detail': None, 'flags': ['developer']}, 'trigger_source': {'name': 'trigger_source', 'default': 'auto', 'path': 'extio', 'options': [['auto', 0, []], ['gpi0', 2, []], ['gpi1', 3, []]], 'units': None, 'brief': 'Select the trigger source', 'detail': None, 'flags': ['hidden']}, 'io_voltage': {'name': 'io_voltage', 'default': '3.3V', 'path': 'extio', 'options': [['1.8V', 1800, []], ['2.1V', 2100, []], ['2.5V', 2500, []], ['2.7V', 2700, []], ['3.0V', 3000, []], ['3.3V', 3300, []], ['3.6V', 3600, []], ['5.0V', 5000, []]], 'units': None, 'brief': 'The GPI/O high-level voltage.', 'detail': None, 'flags': []}, 'gpo0': {'name': 'gpo0', 'default': '0', 'path': 'extio', 'options': [['0', 0, [0]], ['1', 1, [1]]], 'units': None, 'brief': 'The GPO bit 0 output value.', 'detail': None, 'flags': []}, 'gpo1': {'name': 'gpo1', 'default': '0', 'path': 'extio', 'options': [['0', 0, [0]], ['1', 1, [1]]], 'units': None, 'brief': 'The GPO bit 1 output value.', 'detail': None, 'flags': []}, 'current_lsb': {'name': 'current_lsb', 'default': 'normal', 'path': 'extio', 'options': [['normal', 0, []], ['gpi0', 2, []], ['gpi1', 3, []]], 'units': None, 'brief': 'The current signal least-significant bit mapping.', 'detail': None, 'flags': []}, 'voltage_lsb': {'name': 'voltage_lsb', 'default': 'normal', 'path': 'extio', 'options': [['normal', 0, []], ['gpi0', 2, []], ['gpi1', 3, []]], 'units': None, 'brief': 'The voltage signal least-significant bit mapping.', 'detail': None, 'flags': []}, 'control_test_mode': {'name': 'control_test_mode', 'default': 'normal', 'path': 'setting', 'options': [['normal', 3, []], ['usb', 129, []], ['fpga', 130, []], ['both', 131, []]], 'units': None, 'brief': 'Set the test mode', 'detail': None, 'flags': ['developer']}, 'transfer_length': {'name': 'transfer_length', 'default': '256', 'path': 'setting', 'options': [['1', 1, []], ['2', 2, []], ['4', 4, []], ['8', 8, []], ['16', 16, []], ['32', 32, []], ['64', 64, []], ['128', 128, []], ['256', 256, []]], 'units': 'packets', 'brief': 'Set the USB transfer length in packets', 'detail': None, 'flags': ['developer', 'skip_update']}, 'transfer_outstanding': {'name': 'transfer_outstanding', 'default': '8', 'path': 'setting', 'options': [['1', 1, []], ['2', 2, []], ['4', 4, []], ['8', 8, []]], 'units': None, 'brief': 'Set the maximum number of USB transfers issued simultaneously', 'detail': None, 'flags': ['developer', 'skip_update']}, 'current_ranging': {'name': 'current_ranging', 'default': None, 'path': 'current_ranging', 'options': [], 'units': None, 'brief': None, 'detail': None, 'flags': ['hidden']}, 'current_ranging_type': {'name': 'current_ranging_type', 'default': 'interp', 'path': 'current_ranging', 'options': [['off', 'off', []], ['mean', 'mean', []], ['interp', 'interp', ['interpolate']], ['NaN', 'nan', ['nan']]], 'units': None, 'brief': 'The filter type.', 'detail': None, 'flags': []}, 'current_ranging_samples_pre': {'name': 'current_ranging_samples_pre', 'default': '1', 'path': 'current_ranging', 'options': [['0', 0, [0]], ['1', 1, [1]], ['2', 2, [2]], ['3', 3, [3]], ['4', 4, [4]], ['5', 5, [5]], ['6', 6, [6]], ['7', 7, [7]], ['8', 8, [8]]], 'units': None, 'brief': 'The number of samples before the range switch to include.', 'detail': 'Only valid for type "mean" - ignored for "off", "interp", and "NaN".', 'flags': []}, 'current_ranging_samples_window': {'name': 'current_ranging_samples_window', 'default': 'n', 'path': 'current_ranging', 'options': [['m', 'm', []], ['n', 'n', []], ['0', 0, [0]], ['1', 1, [1]], ['2', 2, [2]], ['3', 3, [3]], ['4', 4, [4]], ['5', 5, [5]], ['6', 6, [6]], ['7', 7, [7]], ['8', 8, [8]], ['9', 9, [9]], ['10', 10, [10]], ['11', 11, [11]], ['12', 12, [12]]], 'units': None, 'brief': 'The number of samples to adjust.', 'detail': 'Use "n" for automatic duration based upon known response time. Use "m" for shorter automatic duration that may result in min/max distortion.', 'flags': []}, 'current_ranging_samples_post': {'name': 'current_ranging_samples_post', 'default': '1', 'path': 'current_ranging', 'options': [['0', 0, [0]], ['1', 1, [1]], ['2', 2, [2]], ['3', 3, [3]], ['4', 4, [4]], ['5', 5, [5]], ['6', 6, [6]], ['7', 7, [7]], ['8', 8, [8]]], 'units': None, 'brief': 'The number of samples after the range switch to include.', 'detail': 'Only valid for type "mean" - ignored for "off", "interp", and "NaN".', 'flags': []}, 'buffer_duration': {'name': 'buffer_duration', 'default': '30 seconds', 'path': 'setting', 'options': [['15 seconds', 15, [15]], ['30 seconds', 30, [30]], ['1 minute', 60, [60]], ['2 minutes', 120, [120]], ['5 minutes', 300, [300]], ['10 minutes', 600, [600]], ['20 minutes', 1200, [1200]], ['1 hour', 3600, [3600]], ['2 hours', 7200, [7200]], ['5 hours', 18000, [18000]], ['10 hours', 36000, [36000]], ['1 day', 86400, [86400]]], 'units': 'seconds', 'brief': 'The amount of sample data to store in memory.', 'detail': 'Use care when setting this value. The software requires 1.5 GB of RAM for every 60 seconds at the full 2 MSPS rate.', 'flags': ['skip_update']}, 'reduction_frequency': {'name': 'reduction_frequency', 'default': '2 Hz', 'path': 'setting', 'options': [['100 Hz', 100, [100]], ['50 Hz', 50, [50]], ['20 Hz', 20, [20]], ['10 Hz', 10, [10]], ['5 Hz', 5, [5]], ['2 Hz', 2, [2]], ['1 Hz', 1, [1]]], 'units': 'Hz', 'brief': 'The rate that the device produces statistics, including multimeter values.', 'detail': None, 'flags': ['skip_update']}, 'sampling_frequency': {'name': 'sampling_frequency', 'default': '2 MHz', 'path': 'setting', 'options': [['2 MHz', 2000000, [2000000, 'auto', None, 'default']], ['1 MHz', 1000000, [1000000]], ['500 kHz', 500000, [500000]], ['200 kHz', 200000, [200000]], ['100 kHz', 100000, [100000]], ['50 kHz', 50000, [50000]], ['20 kHz', 20000, [20000]], ['10 kHz', 10000, [10000]], ['5 kHz', 5000, [5000]], ['2 kHz', 2000, [2000]], ['1 kHz', 1000, [1000]], ['500 Hz', 500, [500]], ['200 Hz', 200, [200]], ['100 Hz', 100, [100]], ['50 Hz', 50, [50]], ['20 Hz', 20, [20]], ['10 Hz', 10, [10]]], 'units': 'Hz', 'brief': 'The rate that the device produces samples.', 'detail': None, 'flags': ['skip_update']}, 'model': {'name': 'model', 'default': None, 'path': 'info', 'options': [], 'units': None, 'brief': None, 'detail': None, 'flags': ['read_only', 'hidden']}, 'device_serial_number': {'name': 'device_serial_number', 'default': None, 'path': 'info', 'options': [], 'units': None, 'brief': None, 'detail': None, 'flags': ['read_only', 'hidden']}, 'hardware_serial_number': {'name': 'hardware_serial_number', 'default': None, 'path': 'info', 'options': [], 'units': None, 'brief': None, 'detail': None, 'flags': ['read_only', 'hidden']}}}
INFO:2021-09-22 12:29:49,158:client.py:73:joulescope_server.client:req: {'id': 4, 'type': 'info', 'phase': 'req', 'device': 'Joulescope:000147'}
INFO:2021-09-22 12:29:49,160:client.py:84:joulescope_server.client:rsp: {'id': 4, 'type': 'info', 'phase': 'rsp', 'device': 'Joulescope:000147', 'status': 200, 'status_msg': 'Success', 'data': {'type': 'info', 'ver': 1, 'ctl': {'mfg': {'country': 'USA', 'location': 'MD_01', 'lot': '201927_00'}, 'hw': {'rev': 'H', 'sn_mcu': 'E10230201E078CAAADDCD9854091005F', 'sn_mfg': '000147'}, 'fw': {'ver': '1.3.2'}, 'fpga': {'ver': '0.2.0', 'prod_id': '0x9314acf2'}}, 'sensor': {'fw': {'ver': '1.3.2'}, 'fpga': {'ver': '1.2.1'}}}}
INFO:2021-09-22 12:29:49,160:client.py:73:joulescope_server.client:req: {'id': 5, 'type': 'parameter_get', 'phase': 'req', 'device': 'Joulescope:000147', 'data': {'name': 'i_range'}}
INFO:2021-09-22 12:29:49,161:client.py:84:joulescope_server.client:rsp: {'id': 5, 'type': 'parameter_get', 'phase': 'rsp', 'device': 'Joulescope:000147', 'data': 'auto', 'status': 200, 'status_msg': 'Success'}
INFO:2021-09-22 12:29:49,161:client.py:73:joulescope_server.client:req: {'id': 6, 'type': 'parameter_set', 'phase': 'req', 'device': 'Joulescope:000147', 'data': {'name': 'i_range', 'value': 'auto'}}
INFO:2021-09-22 12:29:49,161:client.py:84:joulescope_server.client:rsp: {'id': 6, 'type': 'parameter_set', 'phase': 'rsp', 'device': 'Joulescope:000147', 'data': {'name': 'i_range', 'value': 'auto'}, 'status': 200, 'status_msg': 'Success'}
INFO:2021-09-22 12:29:49,161:client.py:73:joulescope_server.client:req: {'id': 7, 'type': 'start', 'phase': 'req', 'device': 'Joulescope:000147', 'data': {'fields': ['current', 'voltage']}}
INFO:2021-09-22 12:29:49,163:client.py:84:joulescope_server.client:rsp: {'id': 7, 'type': 'start', 'phase': 'rsp', 'device': 'Joulescope:000147', 'data': True, 'status': 200, 'status_msg': 'Success'}
current: 32256
voltage: 32256
current: 32256
voltage: 32256
...
current: 32256
voltage: 32256
INFO:2021-09-22 12:29:50,190:client.py:59:joulescope_server.client:async: {'type': 'statistics', 'phase': 'async', 'device': 'Joulescope:000147', 'data': {'time': {'range': {'value': [0.5, 1.0], 'units': 's'}, 'delta': {'value': 0.5, 'units': 's'}, 'samples': {'value': 1000000, 'units': 'samples'}, 'sample_range': {'value': [1000000, 2000000], 'units': 'input_samples'}}, 'signals': {'current': {'µ': {'value': -2.3213177639670936e-09, 'units': 'A'}, 'σ2': {'value': 7.45609253180676e-16, 'units': 'A'}, 'min': {'value': -1.0497814173504594e-07, 'units': 'A'}, 'max': {'value': 8.99615457683467e-08, 'units': 'A'}, 'p2p': {'value': 1.9493968750339263e-07, 'units': 'A'}, '∫': {'value': -1.1606588819835468e-09, 'units': 'C'}}, 'voltage': {'µ': {'value': -0.0009271737867749834, 'units': 'V'}, 'σ2': {'value': 1.8944171830659998e-05, 'units': 'V'}, 'min': {'value': -0.01124096941202879, 'units': 'V'}, 'max': {'value': 0.00918980035930872, 'units': 'V'}, 'p2p': {'value': 0.02043076977133751, 'units': 'V'}}, 'power': {'µ': {'value': 9.36213822781648e-12, 'units': 'W'}, 'σ2': {'value': 1.2505675908742891e-20, 'units': 'W'}, 'min': {'value': -7.121401801590821e-10, 'units': 'W'}, 'max': {'value': 7.803207524581524e-10, 'units': 'W'}, 'p2p': {'value': 1.4924609326172344e-09, 'units': 'W'}, '∫': {'value': 4.68106911390824e-12, 'units': 'J'}}, 'current_range': {'µ': {'value': 6.0, 'units': ''}, 'σ2': {'value': 0.0, 'units': ''}, 'min': {'value': 6.0, 'units': ''}, 'max': {'value': 6.0, 'units': ''}, 'p2p': {'value': 0.0, 'units': ''}}, 'current_lsb': {'µ': {'value': 0.5333340000000001, 'units': ''}, 'σ2': {'value': 0.2488890933330933, 'units': ''}, 'min': {'value': 0.0, 'units': ''}, 'max': {'value': 1.0, 'units': ''}, 'p2p': {'value': 1.0, 'units': ''}}, 'voltage_lsb': {'µ': {'value': 0.5333340000000001, 'units': ''}, 'σ2': {'value': 0.2488890933330933, 'units': ''}, 'min': {'value': 0.0, 'units': ''}, 'max': {'value': 1.0, 'units': ''}, 'p2p': {'value': 1.0, 'units': ''}}}, 'source': 'stream_buffer', 'accumulators': {'charge': {'value': -1.1600000000000001e-09, 'units': 'C'}, 'energy': {'value': 4e-12, 'units': 'J'}}}, 'status': 200, 'status_msg': 'Success'}
...
INFO:2021-09-22 12:29:52,158:client.py:73:joulescope_server.client:req: {'id': 8, 'type': 'stop', 'phase': 'req', 'device': 'Joulescope:000147'}
current: 32256
voltage: 32256
INFO:2021-09-22 12:29:52,184:client.py:84:joulescope_server.client:rsp: {'id': 8, 'type': 'stop', 'phase': 'rsp', 'device': 'Joulescope:000147', 'status': 200, 'status_msg': 'Success', 'data': True}
INFO:2021-09-22 12:29:52,184:client.py:73:joulescope_server.client:req: {'id': 9, 'type': 'close', 'phase': 'req', 'device': 'Joulescope:000147'}
INFO:2021-09-22 12:29:52,185:client.py:59:joulescope_server.client:async: {'type': 'stop', 'phase': 'async', 'device': 'Joulescope:000147', 'data': {'event': 0, 'message': ''}, 'status': 200, 'status_msg': 'Success'}
INFO:2021-09-22 12:29:52,186:client.py:84:joulescope_server.client:rsp: {'id': 9, 'type': 'close', 'phase': 'rsp', 'device': 'Joulescope:000147', 'status': 200, 'status_msg': 'Success'}
Close the socket

Does this match what you see?

Note that this line of the server output is very important:

INFO:2021-09-22 12:29:49,162:device.py:776:joulescope.usb.winusb.device:read_stream_start 2

Now, with your LabVIEW client, do you see the same server line?

If so, then your client is correctly sending the TAG_AJS start command, and the client is likely not handling the TAG_ABN binary streaming data response.

If not, we have to make sure that you are sending the correct command.

Let me know what you see!

You should say hello (ideally checking the version), scan, open, set i_range to auto (which I think it should be by default), then start, somewhat like this:

    rsp = await client.transact('hello')
    rsp = await client.transact('scan', config='auto')
    if not len(rsp['data']):
        print('Device not found')
        writer.close()
        return
    device = rsp['data'][0]
    rsp = await client.transact('open', device=device)
    rsp = await client.transact('parameter_set', device=device, data={'name': 'i_range', 'value': 'auto'})
    rsp = await client.transact('start', device=device, data={'fields': ['current', 'voltage']})

Hi Matt,

thank you for this very detailed and precised answer !

Unfortunately I’m not at the office today so I’ll be able test it with Joulescope only tomorrow.
I agree with you the line “INFO:2021-09-22 12:29:49,162:device.py:776:joulescope.usb.winusb.device:read_stream_start 2” of the server output following the line “INFO:2021-09-22 12:29:49,161:client.py:73:joulescope_server.client:req: {‘id’: 7, ‘type’: ‘start’, ‘phase’: ‘req’, ‘device’: ‘Joulescope:000147’, ‘data’: {‘fields’: [‘current’, ‘voltage’]}}” of the client output is the very important : it will be the first I’ll look tomorrow.
But I think the answer to my problem is contained in your sentence “If so, then your client is correctly sending the TAG_AJS start command, and the client is likely not handling the TAG_ABN binary streaming data response.” : indeed I thought the answer to all the TAG_AJS command was equally TAG_AJS …