JS110 python driver read

Hi,

I’m having difficulty finding an efficient way to read V/A/W values using a Joulescope JS110 (S/N 002973) in Python.

I’ve been using the Joulescope Python package (version 1.1.5) and have had some success with reading statistics. However, I ran into a limitation with the reduction frequency, which maxes out at 100 Hz—unfortunately, that’s not sufficient for my use case. I should mention that I’m not an advanced Python user, and I find the drivers somewhat challenging to navigate.

I attempted to use the read function, but frequently encountered timeout errors, although not every time. Is there a reliable and efficient way to read out values every 0.5–1 ms in a Python script and store them in an array? Also, is there any additional documentation beyond the API instructions? Would you recommend using a different driver or approach for this purpose?

Thanks for your help!

Errors when I use the read example :

Traceback (most recent call last):
File “/home/dominik/Documents/ina/test_joulescope_raw.py”, line 7, in
js.close(timeout=1 )
File “/home/dominik/.local/lib/python3.10/site-packages/joulescope/v1/device.py”, line 395, in close
return self._driver.close(self._path, timeout)
File “pyjoulescope_driver/binding.pyx”, line 879, in pyjoulescope_driver.binding.Driver.close
File “pyjoulescope_driver/binding.pyx”, line 593, in pyjoulescope_driver.binding._handle_rc
TimeoutError: jsdrv_close timed out | u/js110/002973

OR:

_on_cmd_publish_cbk(u/js110/002973/s/v/!data)
Traceback (most recent call last):
File “pyjoulescope_driver/binding.pyx”, line 893, in pyjoulescope_driver.binding._on_cmd_publish_cbk
File “/home/dominik/.local/lib/python3.10/site-packages/joulescope/v1/device.py”, line 445, in _on_stream
_, e1 = b.sample_id_range
AttributeError: ‘NoneType’ object has no attribute ‘sample_id_range’
_on_cmd_publish_cbk(u/js110/002973/s/p/!data)
Traceback (most recent call last):
File “pyjoulescope_driver/binding.pyx”, line 893, in pyjoulescope_driver.binding._on_cmd_publish_cbk
File “/home/dominik/.local/lib/python3.10/site-packages/joulescope/v1/device.py”, line 445, in _on_stream

Hi @Dominik - Did you really mean joulescope package 1.1.5? The latest is 1.1.15 with pyjoulescope_driver 1.5.6.

PS C:\tmp> python -m pyjoulescope_driver info

    SYSTEM INFORMATION
    ------------------
    python               3.12.4 (tags/v3.12.4:8e8a4ba, Jun  6 2024, 19:30:16) [MSC v.1940 64 bit (AMD64)]
    python impl          CPython
    platform             Windows-11-10.0.22631-SP0
    processor            Intel64 Family 6 Model 183 Stepping 1, GenuineIntel
    CPU cores            24 physical, 32 total
    CPU frequency        3000 MHz (0 MHz min to 3000 MHz max)
    RAM                  38.6 GB available, 63.7 GB total (60.5%)

    PYTHON PACKAGE INFORMATION
    --------------------------
    jls                  0.10.0
    joulescope           1.1.15
    numpy                1.26.4
    pyjoulescope_driver  1.5.6


    JOULESCOPE INFORMATION
    ----------------------
    u/js110/000494

Are you simply trying to capture Joulescope data from the command line? You don’t even need a python script for this. How about something like:

python -m pyjoulescope_driver record --frequency 1000 --duration 10 out.jls

It’s really hard to troubleshoot your script without seeing it. Can you post it? Also, share the output of:

python -m pyjoulescope_driver info

You really do not want to be closing and opening the JS110 quickly. Just keep it open. The JS110 also has missing samples sometimes very soon after stream start on some computers. If you want data over lots of very small windows, it’s better to keep it streaming and simply use the data you want.

You have two choices for APIs: joulescope and the lower-level pyjoulescope_driver. The joulescope API limits statistics to 100 Hz, but you can specifify faster rates with pyjoulescope_driver. While both APIs work, I like the pyjoulescope_driver if you are trying to process sample data on the fly. See read_by_pyjoulescope_driver for an example.

If you can provide more detail on what you are trying to automate, I can be more helpful. For example:

  1. How are you determining when to start & stop Joulescope captures?
  2. How long are the captures and the intervals between them?
  3. Are you trying to do online processing of the Joulescope data?

Thank you for your very quick answer I really appreciate that. We are using the Joulescope for a long time and a lot and I would like to say; It’s very nice device to work with and I love it :slight_smile:

I’m currently running on a VM on Linux

    ------------------
    python               3.10.12 (main, Sep 11 2024, 15:47:36) [GCC 11.4.0]
    python impl          CPython
    platform             Linux-5.15.0-124-generic-x86_64-with-glibc2.35
    processor            x86_64
    CPU cores            2 physical, 2 total
    CPU frequency        3294 MHz (0 MHz min to 0 MHz max)   
    RAM                  5.9 GB available, 7.7 GB total (76.2%)
    
    PYTHON PACKAGE INFORMATION
    --------------------------
    jls                  0.10.0
    joulescope           1.1.15
    numpy                1.26.4
    pyjoulescope_driver  1.5.6
    

    JOULESCOPE INFORMATION
    ----------------------


My goal is to start the Joulscope; and after approximately 3 sec start capturing measurements every 1ms or less and collect data into an array. I don’t like to use it via command line, I need to write my own script.

  1. There is no set time when the joulescope starts. It always has to be activated when the program starts and then there are a few seconds until I need the measured values.
  2. 1ms
  3. I need the samples to calculate the mean for short measurements ~200 sec ( 1ms sample frequency) and log measurements 24h (10ms sample frequency)

I’snt it possible to simply use the read function from an example and modify inervalls?

import joulescope
import numpy as np
with joulescope.scan_require_one(config='auto') as js:
    data = js.read(contiguous_duration=0.1)
current, voltage = np.mean(data, axis=0, dtype=np.float64)
print(f'{current} A, {voltage} V')

So I had a quick look also into pyjoulescope_examples/bin/read_by_pyjoulescope_driver.py at main · jetperch/pyjoulescope_examples · GitHub

The problem is here that I have to isolate the reading from set configuration and start of the device because I would like to not do that in series. The challenge is that I have to start another peripheral (measurement device) in parallel in my script I want to create.

Hi, sorry that I respond so often but I want to share my measurements with the example measurements script you forwarded to me:

/usr/bin/python3 /home/dominik/Documents/ina/pyjoulescope_examples/bin/read_by_pyjoulescope_driver.py -v -f 100
Find the connected devices
Found devices: ['u/js110/002973']
Open and configure each device
Perform the sample read
2024-10-22 09:56:03,995 WARNING  jsdrv pkt_index skip: expected 0, received 1
Display the mean (ignoring NaNs) for each signal
u/js110/002973.current:   -6.548361852765083e-09 A | ignored 20 NaNs in 500 samples => 4.00%
u/js110/002973.voltage:        3.204911829471588 V | 500 samples
2024-10-22 09:56:12,094 WARNING  jsdrv pkt_index skip: expected 0, received 15041
2024-10-22 09:56:12,095 WARNING  jsdrv pkt_index skip: expected 15072, received 0
Display the mean (ignoring NaNs) for each signal
u/js110/002973.current:   -6.577587202346898e-09 A | ignored 21 NaNs in 500 samples => 4.20%
u/js110/002973.voltage:        3.244217670440674 V | 500 samples```

Is it correct that the joulscope loses this samples also with a very low frequency?

Hi @Dominik. You have two choices for data type: statistics or downsampled data. If you go with statistics, you have to directly use pyjoulescope_driver since the joulescope package only supports up to 100 Hz. The downsampled data works in both cases, but the joulescope package includes the additional stream_buffer abstraction. With pyjoulescope_driver, you simply get the downsampled data for each channel when it becomes available.

Getting 1 kHz statistics data is probably the easiest. See the pyjoulescope_driver statistics entry point for an example.

Here is a command-line example:

python -m pyjoulescope_driver statistics --js110_host --frequency 1000

You can hard-code these arguments in your script. You also need to modify _on_statistics_value with do whatever you want with the statistics data. Note that 24 hours at 1 kHz is 86.4 M points. Assuming float32 of i,v,p, this is about 1 GB, which you can likely keep in RAM.

Regarding your other questions:
a. If you want to capture data over a long region, you cannot make individual measurements. Individual measurements have have gaps, so you may miss things. You want to operate your Joulescope continously, like the Joulescope UI does.
b. The JS110 does not always start and stop streaming cleanly. It can have a gap after starting. If you want to measure over a long duration, you should not stop and start sample streaming, which is what read does.
c. We do not officially support operation under VMs. Joulescopes really push USB high-speed capabilities, and we cannot guarantee that the VM abstraction layer keeps up.

Does this make sense? Does capturing statistics like this work for your application?

Hi Milberty,

Sorry for the late response. Thank you for your message. The “statistics entry point” example helped a lot. My program seems to work now. It was a bit confusing for me to find the right driver. Can you explain the history of the driver ? Seems that the investigation for the normal joulescope python driver is ending ? Would you recommend only using the pyjoulscope_driver now?

Hi @Dominik ,

We plan to support both the Python joulescope package and the pyjoulescope_driver package for quite some time.

The joulescope package (which I often call pyjoulescope) is the original Python package that we released in 2019. It provides a procedural API that is easy for the most common tasks. It also has the stream_buffer abstraction which can be nice for dealing with relatively short windows of time (seconds to minutes).

However, as soon as you want to do anything more complicated, the lower-level pyjoulescope_driver package provides more options. It provides an asynchronous Publish-Subscribe API, and exposes everything that you can do with Joulescopes. The Joulescope UI uses pyjoulescope_driver directly.

The joulescope_driver is implemented in C, and has much improved performance from the original joulescope backend. We released this along with the JS220 in 2022. You can use joulescope_driver from C & C++, and we also provide the Python bindings (pyjoulescope_driver) and node.js bindings.

Note that the joulescope package now uses pyjoulescope_driver as the backend to actually talk with Joulescopes!

Hope this helps!