Author Topic: Program that can log/control many multimeters and other devices.  (Read 1789513 times)

0 Members and 79 Guests are viewing this topic.

Online Gertjan

  • Frequent Contributor
  • **
  • Posts: 377
  • Country: nl
Re: Program that can log/control many multimeters and other devices.
« Reply #4675 on: September 23, 2025, 02:56:40 pm »
So, YES, please synchronise the param sweeper with the logging! The delay setting for the measurement would be the icing on the cake :)

regards, Gertjan.

What kind of logging are you referring to?
When using the param sweeper, the resulting measurements are logged. But sometimes, there is twice the same measurement in the table (belonging to a previous or next step). For a lot of measurements, like temperature or frequency response, this is not a problem, as the previous and next measured value will be very close.

But when sweeping a device from "min output" to "max output", and measuring the result, a wrong measurement will be very noticeable. Especially when you calculate the difference between input and output, to see the linearity. See an example below:


Full size image: param-sweeper-log-error-1000pix.png

Quote
I've only done basic sweeps with the parameter sweeper, but it always saved its own CSV log, and there are delay settings on the sweeper setup as well. Attached is recent parameter sweeper results before self cal on an AWG.

Thanks,
Josh

I am very interested where you found these delay settings in the param sweeper.....

regards, Gertjan.
 

Online HKJTopic starter

  • Super Contributor
  • ***
  • Posts: 4974
  • Country: dk
    • Tests
Re: Program that can log/control many multimeters and other devices.
« Reply #4676 on: September 23, 2025, 03:26:50 pm »
I have implemented a option to synchronize the log to the param sweeper. It switches the log to advance logging SingleOnCommand mode. This means that TC will read data as fast as it can from the device and only log sample when requested (From param sweeper).
I have not added any option to adjust the offset, but place the trig command midways in the time.
Due to the increased communication I will generally recommend to run the param sweeper slower when using this option.

The test version is at the usually location: http://lygte-info.dk/pic/Projects/TestController/TestController.jar

 
The following users thanked this post: KungFuJosh

Online KungFuJosh

  • Super Contributor
  • ***
  • Posts: 8489
  • Country: us
  • TEAS is real.
Re: Program that can log/control many multimeters and other devices.
« Reply #4677 on: September 23, 2025, 03:27:58 pm »
I would like a Control multi that can handle separate read/write functions. Something like this:
Code: [Select]
#cmdSetup multi Math_CH1_Setup Math
:read: :MATH1:UNIT?;:MATH1:OFFS?;:MATH1:SCAL?
:write: :MATH1:UNIT (value);:MATH1:OFFS (value);:MATH1:SCAL (value)
:update: Math_CH1_Setup
:tip: Enter desired setup values.
text Unit
number Offset _ 0 6
text Scale

You can already do this:
:read: :MATH1:UNIT?;:MATH1:OFFS?;:MATH1:SCAL?
:write: :MATH1:UNIT (value);:MATH1:OFFS (value2);:MATH1:SCAL (value3)

or this (Assuming they are in sequence):
:write: :MATH1:UNIT (#);:MATH1:OFFS (#);:MATH1:SCAL (#)

Thank you,  but that only works with number inputs, not text. With a text input, it breaks it. Individually Unit/Offset/Scale are shown in the screenshot along with this attempted combination of the three:
Code: [Select]
#cmdSetup multi Math_CH1_Setup Math
:read: :MATH1:UNIT?;:MATH1:OFFS?;:MATH1:SCAL?
:write: :MATH1:UNIT (value);:MATH1:OFFS (value2);:MATH1:SCAL (value3)
:update: Math_CH1_Setup
:tip: Enter desired setup values.
text Unit
number Offset _ 0 6
text Scale

Scale could be a number, but Unit cannot.

Thanks,
Josh
"Experience is something you don't get until just after you need it." - Steven Wright
Best Continuity Tester Ever
Best Continuity Tester Ever...Got Betterer!
 

Online KungFuJosh

  • Super Contributor
  • ***
  • Posts: 8489
  • Country: us
  • TEAS is real.
Re: Program that can log/control many multimeters and other devices.
« Reply #4678 on: September 23, 2025, 03:31:06 pm »
I am very interested where you found these delay settings in the param sweeper.....

I think "Step time" on the primary control page should do what you want to slow down the stepping. From what you displayed, it looks like one of the devices couldn't keep up, so slowing down the step time could correct that.

Thanks,
Josh
"Experience is something you don't get until just after you need it." - Steven Wright
Best Continuity Tester Ever
Best Continuity Tester Ever...Got Betterer!
 

Offline gby

  • Frequent Contributor
  • **
  • Posts: 282
  • Country: us
Re: Program that can log/control many multimeters and other devices.
« Reply #4679 on: September 23, 2025, 03:35:05 pm »
HKJ,

Thanks for the quick reply.  I dug into my issue some more.  With the following in the device file:
   #value TPA1_W Watt SI
   #value TPA1_VA VA SI
   #value TPA1_V Volt SI
   #value TPA1_A Amp SI
   #value TPA2_V Volt SI
   #value TPA2_A Amp SI
   #value TPA2_W Watt SI
   #value TPA2_VA VA SI
   #value TPA2_f Hertz SI

   #askValues :FRD:CH1?; :FRD:CH2?

When I run logging in debug mode I see the following traffic:
Code: [Select]
;; PA4000: Tx <:FRD:CH1?>
;; PA4000: Rx <+3.7072e-06,+2.2935e-05,+1.1914e-03,+3.6815e-05>
;; PA4000: Tx <:FRD:CH2?>
;; PA4000: Rx <+1.7777e-03,+3.1466e-03,-3.4911e-06,+5.5937e-06,+0.0000e+00>
;; PA4000: Rx as numbers <3.7072E-6 2.2935E-5 0.0011914 3.6815E-5>
;; PA4000: Tx <:FRD:CH1?>

The last Rx as numbers line only gets 4 numbers.  In test controller Current values, Chart, Range tabs the five TPA2_x values are all zero.  From the log I can see both #askValues commands with their individual replies working correctly.  But the final Rx as numbers only shows the first 4 numbers from the first #askValues command and ignores the second commands 5 received numbers.

How to get all 9 numbers read into the logging??
 

Online HKJTopic starter

  • Super Contributor
  • ***
  • Posts: 4974
  • Country: dk
    • Tests
Re: Program that can log/control many multimeters and other devices.
« Reply #4680 on: September 23, 2025, 03:36:25 pm »
Thank you,  but that only works with number inputs, not text. With a text input, it breaks it. Individually Unit/Offset/Scale are shown in the screenshot along with this attempted combination of the three:

Try adding a :string: tag
 
The following users thanked this post: KungFuJosh

Online HKJTopic starter

  • Super Contributor
  • ***
  • Posts: 4974
  • Country: dk
    • Tests
Re: Program that can log/control many multimeters and other devices.
« Reply #4681 on: September 23, 2025, 03:41:18 pm »
HKJ,

Thanks for the quick reply.  I dug into my issue some more.  With the following in the device file:
   #value TPA1_W Watt SI
   #value TPA1_VA VA SI
   #value TPA1_V Volt SI
   #value TPA1_A Amp SI
   #value TPA2_V Volt SI
   #value TPA2_A Amp SI
   #value TPA2_W Watt SI
   #value TPA2_VA VA SI
   #value TPA2_f Hertz SI

   #askValues :FRD:CH1?; :FRD:CH2?

When I run logging in debug mode I see the following traffic:
Code: [Select]
;; PA4000: Tx <:FRD:CH1?>
;; PA4000: Rx <+3.7072e-06,+2.2935e-05,+1.1914e-03,+3.6815e-05>
;; PA4000: Tx <:FRD:CH2?>
;; PA4000: Rx <+1.7777e-03,+3.1466e-03,-3.4911e-06,+5.5937e-06,+0.0000e+00>
;; PA4000: Rx as numbers <3.7072E-6 2.2935E-5 0.0011914 3.6815E-5>
;; PA4000: Tx <:FRD:CH1?>

The last Rx as numbers line only gets 4 numbers.  In test controller Current values, Chart, Range tabs the five TPA2_x values are all zero.  From the log I can see both #askValues commands with their individual replies working correctly.  But the final Rx as numbers only shows the first 4 numbers from the first #askValues command and ignores the second commands 5 received numbers.

How to get all 9 numbers read into the logging??

I do not know what goes wrong, but try adding a :readmath: fffffffff it tells TC that there is supposed to be 9 numbers.

 

Offline gby

  • Frequent Contributor
  • **
  • Posts: 282
  • Country: us
Re: Program that can log/control many multimeters and other devices.
« Reply #4682 on: September 23, 2025, 03:49:52 pm »
HKJ,

Thanks.  All good now.  I should have known to try that myself....sorry to bother you.
 

Online KungFuJosh

  • Super Contributor
  • ***
  • Posts: 8489
  • Country: us
  • TEAS is real.
Re: Program that can log/control many multimeters and other devices.
« Reply #4683 on: September 23, 2025, 03:52:11 pm »
This is frustrating. It gave me "known mode" errors with the #askMode not matching, so I changed it to:

I am not really sure what you did wrong here.
I don't know either. Everything seems like it should work.

Quote
I have made the #modeFromVar, but it is  completely untested, i.e. start by using printLog() function to see that it returns anything useful.

The syntax is #modeFromVar varName
No expression, quotes or anything else allowed, it goes directly into the var table lookup, not to a parser.

Thank you!

First issue, it doesn't appear to support multiple values?

This partially worked:
#modeFromVar meas1Unit

This didn't work at all:
#modeFromVar meas1Unit;meas2Unit;meas3Unit;meas4Unit;meas5Unit

Here's the log:
Code: [Select]
;; Magnova: Tx <DynamicM1?>
;; Magnova: Script start
;; Magnova: Tx <:MEAS:VPP:CURR? CHAN1>
;; IP: Tx: <:MEAS:VPP:CURR? CHAN1.> 3A 4D 45 41 53 3A 56 50 50 3A 43 55 52 52 3F 20 43 48 41 4E 31 0A
;; IP: Rx: <0.5038375> 30 2E 35 30 33 38 33 37 35 0A
;; Magnova: Rx <0.5038375>
;; Magnova: Script end <0.5038375>
;; Magnova: Rx <0.5038375>
;; Magnova: Tx <DynamicM2?>
;; Magnova: Script start
;; Magnova: Tx <:MEAS:VAMP:CURR? CHAN1>
;; IP: Tx: <:MEAS:VAMP:CURR? CHAN1.> 3A 4D 45 41 53 3A 56 41 4D 50 3A 43 55 52 52 3F 20 43 48 41 4E 31 0A
;; IP: Rx: <0.4997> 30 2E 34 39 39 37 0A
;; Magnova: Rx <0.4997>
;; Magnova: Script end <0.4997>
;; Magnova: Rx <0.4997>
;; Magnova: Tx <DynamicM3?>
;; Magnova: Script start
;; Magnova: Tx <:MEAS:VMAX:CURR? CHAN1>
;; IP: Tx: <:MEAS:VMAX:CURR? CHAN1.> 3A 4D 45 41 53 3A 56 4D 41 58 3A 43 55 52 52 3F 20 43 48 41 4E 31 0A
;; IP: Rx: <0.249175> 30 2E 32 34 39 31 37 35 0A
;; Magnova: Rx <0.249175>
;; Magnova: Script end <0.249175>
;; Magnova: Rx <0.249175>
;; Magnova: Tx <DynamicM4?>
;; Magnova: Script start
;; Magnova: Tx <:MEAS:VMIN:CURR? CHAN1>
;; IP: Tx: <:MEAS:VMIN:CURR? CHAN1.> 3A 4D 45 41 53 3A 56 4D 49 4E 3A 43 55 52 52 3F 20 43 48 41 4E 31 0A
;; IP: Rx: <-0.25385> 2D 30 2E 32 35 33 38 35 0A
;; Magnova: Rx <-0.25385>
;; Magnova: Script end <-0.25385>
;; Magnova: Rx <-0.25385>
;; Magnova: Tx <DynamicM5?>
;; Magnova: Script start
;; Magnova: Tx <:MEAS:VRMS:CURR? CHAN1>
;; IP: Tx: <:MEAS:VRMS:CURR? CHAN1.> 3A 4D 45 41 53 3A 56 52 4D 53 3A 43 55 52 52 3F 20 43 48 41 4E 31 0A
;; IP: Rx: <0.173576897134> 30 2E 31 37 33 35 37 36 38 39 37 31 33 34 0A
;; Magnova: Rx <0.173576897134>
;; Magnova: Script end <0.173576897134>
;; Magnova: Rx <0.173576897134>
;; Magnova: Rx as numbers <0.5038375 0.4997 0.249175 -0.25385 0.173576897134>
Thread for Magnova
dk.hkj.vars.VarExceptions$NameException: meas1Unit;meas2Unit;meas3Unit;meas4Unit;meas5Unit not found
        at dk.hkj.vars.Var.get(Var.java:1342)
        at dk.hkj.script.Script.getLocalVar(Script.java:1166)
        at dk.hkj.main.DeviceInterface.getValuesFromDevices(DeviceInterface.java:416)
        at dk.hkj.devices.DeviceSCPI.getValuesFromDevices(DeviceSCPI.java:99)
        at dk.hkj.main.InterfaceThreads$DeviceThread.run(InterfaceThreads.java:1632)


Here's the full code from that section:
Code: [Select]
#scpiCmd DynamicM1? #pgm#
var fullCommand=":MEAS:" + unQuote(meas1Type) + ":CURR? ";
var result=deviceRead(handle, fullCommand + unQuote(meas1Chan));
print(result);
#scpiCmd DynamicM2? #pgm#
var fullCommand=":MEAS:" + unQuote(meas2Type) + ":CURR? ";
var result=deviceRead(handle, fullCommand + unQuote(meas2Chan));
print(result);
#scpiCmd DynamicM3? #pgm#
var fullCommand=":MEAS:" + unQuote(meas3Type) + ":CURR? ";
var result=deviceRead(handle, fullCommand + unQuote(meas3Chan));
print(result);
#scpiCmd DynamicM4? #pgm#
var fullCommand=":MEAS:" + unQuote(meas4Type) + ":CURR? ";
var result=deviceRead(handle, fullCommand + unQuote(meas4Chan));
print(result);
#scpiCmd DynamicM5? #pgm#
var fullCommand=":MEAS:" + unQuote(meas5Type) + ":CURR? ";
var result=deviceRead(handle, fullCommand + unQuote(meas5Chan));
print(result);

#scpiCmd MeasType1 #pgm#
var type=value;
var meas1Type=value;
var meas1Unit="";
var fullunit1Command=meas1Chan + ":UNIT?";
var unit1result=deviceRead(handle, fullunit1Command);
if (type=="VMIN" || type=="VMAX" || type=="VPP" || type=="VBASe" || type=="VTOP" ||
    type=="VAMP" || type=="VLOWer" || type=="VUPPer" || type=="VMID" || type=="VAVG" ||
    type=="VRMS" || type=="VSDeviation" || type=="VPPReshoot" || type=="VNPReshoot" ||
    type=="VPOVershoot" || type=="VNOVershoot")
    if (unit1result=="V")
    var meas1Unit="V";
    elseif (unit1result=="A")
    var meas1Unit="A";
endif
elseif (type=="VPARea" || type=="VNARea" || type=="VAARea" || type=="VNAArea" ||
           type=="VPPArea" || type=="VNPArea" || type=="VAPArea" || type=="VNAPArea")
    var meas1Unit="Vs";
elseif (type=="HRTime" || type=="HFTime" || type=="HPERiod" || type=="HHWidth" ||
           type=="HLWidth")
    var meas1Unit="s";
elseif (type=="HFReq")
    var meas1Unit="Hz";
elseif (type=="HHDuty" || type=="HLDuty")
    var meas1Unit="Percent";
elseif (type=="RECount" || type=="FECount" || type=="PPCount" || type=="NPCount" || type=="")
    var meas1Unit="";
endif
#scpiCmd getMeasType1? none?
:readmath: meas1Type
#scpiCmd getMeasUnit1? none?
:readmath: meas1Unit
#scpiCmd MeasType2 #pgm#
var type=value;
var meas2Type=value;
var meas2Unit="";
var fullunit2Command=meas2Chan + ":UNIT?";
var unit2result=deviceRead(handle, fullunit2Command);
if (type=="VMIN" || type=="VMAX" || type=="VPP" || type=="VBASe" || type=="VTOP" ||
    type=="VAMP" || type=="VLOWer" || type=="VUPPer" || type=="VMID" || type=="VAVG" ||
    type=="VRMS" || type=="VSDeviation" || type=="VPPReshoot" || type=="VNPReshoot" ||
    type=="VPOVershoot" || type=="VNOVershoot")
    if (unit2result=="V")
    var meas2Unit="V";
    elseif (unit2result=="A")
    var meas2Unit="A";
endif
elseif (type=="VPARea" || type=="VNARea" || type=="VAARea" || type=="VNAArea" ||
           type=="VPPArea" || type=="VNPArea" || type=="VAPArea" || type=="VNAPArea")
    var meas2Unit="Vs";
elseif (type=="HRTime" || type=="HFTime" || type=="HPERiod" || type=="HHWidth" ||
           type=="HLWidth")
    var meas2Unit="s";
elseif (type=="HFReq")
    var meas2Unit="Hz";
elseif (type=="HHDuty" || type=="HLDuty")
    var meas2Unit="Percent";
elseif (type=="RECount" || type=="FECount" || type=="PPCount" || type=="NPCount" || type=="")
    var meas2Unit="";
endif
#scpiCmd getMeasType2? none?
:readmath: meas2Type
#scpiCmd getMeasUnit2? none?
:readmath: meas2Unit
#scpiCmd MeasType3 #pgm#
var type=value;
var meas3Type=value;
var meas3Unit="";
var fullunit3Command=meas3Chan + ":UNIT?";
var unit3result=deviceRead(handle, fullunit3Command);
if (type=="VMIN" || type=="VMAX" || type=="VPP" || type=="VBASe" || type=="VTOP" ||
    type=="VAMP" || type=="VLOWer" || type=="VUPPer" || type=="VMID" || type=="VAVG" ||
    type=="VRMS" || type=="VSDeviation" || type=="VPPReshoot" || type=="VNPReshoot" ||
    type=="VPOVershoot" || type=="VNOVershoot")
    if (unit3result=="V")
    var meas3Unit="V";
    elseif (unit3result=="A")
    var meas3Unit="A";
endif
elseif (type=="VPARea" || type=="VNARea" || type=="VAARea" || type=="VNAArea" ||
           type=="VPPArea" || type=="VNPArea" || type=="VAPArea" || type=="VNAPArea")
    var meas3Unit="Vs";
elseif (type=="HRTime" || type=="HFTime" || type=="HPERiod" || type=="HHWidth" ||
           type=="HLWidth")
    var meas3Unit="s";
elseif (type=="HFReq")
    var meas3Unit="Hz";
elseif (type=="HHDuty" || type=="HLDuty")
    var meas3Unit="Percent";
elseif (type=="RECount" || type=="FECount" || type=="PPCount" || type=="NPCount" || type=="")
    var meas3Unit="";
endif
#scpiCmd getMeasType3? none?
:readmath: meas3Type
#scpiCmd getMeasUnit3? none?
:readmath: meas3Unit
#scpiCmd MeasType4 #pgm#
var type=value;
var meas4Type=value;
var meas4Unit="";
var fullunit4Command=meas4Chan + ":UNIT?";
var unit4result=deviceRead(handle, fullunit4Command);
if (type=="VMIN" || type=="VMAX" || type=="VPP" || type=="VBASe" || type=="VTOP" ||
    type=="VAMP" || type=="VLOWer" || type=="VUPPer" || type=="VMID" || type=="VAVG" ||
    type=="VRMS" || type=="VSDeviation" || type=="VPPReshoot" || type=="VNPReshoot" ||
    type=="VPOVershoot" || type=="VNOVershoot")
    if (unit4result=="V")
    var meas4Unit="V";
    elseif (unit4result=="A")
    var meas4Unit="A";
endif
elseif (type=="VPARea" || type=="VNARea" || type=="VAARea" || type=="VNAArea" ||
           type=="VPPArea" || type=="VNPArea" || type=="VAPArea" || type=="VNAPArea")
    var meas4Unit="Vs";
elseif (type=="HRTime" || type=="HFTime" || type=="HPERiod" || type=="HHWidth" ||
           type=="HLWidth")
    var meas4Unit="s";
elseif (type=="HFReq")
    var meas4Unit="Hz";
elseif (type=="HHDuty" || type=="HLDuty")
    var meas4Unit="Percent";
elseif (type=="RECount" || type=="FECount" || type=="PPCount" || type=="NPCount" || type=="")
    var meas4Unit="";
endif
#scpiCmd getMeasType4? none?
:readmath: meas4Type
#scpiCmd getMeasUnit4? none?
:readmath: meas4Unit
#scpiCmd MeasType5 #pgm#
var type=value;
var meas5Type=value;
var meas5Unit="";
var fullunit5Command=meas5Chan + ":UNIT?";
var unit5result=deviceRead(handle, fullunit5Command);
if (type=="VMIN" || type=="VMAX" || type=="VPP" || type=="VBASe" || type=="VTOP" ||
    type=="VAMP" || type=="VLOWer" || type=="VUPPer" || type=="VMID" || type=="VAVG" ||
    type=="VRMS" || type=="VSDeviation" || type=="VPPReshoot" || type=="VNPReshoot" ||
    type=="VPOVershoot" || type=="VNOVershoot")
    if (unit5result=="V")
    var meas5Unit="V";
    elseif (unit5result=="A")
    var meas5Unit="A";
endif
elseif (type=="VPARea" || type=="VNARea" || type=="VAARea" || type=="VNAArea" ||
           type=="VPPArea" || type=="VNPArea" || type=="VAPArea" || type=="VNAPArea")
    var meas5Unit="Vs";
elseif (type=="HRTime" || type=="HFTime" || type=="HPERiod" || type=="HHWidth" ||
           type=="HLWidth")
    var meas5Unit="s";
elseif (type=="HFReq")
    var meas5Unit="Hz";
elseif (type=="HHDuty" || type=="HLDuty")
    var meas5Unit="Percent";
elseif (type=="RECount" || type=="FECount" || type=="PPCount" || type=="NPCount" || type=="")
    var meas5Unit="";
endif
#scpiCmd getMeasType5? none?
:readmath: meas5Type
#scpiCmd getMeasUnit5? none?
:readmath: meas5Unit

#value M1_Volts V SI V
#value M1_Amps A SI A
#value M1_Vs V SI Vs
#value M1_Seconds s SI s
#value M1_Hertz Hz SI Hz
#value M1_Percent Percent SI Percent
#value M1_ _ SI _

#value M2_Volts V SI V
#value M2_Amps A SI A
#value M2_Vs V SI Vs
#value M2_Seconds s SI s
#value M2_Hertz Hz SI Hz
#value M2_Percent Percent SI Percent
#value M2_ _ SI _
#value M3_Volts V SI V
#value M3_Amps A SI A
#value M3_Vs V SI Vs
#value M3_Seconds s SI s
#value M3_Hertz Hz SI Hz
#value M3_Percent Percent SI Percent
#value M3_ _ SI _
#value M4_Volts V SI V
#value M4_Amps A SI A
#value M4_Vs V SI Vs
#value M4_Seconds s SI s
#value M4_Hertz Hz SI Hz
#value M4_Percent Percent SI Percent
#value M4_ _ SI _
#value M5_Volts V SI V
#value M5_Amps A SI A
#value M5_Vs V SI Vs
#value M5_Seconds s SI s
#value M5_Hertz Hz SI Hz
#value M5_Percent Percent SI Percent
#value M5_ _ SI _

askMode getMeasUnit1?;getMeasUnit2?;getMeasUnit3?;getMeasUnit4?;getMeasUnit5?
#askValues DynamicM1?;DynamicM2?;DynamicM3?;DynamicM4?;DynamicM5?
#modeFromVar meas1Unit;meas2Unit;meas3Unit;meas4Unit;meas5Unit

#readingDelay 1


Each Measurement channel has a setup that looks like this:
Code: [Select]
; ******** Dynamic Measurement 1 ********
#scpiCmd MeasChan1 none
:setvar: meas1Chan=inputValue
#scpiCmd getMeasChan1? none?
:readmath: meas1Chan
#cmdSetup combobox M1_Channel Measure
:read: getMeasChan1?
:write: MeasChan1 (value)
:update: M1_Channel
:string:
CH1 CHANnel1
CH2 CHANnel2
CH3 CHANnel3
CH4 CHANnel4
DO DIGital0
D1 DIGital1
D2 DIGital2
D3 DIGital3
D4 DIGital4
D5 DIGital5
D6 DIGital6
D7 DIGital7
D8 DIGital8
D9 DIGital9
D10 DIGital10
D11 DIGital11
D12 DIGital12
D13 DIGital13
D14 DIGital14
D15 DIGital15
:tip: Select measurement source
#cmdSetup combobox M1_Type Measure
:read: getMeasType1?
:write: MeasType1
:update: M1_Type
:string:
V_Min VMIN
V_Max VMAX
V_PP VPP
V_Base VBASe
V_Top VTOP
V_AMP VAMP
V_Lower VLOWer
V_Upper VUPPer
V_MID VMID
V_AVG VAVG
V_RMS VRMS
V_SD VSDeviation
Pos_Preshoot VPPReshoot
Neg_Preshoot VNPReshoot
Pos_Overshoot VPOVershoot
Neg_Overshoot VNOVershoot
Pos+ VPARea
Neg_Area VNARea
|Area| VAARea
Area VNAArea
Pos_Period_Area VPPArea
Neg_Period_Area VNPArea
|Period_Area| VAPArea
Period_Area VNAPArea
Time_Rise HRTime
Time_Fall HFTime
Period HPERiod
Frequency HFReq
Pos_Width HHWidth
Neg_Width HLWidth
Pos_Duty HHDuty
Neg_Duty HLDuty
Pos_Edge_Count RECount
Neg_Edge_Count FECount
Pos_Pulse_Count PPCount
Neg_Pulse_Count NPCount
:tip: Select measurement type

The variables get set correctly, and the scope control responds correctly. The issue remains to set the Unit mode.

Even when I reduced the #values to a single option, it didn't work correctly. It had a similar error, where I could set to Hz, but it wouldn't switch to anything after that.

I can send you the whole definition if you want, but I don't want to post it publicly yet.

Thanks,
Josh
« Last Edit: September 23, 2025, 04:05:50 pm by KungFuJosh »
"Experience is something you don't get until just after you need it." - Steven Wright
Best Continuity Tester Ever
Best Continuity Tester Ever...Got Betterer!
 

Online HKJTopic starter

  • Super Contributor
  • ***
  • Posts: 4974
  • Country: dk
    • Tests
Re: Program that can log/control many multimeters and other devices.
« Reply #4684 on: September 23, 2025, 04:36:28 pm »
I can send you the whole definition if you want, but I don't want to post it publicly yet.

I do nor believe it is much use without the device.

The #modeFromVar only takes one var name, you must sting them together where you make them.
 
The following users thanked this post: KungFuJosh

Online KungFuJosh

  • Super Contributor
  • ***
  • Posts: 8489
  • Country: us
  • TEAS is real.
Re: Program that can log/control many multimeters and other devices.
« Reply #4685 on: September 23, 2025, 04:46:22 pm »
I can send you the whole definition if you want, but I don't want to post it publicly yet.

I do nor believe it is much use without the device.
The device works as expected consistently; it's the variable reading mode change that's the issue.

Quote
The #modeFromVar only takes one var name, you must sting them together where you make them.
How does it work then? Does it want the same setup: "variable1 variable2 variable3 etc"?
If it would combine them, then how does it separate them after?

Ideally, I would prefer it could read variables the same way it does for multiples like other commands..
Either with reading variables directly:
#modeFromVar meas1Unit;meas2Unit;meas3Unit;meas4Unit;meas5Unit

Or the command to read the variables:
#modeFromVar getMeasUnit1?;getMeasUnit2?;getMeasUnit3?;getMeasUnit4?;getMeasUnit5?

Whichever would be easier for you to implement.

Thanks,
Josh
"Experience is something you don't get until just after you need it." - Steven Wright
Best Continuity Tester Ever
Best Continuity Tester Ever...Got Betterer!
 

Online HKJTopic starter

  • Super Contributor
  • ***
  • Posts: 4974
  • Country: dk
    • Tests
Re: Program that can log/control many multimeters and other devices.
« Reply #4686 on: September 23, 2025, 05:09:34 pm »
How does it work then? Does it want the same setup: "variable1 variable2 variable3 etc"?
If it would combine them, then how does it separate them after?

Ideally, I would prefer it could read variables the same way it does for multiples like other commands..
Either with reading variables directly:
#modeFromVar meas1Unit;meas2Unit;meas3Unit;meas4Unit;meas5Unit

Or the command to read the variables:
#modeFromVar getMeasUnit1?;getMeasUnit2?;getMeasUnit3?;getMeasUnit4?;getMeasUnit5?

Whichever would be easier for you to implement.

Just use a:

var allModes=v1+","+v2+","+v3+","+v4+","+v5

At the bottom of each getMeasUnitX?

TC looks after , to split modes.
 
The following users thanked this post: KungFuJosh

Online KungFuJosh

  • Super Contributor
  • ***
  • Posts: 8489
  • Country: us
  • TEAS is real.
Re: Program that can log/control many multimeters and other devices.
« Reply #4687 on: September 23, 2025, 06:26:22 pm »
Just use a:

var allModes=v1+","+v2+","+v3+","+v4+","+v5

At the bottom of each getMeasUnitX?

TC looks after , to split modes.

I added var allModes=meas1Unit+","+meas2Unit+","+meas3Unit+","+meas4Unit+","+meas5Unit there, but it didn't help. The combo boxes in the cmdSetup need to update the variables when they're changed, so I put it in the combo boxes instead (I tried both places at the same time to see if it made a difference, but it did not).

However, the issue persisted, and I figured out part of the problem. The channels require unique selectors to work independently. Here's the updated #value set:
Code: [Select]
#value M1_Volts V SI V1
#value M1_Amps A SI A1
#value M1_Vs V SI Vs1
#value M1_Seconds s SI s1
#value M1_Hertz Hz SI Hz1
#value M1_Percent Percent SI Percent1
#value M1_ _ SI noU1
#value M2_Volts V SI V2
#value M2_Amps A SI A2
#value M2_Vs V SI Vs2
#value M2_Seconds s SI s2
#value M2_Hertz Hz SI Hz2
#value M2_Percent Percent SI Percent2
#value M2_ _ SI noU2
#value M3_Volts V SI V3
#value M3_Amps A SI A3
#value M3_Vs V SI Vs3
#value M3_Seconds s SI s3
#value M3_Hertz Hz SI Hz3
#value M3_Percent Percent SI Percent3
#value M3_ _ SI noU3
#value M4_Volts V SI V4
#value M4_Amps A SI A4
#value M4_Vs V SI Vs4
#value M4_Seconds s SI s4
#value M4_Hertz Hz SI Hz4
#value M4_Percent Percent SI Percent4
#value M4_ _ SI noU4
#value M5_Volts V SI V5
#value M5_Amps A SI A5
#value M5_Vs V SI Vs5
#value M5_Seconds s SI s5
#value M5_Hertz Hz SI Hz5
#value M5_Percent Percent SI Percent5
#value M5_ _ SI noU5

Unfortunately, even with the unique identifiers, only one Measurement channel can have the units updated. For example, if I change M1 to Hz, it will work if I'm not on the Current Value screen. Switch to CV, and it shows Hz. Then I try to change another M channel, and the value changes appropriately, but the unit doesn't update, despite the allModes variable updating correctly. For example:
getallModes?
;; noU1,V2,V3,Hz4,V5

That will show no unit on M1 (as expected), but M2 through M5 still show V as the unit, despite M4 clearly being set to Hz. Whichever mode I change first will update once, but any change after that is ignored, even on the same M# channel.


This is the current test setup:
Code: [Select]
#askMode getallModes?
#askValues DynamicM1?;DynamicM2?;DynamicM3?;DynamicM4?;DynamicM5?
#modeFromVar allModes

#cmdModeLayout 1 5
#cmdMode Update_Modes getallModes?
getallModes?

I added that cmdMode to see if it would work, and it does. Running that command correctly updates each of the M# channels to the correct independent units.

Each command looks like this now (with their respective #s):
Code: [Select]
#scpiCmd MeasType5 #pgm#
var type=value;
var meas5Type=value;
var meas5Unit="";
var fullunit5Command=meas5Chan + ":UNIT?";
var unit5result=deviceRead(handle, fullunit5Command);
if (type=="VMIN" || type=="VMAX" || type=="VPP" || type=="VBASe" || type=="VTOP" ||
    type=="VAMP" || type=="VLOWer" || type=="VUPPer" || type=="VMID" || type=="VAVG" ||
    type=="VRMS" || type=="VSDeviation" || type=="VPPReshoot" || type=="VNPReshoot" ||
    type=="VPOVershoot" || type=="VNOVershoot")
    if (unit5result=="V")
    var meas5Unit="V5";
    elseif (unit5result=="A")
    var meas5Unit="A5";
endif
elseif (type=="VPARea" || type=="VNARea" || type=="VAARea" || type=="VNAArea" ||
           type=="VPPArea" || type=="VNPArea" || type=="VAPArea" || type=="VNAPArea")
    var meas5Unit="Vs5";
elseif (type=="HRTime" || type=="HFTime" || type=="HPERiod" || type=="HHWidth" ||
           type=="HLWidth")
    var meas5Unit="s5";
elseif (type=="HFReq")
    var meas5Unit="Hz5";
elseif (type=="HHDuty" || type=="HLDuty")
    var meas5Unit="Percent5";
elseif (type=="RECount" || type=="FECount" || type=="PPCount" || type=="NPCount" || type=="")
    var meas5Unit="noU5";
endif
var allModes=meas1Unit+","+meas2Unit+","+meas3Unit+","+meas4Unit+","+meas5Unit
#scpiCmd getMeasType5? none?
:readmath: meas5Type
#scpiCmd getMeasUnit5? none?
:readmath: meas5Unit

#scpiCmd getallModes? none?
:readmath: allModes

So, what is still missing to get the unit mode to update at any time?

Does #modeFromVar need some tweaking?

Thanks,
Josh
« Last Edit: September 23, 2025, 06:50:09 pm by KungFuJosh »
"Experience is something you don't get until just after you need it." - Steven Wright
Best Continuity Tester Ever
Best Continuity Tester Ever...Got Betterer!
 

Online KungFuJosh

  • Super Contributor
  • ***
  • Posts: 8489
  • Country: us
  • TEAS is real.
Re: Program that can log/control many multimeters and other devices.
« Reply #4688 on: September 23, 2025, 07:01:33 pm »
This is sorta interesting, but I guess doesn't change anything. If I change values on multiple M# channels before viewing the Current Values screen, it gives an error, but switching back and forth a couple times, it will change multiple channels at once, the first time only. Then everything else persists the same way.

Code: [Select]
;; Magnova: Tx <MeasType1 HRTime>
;; Magnova: Script start
;; Magnova: Tx <CHAN1:UNIT?>
;; IP: Tx: <CHAN1:UNIT?.> 43 48 41 4E 31 3A 55 4E 49 54 3F 0A
;; IP: Rx: <V> 56 0A
;; Magnova: Rx <V>
;; Magnova: Script end <>
;; Magnova: Tx <getMeasType1?>
;; Magnova: Tx <none?>
;; Magnova: Rx <HRTime>
;; Magnova: Tx <MeasType2 VNAArea>
;; Magnova: Script start
;; Magnova: Tx <CHAN1:UNIT?>
;; IP: Tx: <CHAN1:UNIT?.> 43 48 41 4E 31 3A 55 4E 49 54 3F 0A
;; IP: Rx: <V> 56 0A
;; Magnova: Rx <V>
;; Magnova: Script end <>
;; Magnova: Tx <getMeasType2?>
;; Magnova: Tx <none?>
;; Magnova: Rx <VNAArea>
;; Magnova: Tx <MeasType3 VAMP>
;; Magnova: Script start
;; Magnova: Tx <CHAN1:UNIT?>
;; IP: Tx: <CHAN1:UNIT?.> 43 48 41 4E 31 3A 55 4E 49 54 3F 0A
;; IP: Rx: <V> 56 0A
;; Magnova: Rx <V>
;; Magnova: Script end <>
;; Magnova: Tx <getMeasType3?>
;; Magnova: Tx <none?>
;; Magnova: Rx <VAMP>
;; Magnova: Tx <MeasType4 HFReq>
;; Magnova: Script start
;; Magnova: Tx <CHAN1:UNIT?>
;; IP: Tx: <CHAN1:UNIT?.> 43 48 41 4E 31 3A 55 4E 49 54 3F 0A
;; IP: Rx: <V> 56 0A
;; Magnova: Rx <V>
;; Magnova: Script end <>
;; Magnova: Tx <getMeasType4?>
;; Magnova: Tx <none?>
;; Magnova: Rx <HFReq>
;; Magnova: Tx <MeasType5 RECount>
;; Magnova: Script start
;; Magnova: Tx <CHAN1:UNIT?>
;; IP: Tx: <CHAN1:UNIT?.> 43 48 41 4E 31 3A 55 4E 49 54 3F 0A
;; IP: Rx: <V> 56 0A
;; Magnova: Rx <V>
;; Magnova: Script end <>
;; Magnova: Tx <getMeasType5?>
;; Magnova: Tx <none?>
;; Magnova: Rx <RECount>
;; Magnova: Tx <DynamicM1?>
;; Magnova: Script start
;; Magnova: Tx <:MEAS:HRTime:CURR? CHAN1>
;; IP: Tx: <:MEAS:HRTime:CURR? CHAN1.> 3A 4D 45 41 53 3A 48 52 54 69 6D 65 3A 43 55 52 52 3F 20 43 48 41 4E 31 0A
;; IP: Rx: <2.95566E-07> 32 2E 39 35 35 36 36 45 2D 30 37 0A
;; Magnova: Rx <2.95566E-07>
;; Magnova: Script end <2.95566E-07>
;; Magnova: Rx <2.95566E-07>
;; Magnova: Tx <DynamicM2?>
;; Magnova: Script start
;; Magnova: Tx <:MEAS:VNAArea:CURR? CHAN1>
;; IP: Tx: <:MEAS:VNAArea:CURR? CHAN1.> 3A 4D 45 41 53 3A 56 4E 41 41 72 65 61 3A 43 55 52 52 3F 20 43 48 41 4E 31 0A
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException: Cannot read field "modes" because "this.form" is null
        at dk.hkj.devices.SetupFormats.syncModeChange(SetupFormats.java:428)
        at dk.hkj.main.PopupSetupSelection.syncModeChange(PopupSetupSelection.java:189)
        at dk.hkj.main.DeviceInterface$4.run(DeviceInterface.java:496)
        at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
        at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:773)
        at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
        at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:87)
        at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
        at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
        at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
;; IP: Rx: <-6.152E-09> 2D 36 2E 31 35 32 45 2D 30 39 0A
;; Magnova: Rx <-6.152E-09>
;; Magnova: Script end <-6.152E-09>
;; Magnova: Rx <-6.152E-09>
;; Magnova: Tx <DynamicM3?>
;; Magnova: Script start
;; Magnova: Tx <:MEAS:VAMP:CURR? CHAN1>
;; IP: Tx: <:MEAS:VAMP:CURR? CHAN1.> 3A 4D 45 41 53 3A 56 41 4D 50 3A 43 55 52 52 3F 20 43 48 41 4E 31 0A
;; IP: Rx: <0.500175> 30 2E 35 30 30 31 37 35 0A
;; Magnova: Rx <0.500175>
;; Magnova: Script end <0.500175>
;; Magnova: Rx <0.500175>
;; Magnova: Tx <DynamicM4?>
;; Magnova: Script start
;; Magnova: Tx <:MEAS:HFReq:CURR? CHAN1>
;; IP: Tx: <:MEAS:HFReq:CURR? CHAN1.> 3A 4D 45 41 53 3A 48 46 52 65 71 3A 43 55 52 52 3F 20 43 48 41 4E 31 0A
;; IP: Rx: <999550.982956875> 39 39 39 35 35 30 2E 39 38 32 39 35 36 38 37 35 0A
;; Magnova: Rx <999550.982956875>
;; Magnova: Script end <999550.982956875>
;; Magnova: Rx <999550.982956875>
;; Magnova: Tx <DynamicM5?>
;; Magnova: Script start
;; Magnova: Tx <:MEAS:RECount:CURR? CHAN1>
;; IP: Tx: <:MEAS:RECount:CURR? CHAN1.> 3A 4D 45 41 53 3A 52 45 43 6F 75 6E 74 3A 43 55 52 52 3F 20 43 48 41 4E 31 0A
;; IP: Rx: <3> 33 0A
;; Magnova: Rx <3>
;; Magnova: Script end <3>
;; Magnova: Rx <3>
;; Magnova: Rx as numbers <2.95566E-7 -6.152E-9 0.500175 999550.982956875 3.0>
;; Magnova: Tx <DynamicM1?>
;; Magnova: Script start
;; Magnova: Tx <:MEAS:HRTime:CURR? CHAN1>
;; IP: Tx: <:MEAS:HRTime:CURR? CHAN1.> 3A 4D 45 41 53 3A 48 52 54 69 6D 65 3A 43 55 52 52 3F 20 43 48 41 4E 31 0A
;; IP: Rx: <2.92988E-07> 32 2E 39 32 39 38 38 45 2D 30 37 0A
;; Magnova: Rx <2.92988E-07>
;; Magnova: Script end <2.92988E-07>
;; Magnova: Rx <2.92988E-07>
;; Magnova: Tx <DynamicM2?>
;; Magnova: Script start
;; Magnova: Tx <:MEAS:VNAArea:CURR? CHAN1>
;; IP: Tx: <:MEAS:VNAArea:CURR? CHAN1.> 3A 4D 45 41 53 3A 56 4E 41 41 72 65 61 3A 43 55 52 52 3F 20 43 48 41 4E 31 0A
;; IP: Rx: <-5.504E-09> 2D 35 2E 35 30 34 45 2D 30 39 0A
;; Magnova: Rx <-5.504E-09>
;; Magnova: Script end <-5.504E-09>
;; Magnova: Rx <-5.504E-09>
;; Magnova: Tx <DynamicM3?>
;; Magnova: Script start
;; Magnova: Tx <:MEAS:VAMP:CURR? CHAN1>
;; IP: Tx: <:MEAS:VAMP:CURR? CHAN1.> 3A 4D 45 41 53 3A 56 41 4D 50 3A 43 55 52 52 3F 20 43 48 41 4E 31 0A
;; IP: Rx: <0.4989> 30 2E 34 39 38 39 0A
;; Magnova: Rx <0.4989>
;; Magnova: Script end <0.4989>
;; Magnova: Rx <0.4989>
;; Magnova: Tx <DynamicM4?>
;; Magnova: Script start
;; Magnova: Tx <:MEAS:HFReq:CURR? CHAN1>
;; IP: Tx: <:MEAS:HFReq:CURR? CHAN1.> 3A 4D 45 41 53 3A 48 46 52 65 71 3A 43 55 52 52 3F 20 43 48 41 4E 31 0A
;; IP: Rx: <1000156.27441788> 31 30 30 30 31 35 36 2E 32 37 34 34 31 37 38 38 0A
;; Magnova: Rx <1000156.27441788>
;; Magnova: Script end <1000156.27441788>
;; Magnova: Rx <1000156.27441788>
;; Magnova: Tx <DynamicM5?>
;; Magnova: Script start
;; Magnova: Tx <:MEAS:RECount:CURR? CHAN1>
;; IP: Tx: <:MEAS:RECount:CURR? CHAN1.> 3A 4D 45 41 53 3A 52 45 43 6F 75 6E 74 3A 43 55 52 52 3F 20 43 48 41 4E 31 0A
;; IP: Rx: <3> 33 0A
;; Magnova: Rx <3>
;; Magnova: Script end <3>
;; Magnova: Rx <3>
;; Magnova: Rx as numbers <2.92988E-7 -5.504E-9 0.4989 1000156.27441788 3.0>
;; Magnova: Tx <getallModes?>
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException: Cannot read field "modes" because "this.form" is null
        at dk.hkj.devices.SetupFormats.syncModeChange(SetupFormats.java:428)
        at dk.hkj.main.PopupSetupSelection.syncModeChange(PopupSetupSelection.java:189)
        at dk.hkj.main.DeviceInterface.initColumns(DeviceInterface.java:490)
        at dk.hkj.devices.DeviceSCPI.initColumns(DeviceSCPI.java:125)
        at dk.hkj.main.DeviceInterface$2.actionPerformed(DeviceInterface.java:453)
        at java.desktop/javax.swing.Timer.fireActionPerformed(Timer.java:311)
        at java.desktop/javax.swing.Timer$DoPostEvent.run(Timer.java:243)
        at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
        at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:773)
        at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
        at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:87)
        at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
        at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
        at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException: Cannot read field "modes" because "this.form" is null
        at dk.hkj.devices.SetupFormats.syncModeChange(SetupFormats.java:428)
        at dk.hkj.main.PopupSetupSelection.syncModeChange(PopupSetupSelection.java:189)
        at dk.hkj.main.DeviceInterface$4.run(DeviceInterface.java:496)
        at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
        at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:773)
        at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
        at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:87)
        at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
        at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
        at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
;; Magnova: Tx <none?>
;; Magnova: Rx <s1,Vs2,V3,Hz4,noU5>
;; Magnova: Tx <DynamicM1?>
;; Magnova: Script start
;; Magnova: Tx <:MEAS:HRTime:CURR? CHAN1>
;; IP: Tx: <:MEAS:HRTime:CURR? CHAN1.> 3A 4D 45 41 53 3A 48 52 54 69 6D 65 3A 43 55 52 52 3F 20 43 48 41 4E 31 0A
;; IP: Rx: <2.94688E-07> 32 2E 39 34 36 38 38 45 2D 30 37 0A
;; Magnova: Rx <2.94688E-07>
;; Magnova: Script end <2.94688E-07>
;; Magnova: Rx <2.94688E-07>
;; Magnova: Tx <DynamicM2?>
;; Magnova: Script start
;; Magnova: Tx <:MEAS:VNAArea:CURR? CHAN1>
;; IP: Tx: <:MEAS:VNAArea:CURR? CHAN1.> 3A 4D 45 41 53 3A 56 4E 41 41 72 65 61 3A 43 55 52 52 3F 20 43 48 41 4E 31 0A
;; IP: Rx: <-5.442E-09> 2D 35 2E 34 34 32 45 2D 30 39 0A
;; Magnova: Rx <-5.442E-09>
;; Magnova: Script end <-5.442E-09>
;; Magnova: Rx <-5.442E-09>
;; Magnova: Tx <DynamicM3?>
;; Magnova: Script start
;; Magnova: Tx <:MEAS:VAMP:CURR? CHAN1>
;; IP: Tx: <:MEAS:VAMP:CURR? CHAN1.> 3A 4D 45 41 53 3A 56 41 4D 50 3A 43 55 52 52 3F 20 43 48 41 4E 31 0A
;; IP: Rx: <0.4987> 30 2E 34 39 38 37 0A
;; Magnova: Rx <0.4987>
;; Magnova: Script end <0.4987>
;; Magnova: Rx <0.4987>
;; Magnova: Tx <DynamicM4?>
;; Magnova: Script start
;; Magnova: Tx <:MEAS:HFReq:CURR? CHAN1>
;; IP: Tx: <:MEAS:HFReq:CURR? CHAN1.> 3A 4D 45 41 53 3A 48 46 52 65 71 3A 43 55 52 52 3F 20 43 48 41 4E 31 0A
;; IP: Rx: <999472.934194858> 39 39 39 34 37 32 2E 39 33 34 31 39 34 38 35 38 0A
;; Magnova: Rx <999472.934194858>
;; Magnova: Script end <999472.934194858>
;; Magnova: Rx <999472.934194858>
;; Magnova: Tx <DynamicM5?>
;; Magnova: Script start
;; Magnova: Tx <:MEAS:RECount:CURR? CHAN1>
;; IP: Tx: <:MEAS:RECount:CURR? CHAN1.> 3A 4D 45 41 53 3A 52 45 43 6F 75 6E 74 3A 43 55 52 52 3F 20 43 48 41 4E 31 0A
;; IP: Rx: <3> 33 0A
;; Magnova: Rx <3>
;; Magnova: Script end <3>
;; Magnova: Rx <3>
;; Magnova: Rx as numbers <2.94688E-7 -5.442E-9 0.4987 999472.934194858 3.0>
"Experience is something you don't get until just after you need it." - Steven Wright
Best Continuity Tester Ever
Best Continuity Tester Ever...Got Betterer!
 

Online KungFuJosh

  • Super Contributor
  • ***
  • Posts: 8489
  • Country: us
  • TEAS is real.
Re: Program that can log/control many multimeters and other devices.
« Reply #4689 on: September 23, 2025, 07:10:44 pm »
Thank you,  but that only works with number inputs, not text. With a text input, it breaks it. Individually Unit/Offset/Scale are shown in the screenshot along with this attempted combination of the three:

Try adding a :string: tag

I tried adding :string: a few different ways, and it made no difference. The only way I could get it to work is if everything was a number. With :string: and everything as text, it shows nothing but the set button.

Thanks,
Josh
"Experience is something you don't get until just after you need it." - Steven Wright
Best Continuity Tester Ever
Best Continuity Tester Ever...Got Betterer!
 

Online Gertjan

  • Frequent Contributor
  • **
  • Posts: 377
  • Country: nl
Re: Program that can log/control many multimeters and other devices.
« Reply #4690 on: September 24, 2025, 09:25:24 am »
I have implemented a option to synchronize the log to the param sweeper. It switches the log to advance logging SingleOnCommand mode. This means that TC will read data as fast as it can from the device and only log sample when requested (From param sweeper).
I have not added any option to adjust the offset, but place the trig command midways in the time.
Due to the increased communication I will generally recommend to run the param sweeper slower when using this option.

The test version is at the usually location: http://lygte-info.dk/pic/Projects/TestController/TestController.jar

Hi HKJ,

I tested your test version.
It works when using fast measurements, like 1NPLC. The previous problem of sometimes twice the same value  in the table is gone. (as expected with a delay after the param sweeper step)

But when higher accuracy is needed, this is not going to work... Metrology grade measurements are invariably slow. A measurement with 100NPLC will take 2...3 seconds (double with Auto Zero). Measuring OCXO drift with mHz resolution will need 10 seconds gate time with most (better) counters.
Sometimes you need the delay to let the measurement settle. Think of dielectric absorption in cables, or just the settling time of the output of the controlled device.

So I would propose this solution:
The param sweeper triggers the next step for the controlled device -> param sweeper waits for the set delay time -> Param sweeper triggers the log system for ONE measurement.

This way the measurements are always synchronous. The step time can be set to just the time needed for the delay + measurement. And with delay set to zero, the param sweeper will be as fast as it is now.

Thank you for looking into this & regards, Gertjan.
 

Online HKJTopic starter

  • Super Contributor
  • ***
  • Posts: 4974
  • Country: dk
    • Tests
Re: Program that can log/control many multimeters and other devices.
« Reply #4691 on: September 24, 2025, 09:45:22 am »
I tried adding :string: a few different ways, and it made no difference. The only way I could get it to work is if everything was a number. With :string: and everything as text, it shows nothing but the set button.

The :string: tag switches to reading it as a string, split the answer on ;, and space then distributes it to the different controls. The numeric controls will use a parser to convert strings to numbers.

That is how the code is written, I do not know why you have issues with it.
 

Online HKJTopic starter

  • Super Contributor
  • ***
  • Posts: 4974
  • Country: dk
    • Tests
Re: Program that can log/control many multimeters and other devices.
« Reply #4692 on: September 24, 2025, 10:02:45 am »
So I would propose this solution:
The param sweeper triggers the next step for the controlled device -> param sweeper waits for the set delay time -> Param sweeper triggers the log system for ONE measurement.

This way the measurements are always synchronous. The step time can be set to just the time needed for the delay + measurement. And with delay set to zero, the param sweeper will be as fast as it is now.

I understand the problem, but it is not a easy modification to TC. What I did was simply use another log mode. To do what you request would require a new log mode, or cheating the logging system some way. The second option is possible the easiest, but I will need some time to look at it.
 

Online HKJTopic starter

  • Super Contributor
  • ***
  • Posts: 4974
  • Country: dk
    • Tests
Re: Program that can log/control many multimeters and other devices.
« Reply #4693 on: September 24, 2025, 10:15:41 am »
Unfortunately, even with the unique identifiers, only one Measurement channel can have the units updated. For example, if I change M1 to Hz, it will work if I'm not on the Current Value screen. Switch to CV, and it shows Hz. Then I try to change another M channel, and the value changes appropriately, but the unit doesn't update, despite the allModes variable updating correctly. For example:
getallModes?
;; noU1,V2,V3,Hz4,V5

That will show no unit on M1 (as expected), but M2 through M5 still show V as the unit, despite M4 clearly being set to Hz. Whichever mode I change first will update once, but any change after that is ignored, even on the same M# channel.

Doing a mode/column change is a fairly complicated procedure in TC, this makes it hard for me to inspect the code and guess on what goes wrong.
One detail: Please do not use invalid column names like noU1, instead leave it out. Columns with a column name that is not present in the mode list will not be shown.

One option is I make a special TC with some extra logging build in and you test with that?
 

Online Gertjan

  • Frequent Contributor
  • **
  • Posts: 377
  • Country: nl
Re: Program that can log/control many multimeters and other devices.
« Reply #4694 on: September 24, 2025, 10:37:38 am »
So I would propose this solution:
The param sweeper triggers the next step for the controlled device -> param sweeper waits for the set delay time -> Param sweeper triggers the log system for ONE measurement.

This way the measurements are always synchronous. The step time can be set to just the time needed for the delay + measurement. And with delay set to zero, the param sweeper will be as fast as it is now.

I understand the problem, but it is not a easy modification to TC. What I did was simply use another log mode. To do what you request would require a new log mode, or cheating the logging system some way. The second option is possible the easiest, but I will need some time to look at it.

Hi HKJ,

There is no hurry, for now I have found a workaround (temporary editing the device files with #askValues starting with a delay)

But the Param Sweeper is a much used pop-up. So improving it would be very worthwhile.

regards, Gertjan.
 

Online KungFuJosh

  • Super Contributor
  • ***
  • Posts: 8489
  • Country: us
  • TEAS is real.
Re: Program that can log/control many multimeters and other devices.
« Reply #4695 on: September 24, 2025, 02:40:00 pm »
I tried adding :string: a few different ways, and it made no difference. The only way I could get it to work is if everything was a number. With :string: and everything as text, it shows nothing but the set button.

The :string: tag switches to reading it as a string, split the answer on ;, and space then distributes it to the different controls. The numeric controls will use a parser to convert strings to numbers.

That is how the code is written, I do not know why you have issues with it.

I've tried it different ways, and it doesn't work. The instructions on your website also say it won't work, so if there's a way to make it work, clear guidance would be appreciated.

string text only.jpg:
Code: [Select]
#cmdSetup multi Math_CH1_Setup Math
:read: :MATH1:UNIT?;:MATH1:OFFS?;:MATH1:SCAL?
:write: :MATH1:UNIT (value);:MATH1:OFFS (value2);:MATH1:SCAL (value3)
:update: Math_CH1_Setup
:string:
:tip: Enter desired setup values.
text Unit
text Offset
text Scale

string text number text.jpg:
Code: [Select]
#cmdSetup multi Math_CH1_Setup Math
:read: :MATH1:UNIT?;:MATH1:OFFS?;:MATH1:SCAL?
:write: :MATH1:UNIT (value);:MATH1:OFFS (value2);:MATH1:SCAL (value3)
:update: Math_CH1_Setup
:string:
:tip: Enter desired setup values.
text Unit
number Offset _ 0 6
text Scale

no string numbers only.jpg:
Code: [Select]
#cmdSetup multi Math_CH1_Setup Math
:read: :MATH1:UNIT?;:MATH1:OFFS?;:MATH1:SCAL?
:write: :MATH1:UNIT (value);:MATH1:OFFS (value2);:MATH1:SCAL (value3)
:update: Math_CH1_Setup
:tip: Enter desired setup values.
number Unit _ 0 6
number Offset _ 0 6
number Scale _ 0 6

This version almost works, but still doesn't:
inline string tags and number.jpg:
Code: [Select]
#cmdSetup multi Math_CH1_Setup Math
:read: :MATH1:UNIT?;:MATH1:OFFS?;:MATH1:SCAL?
:write: :MATH1:UNIT (value);:MATH1:OFFS (value2);:MATH1:SCAL (value3)
:update: Math_CH1_Setup
:tip: Enter desired setup values.
number Unit :string:
number Offset _ 0 6
number Scale _ 0 6

What's missing? What's the correct way to do it?

Thanks,
Josh

ETA:

I changed text to a combobox, and it works as expected. It seems text is not currently an option for control multi.

This works:
Code: [Select]
#cmdSetup multi Math_CH1_Setup Math
:read: :MATH1:UNIT?;:MATH1:OFFS?;:MATH1:SCAL?
:write: :MATH1:UNIT (value);:MATH1:OFFS (value2);:MATH1:SCAL (value3)
:update: Math_CH1_Setup,Math_CH1_Scale,Math_CH1_Offset,Math_CH1_Unit
:tip: Enter desired setup values.
combobox Unit:V V Unit:A A :string:
number Offset _ 0 100
number Scale _ 0 100

Is it possible to add a label for the combobox? I'm just curious, I actually do need text to work (value can be anything, not limited to a few options).
« Last Edit: September 24, 2025, 04:44:55 pm by KungFuJosh »
"Experience is something you don't get until just after you need it." - Steven Wright
Best Continuity Tester Ever
Best Continuity Tester Ever...Got Betterer!
 

Online KungFuJosh

  • Super Contributor
  • ***
  • Posts: 8489
  • Country: us
  • TEAS is real.
Re: Program that can log/control many multimeters and other devices.
« Reply #4696 on: September 24, 2025, 03:09:34 pm »
Unfortunately, even with the unique identifiers, only one Measurement channel can have the units updated. For example, if I change M1 to Hz, it will work if I'm not on the Current Value screen. Switch to CV, and it shows Hz. Then I try to change another M channel, and the value changes appropriately, but the unit doesn't update, despite the allModes variable updating correctly. For example:
getallModes?
;; noU1,V2,V3,Hz4,V5

That will show no unit on M1 (as expected), but M2 through M5 still show V as the unit, despite M4 clearly being set to Hz. Whichever mode I change first will update once, but any change after that is ignored, even on the same M# channel.

Doing a mode/column change is a fairly complicated procedure in TC, this makes it hard for me to inspect the code and guess on what goes wrong.
One detail: Please do not use invalid column names like noU1, instead leave it out. Columns with a column name that is not present in the mode list will not be shown.

One option is I make a special TC with some extra logging build in and you test with that?

I'd be happy to try a extra logging build to sort this out. I think there is a bug hiding when using complex unit changes.

noU1 is a valid selector following the format:
;#value name unit format {selector}

noU1 works fine when selected. TC requires each M# to have a unique {selector}, otherwise each M# with a matching {selector} will have that {selector} line visible on each channel, whether intended or not (for example, 5 channels, 5 data sets, activating a 2nd mode will show 2 modes for each channel with matching selectors; creating 10 channels, and still only receiving 5 data sets if the selectors are not unique).

Each of the items in this works as expected:
;; noU1,V2,V3,Hz4,V5

noU1 is no units (uses _ for Unit column) on M1, V2 is Voltage on M2, V3 is Voltage on M3, Hz4 is Hertz on M4, and V5 is Voltage on M5.

This is the first 2 M# channels:
Code: [Select]
;#value name unit format {selector}
#value M1_Volts V SI V1
#value M1_Amps A SI A1
#value M1_Vs V SI Vs1
#value M1_Seconds s SI s1
#value M1_Hertz Hz SI Hz1
#value M1_Percent Percent SI Percent1
#value M1_ _ SI noU1
#value M2_Volts V SI V2
#value M2_Amps A SI A2
#value M2_Vs V SI Vs2
#value M2_Seconds s SI s2
#value M2_Hertz Hz SI Hz2
#value M2_Percent Percent SI Percent2
#value M2_ _ SI noU2

I can set any unit {selector} variable, and it will work correctly when I use the cmdMode button:
Code: [Select]
#scpiCmd getallModes? none?
:readmath: allModes

#askMode getallModes?
#askValues DynamicM1?;DynamicM2?;DynamicM3?;DynamicM4?;DynamicM5?
#modeFromVar allModes

#readingDelay 1
#modeChangeDelay 1

#cmdModeLayout 1 5
#cmdMode Update_Modes getallModes?
getallModes?

As long as I'm not on the Current Values tab, I can set the modes however I want ONE time using cmdSetup:


Then I can switch the values in cmdSetup, and it correctly sets the variables, and updates the scope data acquisition correctly, but the displayed mode units do not update as expected:


Instead, I must go to the Modes button and (when not on the Current Values screen) I can click the button to update the modes, and it works correctly:


So this seems to be an issue with the way TC updates the modes/units. The issue with #modeFromVar seems similar to how it was before, so the bug might be deeper. I don't know. I'm happy to run a more detailed logging version to try and find out.

Alternatively, if you specify a device that you have with simple SCPI, I can make a modified version of that device's file with similar mode switching (actual data from the device is irrelevant, we just need modes to switch) that you could test as well.

Thanks,
Josh

ETA: I did further testing, and it doesn't matter how many channels or mode selectors are used. I reduced it to 1 channel with 2 mode selector options, and the behavior described above persisted. Updating based on a Variable appears to be the issue.
« Last Edit: September 24, 2025, 03:18:46 pm by KungFuJosh »
"Experience is something you don't get until just after you need it." - Steven Wright
Best Continuity Tester Ever
Best Continuity Tester Ever...Got Betterer!
 

Online Gertjan

  • Frequent Contributor
  • **
  • Posts: 377
  • Country: nl
Re: Program that can log from many multimeters.
« Reply #4697 on: September 24, 2025, 05:51:57 pm »
I wrote a configuration file for the Wrytech PDVS 2 mini v2.
It looks very nice with a computer controlled reference, with TC you can easily do a computer controlled sweep and using math channels make a curve that shows the difference between the reference and a voltmeter.

Hi HKJ,

I took that measurement, and wrote about it in this post: Wrytech PDVS2 mini v2 linearity.

regards, Gertjan.
 

Online HKJTopic starter

  • Super Contributor
  • ***
  • Posts: 4974
  • Country: dk
    • Tests
Re: Program that can log/control many multimeters and other devices.
« Reply #4698 on: September 25, 2025, 11:11:47 am »
I'd be happy to try a extra logging build to sort this out. I think there is a bug hiding when using complex unit changes.

I have made a new .jar file with extra logging, it is always on and goes to the console output (Not the log window).
There is extra logging for both mode changes and the multi control.
 
The following users thanked this post: KungFuJosh

Online HKJTopic starter

  • Super Contributor
  • ***
  • Posts: 4974
  • Country: dk
    • Tests
Re: Program that can log/control many multimeters and other devices.
« Reply #4699 on: September 25, 2025, 11:15:37 am »
There is no hurry, for now I have found a workaround (temporary editing the device files with #askValues starting with a delay)

But the Param Sweeper is a much used pop-up. So improving it would be very worthwhile.

I have made a workaround. TC uses a extremely slow logging when synchronized to param sweeper and will then reset the wait time for next log entry, when a log entry needs to be taken.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf

 

- - -
-->