What is the preferred way to communicate with non-SCPI instruments (R2D2) and “strange” serial protocols?
As I understand the Instrument class doesn’t provide “low-level” VISA I/O methods?
If the instrument is VISA based you can leverage the ScpiIO class to see how we implement VISA:
If it is serial, I’d just recommend using one of the C# Serial libraries for example, this is what we did for a barcode scanner:
For serial devices I think it is a must to use some external libraries since most serial devices doesnt speak SCPI and it’s not(?) possible to control baudrate, parity etc.
Room for improvement?
So far, people have gotten by with the 3rd party libraries, but I could see an open source DUT plugin base class existing. Sounds like you would find that useful as well?
Yes, and exposing more of the underlaying VISA properties so baudrate etc. can be set/get. I think it’s a big advantage if as much as possible of I/O can be done using OpenTAP’s I/O layer
Found out, the hard way, ScpiInstrument always sends some commands in Open:
ViClear can be disabled in Settings but not the rest (*IDN?, *CLS and ReadSTB)
This makes it impossible to use OpenTAP’s I/O layer for non-SCPI (actually non-488.2 compatible) devices incl most serial devices and old GPIB instruments.
I think ScpiInstrument class settings need more granularity. Like a non-SCPI/488.2 mode (in addition to be able to set/get serial settings).
Alternatively expand the Instrument class to include basic and low-level VISA functionality.
The original intention of that exposing that class was SPCI based instruments that had some non-standard read/write commands. It would be possible to have a custom class that used the IScpi2 interface similar to ScpiInstrument. You would then be able to customize the Open method which is where those commands are called:
In general, I understand your point on the serial settings. However, I think ultimately, this would make most sense as a separate class, not an extension of the ScpiInstrument. I’ll submit an issue on it, but in the meantime if you come up with something, I think would be something really valuable that could be contributed back if interested.
for serial comms I use ScipiInstrument as the base class. The instrument then looks like all other instruments. The address will also use the standard SCPI format, selectable from the address dropdown. In this example, I haven’t exposed any other serial comms parameters thought.
Simply create a SerialComms class to use instead of the usual Scpi calls. Initially I wasn’t going to use ScpiInstrument but it made address selection easy.
… use in your instrument like this.
public override void Open()
{
SerialComms = new SerialComms();
SerialComms.Open(VisaAddress);
IsConnected = true;
}
… comms class.
public SerialComms()
{
_serialPort = new SerialPort()
{
BaudRate = 9600,
Parity = Parity.None,
DataBits = 8,
StopBits = StopBits.One,
Handshake = Handshake.None,
ReadTimeout = 500,
WriteTimeout = 500,
Encoding = Encoding.ASCII
};
}
private SerialPort _serialPort;
public void Open(string port)
{
_serialPort.PortName = port;
_serialPort.Open();
}
public void Close()
{
_serialPort.Close();
}
public string Read()
{
return _serialPort.ReadExisting();
}
public byte[] ReadBytes()
{
var byteBuffer = new byte[6];
_serialPort.Read(byteBuffer, 0, 6);
return byteBuffer;
}
public void Send(string msg)
{
_serialPort.WriteLine(msg);
}
public void SendBytes(byte[] byteBuffer)
{
_serialPort.Write(byteBuffer, 0, 6);
}
public string QueryInstrument(string message)
{
this.Send(message);
TapThread.Sleep(300);
var answer = this.Read();
return answer;
}
public byte[] QueryInstrument(byte[] bytes)
{
SendBytes(bytes);
TapThread.Sleep(300);
var answer = ReadBytes();
return answer;
}
}
Good solution! Agree, you really want it to “look” like all other instruments. Key point is to avoid/remove ScpiInstrument base.Open() I guess. There are no side-effects of not using base.Open()?
No side-effect at all.
I assume you use System.IO.Ports? Can you use a VisaAddress as PortName?
Yeah System.IO.Ports, sorry, missed that. VisaAddress works fine but I may use COM3 in the dropdown. Not infront of my system so I can’t confirn this.
Back in the lab, so I can now confirm I use COM3 and not the visa ASRL3:INSTR address.
Yes, no surprise. I guess you convert ASRLx to COMx? So what was the reason to use ScpiInstrument as base and not Instrument? (since none of the VISA/SCPI Bench settings are used or can be used)
I have phased out GPIB connections, so all instruments will communicate using LXI, USB or serial now. In this case, it was a temperature chamber and serial was the only other interface available. It was some time ago now so I probably just left it in for convenience. Now you’ve reminded me, I’ll look at getting rid of it now.
@GoranJohnsson For whatever it’s worth, I’ll share my general practices. I don’t use the ScpiInstrument class much, I just use Instrument and implement all the IO myself per the hardware programming manuals. Sometimes that involves a FormattedIO488 class, sometimes SerialPort (as you’re showing here), and sometimes more specific drivers like for PXI etc. I typically put the IO reads and writes into a separate base class that can be inherited by multiple instrument classes.
@david-wsd interested in why you don’t generally use ScpiInstrument is it that you are generally not using SCPI or just that the control you need is better in a common base class?
Related to all the discussion, would anyone be interested in collaborating on an open source plugin for basic control of Serial/COM devices? It comes up often, I know your team has a few examples. It sounds like @david-wsd and @GoranJohnsson have something as well. Maybe we can come up with a good standard base class.
@brennen_direnzo Ya I should have clarified the reason. We don’t use the ScpiInstrument for legacy reasons, it’s no fault of the ScpiInstrument class. I’m sure it’s a great class. We migrated a legacy application to OpenTAP, so all the IO was already developed in pre-existing classes.
That said, it’s also nice to have access to as much of the IO stack as possible. This is helpful for things like globally wrapping every read/write in a try-catch statement, where the catch can do something like assert a device clear, for example. Not to say we couldn’t do that with ScpiInstrument, but I imagine ScpiInstrument may hide a layer of IO that some might wish to customize.
@brennen_direnzo I my opinion there is also a missing class in between Instrument and ScpiInstrument classes. In most systems I have been involved in there are always some non-SCPI devices (typically older GPIB instrument)
Either add a non-SCPI mode to ScpiInstrument or perhaps a new ‘VisaInstrument’ class?
@brennen_direnzo A Serial plug-in would definitely be useful. I’m not sure if we need Serial in my current project but I’m interested. I did some tests using System.IO