MC-Basic Language Fundamentals

From SoftMC-Wiki
Jump to: navigation, search


More Info


softMC is programmed in MC-Basic, a version of the BASIC programming language enhanced for multitasking motion control. If you are familiar with BASIC, you already know much of MC-Basic.

To develop your application on softMC, you must install ControlStudio, a software interface.

Command Reference Format

All MC-Basic commands are presented in the list of MC-Basic Commands. The reference entry for each command contains the information needed for correct use of the command or property. Each entry for a command or property contains all or most of the following elements:

Description A description of the command or property.
Short Form Where applicable, a short form of the longer command can be used to simplify typing the command or property name. In such instances, the short form is denoted. The short form of a command or property name may be used interchangeably with the long version.
Syntax In describing the syntax of an instruction, different notations are used.
< > Field to be filled by user. For example, ABS ( <expression> ) indicates that <expression> is the user\’s data.
{ } Optional data. Many instructions have optional fields, which are used to override default values. For example, the VelocityCruise property is optional within a Move command. However, there is an exception to this rule, in that \{ \} are used for vector notation. When the optional data may be repeated, an asterisk (\*) is used to indicate this.
| Or. Indicates that either one of the values may be used.
Availability Various versions of the firmware add new features, and often significantly change the syntax or behavior of commands and properties. The attribute Availability included in the descriptions denotes the applicability of each function (command, property)to the specified version of the firmware.
Type Refer to the section Data Types, below.
Range Range of valid values
Units When parameter values imply dimensional units of measurement, these units are specified in the description of the command or property where they apply.
Default Default value
Scope Instructions can be executed from any of three contexts: the configuration file (CONFIG.PRG), the terminal, and within a task. Not all instructions can be executed from all three contexts; their scope of operation is limited. For each instruction, the scope of operation is defined.
Limitations Even when an instruction can be executed in a given context, there may still be limitations on its use. For example, a MOVE command can be executed from within a task, but there is a limitation in that the motion element being moved must first be attached to the task by the ATTACH command.
Examples Examples of use
See Also Links to related commands


Instructions are the building blocks of BASIC. Instructions set variables, call functions, control program flow, and start processes such as events and motion. In this documentation, the terms instruction and command are used interchangeably.

Syntax is the set of rules that must be observed to construct a legal command (that is, a command the softMC can recognize).

MC-Basic is line-oriented. The end of the line indicates the end of the instruction. Whitespace (i.e., spaces and tabs within the statement line and blank lines), is ignored by the BASIC interpreter. You can freely use indentation to delineate block structures in your program code for easier readability. The maximum allowed length of a line is 80 characters.

MC-Basic is case insensitive. Commands, variable names, filenames, and task names may be written using either upper case or lower case letters. The only exception is that when printing strings with the “Print” and “PrintUsing” commands, upper and lower case characters can be specified.

Syntax uses the following notation:
[ ] indicates the contents are required.
{ } indicates the contents are optional for the command

Example lines of text are shown in Courier type font and with a border:

X = 1

Types of Instructions

There are many types of instructions: comments, assignments, memory allocation, flow control, task control, and motion.

Comments allow you to document your program. Indicate a comment with either the Rem command or a single apostrophe ('). You can add comments to the end of an instruction with either Rem or an apostrophe.

Rem This is a comment
' This is a comment too.
X = 1 'This comment is added to the line X = 1X = 1 REM This is a comment too

Use comments generously throughout your program. They are an asset when you need support from others and they avoid confusing code.

Declarations allocate softMC memory for variables and system elements (groups, cam tables, etc.). This might be a simple type as an integer, or a complex structure as a cam table.

Assignments are instructions that assign a new value to a variable.

The syntax of an assignment is [Lvalue] [=] [expression]

For example:

X = Y + 1

The term, Lvalue, is a shorthand notation, which indicates the value to the left of the equals sign. Valid Lvalues are variables or writable properties, which can be assigned. Expressions can be variables, constants, properties and function calls, as well as various combinations of them in arithmetic and logical statements . An exception to this rule is generic elements’ assignment, at which the right side of the equal sign is not an expression, but an axis or a group (either real or generic), and Lvalue is a generic elements. If you assign a Double (floating point) value (expression, variable or constant) to a Long variable, the fractional portion of the double value is truncated, and the integer portion is assigned to the long variable. To query a variable or expression from the ControlStudio terminal window, use the PRINT or ? command:

PRINT 1/100
? X1

MC-Basic also provides the standard PRINTUSING (PrintU) command for formatted printing.

Commands for flow control change the way your program is executed. Without flow control, program execution is limited to processing the line immediately following the current command. Examples of flow control include GOTO, FOR…NEXT, and IF…THEN.

MC-Basic is a multitasking language in which many tasks can run concurrently. Generally, tasks run independently of each other. However, tasks can control each other using inter-task control instructions. One task can start, idle, or terminate another task.

Most commands are started and finished immediately. For example:

x = 1 ' this line is executed completely…
y = 2 ' …before this line is started

For general programming, one command is usually finished before the next command starts. Effects of these commands do not persist beyond the time required to execute them. However, the effects of many other commands persist long after the execution of the command. In general programming, for example, the effects of opening a file or allocating memory persist indefinitely. In real-time systems, persistence is more complicated because the duration of persistence is less predictable.

Consider a command that specifies a 1,000,000 counts move on an axis named, A2:

Move A2 1000000.0
Y = 2

The softMC does not wait for the 1,000,000 move to be complete before executing Y=2. Instead, the first command starts the motion and then the softMC continues with the next line (Y = 2). The move continues well after the move command has been executed.

Persistence can affect programs. For example, you may not want to start one move until the previous move is complete. In general, you need access to persistent processes if you are to control your program according to their state of execution. As you will see later, MC-Basic provides this access.

Line Concatenations

Performs concatenation of program or command line input. Useful when input string is longer than translator buffer (128 chars).

A = B + \
C + D

Is equal to:

A = B + C + D

Constants and Variables

All constant, variable and system element names must start with an alphabetical character (a-z, A-Z) and may be followed with up to 31 alphabetical characters, numbers (0-9) and underscores (“_”). Keywords may not be used as names.


Constants are numbers that are written as ordinary text characters,

Refer to: MC-Basic Constants


You must declare a variable in MC-Basic before you can it. In the declaration, you define variable name, scope and variable type. MC-Basic supports Long for integer values, Double for floating point values, and String for ASCII character strings.

Besides these basic types, MC-Basic also supports Structure-like variables and some MC-Basic specific types, such as points (Joints and Locations), generic motion elements (Axes and Groups) and UEAs (user error assertions-Errors and Notes).

DeleteVar deletes a global variable. Since variable name can include wildcards, a single DELETEVAR can be used to delete more than one variable.

DeleteVar int1
DeleteVar int* ' Deletes all variables starting with int

Current values of global variables (both scalar and arrays) can be stored in a Prg file, in assignment format, within an automatically executable Program Continue…Terminate Program block. Obligatory parameters of SAVE are the name of storage file, and type of stored variables (could be all types). Optional parameters are robot type (for point variables), variable name (which may include wildcards) and mode of writing to storage file (overwriting or appending). Variable types available for storage through SAVE are longs, doubles, strings, joints and locations, but not structures, user-defined exceptions nor generic motion elements.

Save File = “IntFile.Prg” Type = All VariableName = “int*”
‘ Save all variables starting with int in IntFile.Prg (overwrite file)
Save File = “Points.Prg” Type = Joint RobotType = XYZR Mode = Append
‘ Append all joint-type points with XYZR robot-type to Points.Prg file

Scope defines how widely a variable can be accessed. The broadest scope is global. A global variable can be read from any part of the system software. Other scopes are more restrictive, limiting access of variables to certain sections of code. MC-Basic supports three scopes: global, task, and local. Task variables can be read from or written to anywhere within the task where it is defined, but not from outside the task. Local variables can only be used within their declaration block, i.e. program, subroutine or function blocks. The scope of a variable is implicitly defined when a variable is declared using the keywords: Common, Shared, and Dim.

Global variables can be defined within the system configuration task, Config.Prg, within a task files (Prg files), before the program block, within library files (Lib files), before the first subroutine or function block, or from the terminal window of ControlStudio. To declare a variable of global scope use the Common Shared instruction.

Task variables are defined within a task or a library. To declare a variable of task scope use the Dim Shared instruction.

All Dim Shared commands must appear above the Program statement in task files. In library files, all Dim Shared commands must appear above the first block of subroutine or function. The values of variables declared with Dim Shared persist as long as the task is loaded, which is usually the entire time the unit is operational. This is commonly referred to as being static.

Local variables are defined and used within a program, a subroutine, or a function. To declare a local variable, use the Dim instruction. The Dim command for local variables must be entered immediately below the Program, Sub, or Function statement. Local variables cannot be declared within event blocks, and events cannot use local variables declared within the program.

See also: Namespace

Data Types

Numeric Data Types

MC-Basic has two numeric data types: Long and Double. Long is the only integer form supported by MC-Basic. Long and Double are MC-Basic primitive data types.

Type Description Range
Long 32 bit signed integer -2,147,483,648 (MinInteger) to 2,147,483,647 (MaxInteger)
Double Double precision floating point(about 16 places of accuracy) ±1.79769313486223157 E+308

String Data Type

MC-Basic provides the string data type which consists of a string of ASCII-coded characters. MC-Basic strings are dynamic. Reallocation of memory for new strings is preformed through a simple assignment of the string variable, and there is no need to specify the length of the new string. A full complement of string functions is provided to create and modify strings.

Type Description Range
String ASCII character string (no string length limit) 0 to 255 (ASCII code)

String parameters are based on the 8-bit ASCII character code set, which comprises 255 character codes, with code values from 1 to 255.


Refer to: MC-Basic Strings

In UTF-8 supporting versions (4.5.1 and higher), range was expanded to character codes from 0 to 255, since NULL characters are no longer cut out from strings. If string functions are used with parameter values outside the specified range, the behavior of the function may vary (e.g., the function may return an error message, the function may return a value different from the correct value, or the function may return the correct value). String values must be delimited by double quotes (“string value”). The maximum number of characters allowed in a string is limited only by the amount of free memory space.

Point Data Types

Refer to:

MC-Basic has two point data types: JOINT and LOCATION. A point variable is related to a fixed robot type, which is determined during variable declaration. Robot type examples: XY – two axes XY table, XYZ – three axes XYZ system, XYZR – three cartesian axes + roll, etc.

Type Description Range
Joint A set of 2-10 double precision floating point joint (motor) coordinates ±1.79769313486223157 E+308 for each coordinate
Location A set of 2-10 double precision floating point cartesian coordinates ±1.79769313486223157 E+308 for each coordinate

Generic Point Data Types

This type of point variables also has the same two point data types, i.e., JOINT and LOCATION. However, these point variables are declared without robot types, and therefore are not attached to a certain robot type. Actually, their robot type can be changed numerous times throughout application by casting functions or assignment.

Common Shared XYZPnt As Joint of XY
Common Shared XYZRPnt As Joint of XYZR

Common Shared GenPnt As Generic Joint     ' GenPnt doesn't have a robot type

XYPnt = XYZRPnt    ' will result in translation error due to robot type mismatch

GenPnt = XYZRPnt   ' GenPnt acquires the XYZR robot type
XYPnt = GenPnt     ' will result in translation error due to robot type mismatch

GenPnt = XYPnt     ' GenPnt's robot type is changed to XY
XYPnt = GenPnt 


Refer to: MC-Basic Structures

MC-Basic enables definition of structure-like data types, composed of of long, double, string and point (joint and/or location) scalar and array elements. Array elements can have up to ten dimensions. Name of structure type and composition of elements are defined by the user within configuration file (Config.Prg) and library files.


MC-Basic enables definition of arrays of longs, doubles, strings, semaphores, PLS, generic axes and groups, points (joint and/or location) and structures. Array can have up to ten dimensions.

Common Shared array1[5] As long ' array of integers
Common Shared array2[20][40] As double ' array of floating points
dim    Shared array3[100] As string ' array of strings
dim    array4[120] As utf8' array of UTF8 strings
common shared array5[32] As generic axis ' array of generic axes

User Error Assertion

MC-Basic has two UEA (user error assertion) data types (severities): Error and Note. Each UEA is defined with a string-type error message given by the user and a unique exception number, which might be determined either by the user or by the system. The softMC handles UEAs similar to internal exceptions.

Type Description Range
Error An ASCII message string and a unique integer exception number 20001-20499 for user determined exception number
20500-20999 for system determined exception number
Note An ASCII message string and a unique integer exception number 20001-20499 for user determined exception number
20500-20999 for system determined exception number

Generic Element Data Types

Refer to: Generic Elements

MC-Basic provides generic element data types designed to serve as a reference to real axes and groups. Through a simple assignment statement, the generic element gets the element identifier (see below) of a real motion element, thus acquiring all its properties. Afterwards, all activities preformed on the generic element identically affect the real element. The referenced element can be changed, through recurring assignments, as many times as the user wishes.

Type Description Range
Generic Axis An integer element identifier 0 (before first assignment) 1 to number of axes in system (up to 32)
Generic Group An integer element identifier 0 (before first assignment) 33 to number of groups in system (up to 64)

Each real motion element gets a unique element identifier from the system during its declaration. Axes get successive element identifiers ranging from 1 to 32 according to axis number. Groups get successive identifiers ranging from 33 to 64 according to declaration order. Value of element identifier can be queried directly through ELEMENTID.

Common Shared G2 As Group AxNm = A1 AxNm = A2
Common Shared G1 As Group AxNm = A1 AxNm = A2

MC-Basic uses integers to support Boolean (logical) operations. Logical variables have one of two values: true or false. MC-Basic uses type Long to support logical expressions. The value 0 is equivalent to false. Usually, 1 is equivalent to true, although any non-zero value is taken to be true. Boolean expressions are used in conditional statements such as If…Then, and with Boolean operators like And, Or, and Not.

Arrays can be any data type. Arrays may have from 1 to 10 dimensions. The maximum number of elements in any dimension is 32,767. Array dimensions always start at 1.

System Elements

There are several system elements: axes, groups, cam tables, PLSs, conveyers and compensation tables. These are not regular data types, but are more like user interfaces of the system's internal memory or internal function calls. You cannot handle them as a whole in expressions. Each system element has a set of properties, which is accessed through syntax resembling data elements of a structure, using the point character.

Despite the syntax, properties are not data elements, since a system element and its properties are not located on a continuous block of memory. All properties return a value, so they can be printed, combined in expressions and passed by value to functions and subroutines. Many properties are also writable and can be assigned like variables.

Unlike variables, properties do not have a fixed address in memory and cannot be passed by reference. Data types of properties are Long, Double, String, Joint and Location. For axis A1 and cam table Cam1, and a long type variable named Var1:

? A1.Enable ‘ Query
A1.Enable = 1 ‘ Set (read-write property) 
? A1.PositionCommand ‘ Query
A1.PositionCommand = 0 ‘ Syntax Error (read-only property)
Var1 = Cam1.Cycle ‘ Query
Cam1.Cycle = -1 ‘ Set (read-write property)
Var1 = Cam1.Inuse ‘ Query
Cam1.Inuse = 1 ‘ Syntax Error (read-only property)


Many variables have associated units. This include variables, which contain quantities of position, velocity, acceleration, and time. Some units are fixed. For example, time is always in milliseconds. MC-Basic allows you to define units of position, velocity and acceleration independently. In the next chapter, we will discuss how to set up units.


Refer to: MC-Basic Operators

Expressions are combinations of operators and value-returning entities, such as variables, constants, function calls, which are all calculated into a value. In MC-Basic, expressions can also contain unique entities like element properties (see above) and system properties (see below). Operators (like + and -) specify how to combine the variables and constants. Expressions are used in almost all commands.

An expression has one of two syntax forms

[operand] [binary operator] [operand][unary operator] [operand]

An operand can be a constant (123.4), variable name (X), or another expression. Most operators are binary (they take two operands), but some are unary (taking only one operand). So, -5.5 is a valid expression. It has the unary minus (also called negation) and a single operand.

There are two types of expressions: algebraic and logical (or Boolean).

Algebraic expressions are combinations of data and algebraic operators. The results of all algebraic operations are converted to double precision floating-point after executing the expression.

Logical expressions are combinations of data and logical operators. For example, X1 And X2 is a logical expression. The data and results of logical elements are type Long. Double variables are not allowed in logical expressions. The terms, logical and Boolean are considered interchangeable.

Logical expressions are evaluated from left to right. They are evaluated only far enough to determine the result. So, in A And B And C, if A is 0 (false), the result is false without evaluating B or C.

Precedence dictates which operator is executed first. If two operators appear in an expression, the operator with higher precedence is executed first. For example, multiplication has a higher precedence than addition. The expression 1+2*3 is evaluated as 7 ((2 * 3) + 1), not 9 ((2 + 1) * 3). The minus sign in the math operators’ table (below) is sometimes confusing since it shows up twice in the table: once with a high precedence (unary negation) and once with low precedence subtraction (binary minus). This difference in precedence is intuitive: 5 * -6 only makes sense if the negation is executed first.

The tables that follow list different types of operators. The entries in the tables are listed in order of precedence: the higher in the table, the higher the operator precedence. Also, the tables themselves are arranged in order of precedence with respect to one another. Math operators have the highest precedence. So, all math operations are executed before any other type of operator is executed. Finally, any time you need to change the standard precedence, use parentheses. Parentheses have the highest precedence of all.

Algebraic Operator Symbol Unary/Binary Operand Type
Parentheses ( ) NA double, long, string, joint, location
Exponentiation ^ Binary double, long
Negation - Unary double, long, joint, location
Unary Plus + Unary double, long, joint, location
Multiplication * Binary double, long, joint, location
Division / Binary double, long, joint, location
Modulo Mod Binary double, long
Addition + Binary double, long, string, joint, location
Subtraction - Binary double, long, joint, location
Compound : Binary location
Relational Operator Symbol Binary/Unary Operand Type
Parentheses ( ) Not applicable double, long, string
Equality = Binary double, long, string
Inequality <> Binary double, long, string
Less than < Binary double, long, string
Greater than > Binary double, long, string
Less than or equal to <= Binary double, long, string
Greater than or equal to >= Binary double, long, string
Word-wise Logical Operator Symbol Binary/Unary Operand Type
And And Binary long
Or Or Binary long
Exclusive or Xor Binary long
Not Not Unary long
Bit-Wise Logical Operator Symbol Binary/Unary Operand Type
Bitwise Negation BNot Unary long
Bitwise And BAnd Binary long
Bitwise Or BOr Binary long
Bitwise Xor BXor Binary long
Shift Left SHL Binary long
Shift Right SHR Binary long

Negation is simply placing a minus sign in front of a constant or variable to invert its arithmetic sign. Modulo division produces the remainder of an addition. For example, 82 Mod 5 is equal to 2 (the remainder of 82/5). If the first operand is negative, the resultant value is negative (-2). The sign of the result is determined by the sign of the first operand, and the sign of the second operand has no effect.

The relative precedence of exponentiation and negation may seem somewhat counter-intuitive. The following examples illustrate the actual behavior.

Common shared D as double
D = -1
? D^2
? -1^2

In the second section of the above example, exponentiation is performed first then negation is performed.

Common shared D as double
D = -1
? D = -1

In the example above, the “=” sign is taken as a relational operator (i.e., Is D = -1?) The relation is True, or 1.

? D^2 = -1^2

In the example above, the “=” sign is taken as a relational operator, (i.e., Is D^2 = -1^2?). Again, the exponentiation is performed first, and then the relation is evaluated as False, or 0.

The "+" operator, when used with strings, performs concatenation of strings.

In points, “+” (addition) and “-“ (subtraction) operators can be used between points of the same type and size, or between a point and a long or double type scalar. On the other hand, “*” (multiplication) and “/” (division) operators can only be operated between a point and double or long scalar, but not between two points.

In Logical operations, every value that is not 0 is assumed true and set to 1. And-ing combines two values so the result is true (1) if both values are true (that is, non-zero). Or-ing combines them so the result is true (1) if either value is true. Exclusive-Or produces true if one or the other value is true. It produces false (0) if both or neither are true. Before logical operations begin, all operands are converted to 1 (true) or 0 (false). The rule is that everything that is not 0 becomes 1.

Bit-wise expressions differ from logical expressions in that there may be many results from a single operation. Bitwise operations are frequently used to mask I/O bits. For example, the standard softMC inputs can be operated on with BAnd (Bitwise And) to mask off some of the inputs. The following example masks off all bits of the digital outputs, except the rightmost four:

Dim Shared MaskedBits As Long
MaskedBits = System.Dout Band 0xF
‘Mask all but rightmost four bits

All bitwise operations produce 32-bit result from two 32-bit numbers. Bitwise operations are really 32 independent, bit-by-bit operations. For example:

15 (Binary 1111) BAnd 5 (Binary 101) is 5 (Binary 101)BNot 15 is 0xFFFFFFF0.

Automatic Conversion of Data Types

If the assignment of an expression is an integer, the expression is still evaluated in double precision. For example:

Common Shared I as Long
I = 6.33 * 2.79

The value of the expression (6.33 * 2.79) is converted from double to long when the value (17) is copied into I. In the conversion to long, the number is truncated to the integer portion of the floating-point value.

Math Functions

MC-Basic provides a large assortment of mathematical functions. All take either numeric type as input (Double and Long) and all but Int and Sgn produce Double results. Int and Sgn produce Long results.

Abs(x) Returns the absolute value of X.
Acos(x) Returns the arc cosine of X. X is assumed to be in radians.
Asin(x) Returns the arc sine of X. X is assumed to be in radians.
Atan2(Y, X) Returns the inverse tangent of Y/X in radians. The range of the result is between ±PI radians (±180°). Atan2 is an improvement over ATN(Y/X) in that it works correctly if X is zero, and if X<0.
Atn(X) Returns the inverse tangent of X in radians. The range of the result is between ±PI/2 radians (±90°).
Cos(X) Returns the cosine of X. X is assumed to be in radians.
Exp(X) Returns ex.
Int(X) Returns the largest long value less than or equal to a numeric expression (for example, ?Int(12.5) returns 12 ?Int(-12.5) returns -13)
Log(X) Returns the natural logarithm of X. X must be > 0. If you want the base-10 log, use Y = LOG(X)/LOG(10).
Sgn(X) Returns the arithmetic sign of X. If X > 0, return 1. If X < 0, return -1. If X = 0, return 0.
Sin(X) Returns the sine of X. X is assumed to be in radians.
Sqrt(X) Returns the positive square root of X. X must be >= 0.
Tan(X) Returns the tangent of X. X is assumed to be in radians.
Round(X) Returns the integer nearest to X. If X falls exactly between two integers (for example, 1.5), return the even integer. So 1.5 and 2.5 round to 2.

String Functions

Note: Table requires updating

MC-Basic supports all the common string functions supported in standard BASIC.

ASC(S,I) Returns an ASCII character value from within a string, S, at position, I.
BIN$(X) Returns the string representation of a number (X) in binary format (without the Ob prefix).
CHR$(X) Returns a one-character string corresponding to a given ASCII value, X.
HEX$(X) Returns the string representation of a number (X) in hexadecimal format (without the 0x prefix).
INSTR(I,SS,S) Returns the position, I, of the starting character of a substring, SS, in a string, S.
LCASE$(S) Returns a copy of the string, S, passed to it with all the uppercase letters converted to lowercase.
LEFT$(S,X) Returns the specified number, X, of characters from the left-hand side of the string, S.
LEN(S) Returns the number of characters in an ASCII-8 string, and the number of symbols in a UTF-8 string.
LTRIM$(S) Returns the right-hand part of a string, S, after removing any blank spaces at the beginning.
MID$(S,I,X) Returns the specified number of characters, X, from the string, S, starting at the character at position, I.
RIGHT$(S,X) Returns the specified number of characters, X, from the right-hand side of the string, S.
RTRIM$(S) Returns the left-hand part of a string, S, after removing any blank spaces at the end.
SIZE(S) Returns the number of bytes in a string. In UTF-8 strings, this value may differ from the value returned by LEN().
SPACE$(X) Generates a string consisting of the specified number, X, of blank spaces.
STR$(X) Returns the string representation of a number, X.
STRD$(X,S) Returns the string representation of double-type number, X.
STRING$(X,\{S\},\{Y\}) Creates a new string with the specified number, X, of characters, each character of which is the first character of the specified string argument, S, or the specified ASCII code, Y.
STRL$(X,S) Returns the string representation of long-type number, X.
TOASCII8$(S) Converts the UTF-8 coding format of the input string S into the ASCII-8 coding format.
TOUTF8(S) Converts the ASCII-8 coding format of the input string S into the UTF-8 coding format.
TYPEOF(S) Returns a number representing the type of the string (0 for no-type, 1 for ASCII-8, or 2 for UTF-8).
UCASE$(S) Returns a copy of the string, S, passed to it with all the lowercase letters converted to uppercase.
UTF$(X) Returns a UTF-8 string corresponding to a given Unicode value, X.
UTFSTRING$(X,\{S\},\{Y\}) Creates a new UTF-8 string with the specified number, X, of symbols, each symbol of which is the first symbol of the specified string argument, S, or the specified Unicode value, Y.
VAL(S) Returns the real value represented by the characters in the input string, S.

In UTF-8 (supported in firmware version 4.5.1 and later), NULL characters are not cut from strings. The string resulting from concatenation is composed from 'A\0B'; i.e., there is a NULL character in the MIDDLE of the string:

Display cuts the string in the middle NULL:

-->?"A" + Chr$(0) + "B"


Mid$ gives NULL for the second character:

-->?Mid$("A" + Chr$(0) + "B", 2, 1)


Value of Len is 3:

-->?Len("A" + Chr$(0) + "B")


Len of Chr$(0) is 1:



In firmware versions prior to 4.5.1 (UTF-8 not supported), NULL characters could not appear in the middle of strings, since the concatenation process cut these characters from the resulting string.

System Commands

Note: Table requires updating

System commands provide information about the system. You can issue these commands at any time either from task, terminal or the CONFIG.PRG file (with some exceptions).

AxisList Returns a comma-separated-list of the axes' names defined in the system. If wildcards are used, the query returns the proper axes.
BreakPointList Lists all the breakpoints in the task, loaded to memory.
CamList This query returns a list of the cam table names defined in the system. If wildcards are used, the query returns the proper existing cam names.
Dir Lists all files that exist on the RAM disk and on the Flash disk. The File Specification may contain the \* and ? wildcard characters, in order to refine the list. When invoked without a parameter, all the files are listed.
ErrorHistory Displays the log file containing the last 64 errors that occurred in the system.
ErrorHistoryClear Clears the error log file.
EventList Lists the names of the existing events and their states. If a task name precedes EventList, only events belonging to the specified task are listed.
GroupList Lists the names of the groups defined in the system. Each group name is followed by a list of the axes\’ names that are part of that group.
PlsList Returns a list of the PLS names defined in the system. If wildcards are used, the query returns the correct existing PLS data.
ProgramPassword Sets the file password and toggles the password protection state.
Tasks Reset All removes all tasks, variables, and system variables from program memory. All external outputs are turned off and all drives are disabled. Reset All runs Config.prg, not Autoexec.prg. Reset All is only issued from the terminal.

Reset Tasks removes all tasks from memory, but leaves system variables loaded. It deallocates all defined variables and user programs. Reset Tasks does not disable motors, or reset outputs. Reset Tasks is only issued from the terminal.

System.AccelerationRate Queries or sets the system acceleration exchange rate.
System.AutostartTask Queries or sets the name of the auto-start task. The default auto-start task is Autoexec.Prg. Assignment of an empty string prevents auto-start task run.
System.AverageLoad Returns the average realtime load on the CPU. This is the average realtime load measured during a 0.5 second interval.
System.Clock Returns the number of system clock ticks. This is the clock run by the operating system. One clock tick corresponds to 1 millisecond.
System.CpuType Returns the type and model of the CPU that was found during the system\’s power-up. Supports only Intel, AMD and Cyrix processors.
System.Date Queries or sets the date. The date is entered as a character string and must be enclosed between double quotes (“). The parameters Day, Month, and Year, must be separated with the / (slash) character.
System.DecelerationRate Queries or sets the system deceleration exchange rate.
System.DIn Returns the value of one or more of the 23 digital inputs. System.DIn returns the values of the individual bits in the system input word. In order to read the value of a single input bit, bit number should be specified as System.DIn.<bit number>.
System.DipSwitch Returns the value of one or more of the eight DIPswitch inputs. System.DipSwitch returns the values of the eight individual bits in the DIPswitch byte. To read the value of a single input bit, bit number should be specified as System.DipSwitch.<bit number>.
System.DiskFreeSpace Returns the amount of free space on the flash disk.
System.DoubleFormat Queries and sets the printing format of Doubles. Zero value stands for d.ddddddddddddddde+/-dd style, with precision of 15 digits after the decimal point. 1 relates to the ddd.ddd style if the exponent is between -4 and 5, and to style otherwise. Setting can be done only in Config.Prg file, and therefore requires system reset (through RESET All or hardware reset).
System.DOut Queries and sets the value of one or more of the 20 digital outputs. System.DOut sets or returns the values of the individual bits in the system output word. In order to read or write into a single output bit, bit number should be specified as System.DOut.<bit number>.
System.Enable Enables and disables the system.
System.Error Queries the last system error message.
System.ErrorHandlerMode Determines the scope of the effect of an error occurring in task context. When the value of System.ErrorHandlerMode is one (the default value), the error will affect the entire system by stopping all motion, idling all tasks that have attached elements and turning off System.Motion flag. Setting this property to zero results in limiting the Motion stop and task idling to the erroneous task itself.
System.ErrorNumber Queries the number of the last system error and returns only the error number.
System.ErrorPrintLevel Controls which errors are printed, according to the severity of the error. Only asynchronous errors are printed. Synchronous errors are not affected.
System.FlashDiskSize Returns the size of the Flash disk.
System.Information Returns information found during system power-up. Performs a test on the SERCON chip cycle time. The result is the average cycle time found in a 500 ms test.
System.IPAddressMask Queries or sets the IP address and subnet mask for the Ethernet interface.
System.JerkRate Queries or sets the system jerk exchange rate.
System.Led Queries and sets one or more of the three general purpose LEDs. In order to read or write into a single LED, LED number should be specified as System.LED.<LED number>.
System.MaxMemBlock Returns the size (in bytes), of the largest block of free memory.
System.MCDouble Reads or writes to one of eight double-type DPRAM variables available for use by the softMC.
System.MCInteger Reads or writes to one of the long-type DPRAM variables available for use by the softMC.
System.Motion Enables and disables Motion commands.
System.MotionAssistance Enables and disables display of additional notes returned from the motion task.
System.Name Queries and sets the name of the controller.
System.NoMotion Enables and disables resetting of System.Motion to zero in case of motion error.
System.NumberAxes Returns the number of axes currently loaded in the system. This is a read-only variable. It can be used in the terminal window or in any task.
System.PeakLoad Returns the peak realtime load on the CPU. This is the maximum value of the realtime load measured during a 0.5 second interval.
System.PipeMode Queries and sets the type of motion pipe mode. Available types are: active, position only, or position and velocity.
System.PrintMode Queries and sets the printing format of Longs. Optional formats are DECIMAL (decimal format), HEX (hexadecimal format) and BIN (binary format). Default format is decimal.
System.RamDriveFreeSpace Returns the amount of free space on the RAM drive.
System.RamSize Returns the size of the RAM found during the system power-up.
System.RtsTimeout Queries and sets the timeout of the real-time scheduler.
System.SerialNumber Returns the serial number of the softMC.
System.ServicePrintLevel Controls (query or set) printing of service messages (ON or OFF).
System.Time Queries or sets the current time of day. Hours, minutes, and seconds are each specified using two digits. The softMC uses 24-hour clock notation. Time is entered as a character string and must be enclosed between double quotes ("). The parameters, Hours, Minutes, and Seconds, must be separated with : (colon) characters.
System.UserAuthorizationCode Returns the user authorization code.
System.VelocityOverride Queries or sets the system velocity override.
System.VelocityRate Queries or sets the system velocity exchange rate.
System.VIn Returns the value of one or more of the 32 virtual inputs. System.VIn returns the values of the individual bits in the system input word. In order to read the value of a single input bit, bit number should be specified as System.VIn.<bit number>.
System.VOut Queries and sets the value of one or more of the 32 virtual outputs. System.VOut sets or returns the values of the individual bits in the system output word. In order to read or write into a single output bit, bit number should be specified as System.VOut.<bit number>.
TaskList Lists the names and states of loaded tasks.
VarList Returns a list of the variable names defined in the system.
Version Returns information pertaining to the version of ControlStudio loaded into your softMC.
With…End_With Simplifies blocks of code, which set a number of parameters on the same motion element (axis or group). After a With is encountered, all parameters where the element is not specified are assumed to belong to the element specified in the With. With is valid in Configuration, Task, or Terminal contexts. The scope of a configuration With is global, whereas the scopes of both terminal and task With’s are limited to terminal and task, respectively.

To put off the With’s effect, use End With. A task With must be followed by the End With, thus creating a closed With block. A With block must be closed within the same block it was opened (i.e., Program, Sub and Function blocks). For example:

A1.VMax = 5000
A1.Vord = 5000
A1.VCruise = 3000
A1.PEMax = 10
A1.PESettle = 0.01
Move A1 100

Can be simplified using With:

With A1
VMax = 5000
 Vord = 5000
 VCruise = 3000
 PEMax = 10
 PESettle = 0.01
 Move 100
End With


MC-Basic provides unformatted and formatted printing using the PRINT and PRINTUSING commands.

The Print command (short form, ?) is used to print expressions from the terminal window or from your program. If you issue print commands from the terminal window, they print to the terminal window. If you issue them from your program, they print to the ControlStudio Message Log. You can view the message log by selecting Window, Message Log.

Within programs, PRINT allows you to suppress the carriage return at the end of a line by terminating the command with a comma or a semicolon. Semicolon and comma have no effect when added to the end of print commands from the terminal window.

Print “Hello, “;
Print “ world.” 'Prints:
 Hello, world.

When commas are added to print command as separators between expressions, a tabular space is placed between the expressions in the printed outcome.

Print “Hello, “,
Print “ world.” 'Prints:
 Hello, world.

On the other hand, expressions separated by a semicolon or a space in the print command are printed adjacently.

Print 1,2
1 2

Print 1;2

Print 1 2

PrintUsing introduces formatting for printing. You can control the format and the number of digits that print. For example, by using the “#” sign and the decimal point, you can specify a minimum number of characters to be printed.

PrintU "The number is #, # ";j1,j2
-->The number is 1, 2

Be aware that using a single format to print more than one expression will result in repetition of any text written within string format according to the number of printed expressions.

PrintU "The number is #, ";j1,j2
-->The number is 1, The number is 2,

By specifying the number of digits to print, data can be printed in tabular form since the number of places printed will not vary with the value of the number.

PrintU “Keep numbers to a fixed length with PrintUsing: ######” ; 100

Be aware that if the number requires more digits than you have allocated, it overruns the space.

PrintU “Overrun: ##” ; 1000000

Takes 7 spaces for 1,000,000 even though PrintU allocates only 2.

For printing of double type expressions, formatted printing also enables to control precision, i.e. number of digits printed after the decimal point.

PrintU “Print PI with 3 digits after decimal point: #.###” ; 3.14159

Prints only 3 digits after the decimal point, while rounding the PI’s value to 3.142.

You can also precede the “#” signs with a “+” to force PrintU to output a sign character (+ or -). Normally, the sign is printed for negative numbers, not positive numbers.

Finally, you can terminate the format string with “^^^^” to force the number to print in exponential format.

PrintU “Exponential format: ####.##^^^^” ; 100

Prints 1e+02. You must include exactly four “^” characters for this format to work.

Be aware that while PRINT and PRINTUSING allow you to print out many expressions on a single line, these expressions are not synchronized to each other. The values can and usually do come from different servo cycles. If you are monitoring motion and need the command to be synchronized, you must use Record.

Normally, printing of longs is done in decimal format. To change printing to Hexadecimal format, type:

System.PrintMode = HEX

To change printing to Binary format, type:

System.PrintMode = BIN

To restore printing to Decimal format, enter:

System.PrintMode = DECIMAL

Printing double floating point numbers is not affected by System.PrintMode. As an alternative to PrintMode, you can place the keywords Decimal, Hex or Binat the end of Print or PrintUsing to print expressions in these formats. Subsequent print instructions (?, PRINT, PRINTU, and PRINTUSING) are not affected.

INPB, INPW, PEEKB, and PEEKW return long values. If you query any of these functions while in PrintMode decimal, the result is misleading. Change to Hex or Bin for the correct result.

System.DoubleFormat , defined from the configuration file , sets the double number printing format for print of double-type numbers.

System.DoubleFormat = 1 – print in Floating point format ( 132.555 )

System.DoubleFormat = 0 - print in Exponential format ( 1.325550000000000e+02 )

Sys.DoubleFormat = 1
End Program

Output Redirection

Typically, tasks inherit their standard output from the loading context, such as the entry station or standard output of a loader task. Sometimes, you must redirect task output (print) to a different place, such as another entry station or even a virtual entry station. RedirectStdOut/RedirectStdOut$ provides this capability.

-->RedirectStdOut task32.prg NewStdOut=1

NewStdOut may be:

  • 1 – Ethernet
  • 3 – Virtual Entry Station
  • 4 – Ethernet2

Flow Control

Flow control is the group of instructions that control the sequence of execution of all other instructions. For detailed information on any of the flow control commands (including examples), refer to the MC Reference Manual.

If…Then is the most basic flow control statement. The syntax of If…Then is:

If condition Then

<first statement to execute if condition is true>

{multiple statements to execute if condition is true}


<first statement to execute if condition is false>

{multiple statements to execute if condition is false}}

End If


If…Then must be followed by at least one statement.

Else is optional, but if present must be followed by at least one statement.

There is no Else if. If you use an If after an Else, you must place the If on a new line.

Select…Case is an extension of If…Then. Anything that can be done with Select…Case can also be done with If…Then. Many times, Select…Case simplifies programming logic.

On the first line of a Case block of commands, you specify the variable or expression you want tested. For example:

Select Case I

Tests the variable I for a range of conditions.

You can also select expressions:

Select Case I - M/N

After you have specified the variable or expression, list one or more values or value ranges that the variable can take. There are four ways you can specify cases:

  • Exact Value
  • Logical Condition
  • Range
  • Else

The syntax of Select…Case is:

Select Case SelectExpression

{Case Expression1

{statements to be executed if SelectExpression = Expression1}}

{Case Expression2 {statements to be executed if SelectExpression = Expression2}}

{Case Is RelationalOperator Expression3 {statements to be executed if the condition is true}}

{Case Expression4 To Expression5 {statements to be executed if SelectExpression is between values}}

{Case Else {statements to be executed if none of the above conditions are met}}

End Select


SelectExpression is a Long, Double or String expression

in Case…To…, if Expression4 > Expression5, the case is never true; no error is flagged.

Select…Case block. The following example puts all four types of cases together:

Dim N as Long
Select Case N
Case 0
Print "N = 0"
Case 1
Print "N = 1"
Case is >=10
Print "N >= 10"
Case is < 0 ‘No requirement for statements after Case
Case 5 TO 9
Print "N is between 5 and 9"
Case Else
Print "N is 2, 3, or 4"
End Select
End Program

For…Next statements allow you to define loops in your program. The syntax is:

For counter = Start To End {Step Size}]

{Loop Statements}

Next {counter}


If Size is not defined, it defaults to 1.

The loop is complete when the counter value exceeds End. For positive Size, this occurs when counter>End. For negative Size, when counter<End.

Counter, Start, End, and Size may be Long or Double.

For example:

For I = 2 TO 5
Print "I = " I 'Prints 2, 3, 4, 5
Next I

For I = 4 TO 2 STEP –0.5
Print "I = " I 'Prints 4.0, 3.5, 3.0, 2.5, 2.0

While…End While allows looping dependent on a dynamic condition. For example, you may want to remain in a loop until the velocity exceeds a certain value.

The syntax of While is:

While Condition

{statements to execute as long as condition is true}

End While


The condition is evaluated before any statements are executed. If the condition is initially false, no statements are executed.

Statements are optional. If none are included, While…End While acts as a delay.

You can have any number of statements (including zero) to be executed.

For example:

While A2.VelocityFeedback < 1000
Print "Axis 2 Velocity Feedback still under 1000"
End While
End Program

Using the While or Do…Loop, the CPU repeatedly executes the While block (even if the block is empty). This is sometimes a problem. These commands do not relinquish system resources to other tasks. If you want to free up CPU resources during a While block or Do…Loop, include the Sleep command within the block as follows:

While A1.VCmd < 1000
 Sleep 1
End While
End Program

The Do...Loop is similar to While except that the statement block is executed before the first evaluation of the condition. With the Do...Loop, the statement block are always executed at least once. Do...Loop also allows an option on the condition. Use While to execute while the condition is true, or Until to execute while the condition is false. The syntax of the Do...Loop is:



LOOP While|Until Condition


The statements are executed at least once.

Statements are optional. If none are included, Do...Loop acts as a delay.

For example:

Dim Shared i as Long
i = 0
i = i + 1
Print i
Loop Until i = 10
End Program

or, equivalently, you can use Loop While:

Dim Shared i as Long
i = 0
i = i + 1
Print i
Loop While i < 10
End Program

GoTo unconditionally redirects program execution. The syntax is:

GoTo Label1



Label1 is a valid label within the same task as the GoTo.

The label must be on a separate line.

You can only branch within a Program, Event, Function, or Subroutine.

You can GoTo a label placed within a program block (If…Then, For…Next, Select…Case, While…End While, and Do...Loop) only if the GoTo and label are within the same block.

If the program is within a program block, you cannot GoTo a label outside that block.

Avoid GoTo wherever possible. History has shown that excessive use of GoTo makes programs harder to understand and debug. Use the other program control statements whenever possible.

Error Trapping

There are four ways to specify catch statements: Exact Value, Logical Condition, Range, and Else. The syntax used is:

Catch Error_Number {statements to execute if error Error_Number had occurred}

Catch Is <RelationalOperator> Error_Number {statements to execute if the condition is true}

Catch Error_Number1 To Error_Number2 {statements to execute if error number is between values}

Catch Else {statements to execute if all other errors had occurred}


The number of Catch statements is not explicitly limited.

Error_Numbers can only be long-type numeric values.

In Catch…To…, if Error_Number1 > Error_Number2, the catch statement is never true and no error is flagged.

Catch statements are used within three types of error trapping blocks.

The Try block is designed to trap synchronous errors within task context (For more details, see the Error Handling section). There is no explicit limitation on the number of Try blocks instances in a program. The syntax for a Try block is:


{code being examined for synchronous errors}

{Catch Error_Number {statements to be executed}}

{Catch Is <RelationalOperator> Error_Number {statements to be executed}}

{Catch Error_Number1 To Error_Number2 {statements to be executed}}

{Catch Else {statements to be executed}}

{Finally {statements to be executed if an error was trapped}}

End Try

An example of a Try block, designed to catch errors in the loading process of Task1.Prg:

Load Task1.Prg
Catch 4033 ‘ File does not exist
Print “Task not found”
Catch 6007 ‘ Task must be killed first
KillTask Task1.Prg
Unload Task1.Prg
Load Task1.Prg
Catch Else
Print “Error while loading Task1.Prg”
Print “Caught error: “ Task1.prg.Error
End Try

The OnError block is designed to trap and process both synchronous and asynchronous errors in a task. OnError traps errors not trapped by the Try/Finally mechanism within the task. (For more details, see “Error Handling” section). Only one instance of OnError may exist in a program. The syntax for OnError block is:


{Catch Error_Number {statements to be executed}}

{Catch Is <RelationalOperator> Error_Number {statements to be executed}}

{Catch Error_Number1 To Error_Number2 {statements to be executed}}

{Catch Else {statements to be executed}}

End OnError

An example of an OnError block, designed to stop motion in case of a motion error:

Catch 3001 To 3999 ‘ Motion errors
System.Motion = 0
A1.Enable = 0
? VESExecute("System.Motion = 1")
A1. Enable = 1
Print "Caught a Motion error: " ThisTask.Prg.Error
Catch Else
Print "Caught a non-Motion error: " ThisTask.Prg.Error
End Onerror

The OnSystemError block is designed to trap and process both synchronous and asynchronous errors in all tasks, as well as errors that occur within the context of the system (For more details, see the Error Handling section). Only one instance of OnSystemError may exist in the system. The syntax for OnSystemError block is:


{Catch Error_Number {statements to be executed}}

{Catch Is <RelationalOperator> Error_Number {statements to be executed}}

{Catch Error_Number1 To Error_Number2 {statements to be executed}}

{Catch Else {statements to be executed}}

End OnSystemError

An example of an OnSystemError block, designed to monitor errors in task Errors.Prg:

Catch Is < 12000
Print “Caught a MC error: ” System.Error
‘ MC errors
KillTask Errors.Prg
Catch Is > 20000
Print “Caught a user error: ” System.Error
‘ User defined errors
KillTask Errors.Prg
End OnSystemError


Program control commands can be nested. Nesting is when one program control command (or block of commands) is within another. There is no specified limit on the number of levels of nesting.

For example, the following program nests a WHILE…END WHILE sequence within a FOR…NEXT sequence:

For I = 1 to 10
 While N>0
  N=N-1 'This command will be executed 50 times
 End While
Next I

There is no specified limit on the number of levels of nesting. The Sample Nesting Program in Appendix A shows numerous combinations of nesting.


FAQs - MC-Basic - Ask the developers a question