For a hardware evaluation project I'm working on, I want to create a device that can be controlled via LabView. LabView can talk to instruments using serial out of the box, and it knows how to talk Standard Commands for Programmable Instruments (SCPI).
In this blog I'm checking the excellent error handling of the SCPI library. |
Error Handling Works by Default
The SCPI parser library that I use has out-of-box support for standard behaviour. One of the supported features is error handling.
If you send a bogus SCPI command or make a syntax error, this is registered by the library.
The error description is pushed on an error stack. The parser returns to its normal work.
As an instrument firmware designer, you can also push custom error situations to the error stack.
A possible use case is for a PWM generator where the user requests a frequency higher than the maximum.
You can check if errors occurred by sending the SCPI command:
SYST:ERR:COUN?
If errors happened, you get a number back. That's the count of errors on the stack.
e.g.:
5
Each error can be retrieved by firing:
SYST:ERR?
A possible return value (one of the default error messages from our parser lib):
-113,"Undefined header"
Each time you ask an error message, the error is popped off the stack and the error count decreases.
When you've retrieved the last message, you get the following reply when shooting a SYST:ERR:COUN? :
0
If you check for an error message when the error stack is empty, (SYST:ERR?), you get:
0,"No error"
You get all this functionality by default and you can tap into it in your own firmware. Another worry taken out of your hands by this library.
Other standard constructs that are either fully supported, or give you an easy implementation hook are:
{ .pattern = "*CLS", .callback = SCPI_CoreCls,}, { .pattern = "*ESE", .callback = SCPI_CoreEse,}, { .pattern = "*ESE?", .callback = SCPI_CoreEseQ,}, { .pattern = "*ESR?", .callback = SCPI_CoreEsrQ,}, { .pattern = "*IDN?", .callback = SCPI_CoreIdnQ,}, { .pattern = "*OPC", .callback = SCPI_CoreOpc,}, { .pattern = "*OPC?", .callback = SCPI_CoreOpcQ,}, { .pattern = "*RST", .callback = SCPI_CoreRst,}, { .pattern = "*SRE", .callback = SCPI_CoreSre,}, { .pattern = "*SRE?", .callback = SCPI_CoreSreQ,}, { .pattern = "*STB?", .callback = SCPI_CoreStbQ,}, { .pattern = "*TST?", .callback = SCPI_CoreTstQ,}, { .pattern = "*WAI", .callback = SCPI_CoreWai,},
Test with PuTTY
When you want to test special conditions, it's often easier to use a terminal program than LabVIEW. You can just type away, and the results arrive in the parser lib immediately.
When I try to simulate a real test environment, I mock it with LabVIEW. But when I try to exercise a particular part of the library, or want to see how my firmware reacts on each single character (valid or invalid), plain old PuTTY is easier.
PuTTY is also easy to learn the SCPI parser lib. Set a breakpoint in the SCPI_Input() function and type *IDN?<enter> in PuTTY. Your code breaks at each character you type. You can step trough the logic that builds up the command string. You'll also see how the library recognises when it received a full command. You can then step trough the execution of the code that implements that command. If you do that a few times, you'll get a deep understanding of the library. It 'll help you to extend it in the right way. |
Top Comments