LabVIEW support?

So I’ll try tomorrow to intercept this binary flux following the Start command from the client. And of course I’ll let you know what happen :blush:

Thanks again !

Ah, yes. You will get a TAG_AJS response first. Then, as new data becomes available, you will get TAG_ABN. Now, this single payload is also in the same tag-length-value format. The first part is a TAG_AJS describing the data followed by a TAG_ABN corresponding to each field. The TAG_ABN contains the raw data for each field.

The documentation for this does not seem to be great (present?), so any confusion is definitely justified! The JSON map is mostly constructed in DeviceStreamManager._update. The map is then passed to ClientManager._on_stream_data which then constructs the each tag to form the full payload.

Let me know what you find when you take a look tomorrow!

Hy Matt,

with 2 opened terminals , joulescope connected and joulescope_server.server & joulescope_server.client running, all is OK and perform exactly as you mentionned in screen copies you sent in your previous mail.
But when I replace python joulescope_server.client by my labview client all is unfortunatly not OK : if I always receive Stats infos from server every 0.5 sec, I always not receive streaming binary datas … Sorry for this bad new , there is something I don’t understand so I continue to investigate :thinking:

Well, making progress! So, there has to be something different between what the LabVIEW client is doing and what the example client is doing. It’s probably something simple. I just modified the server to log all send and receive messages. Get the latest version, and then run the server and client. The server now displays this (edited to just show messages):

recv: {"id": 0, "type": "hello", "phase": "req"}
send: {"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"}}
recv: {"id": 1, "type": "scan", "phase": "req", "config": "auto"}
send: {"id": 1, "type": "scan", "phase": "rsp", "config": "auto", "status": 200, "status_msg": "Success", "data": ["Joulescope:000147"]}
recv: {"id": 2, "type": "open", "phase": "req", "device": "Joulescope:000147"}
send: {"id": 2, "type": "open", "phase": "rsp", "device": "Joulescope:000147", "status": 200, "status_msg": "Success"}
recv: {"id": 3, "type": "parameters", "phase": "req", "device": "Joulescope:000147"}
send: {"id": 3, "type": "parameters", "phase": "rsp", "device": "Joulescope:000147", "status": 200, "status_msg": "Success", "data": {...}}
recv: {"id": 4, "type": "info", "phase": "req", "device": "Joulescope:000147"}
send: {"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"}}}}
recv: {"id": 5, "type": "parameter_get", "phase": "req", "device": "Joulescope:000147", "data": {"name": "i_range"}}
send: {"id": 5, "type": "parameter_get", "phase": "rsp", "device": "Joulescope:000147", "data": "auto", "status": 200, "status_msg": "Success"}
recv: {"id": 6, "type": "parameter_set", "phase": "req", "device": "Joulescope:000147", "data": {"name": "i_range", "value": "auto"}}
send: {"id": 6, "type": "parameter_set", "phase": "rsp", "device": "Joulescope:000147", "data": {"name": "i_range", "value": "auto"}, "status": 200, "status_msg": "Success"}
recv: {"id": 7, "type": "start", "phase": "req", "device": "Joulescope:000147", "data": {"fields": ["current", "voltage"]}}
send: {"id": 7, "type": "start", "phase": "rsp", "device": "Joulescope:000147", "data": true, "status": 200, "status_msg": "Success"}
...
recv: {"id": 8, "type": "stop", "phase": "req", "device": "Joulescope:000147"}
send: {"id": 8, "type": "stop", "phase": "rsp", "device": "Joulescope:000147", "status": 200, "status_msg": "Success", "data": true}
recv: {"id": 9, "type": "close", "phase": "req", "device": "Joulescope:000147"}
send: {"id": 9, "type": "close", "phase": "rsp", "device": "Joulescope:000147", "status": 200, "status_msg": "Success"}

You can try with the LabVIEW client and see what is different.

Sorry I can’t (don’t know to be more precise :slightly_smiling_face:) send you screen copies as you do …
What I see in server log when Server is connected to Labvie client is : all is similar to Server log when connected to Python client untill :
" INFO:2021-09-25 10:26:21,704:device.py:776:joulescope.usb.winusb.device:read_stream_start 2
INFO:2021-09-25 10:26:21,706:device.py:406:joulescope.usb.winusb.device:endpoint start 0x82 transfer size = 131072 bytes
INFO:2021-09-25 10:26:21,710:server.py:374:joulescope_server.server:send: {“id”: 7, “type”: “start”, “phase”: “rsp”, “device”: “Joulescope:001747”, “data”: true, “status”: 200, “status_msg”:
“Success”} "
in response to Start Command from client.
But just after this we have in the server Log :
"INFO:2021-09-25 10:41:10,105:server.py:215:joulescope_server.server:_on_stream_data, but device Joulescope:001747 not streaming "

So it certainly explains why Labview client doesn’t receive streaming data even if I don’t understand why "device Joulescope:001747 not streaming " …

At the end of the server Log I have also following infos :

“INFO:2021-09-25 10:41:12,076:driver.py:880:joulescope.driver:stop : streaming=False
INFO:2021-09-25 10:41:12,080:device_thread.py:208:joulescope.usb.device_thread:close
INFO:2021-09-25 10:41:12,083:device.py:697:joulescope.usb.winusb.device:WinUsbDevice.close
INFO:2021-09-25 10:41:12,086:device_thread.py:102:joulescope.usb.device_thread:DeviceThread._cmd_process_all close
INFO:2021-09-25 10:41:12,091:device_thread.py:132:joulescope.usb.device_thread:DeviceThread.run flush
INFO:2021-09-25 10:41:12,094:device_thread.py:134:joulescope.usb.device_thread:DeviceThread.run done
INFO:2021-09-25 10:41:12,097:server.py:374:joulescope_server.server:send: {“type”: “close”, “phase”: “rsp”, “id”: 10, “status”: 200, “status_msg”: “Success”, “device”: “Joulescope:001747”, "
data”: []}
ERROR:2021-09-25 10:41:12,100:server.py:380:joulescope_server.server:handle_client error
Traceback (most recent call last):
File “C:\Users\Thierry\AppData\Local\Programs\Python\Python39\lib\site-packages\joulescope_server\server.py”, line 354, in run
msg = await framer.treceive(self._reader)
File “C:\Users\Thierry\AppData\Local\Programs\Python\Python39\lib\site-packages\joulescope_server\framer.py”, line 109, in treceive
raise ValueError(‘unsupported tag’)
ValueError: unsupported tag
INFO:2021-09-25 10:41:12,126:server.py:250:joulescope_server.server:_async_task done
INFO:2021-09-25 10:41:12,126:server.py:386:joulescope_server.server:ClientManager.run done "

I hope it will help you to solve the Mystery of the Lost Binary Data … :slightly_smiling_face:

Thak you again for your precious help !

Hurrah ! Looking again on my labview code to understant why Joulescope device was not streaming, I saw a “minor” difference in Start commande between Labview and Python clients : I had add sample_chunk = 1 in data cluster (I tried this few days ago and forget to suppress it …)
So now with no sample_chunk I’m receiving binary data (I don’t know yet why sample_chunk = 1 stops the binary raw data flux from Joulescope, but it’s not really important at the moment) !
I’m going to extract this raw data now but I’m pretty sure everything wil be OK now.

I’m very sorry to haven’t see this othersight before and for wasting your time a little but fortunatly that’s ends well ! :slightly_smiling_face:

Thank you very much Matt, be sure I’ll recommand you and tour products ! :+1:

1 Like

Excellent! Yes, with sample_chunk=1, the server will try to send a new message for each sample. It undoubtedly cannot keep up with sample_chunk=1. The default is 1/10 of a second (200,000 samples), so quite a difference!

Great to hear that you were able to get this working! If you are able to publish your LabVIEW client publically, I know that a few other people on this thread would be interested.

If you run into any more issues, please don’t hesitate to post here or start a new thread.

I think it will be possible to publish Labview client but now it’s a prototype which still has some small youth’s problems :slight_smile: :

I can decode now binary flux at 2 MBPS (current and voltage simultaneously for instance) but I have a lot of difficulties to modify Joulescope parameters. It’s certainly due to my misanderstanding of the exact syntax of commands to send.
For example, what JSON command client have to send to modify the “i-range” parameter to 18 mA ?
When I send “parameters” command, concerning “i_range” parameter I see :
“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 \u00b5A”, 32, [“5”, 5]], [“18 \u00b5A”, 64, [“6”, 6]], [“off”, 0, []]], “units”: null, “brief”: “Select the current measurement range (shunt resistor)”, “detail”: null, “flags”: []}

I guess it’s a dictionnary but I clearly don’t understand the syntax : does it means I should send { … “data”:{“name”:“i_range”, “value”: “18 mA”} as I thought or { … “data”:{“name”:“i_range”, “options”: “18 mA”} in the “parameter_send” command ? What means “default” / “path” / [“1.8 mA”, 16, [“4”, 4]] for example ?

Have you a doc on this subject (in this case, sorry for the previous questions :slightly_frowning_face:) ?

Thank you for answers !

Hi @Tverc2

I think that there are two parts to your question.

  1. How should the client set a parameter value?
  2. What are the parameters and available values?

(1) is pretty straightforward:
{“id”: your_id, “type”: “parameter_set”, “phase”: “req”, “device”: “your_device”, “data”: {“name”: “your_parameter”, “value”: “your_value”}}

Where you replace all the items in bold for the desired command. If the parameter_set operation is successful, you will receive a response with the same id and with a new key/value of “status”: 200. The return codes use HTTP response codes, where 200 is success.

(2) is a little more complicated. The “parameter” command returns the full list of parameters. Many parameters support an enumeration of available options. Note that the options format is (user_value, internal_value, …[alternatives]). The Joulescope code contains a much nicer format. Your code should parameter_set with the user_value, but you can optionally use any of the alternatives, if alternatives exists for that option.

So, to set the 18 mA range, you would send AJS with:
{“id”: 6, “type”: “parameter_set”, “phase”: “req”, “device”: “Joulescope:000147”, “data”: {“name”: “i_range”, “value”: “18 mA”}}

And you would receive AJS with:
{“id”: 6, “type”: “parameter_set”, “phase”: “rsp”, “device”: “Joulescope:000147”, “data”: {“name”: “i_range”, “value”: “18 mA”}, “status”: 200, “status_msg”: “Success”}

However, for most applications, I recommend using “auto” and allow your Joulescope to autorange.

Hi Matt,
thank you for you very fast and very clear answers (as usual). Now I just have to test them ! :blush:

ps: what about “default” and “path” ?

“default” is the default value when you first connect to the instrument. However, the “auto” configuration, which is the default, will then set these parameters when you open an instrument:

    'i_range': 'auto',
    'v_range': '15V',
    'source': 'on',

“path” provides information to automatically populate a user interface with sensible parameter groupings. You do not need to worry about it for this client/server. The Parameter class contains some documentation for each of these fields:

class Parameter:
    """Define a single parameter accessible by the application.
    :param name: The parameter name.
    :param path: None if the parameter is only changed at the streaming start.
        'setting' if the parameter is part of the settings packet.
    :param default: The default value.
    :param options: The list of acceptable values as ('name', value, ['alias1', ...]) tuples.
    :param units: The units string for the parameter.
    :param brief: The brief user-meaningful description.
    :param detail: The detailed user-meaningful description.
    :param flags: The list of flags which include:
        * developer: This parameter is intended for developers only, not end users.
        * read_only: This parameter can only be read (no write permission).
    :param validator: Function called to validate the parameter value.
    """
    def __init__(self, name, path, default=None, options=None, units=None,
                 brief=None, detail=None,
                 flags=None, validator=None):
    ...

OK, thank you, it’s now much clearer to me !

Unfortunately my problem remains when I’m trying to change the Current range to 18 mA …
Indeed when I look on the server log, it seems all is OK with the i_range change to 18 mA :

INFO:2021-09-27 17:49:59,587:server.py:355:joulescope_server.server:recv: {“type”: “parameter_set”, “phase”: “req”, “id”: 6, “status”: 0, “status_msg”: “”, “device”: “Joulescope:001747”, “data”: {“name”: “i_range”, “value”: “18 mA”}}

INFO:2021-09-27 17:49:59,589:server.py:374:joulescope_server.server:send: {“type”: “parameter_set”, “phase”: “rsp”, “id”: 6, “status”: 200, “status_msg”: “Success”, “device”: “Joulescope:001747”, “data”: {“name”: “i_range”, “value”: “18 mA”}}
INFO:2021-09-27 17:50:00,588:server.py:355:joulescope_server.server:recv: {“type”: “start”, “phase”: “req”, “id”: 7, “status”: 0, “status_msg”: “”, “device”: “Joulescope:001747”, “data”: {“fields”: [“voltage”, “current”]}}

INFO:2021-09-27 17:50:00,591:device.py:776:joulescope.usb.winusb.device:read_stream_start 2

Bwhen we compare the raw data decoded by Labview client

with raw data decoded by Joulescope viewer at i_range = 18mA

and i_range = auto

we can see Client Labview as no changed the i_range to 18 mA but that i_range is clearly maintened to auto mode.

What do you think about this ?

I completely agree that it looks like the parameter_set did not take effect. I took a look at the code, and we have a definitely copy/paste error.

I know other people are using this server, but I suspect that they use the default settings. I am not surprised that this error has gone unnoticed until now.

I updated the code on GitHub to fix this issue. I have also released an updated version to pypi. Please update your local version, which should then fix the issue.

Also, looking at your data, is there a reason you want the fixed 18 mA range? Please be aware of the ±15 µA offset accuracy in the 18 mA range. From page 12 of the Joulescope User’s Guide:

OK so all is explained !

the reason we want to fixe 18mA is that our device under test consums “a lot” in the start phase (I suppose that, if current goes above the limite range, Joulescope not only clips the current but that there is also perturbations on the output voltage. But maybe I’m wrong ? ).
After this starting phase, current decrease a lot and we want to mesure it with a precison better than 1 µA, so effectively we’ll change the i-range to 1.8 mA or below.

On this resolution topic, we can noticed on the Current measurement specifications that for a given range resolution is better than accuracy: we had interpreted this by : résolution = differential linearity / accuracy = integral (absolute) linearity . Is our interpretation OK ?

Last thing about this i_range topic : we can see on pictures above that current shape change a lot with i-range → it means certainly that Jouescope integrates current with a time constant depending of i_range (certainly due to noise reduction reasons (?)). If it’s the case could it be possible for the user to change this time constant for a given i-range if he wants to have a better idea of the real current’s shape ( even if the noise will be increasedof course) ?

I have been just tried the new version :

  • I_range 18mA is effectively fonctionning now ! :blush:
    So I can compare Labview client and Joulescope viewer at i_range = 18 mA → it seems that the raw data received by Labview client are not filtered with i_range not in auto mode while with Joulescope viewer there is a post processing low-pass filter depending of the zoom factor ( about 2 kHz when the windows lenght is at about 250ms for example ) . If it’s the case it answers to the last question of my previous message !
  • it seems also that only “18 mA” and “auto options” are working … I’m not worried, I know it will be corrected very fast ! :slight_smile:

Joulescope is a shunt ammeter meaning that it measures voltage across a known resistance and computes current using Ohm’s law. Normally, Joulescopes maintain < 20 mV burden voltage across the shunt resistor. If your system uses a fixed shunt resistor and draws a lot of current, the voltage drop could be more than 20 mV. The JS110 measures the voltage from IN+ to IN- while the burden voltage is between IN+ and OUT+.

Given your description, you can probably just use the auto current range and let Joulescope’s fast autoranging do all the work for you.

Yes, that is correct. In other words, accuracy is the amount of expected error from the truth for a static measurement averaged over many samples. Resolution is the minimum detectable change.

Unfortunately, your Joulescope does not have control over the shape of this curve. Joulescope has a pretty good measurement bandwidth, but the system bandwidth definitely changes. Joulescope’s shunt resistor and the target’s bypass capacitance form a low-pass filter. In the JS110’s 18 µA range, it uses a 1111 Ω shunt resistor. If your target has 10 µF of capacitance, then you expect:

τ = R C = 1111 Ω * 10e-6 F = 11 ms
bandwidth = BW = f -3db = 1 / (2 π R C) = 14 Hz

I am going to assume you are talking about the yellow trace in the Joulescope UI waveform view. In the waveform view, each pixel can represent many, many samples, especially as you zoom out. The yellow line is the mean (average) of all samples represented by that pixel. Computing mean is a low-pass filter. Since the zoom factor determines the number of samples per pixel, the bandwidth of the yellow trace depends upon the zoom factor. If you turn on min/max, then you will also see the minimum and maximum values for all samples represented by that pixel. For many applications, min/max is often very meaningful. If you select a fixed current range, you definitely want to see min/max to ensure that you are not saturating the range.

Could you provide more detail on the error? I just tried “180 mA” and “18 µA”, and both commands were acknowledged with status 200. Note that you have to be very careful about the “µ” symbol. A more programmer-friendly way is to use integers 0 through 6 where 0 is 10 A and 6 is 18 µA.

Thank you for this very detailed answer (one time again ) !

Sorry for the yellow trace : I did no see my Joulescope viever was in average mode ! So effectively in min/max mode (red curve) I can see all the information ! :slight_smile:

Concerning “180 mA” command here are the server log I received with “18 mA” and “180 mA” :

  • 18 mA

INFO:2021-09-28 15:10:57,069:server.py:355:joulescope_server.server:recv: {“type”: “parameter_set”, “phase”: “req”, “id”: 6, “status”: 0, “status_msg”: “”, “device”: “Joulescope:001747”, “data”: {“name”: “i_range”, “value”: “18 mA”}}

INFO:2021-09-28 15:10:57,084:server.py:374:joulescope_server.server:send: {“type”: “parameter_set”, “phase”: “rsp”, “id”: 6, “status”: 200, “status_msg”: “Success”, “device”: “Joulescope:001747”, “data”: {“name”: “i_range”, “value”: “18 mA”}}
INFO:2021-09-28 15:10:57,085:server.py:355:joulescope_server.server:recv: {“type”: “start”, “phase”: “req”, “id”: 7, “status”: 0, “status_msg”: “”, “device”: “Joulescope:001747”, “data”: {“fields”: [“voltage”, “current”]}}

INFO:2021-09-28 15:10:57,089:device.py:776:joulescope.usb.winusb.device:read_stream_start 2
INFO:2021-09-28 15:10:57,093:device.py:406:joulescope.usb.winusb.device:endpoint start 0x82 transfer size = 131072 bytes
INFO:2021-09-28 15:10:57,097:server.py:374:joulescope_server.server:send: {“type”: “start”, “phase”: “rsp”, “id”: 7, “status”: 200, “status_msg”: “Success”,“device”:“Joulescope:001747”, “data”: true}

  • 180 mA

INFO:2021-09-28 15:16:57,720:server.py:355:joulescope_server.server:recv: {“type”: “parameter_set”, “phase”: “req”, “id”: 6, “status”: 0, “status_msg”: “”, “device”: “Joulescope:001747”, “data”: {“name”: “i_range”, “value”: “180 mA”}}

INFO:2021-09-28 15:16:57,734:server.py:374:joulescope_server.server:send: {“type”: “parameter_set”, “phase”: “rsp”, “id”: 6, “status”: 200, “status_msg”: “Success”, “device”: “Joulescope:001747”, “data”: {“name”: “i_range”, “value”: “180 mA”}}
ERROR:2021-09-28 15:16:57,735:server.py:380:joulescope_server.server:handle_client error
Traceback (most recent call last):
File “C:\Users\Thierry\AppData\Local\Programs\Python\Python39\lib\site-packages\joulescope_server\server.py”, line 354, in run
msg = await framer.treceive(self._reader)
File “C:\Users\Thierry\AppData\Local\Programs\Python\Python39\lib\site-packages\joulescope_server\framer.py”, line 109, in treceive
raise ValueError(‘unsupported tag’)
ValueError: unsupported tag
INFO:2021-09-28 15:16:57,738:server.py:250:joulescope_server.server:_async_task done
INFO:2021-09-28 15:16:57,738:server.py:386:joulescope_server.server:ClientManager.run done

1 Like

Great!

I think that this error is separate from the i_range value. The server is indicating that the message tag was neither AJS or ABN. Let’s make sure that the message does not have any weird behavior due to symbols or quotes. Try using the i_range number, like this:

{"id": 6, "type": "parameter_set", "phase": "req", "device": "Joulescope:000147", "data": {"name": "i_range", "value": 0}}

where

0 = 10 A
1 = 2 A
2 = 180 mA
3 = 18 mA
4 = 1.8 mA
5 = 180 µA
6 = 18 µA

Does that make a difference?

Strange : it seems to be OK with i_range numbers fom 0 to 6 but … I sent by mystake these value in ASCII format (“value”: “4” instead “value”: 4 for example) ! Does “value” field accepts all values from 0 to 255 ?
I’m going to try with numerical values and not ASCII values

OK ! That’s clearly better with numerical values : I therefore don’t recommand ASCII format :slight_smile:
So I’ll use now the number option for i_range.

Thanks a lot !

1 Like