TestController, Configuration of non SCPI devices

FirstImage

The program supports many different devices, not all uses SCPI, to handle them there are a some build in drivers that will translate between a simplified SCPI and the actual instrument protocol. Some of these drives are nearly fully hard coded, i.e. the device file basically list the name of the device, other can be configured with a device file.
For most of these drivers the only practical configuration that can be done without programing is declaring similar devices.
I will not be explaining most tags, see the SCPI configuration for more explanation.

Content
    Single value
    Serial Modbus RTU
        Modbus register types
        Commands to access the registers
        Unsupported commands
        Defining commands
        Other commands
        Modbus error codes
        Definitions that uses this driver
    Non-SCPI ascii devices
        Commands to write and read values
        Defining commands
        Other commands
        Skeleton example
        Definitions that uses this driver
Main page
Functions for use in calculator and definitions


Single value

This driver is for device that returns a single line with a single value on it. It can be something like this: "DC 45.3 mV" or "456.45".
The value can be returned at regular intervals or after a poll.

The first part is similar to SCPI definitions:

Code:
#idString first two parts of *idn? answer
#name The device name
#handle A short handle
#port The port used
#baudrate Baudrate for serial devices
#eol Used to change the standard LF end of line to CR or CRLF or disable with \_.

The id string must be constructed to look similar to real id strings, typical: "brand, brand model,"

To load this driver use:
Code:
#driver SingleValue

Next comes data type definition, either a single line without a selector or multiple lines with a selector matching the mode. Mode will be constructed from letters in the original line, start TestCOntroller in debug mode to see what it is for different modes.

A device with a single mode
Code:
#value Frequency  Hz SI

Device with multiple modes
Code:
#value VoltageDC V d4 DCV
#value CurrentDC A si DCA
#value VoltageAC V d4 ACV
#value CurrentAC A si ACA
#value Resistance ohm si RESISTANCEOHM

Meters will usually use a text for error condition and may also use it for some other stuff.
Code:
#valueText value text
#valueText value "text"

;Examples:
#valueText OL OL
#valueText -OL "-  OL"
#valueText 1 OPEN
It is possible to use OL or -OL as values. To include spaces in the text it must be in quotes.
The text is checked before checking for modes and if a match is found it is removed from the input before assembling the mode string.


The last entry is optional, it is only used if the device must be polled for the string:
Code:
#askValues poll

It is possible to use escapes in the poll, i.e. \r for a return character or 0x17 for character 17 hex.
This poll will be combined with the #EOL value that has a default value of \n (i.e. a linefeed character). Defining "#eol \_" will disable the end of line character.

Example 1
Code:
#idString HKJ,HKJ Test
#name HKJ Test
#handle Test
#port comfixedbaud
#baudrate 1200
#eol \_
#driver SingleValue

#value VoltageAC V d5 ACV
#value VoltageDC V d5 DCV
#value Resistance V d5 RESISTANCEohm

#askValues \r

Example 2
Code:
#idString HKJ,HKJ Test
#name HKJ Test
#handle Test
#port comfixedbaud
#baudrate 1200
#driver SingleValue

#value Frequency Hz SI

For a complete example see the Protek506 definition file.




Serial Modbus RTU

Modbus is a packet based interface, with a couple of fixed formats based in a hardware model with different types of input/output.
This protocol is build on top of SCPI and requires all the stuff that a normal SCPI definition does, in addition to a couple of #scpiCmd definitions.

Modbus register types
Register can be read/write or read only types, this is (hopefully) listen in the device manual.
The 4 different types of registers do not necessarily share address space, i.e. the same address can be different things in the different register types. It is common to combine holding registers to 32 bit data as long or float values.



Commands to access the registers

These commands can be used directly from the command line, but this is mostly for test. The Coil? & dInput? will return all bits in a single number, the other command will return a list of values.
The address can be in decimal or in hex by prefixing with 0x
Reading commands has a optionally count, when not specified one value is read, when specified it defines how many values to read.
The L and F prefix works with 32 bit values for either integers or floats.
The *factor or /factor is used to scale the values, i.e. use /10 to divide by 10 or *10 to multiply by 10
The &mask can be used to remove undefined bits and can be something like "&0xff" to only return 8 bits from the 16 bit answer



Unsupported commands

Do not expect a device to support all the different register access commands, not all registers may be implemented and writing may be restricted to 1 or many registers.
Because TestController automatic select between single and multi register write, there will be a problem with devices not supporting single write (A single write can be simulated with a multi write where the count is 1). To force TestController into always using multi write use this define in the definition file:
Code:
#disableWriteSingle 1



Defining commands

The above commands are only supposed to be used for defining other commands with. By defining commands it makes the definition easier to read and it also makes it easier to directly give commands on the command line.

The format is fairly simple:
Code:
#scpiCmd name register access command with parameters

;Examples:
#scpiCmd Current holdingF 0xa01 (value)
#scpiCmd Current? holdingF? 0xa01
Use (value) to insert parameters from the "name" command. It is possible to use value multiple times and it is also possible to use an expression inside the brackets.
If a value needs to be carried between scpiCmd it can be saved with a ":setvar:" tag
Code:
;Save input value
#scpiCmd mode holding 0xa00 (value)
:setvar: currentMode=value

;Save answer
#scpiCmd mode? holding? 0xb04 1 &0xff
:setvar: currentMode=value

;Using the saved value
#scpiCmd on holding 0xa00 (currentMode);holding 0xa00 (getElement("43 42",value))
It is important that this variable is created before it is used. To do this use a command in "#initCmd" that has a :setVar: for the variable.





Other commands

A few more commands are supported.

To verify it is the correct device that is connected use this command. Often it is possible to read a model number from the device and compare that to the value.
Code:
#verifyDevice value commandToGetvalue

;Example, note mode? is defined with "#scpiCmd model? holding? 0xb06" (I could have used the holding? directly).
#verifyDevice 2 model?

The software always ask for serial number and software versions when connecting to a device, by defining these two command they will be read:
Code:
#scpiCmd getDeviceSW? ...
#scpiCmd getDeviceSN? ...

Not all devices can handle a steady communication, some needs a small delay between each message to work correctly. This is done with this optional setting:
Code:
#cmdDelayTime time in ms

;Example
#cmdDelayTime 50



Modbus error codes
TestController will return error codes as negative value, i.e. -1 is error 1.

Definitions that uses this driver

The power supply definitions RidenRD6006 uses this driver. I has a fairly advanced configuration menu.

Maynuo M97xx definition is a electronic load, it is prepared for handling multiple models, but only one model is defined at the current time (5-2020).




Non-SCPI ascii devices

This interface will work with devices that requires strings of ascii commands, but are not SCPI compliant. It works in a similar way to the Modbus definition.
This protocol is build on top of SCPI and requires all the stuff that a normal SCPI definition does, in addition to a couple of #scpiCmd definitions.



Commands to write and read values

These commands can be used directly from the command line, but this is mostly for test. In a #scpiCmd definition the ; is transmitted directly.
It is very important to use command that waits for an answer, if the cmd will return an answer.



Defining commands

The above commands are only supposed to be used for defining other commands with. By defining commands it makes the definition easier to read and it also makes it easier to directly give commands on the command line.

The format is fairly simple:
Code:
#scpiCmd name tx cmd
#scpiCmd name txrx cmd
#scpiCmd name? txrx? cmd

#scpiCmd name tx cmd (value)
#scpiCmd name txrx cmd (value)
#scpiCmd name? txrx? cmd (value)
Use (value) to insert parameters from the "name" command. It is possible to use value multiple times and it is also possible to use an expression inside the brackets.
If a value needs to be carried between scpiCmd it can be saved with a ":setvar:" tag
Code:
;Save input value
#scpiCmd name tx (value)
:setvar: currentMode=value

;Save answer
#scpiCmd name? txrx? cmd
:setvar: currentMode=value

;Using the saved value
#scpiCmd name tx (currentMode)
It is important that this variable is created before it is used. To do this use a command in "#initCmd" that has a :setVar: for the variable.



Other commands

A few more commands are supported.

To verify it is the correct device that is connected use this command. Often it is possible to read a model number from the device and compare that to the value.
Code:
#verifyDevice value commandToGetvalue

;Example, note model? must defined with "#scpiCmd model? 
#verifyDevice 2 model?

The software always ask for serial number and software versions when connecting to a device, by defining these two command they will be read:
Code:
#scpiCmd getDeviceSW? ...
#scpiCmd getDeviceSN? ...

Not all devices can handle a steady communication, some needs a small delay between each message to work correctly. This is done with this optional setting:
Code:
#cmdDelayTime time in ms

;Example
#cmdDelayTime 50



Skeleton example

Use the below skeleton when starting a new definition.
Code:
#idString brand,brand model
#name brand model
#handle mostlyModel

#driver Ascii

; port can be com, comfixedbaud, comnobaud or a port number for network devices.
#port 5025

; Baudrate definition is needed for comfixedbaud types.
;#baudrate 9600

; The author statement is used for the listing in the About window.
;#author you name or handle

; There must be a line for each of the original device commands that will be used, converting it to a similar SCPI command
;#scpiCmd init tx command to init
;#scpiCmd values? txrx? command to read current value or values. It is possible to define value1?, value2?, etc. and then use them all with a ; between in the #askValues statement.

; A list of possible column name with unit and formatter (SI, Time, Int, D0..D6)
#value Voltage V SI
 
; Use these commands to get a full id line and prevent connection to other devices
;#verifyDevice value commandToGetvalue
;#scpiCmd getDeviceSW? ...
;#scpiCmd getDeviceSN? ...

; This is a single line command
#askValues values?

;Accept this delay when reading values (seconds)
#readingDelay 5

; Prepare the meter to response to #askValues
;#prepareSample

; Initial commands to meter when establishing connection
;#initCmd

; Final command to meter before breaking connection
;#finalCmd 

; Used when output off button is pressed
;#outputOff 


Definitions that uses this driver

FeelElecFY6x00-xxM defines many ARB models using this driver.