Recent

Author Topic: visasession  (Read 7300 times)

MarkMLl

  • Hero Member
  • *****
  • Posts: 8335
Re: visasession
« Reply #15 on: February 07, 2025, 11:34:28 am »
Those are just USB vendor IDs: https://the-sz.com/products/usbid/index.php?v=0X0699&p=&n=
But I wouldn't trust that, but instead rely on the *IDN? result

May I ask a supplementary question here?

I believe that *IDN is mandatory, and I believe that I understand its output format.

What I'm far less happy about is the various status registers that this family of protocols (generally derivatives of HP-IB etc.) implements: which of those are really mandatory, and what is the expected response if a non-mandatory one isn't implemented?

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Laksen

  • Hero Member
  • *****
  • Posts: 794
    • J-Software
Re: visasession
« Reply #16 on: February 07, 2025, 02:12:32 pm »
IEEE 488.2 specifies the mandatory functions as well as the syntax and capitalization rules. I think all will support *IDN? Which will make it possible to detect quirky implementations

Especially low-cost manufacturers tend to ignore the standard very often, Rigol and R&S are some of the worst in my experience

If you call an invalid command or query you should be able to query *STB? to see if there's an error, whether the command completed or if there's a response waiting in the output buffer to be read. But that is problematic on for example ASRL and raw sockets where there isn't a way to query STB without overwriting the output buffer.
On GPIB, USB, VXI11/hislip there is an out of band way of reading STB

CM630

  • Hero Member
  • *****
  • Posts: 1302
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: visasession
« Reply #17 on: February 07, 2025, 02:41:49 pm »
As no suprise, when I dropped the VISA control on the panel it did not work.
So I had to add LoadVisaLib;.
Respectively I added unLoadVisaLib, too.

Code: Pascal  [Select][+][-]
  1. constructor TVisaSession.Create(AOwner: TComponent);
  2. begin
  3.    inherited Create(AOwner);
  4.    LoadVisaLib;
  5.    fThrowException := true;
  6.    fLock := TCriticalSection.Create;
  7.    fActive := false;
  8.    fAddress := '';
  9.    fHandle := 0;
  10.    fConnectTimeout := 2000;
  11. end;
  12.  
  13. destructor TVisaSession.Destroy;
  14. begin
  15.    fThrowException := false;
  16.    Active := false;
  17.    unLoadVisaLib;
  18.    fLock.Free;
  19.    inherited Destroy;
  20. end;  

And maybe :
Code: Pascal  [Select][+][-]
  1.  published
  2. ...
  3.   property VisaDLL: string read fVisaName write SetVisaName;
  4.  end;  


...
I believe that *IDN is mandatory, and I believe that I understand its output format.
...
I had absolutely no experience with Visa until this week, but as I wrote, the R&S did not respond to the *IDN?. Indeed, I have not even read the specs of the device, just plugged it in.
« Last Edit: February 07, 2025, 02:46:01 pm by CM630 »
Лазар 4,0RC2 32 bit (sometimes 64 bit); FPC3,2,2

MarkMLl

  • Hero Member
  • *****
  • Posts: 8335
Re: visasession
« Reply #18 on: February 07, 2025, 02:43:20 pm »
So STB /must/ be accessible. Do you have any comment on the rest of http://www.av.it.pt/medidas/data/Manuais%20&%20Tutoriais/40b%20-%20VNA%20-%20ZVB20/CD/documents/Help_Files/WebHelp_ZVB/Remote_Control/Status_Reporting_System/Status_Reporting_System.htm#Structure which appears to be a fairly concise summary?

I'm considering it in the context of https://github.com/MarkMLl/scpisrv , and wondering whether I could usefully add a register handling unit assumed to apply to all devices.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

CM630

  • Hero Member
  • *****
  • Posts: 1302
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: visasession
« Reply #19 on: February 07, 2025, 03:21:52 pm »
...
I'm considering it in the context of https://github.com/MarkMLl/scpisrv , and wondering whether I could usefully add a register handling unit assumed to apply to all devices.
...
So you have an app which reads data from serial measurement devices and wonder if you could extend it to using VISA devices, too?
Лазар 4,0RC2 32 bit (sometimes 64 bit); FPC3,2,2

MarkMLl

  • Hero Member
  • *****
  • Posts: 8335
Re: visasession
« Reply #20 on: February 07, 2025, 03:34:17 pm »
...
I'm considering it in the context of https://github.com/MarkMLl/scpisrv , and wondering whether I could usefully add a register handling unit assumed to apply to all devices.
...
So you have an app which reads data from serial measurement devices and wonder if you could extend it to using VISA devices, too?

No. I have a library that can be integrated with programs supporting various devices.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

CM630

  • Hero Member
  • *****
  • Posts: 1302
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: visasession
« Reply #21 on: February 10, 2025, 01:36:25 pm »
I cannot figure out how to get an event when data is available.
I tried viEnableEvent with no success.
I need it, because I do not know when the trigger of an oscilloscope will be activated (Query is not applicable). The other option I can think of is checking periodically if data has been received in a timer.
Лазар 4,0RC2 32 bit (sometimes 64 bit); FPC3,2,2

Laksen

  • Hero Member
  • *****
  • Posts: 794
    • J-Software
Re: visasession
« Reply #22 on: February 10, 2025, 02:48:51 pm »
What communications protocol are you using? SRQs don't work through serial for example

MarkMLl

  • Hero Member
  • *****
  • Posts: 8335
Re: visasession
« Reply #23 on: February 10, 2025, 03:04:39 pm »
Interesting. https://helpfiles.keysight.com/csg/N52xxB/Programming/GPIB_Example_Programs/Socket_Client.htm looks like it might be relevant at least at the SCPI layer: in short the software asks the instrument what port to use, and waits for asynchronous messages to arrive on it.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

CM630

  • Hero Member
  • *****
  • Posts: 1302
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: visasession
« Reply #24 on: February 10, 2025, 03:13:33 pm »
What communications protocol are you using? SRQs don't work through serial for example
Tektronix TBS xxxx over USB. If this happens to answer the question, which I do not understand.
USB0::0x0699::............
« Last Edit: February 10, 2025, 03:27:27 pm by CM630 »
Лазар 4,0RC2 32 bit (sometimes 64 bit); FPC3,2,2

Laksen

  • Hero Member
  • *****
  • Posts: 794
    • J-Software
Re: visasession
« Reply #25 on: February 10, 2025, 04:21:54 pm »
This for example should call the SRQ handler when bit 4 (MAV) in the STB byte gets set. This will be done when the instrument responds to the *STB? query. Likewise you could probably use this some way to trigger on a different bit in the instrument status tree (very instrument specific)

Code: Pascal  [Select][+][-]
  1. function handler(vi: ViSession; eventType: ViEventType; event: ViEvent; userHandle: ViAddr): ViStatus; stdcall;
  2. begin
  3.   writeln('Event!');
  4.   result:=0;
  5. end;
  6.  
  7. begin
  8.   visa.viInstallHandler(v, VI_EVENT_SERVICE_REQ, @handler, nil);
  9.   visa.viEnableEvent(v, VI_EVENT_SERVICE_REQ, VI_HNDLR, 0);
  10.  
  11.   instr.Command('*SRE 16');
  12.   instr.Command('*STB?'); // Handler should be called now since output buffer gets filled
  13. end.
  14.  

CM630

  • Hero Member
  • *****
  • Posts: 1302
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: visasession
« Reply #26 on: February 11, 2025, 10:14:34 am »
Thanks!
I did not understand how to execute your code as you wrote it.
So I added
Code: Pascal  [Select][+][-]
  1.  TVisaSession = class(TComponent)
  2. ...
  3. public
  4. ...
  5.   property Handle: ViSession read fHandle;
  6. ...

And then here is a snippet:
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,
  9.   visa,session,visatype;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     Button1: TButton;
  17.     Memo1: TMemo;
  18.     procedure Button1Click(Sender: TObject);
  19.     procedure FormCreate(Sender: TObject);
  20.   private
  21.  
  22.   public
  23.  
  24.   end;
  25.  
  26. var
  27.   Form1: TForm1;
  28.     MyVisaSession : TVisaSession;
  29.  
  30. implementation
  31.  
  32. {$R *.lfm}
  33.  
  34. { TForm1 }
  35.  
  36. function event_handler(vi: ViSession; eventType: ViEventType; event: ViEvent; userHandle: ViAddr): ViStatus; stdcall;
  37. begin
  38.   form1.Memo1.Append ('Event: ' + MyVisaSession.Read);
  39.   result:=0;
  40. end;
  41.  
  42. procedure TForm1.FormCreate(Sender: TObject);
  43. begin
  44.   Memo1.ScrollBars := ssBoth;
  45.   Memo1.WordWrap := false;
  46.   Memo1.Clear;
  47.   Memo1.Refresh;
  48.   MyVisaSession := TVisaSession.Create(nil);
  49.   MyVisaSession.Address :='USB0::0x0699::........';
  50.   MyVisaSession.Active := True;
  51.   visa.viInstallHandler(MyVisaSession.Handle , VI_EVENT_SERVICE_REQ, @event_handler, nil);
  52.   visa.viEnableEvent(MyVisaSession.Handle, VI_EVENT_SERVICE_REQ, VI_HNDLR, 0);
  53.   visa.viDiscardEvents(MyVisaSession.Handle, VI_EVENT_SERVICE_REQ,VI_HNDLR);
  54. end;
  55.  
  56. procedure Wait(Duration: QWord);
  57. var
  58.   StartTick: QWord;
  59. begin
  60.   StartTick := GetTickCount64;
  61.   repeat
  62.     Application.Processmessages;
  63.   until GetTickCount64 > (StartTick + Duration);
  64. end;
  65.  
  66. procedure TForm1.Button1Click(Sender: TObject);
  67. begin
  68.   MyVisaSession.Command('*RST;');
  69.   Wait(500);
  70.   MyVisaSession.Command('*SRE 16');
  71.   MyVisaSession.Command('*STB?'); // Handler should be called now since output buffer gets filled
  72.   Wait(50);
  73.   MyVisaSession.Command('*IDN?');
  74.   Wait(50);
  75.   MyVisaSession.Command('*ESR?');
  76.   Wait(50);
  77.   MyVisaSession.Command('EVM?');
  78.   Wait(50);
  79.   MyVisaSession.Command('*OPC');
  80.   Wait(50);
  81.   MyVisaSession.Command(':HOR:RECO 5000000;:HOR:SEC 0.040000;:HOR:DEL:MOD OFF;POS 2.000000');  //Configures the record properties of the acquisition subsystem.
  82.   //                                            time/div
  83.   Wait(50);
  84.   MyVisaSession.Command(':SEL:CH1 ON;:CH1:PRO:GAIN 1.00000;:CH1:COUP DC;SCA 1.500000;OFFS 0.000000;BAN TWE;DESK 0.000000;');
  85.   //                                          probe 1X                  v/div
  86.   Wait(50);
  87.   MyVisaSession.Command('WFMO:BYT_N?;NR_P?;YOF?;YMU?;YZE?;XIN?;XZE?');
  88.   Wait(50);
  89.   MyVisaSession.Command('CURV?');
  90. end;
  91.  
  92. end.

It succeeds in getting an untriggered waveform, I have not tried with a triggered one yet.
« Last Edit: February 11, 2025, 11:01:19 am by CM630 »
Лазар 4,0RC2 32 bit (sometimes 64 bit); FPC3,2,2

CM630

  • Hero Member
  • *****
  • Posts: 1302
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: visasession
« Reply #27 on: February 17, 2025, 02:33:35 pm »
I have a snippet which almost works.
It gets the data when the trigger is activated it starts to draw it in a TAChart.
But it causes an exception in TAChart.
The data seems valid - if I write the raw string received by the oscilloscope to a file and then load it and process it, there is no issue with TAChart, everything is fine.
Also, if I enable wait(1); in procedure PlotWaveForm the chart is drawn correctly, alas, that takes a lot of time.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, StrUtils,
  9.   TAGraph, TASeries, visa_dyn, session, visatype,
  10.   TADrawUtils, TACustomSeries;
  11.  
  12. type
  13.  
  14.   { TForm1 }
  15.  
  16.   TForm1 = class(TForm)
  17.     Button1: TButton;
  18.     Chart1: TChart;
  19.     Chart1LineSeries1: TLineSeries;
  20.     Label1: TLabel;
  21.     VisaSession: TVisaSession;
  22.     procedure Button1Click(Sender: TObject);
  23.     procedure FormCreate(Sender: TObject);
  24.   private
  25.  
  26.   public
  27.  
  28.   end;
  29.  
  30. var
  31.   Form1: TForm1;
  32.   WaitWaveform: boolean;
  33.  
  34.  // function VisaEventHandler(vi: ViSession; eventType: ViEventType; event: ViEvent; userHandle: ViAddr): ViStatus; stdcall;
  35. implementation
  36.  
  37. {$R *.lfm}
  38.  
  39. { TForm1 }
  40.  
  41. procedure Wait(Duration: QWord);
  42. var
  43.   StartTick: QWord;
  44. begin
  45.   StartTick := GetTickCount64;
  46.   repeat
  47.     Application.Processmessages;
  48.   until GetTickCount64 >= (StartTick + Duration);
  49. end;
  50.  
  51. procedure PlotWaveForm(WaveformData: string);
  52. var
  53.   i: integer;
  54.   plotdata: array of double;
  55.   dt : double = 10/1000;
  56.   plotindex: integer = -1;
  57.   numstring: string ='';
  58.   DataOffset: integer = 0;
  59. begin
  60.   form1.Chart1LineSeries1.Clear;
  61.   form1.Label1.Caption := format('Plotting the waveform...%d samples received',[Length(WaveformData)]);
  62.   if LeftStr(WaveformData,1) <> '#' then
  63.   begin
  64.     form1.Label1.Caption := 'Received data is invalid';
  65.     exit;
  66.   end;
  67.   DataOffset := StrToInt(midstr(WaveformData,2,1)) + 2;
  68.   SetLength(plotdata,Length(WaveformData)-DataOffset);
  69.   plotindex := -1;
  70.   for i:=DataOffset to high(WaveformData)-1 do //Last value is always #10 and it is not a part of the data.
  71.     begin
  72.        inc(plotindex);
  73.         plotdata[plotindex] := Int8(WaveformData[i]);
  74.         form1.Chart1LineSeries1.AddXY(plotindex,plotdata[plotindex]);
  75.         //wait(1); //TAChart does NOT crash if I enable this line, but execution is extremely slow. Even if Application.Processmessages; within Wait is commented, the app does NOT crash.
  76.         form1.Label1.Caption := IntToStr(i);
  77.         numstring := numstring + FloatToStr(plotdata[plotindex]) +',0,'+ #13#10;
  78.     end; //for
  79.   form1.Label1.Caption := 'Ready';
  80. end;
  81.  
  82. function VisaEventHandler(vi: ViSession; eventType: ViEventType; event: ViEvent; userHandle: ViAddr): ViStatus; stdcall;
  83. var
  84.   WaveformData: AnsiString = '';
  85. begin
  86.   if (WaitWaveform = true) then
  87.   begin
  88.     WaitWaveform := false;
  89.     WaveformData := Form1.VisaSession.query('CURV?');
  90.     PlotWaveForm(WaveformData);
  91. end;
  92. end;
  93.  
  94. procedure TForm1.FormCreate(Sender: TObject);
  95. begin
  96.   WaitWaveform := false;
  97.   if not LoadVisaLib then
  98.   begin
  99.     ShowMessage ('CannotLoadVisaLib');
  100.     exit;
  101.   end;
  102.   //VisaSession.Address := 'USB0::0x0699::......'; //Or set it as a property of the control
  103.   VisaSession.Active := true;
  104.   VisaSession.EnableEventHandler(@VisaEventHandler);
  105. end;
  106.  
  107. procedure TForm1.Button1Click(Sender: TObject);
  108. var
  109.   myfs: TFormatSettings;
  110.   dt : double = 10/1000;
  111. begin
  112.   Label1.Caption := '';
  113.   WaitWaveform:= false;
  114.   myfs.DecimalSeparator := '.';
  115.   VisaSession.Command('*RST;');
  116.   VisaSession.Command('*CLS;:HEADER OFF;:WFMO:ENC BIN');   //Default setup
  117. //  VisaSession.Command('CH1:POS -2.500000'); //Vertical offset
  118.   VisaSession.Command(':SEL:CH1 ON;:CH1:PRO:GAIN 1.00000;:CH1:COUP DC;SCA 0.500000;OFFS 0.000000;BAN TWE;DESK 0.000000;');
  119. //                                            probe 1X                  v/div
  120.   VisaSession.Command(':ACQ:STOPA SEQ'); //':ACQ:STOPA RUNST'   //Disable/enable continuous acquisition
  121.   VisaSession.Command(':ACQ:MOD SAM;'); //Configures the common properties of the acquisition subsystem.
  122.   //                        //# samples
  123.   VisaSession.Command(':HOR:RECO 20000;:HOR:SEC ' + FormatFloat('0.000000',dt,myfs) + ';:HOR:DEL:MOD OFF;POS 2.000000');  //Configures the record properties of the acquisition subsystem.
  124.  
  125.   VisaSession.Command(':TRIG:A:EDGE:SOU CH1;:TRIG:A:LEV 0.500000;:TRIG:A:EDGE:SLO RISE;:TRIG:A:EDGE:COUP DC;'); //Set the trigger and wait until it is triggerred
  126.   VisaSession.Command(':DATA:SOU CH1;:DATA:START 1.000000;:DATA:STOP 5000000.000000;'); //probably this sets the buffer size
  127.   VisaSession.Command('ACQUIRE:STATE OFF;ACQuire:STOPAfter SEQuence;SELECT:CH1 ON');
  128.   //
  129.   VisaSession.Command('DESE 1'); //Set registers to await an Operation Complete (OPC) event (bit 1) in the event queue. This event is summarized in the Event Status Bit(ESB) of the Status Byte Register.
  130.   VisaSession.Command('*ESE 1'); //Set the Event Status Bit (bit 5) to await a Service Request (SRQ)
  131.   VisaSession.Command('*SRE 0'); //Clear the event registers
  132.   VisaSession.Command('ACQUIRE:STATE ON');
  133.   Wait(50);
  134.   VisaSession.Command('*SRE 16');
  135.   VisaSession.Command('*STB?'); // Handler should be called now since output buffer gets filled
  136.   Wait(50);
  137.   Label1.Caption := 'Waiting for a waveform...';
  138.   VisaSession.Command('*OPC');
  139.   Wait(50);
  140.   WaitWaveform:= True;
  141.   VisaSession.Command('*OPC?'); //Waits for the trigger
  142. end;
  143.  
  144. end.
  145.  


Maybe the inability to declare function VisaEventHandler(vi: ViSession; eventType: ViEventType; event: ViEvent; userHandle: ViAddr): ViStatus; stdcall; as a part of the form is related (https://forum.lazarus.freepascal.org/index.php/topic,70205.msg547515.html#msg547515) ?


EDIT: It is not TAChart's fault, I tried to populate the data in a StringGrid, it just freaks out.
I tried several DLLs, still no improvement.
I tried static binding to the *VISA32.dll, still the same.

EDIT 2: An example with a working trigger is attached.
« Last Edit: February 19, 2025, 02:33:15 pm by CM630 »
Лазар 4,0RC2 32 bit (sometimes 64 bit); FPC3,2,2

CM630

  • Hero Member
  • *****
  • Posts: 1302
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: visasession
« Reply #28 on: February 20, 2025, 03:29:28 pm »
Can FP-VISA handle Visa TCP Socket connection?

From a quick glimpse:
Code: Pascal  [Select][+][-]
  1. function TVisaSession.Read: string;
  2. var res: ViStatus;
  3. begin
  4.    result := '';
  5.    repeat
  6.       result := result + recv(1024, res);
  7.    until (res <> VI_SUCCESS_MAX_CNT) and (res <> VI_SUCCESS_TERM_CHAR);
  8. end;

I have got the impression that for Socket connection it shall rather be until (res <> VI_SUCCESS_MAX_CNT) and (res <> VI_SUCCESS_TERM_CHAR); and also terminations characters shall be settable somehow.


EDIT:
I tried
Code: Pascal  [Select][+][-]
  1.          CheckError(viSetAttribute(fHandle,VI_ATTR_TERMCHAR_EN,VI_TRUE));
  2.          CheckError(viGetAttribute(fHandle,VI_ATTR_TERMCHAR_EN,@attrval));
viGetAttribute does not return the value provided in viSetAttribute . (attrval is something unrelated).
On the other hand, if I do (just for a test):

Code: Pascal  [Select][+][-]
  1.          CheckError(viSetAttribute(fHandle, VI_ATTR_TMO_VALUE, 120000));
  2.          CheckError(viGetAttribute(fHandle,VI_ATTR_TMO_VALUE,@attrval)) ;
attrval returns 120000, so it seems to me that I am using viSetAttribute and viGetAttribute the right way.
« Last Edit: February 21, 2025, 03:16:54 pm by CM630 »
Лазар 4,0RC2 32 bit (sometimes 64 bit); FPC3,2,2

 

TinyPortal © 2005-2018