MC-Basic Programs
IMPORTANT | |
This entry is outdated and requires revision. |
A project is all the software written for an application. The projects in MC-BASIC are multi-tasking. They consist of many tasks running concurrently with, and independently of, each other. The project is stored in multiple files, one file for each task. Tasks are routines that run simultaneously with many other tasks. Projects also include other files such as cam tables and record files. Projects are controlled from the BASIC Moves (BMDS) software. BMDS automatically sets up a separate directory for each project. For detailed information on any commands listed within this section, refer to the ® MC Reference Manual.
For clarity, a project is managed by BMDS and conveniently handles a group of logically coupled files (programs, CAM tables, etc.), while the MC deals with separate files (PRG, CAM, etc.). The Motion controller does not keep project files in the Flash and it is not aware of logical coupling of files and programs.
Contents
Project Structure
Project files include tasks and cam tables. Each project can contain three types of tasks:
General-purpose task
An optional configuration task (Config.Prg) to declare groups, programmable limit switches (PLS), cams, global variables and load of global libraries.
An optional autoexec task (Autoexec.Prg) to automatically start the application on power-up.
Tasks
The three types of tasks are general-purpose tasks, configuration tasks, and autoexec tasks. Each type of task is outlined below.
General Purpose Tasks
General-purpose tasks are the work horse of the MC language. They implement the basic logic of your application. The great majority of your programming is implemented with general-purpose tasks. Each general-purpose task is divided into three sections: a task-variable section, a main program, and subroutines. The main program is further divided into three sections: a Start-up section, an OnError section, and an OnEvent section.
A task-variable definition sectionThe task-variable definition section, where all task variables are declared with the Dim…Shared command.
The main programMost programming is done in the main programming section. The main programming section falls between the Program…End Program keywords. The main program itself has three sub-sections:
The Start-up sectionThe start-up section immediately follows the Program keyword. This is where task execution begins when you start a task.
OnError sectionThe OnError section responds to errors generated by the task, allowing your program to automatically respond to error conditions and (where possible), gracefully recover and restart the machine. There is (at most) one OnError section for each task and it is normally written just before the OnEvent section.
OnEvent sectionThis section contains optional blocks of code that respond to realtime changes, such as a motor position changing or an input switch turning on. The main program can contain code to automatically respond to events. This reduces the effort required to make tasks respond quickly and easily to realtime events.
Event handlers begin with the OnEvent and end with End OnEvent keywords. One OnEvent…End OnEven keyword combination is required for each realtime event. Event handlers must be contained wholly within the main program.
Optional subroutinesEach task can have any number of subroutines. Subroutines are component parts of the task, and consequently, they can only be called from within the task. If you want to call the same subroutine from two tasks, place one copy in each task.
Configuration Task
The name of the configuration task is Config.Prg. The configuration task is used for declaration of number of axes, global variables and other constructs, such as cam tables, programmable limit switches (PLS), and group. The key to understanding the configuration task is that all data and constructs shared across tasks must be declared in the configuration task. Refer to the following figure.
The configuration task can contain a program. Axes can be renamed here.
AutoExec Task
The AutoExec task (AutoExec.Prg) is executed once on power up, just after the Configuration Task. Use AutoExec to start power-up logic. For example, you might want to use AutoExec to start a task that sets the outputs to the desired starting values. That way, the outputs are set immediately after the MC boots, usually sooner than the PC.
For safety considerations we do not recommend starting of motion from the AutoExec task. Motion should be started by explicit operator’s request either by I/O or communication link from host PC.
Set the AutoExec task to run on power up. To do this, add the keyword Continue to the Program command. Do not include OnError or OnEvent sections in the AutoExec. Limit the AutoExec task to starting other tasks in the system. Refer to the next figure.
Program Declarations
You must declare the start of programs and subroutines. For programs, use the Program…End Program keywords. Use Sub…End Sub keywords for subroutines.
The Program…End Program keywords mark the boundary between the variable declaration section and the main program. Each task must have only one Program keyword and end with the End Program keyword.
Program ‘Standard form of program command <code for program> End Program
The AutoExec task, which must be loaded and run automatically at power-up must have CONTINUE following Program.
You pass parameters (either scalar or array) to the subroutine, which can then be used in the code of the subroutine. In the declaration line for the subroutine (SUB<name>), you declare the variable names and types of the parameters to pass. Parameters are passed either by reference or by value (ByVal). The default method is to pass parameters by reference. Arrays are passed only by reference. When you pass a variable (whether the variable is local to the task or is global) by reference, you pass the address of the variable to the subroutine, which changes the value of the variable (if the code of the subroutine is written to do this). When you pass a variable by value (ByVal) a copy of the value of the local variable is passed to the subroutine. The subroutine cannot change the value of the local variable. The syntax for defining a subroutine is:
SUB <name> ({{ByVal} <p_1> as <type_1> }…{, {ByVal} <p_n> as type_n>})
{ local variable declaration }
{ subroutine code }
END SUB
There is no explicit limit on the number of subroutines allowed in a task. All subroutines must be located following the main program, and must be contained wholly outside the main program. Subroutines can only be called from within the task where they reside. Subroutines may be recursive (call itself).
Use CALL to execute a subroutine:
CALL <subroutine>({<p_1>...<p_n>})
where:
<subroutine> is the name of the subroutine<p_1>...<p_n> are the subroutine parameters
Parentheses are not used in a subroutine if no parameters are passed.
MC-BASIC automatically checks the type of compliance between the subroutine declaration and the subroutine call. Any type mismatch causes an error during program loading. Automatic casting applies to numeric variables types. For example, suppose MySub is a subroutine that takes a Long parameter. In this case, the following scenario applies:
CALL MySub(3.3432) 'OK: The double value 3.3432 is demoted to the Long value, 3 CALL MySub(a) 'Error: a is a string, there is a type mismatch Call MySub(3,4) 'Error: The number of parameters is not correct
See the Subroutine Example in Appendix A for further details.
Subroutines
Parameters (either scalar or array) passed to the subroutine are used within the code of the subroutine. The declaration line for the subroutine (SUB<name>) is used to declare names and types of the parameters to pass.
Parameters are passed either by reference or by value (ByVal). The default method is to pass parameters by reference. Whole arrays are passed only by reference. Trying to pass a whole array by value results in a translation error. However, array elements can be passed both by reference and by value. The syntax for a subroutine is:
SUB <name> ({<par_1>([*])+ as <type_1>}…{, <par_n>([*])+ as<type_n>})
…
END SUB
<par_l>: name of array variable
<par_n>: name of array variable
[*]: dimension of an array without specifying the bounds
+: means one or more [*]
SUB CalculateMean(x[*][*] as DOUBLE, TheMean[*] as LONG) DIM sum as DOUBLE DIM I as LONG FOR i = 1 to 100 sum = sum + x[i][1] NEXT i TheMean[1] = sum/100 END SUB SUB PrintMean(ByVal Mean as LONG) PRINT “Mean Value Is “, Mean END SUB CALL CalculateMean(XArray, TheMeanArray) ‘ Pass entire array by reference CALL PrintMean(TheMeanArray[1]) ‘ Pass a single array element by value
When a variable is passed by reference (whether the variable is local to the task or global), the address of the variable is passed to the subroutine, which changes the value of the original variable (if the code of the subroutine is written to do this).
When a variable is passed by value (ByVal) a local copy of the value of the variable is passed to the subroutine, and the subroutine cannot change the value of the original variable.
There is no explicit limit on the number of subroutines allowed in a task. All subroutines must be located following the main program and must be contained wholly outside the main program. Subroutines can only be called from within the task where they reside. Subroutines may be recursive (can call itself). Use CALL to execute a subroutine with the following syntax:
CALL <subroutine_name>{(<par_1>{, …<par_n>})}
Parentheses are not used in subroutine CALL if no parameters are passed.
MC-BASIC automatically checks the type of compliance between the subroutine declaration and the subroutine call. Any mismatch (in number of parameters or parameters types) causes an error during program loading. Automatic type casting applies only for “by value” long and double parameters.
SUB MySub(RefPar as long, byval ValPar as double) … END SUB CALL MySub(LongVar, “String”) -> type mismatch in second parameter CALL MySub(LongVar) -> wrong number of parameters CALL MySub(LongVar, 2) -> a valid type casting for a by-value parameter CALL MySub(DoubleVar, 2.2) -> invalid type casting for a by-ref parameter
User-Defined Functions
MC BASIC allows the definition of user functions to be used in programs in the same manner as using BASIC's pre-defined functions. User-defined functions are composed with multiple lines and may be recursive (can call itself). Unlike BASIC's system functions, the scope of user-defined functions is limited to the task in which it is defined.
Functions are different from subroutines in one respect. Functions always return a value to the task that called the function. Otherwise, functions and subroutines use the same syntax and follow the same rules of application and behavior.
Because functions return a value, function calls should be treated as expressions. Therefore, function called can be combined within print commands, assignment statements, mathematical operations and conditions of flow control statements. They can also be passed as by-value parameters of system or user-defined functions and subroutines.
PRINT <function_name>{(<par_1>{, …<par_n>})} <variable_name> = <function_name>{(<par_1>{, …<par_n>})} IF <function_name>{(<par_1>{, …<par_n>})} > 10 THEN ? LOG( <function_name>{(<par_1>{, …<par_n>})} )
Parentheses are not used in function CALL if no parameters are passed. Parameters (either scalar or array) passed to the function are used within the code of the function. Declare variable names and types of parameters in the declaration line of the function. Parameters can be passed by reference or by value. The default is by reference.
Arrays can only be passed by reference. Trying to pass a whole array by value results in a translation error. On the other hand, array elements can be passed by reference and by value.
To set up the return value, assign the return value to a virtual local variable with the same name as the function somewhere within the code of the function. This local variable is declared automatically during function declaration and the function uses it to obtain the return value.
There is no explicit limit on the number of functions allowed in a task. All functions must be located following the main program and must be contained wholly outside of the main program.
MC-BASIC automatically checks the type of compliance between the function declaration and the function call. Any mismatch (in number of parameters, in parameters and returned value types) causes an error during program loading. Automatic type casting applies only for long and double returned values and “by value” parameters. For example:
Function LongReturnFunc(…) As Long LongReturnFunc = “String” -> type mismatch in returned value End Function Function LongReturnFunc(…) As Long LongReturnFunc = 43.7 -> valid type casting in returned value End Function
A function can be recursive (can call itself). The following example defines a recursive function to calculate the value of N:
FUNCTION Factorial (ByVal N As Long) As Double 'By declaring N to be long, this truncates floating point numbers 'to integers 'The function returns a Double value If N < 3 then 'This statement stops the recursion Factorial = N '0!=0; 1!=1' 2!=2 Else Factorial=N * Factorial(N-1) 'Recursive statement End If END FUNCTION
When writing a recursive function, you must have an IF statement to force the function to return without the recursive call being executed. Otherwise, the function never returns once it is called.
Arrays
Arrays can only be passed by reference. If a user tries to pass a whole array by value, the translator gives an error. Array syntax is:
SUB <name> ({<p_1>([*])+ as <type_1>}…{, <p_n>([*])+ as <type_n>})
{ local variable declaration }
{ subroutine code }
END SUB
where
<p_l> : name of array variable
<p_n> : name of array variable
[*] : dimension of array without specifying the bounds
+ : means one or more
Syntax example:
SUB mean(x[*][*] as DOUBLE, TheMean[*] as LONG) DIM sum as DOUBLE DIM I as LONG FOR i = 1 to 100 sum = sum + x[i][1] NEXT i TheMean[1] = sum/100 END SUB
Multi-tasking
The MC supports multi-tasking. You can have multiple tasks running independently, sharing a single computer. A task is a section of code that runs in its own context. Microsoft Windows is a multi-tasking system. If you open Explorer and Word at the same time, they run nearly independently of each another.
In this case, both Explorer and Word have their own contexts. They share one computer, but run as if the other were not present. There is inter-task communication. If you double-click on a document in the file manager, it launches Word to edit the file you clicked.
With MC-BASIC, you can use different tasks to control different operational modes: one for power up, one for set-up, one for normal operation, and another for when problems occur. Like Windows, each task can run independently of the others, and you can prescribe interactions between tasks.
Multi-tasking is used when you want multiple processes to run largely independent of each other. For example, if you are using the MC to interface to the operator, you will usually use a separate task to execute the interface code. Another example is when two parts of a machine are largely independent of each other. There is usually some control required between tasks as one task may start or stop another.
If a machine is simple to control, you should try to keep the entire program in one task (in addition to Config.Prg). If you do need to use multi-tasking, you should keep a highly structured architecture. Kollmorgen recommends that you limit use of the main task for axis and group set up, machine initialization, and controlling the other tasks. Normal machine operation should be programmed in other tasks. For example, Main.Prg might be limited to setting up axes, and then starting Pump.Prg, Conveyor.Prg, and Operator.Prg.
Do not split control of an axis or group across tasks. You can put control for multiple axes in one task. Ideally, you should use multiple tasks for machines where different sections operate more or less independently. You can also use tasks to implement different operational modes.
Multi-tasking is a powerful tool, but it carries a cost. It is easy to make errors that are difficult to find. When multiple tasks are running concurrently, complex interaction is difficult to understand and recreate. Limit the use of tasks to situations where they are needed.
Do not create a task as a substitute for an event handler. Events and tasks are not the same. MC-BASIC supports event handlers to respond to realtime events. Events are similar to interrupts in microprocessor systems. They normally run at higher priorities than the programs that contain them. They are ideal for quick responses to realtime events. Add the event handler to an existing task to respond to an event.
Do not use tasks in place of subroutines. Remember that when you start a task, the original task continues to run. When you call a subroutine, you expect the calling program to suspend execution until the subroutine is complete. The behavior of tasks where the two routines continue to execute can cause complex problems.
Knowing when to use multi-tasking and when to avoid it requires some experience. If you are new to multi-tasking, you may want to start slow until you are familiar with how it affects program structure. When you start a new project, BASIC Moves creates the main task as part of opening a new project. After that process is complete, you can add a new task to your project by selecting File, New. You can also press the new task button on the BASIC Moves tool bar.
Loading the Program
BASIC Moves automatically loads all tasks in your project when you select Run Project. You can select Run Project by selecting it from the Debug menu, by pressing the F5 key, or by pressing the “Load Task”and “Run Task” buttons on the tool bar. By default, tasks are loaded from the host PC to the MC at a low priority (Priority = 16).
When you select Run Task, the project’s main task is started at the lowest priority (Priority = 16). You can change the priority of the main task by selecting View-> Project Manager->Options and then changing the priority in the bottom of the window. If you structure your software so that the main program loads all other tasks, the Run Project button starts your machine.
Preemptive Multi-tasking & Priority Levels
Because many tasks share one processor, you must carefully design your system so tasks get processing resources when they need them. You do not want the operator interface taking all the resources when you need fast response to a realtime event. The operating system provides system resources based on two criteria: task priority level and time slice.
When you create a program, you must select the task priority level. MC-BASIC allows you to specify 16 levels of priority. The task with the highest priority takes all the system resources it can use. In fact, no task of a lower priority receives any resources until all tasks of higher priority relinquish them. Most systems have one main task that runs at a medium priority and perhaps a background task that runs at a low priority, with a few high priority tasks. At every time slice, the MC re-evaluates which task has the highest priority and assigns resources to it.
The BASIC Moves terminal window relies on the MC command line task, which runs at priority 2. If you start a task with priority 1, the terminal will not be available until the task is complete or idle. Consequently, you will not be able to communicate with the MC and you may have to power-down the system to recover the terminal window. You can optionally set the priority of a task when you start it. For example:
StartTask Aux.Prg Priority=6
The default priority of events is 1 (highest) and the default priority of programs is 16.
Time Slice is a method by which the operating system divides up resources when multiple tasks share the same priority level. The MC provides the first task with one time slice, the next time slice goes to the second, the next to the third, and so on. The time slice is currently one millisecond duration. This method is sometimes called round robin scheduling.
Inter-Task Communications and Control
Tasks can control one-another. In fact, any task can start, continue, idle, or kill any other task, regardless of which task has the higher priority. For detailed information on these commands, refer to the MC Reference Manual.
StartTask starts tasks from the main task. For testing, you can use STARTTASK from the terminal window. DanaherMotion recommends you do not use STARTTASK in AutoExec.Prg. The syntax of STARTTASK is:
StartTask <TaskName> {Priority = <Level>}{NumberOfLoops = <Loop Count>}
NOTE | |
NOL is a short form for NumberOfLoops. |
where:
<Level> is a long with value between 1 and 16. If <Level> is not entered, it defaults to 16, the lowest priority. Priority = 1 is the highest priority.
<Loop Count> is either -1 (indicating unlimited number of loops) or between 1 and 32768 indicating the number of times the task is executed. If <Loop Count> is not entered, it defaults to 1.
For example:
StartTask Task1.Prg Priority=8 NumberOfLoops = -1 'Run Task1 forever StartTask Main.Prg NOL=1 'Run Main once
IdleTask stops the task at the end of the line currently being executed and idles all its events. An idled task can be continued (using CONTINUETASK) or terminated (using KILLTASK). IDLETASK does not stop motion currently being executed. This is significant because all the events are idled and cannot respond to an axis' motion. Tasks can be idled explicitly by other tasks, but cannot idel itself. This command is issued from a task or the terminal window. The syntax of IdleTask is:
IdleTask <TaskName>
For example:
IdleTask TASK1.PRG
Tasks that have been idled with IDLETASK are restarted only with CONTINUETASK. The command continues an idled task from the point at which it was stopped, or continues task execution after a break point has been reached. It is frequently used to restart tasks from the ONERROR error handler. If a run time error has occured, CONTINUETASK retries the line which caused the error. The error must be corrected before the task continues. This command is issued from any task or the terminal window. The syntax of ContinueTask is:
ContinueTask <TaskName>
For example:
ContinueTask TASK1.PRG
KillTask aborts the execution of a task. The program pointer is left on the line at which the task was stopped. The first action of KILLTASK is to kill and delete all events associated with the task. This is done to ensure that no event initiates an action after KILLTASK was executed. KILLTASK is issued from the terminal window. The syntax of the KillTask is:
KillTask <TaskName>
For example:
KillTask TASK1.PRG
Monitoring Tasks From the Terminal
For detailed information on these commands, refer to the MC Reference Manual.
TASK.STATUS provides the current state of any task. You can query TASK.STATE from the terminal window. You cannot use TASK.STATUS from within a program. The syntax for TASK.STATUS is:
? <TaskName>.Status
For example:
? TASK1.PRG.Status
TASKLIST returns the state and priority of all tasks loaded in the system. You can query TASKLIST only from the terminal window.
For example, if you type:
? TaskList
A typical result is:
TaskName = TASK1.PRG, Status = sstep, Priority=16 TaskName = DO.PRG, Status = suspend, Priority=4
Relinquishing Resources
When tasks of different priorities compete for processor time, the highest priority task always takes all the resources it needs. However, tasks of high priority can relinquish computer resources under some conditions. In these cases, tasks of lower priority run until the high priority tasks again demand the resources. There are three conditions under which a task relinquishes resources: when the task is terminated, when the task is suspended, or when the task is idled. For detailed information on these commands, refer to the MC Reference Manual.
A task terminates when it is finished executing. If a task starts with NUMBEROFLOOPS greater than zero, the task executes the specified number of times and terminates. The task relinquishes all resources. Terminated tasks remain loaded in the system and can be restarted.
One task can terminate another task by issuing KILLTASK. A task relinquishes all resources after the kill command. Killed tasks remain in the system and can be restarted.
Tasks relinquish processing resources temporarily when they are suspended. A task is suspended when it is waiting for a resource or is delayed. Suspended tasks still monitor events as long as the event priority is higher than the task priority. Never run a task at a higher priority level than any of its events.
Use SLEEP to delay a task for a specific period of time. This command can only be issued from within the task. One task cannot issue a SLEEP for another task. SLEEP causes the task to relinquish resources until the sleep time has expired.
Idled tasks relinquish resources. In this case, resources are relinquished until another task revokes the idle by issuing a CONTINUETASK.
Delete Task/Library deletes a file from the Flash Disk. Only filesnot loaded into RAM can be deleted.Files that are protected by a password may not be deleted. For example:
Delete FILE1.PRG
Event Handler
The main program can contain sections which automatically handle events. This reduces the programming effort required to make tasks respond quickly and easily to realtime events. Event handlers begin with OnEvent and end with End OnEvent and occur just after the Program keyword.
After OnEvent is loaded, turn the event On with EventOn just after the End OnEvent keyword (enable immediately). However, you can enable and disable OnEvent at any time using EventOn and EventOff. Multiple OnEvents can be written sequentially. The MC system can support up to 64 events. The number of OnEvent(s) in a single task is not restricted, so a task may have from 0 to 64 OnEvent(s).
It is important to understand that OnEvents are different from ordinary tasks. OnEvents are preemptive within the task. That is, an OnEvent runs until complete and the program execution returns to the main program. While an OnEvent is executing, it does not release CPU time to the parent task or any other task. In this sense, OnEvents are similar to interrupt calls. They run to completion before execution returns to the main program. An OnEvent must have a higher priority than its parent task to ensure that when an event occurs, it interrupts its parent task and runs to completion. The rules are valid for a single process, (that is, the parent task and its events), while events of the respective tasks in the system share the CPU among themselves.
OnEvent
The syntax of OnEvent is:
OnEvent [EventName] [Condition] {Priority=EventPriority}{ScanTime=time}
where
EventName is any legal name that is otherwise not used in the task.
Condition is any logical expression such as System.Dout.1 = 1. The event fires on transitions of the condition from false to true.
Priority is an integer from 1 (highest) to 16 (lowest). If not entered, priority defaults to 1. The priority should always be higher than the priority of the task or the event never runs.
Time is an integer indicating the number of cycles between each scan. Time defaults to 1.
In this example, an event is set up to move axis "X-axis" to 10000 counts each time an input goes high:
OnEvent MOVE_ON_TRIGGER System.Din.1=ON Move X-axis 10000 End OnEvent
Normally, event handlers run at a high priority so that once the event occurs, they run to completion. In most cases, this code should be very short as it usually takes all resources until it is complete.
ScanTime is in cycles of the SERCOS update rate. This is normally 2 or 4 milliseconds. Setting ScanTime to 5 configures the system to check the event condition every 10 or 20 milliseconds, depending on your update rate. For example:
OnEvent System.Din.2 = ON ScanTime = 5
Events can either be controlled from within the task in which they reside, or from the terminal. The main program or any subroutine can issue EventOn (to enable the OnEvent command) or EventOff (to disable it). OnEvents cannot be controlled from other tasks.
EventOn
EventOn enables OnEvent. The syntax of EventOn is:
EventOn [Event Name]
EventOn must come after the definition of the OnEvent.
EventOff
EventOff disables OnEvent. The syntax of EventOff is:
EventOff [Event Name]
Refer to the MC Reference Manual for information additional information about OnEvent, EventOn, and EventOff.
EventList
EventList provides a complete list of all events in all tasks with their name, the task name, the priority, whether the event is armed, and current status. EventList is valid only from the terminal window. For example:
? EventList
the result is something like the following line for each task:
Name = IOEvent Owner=Task1 Edge=1 Status=1 Scan=1 Priority=5 Action = Stop
where:
edge=1 indicates the event is armed (that is, the condition is false so that the condition becoming true will fire the OnEvent)
status=1 means the event is enabled
EventDelete
Deletes the specified event. The event does not respond to the specified condition until the task is executed again and the event is enabled.
EventDelete EVENT1
Events at Start-up
Events are normally triggered by the OnEvent condition changing from false to true. So a single transition in the condition is required to run OnEvent. One exception to this is start-up. At start-up, if the condition is true, OnEvent executes once, even if there has not been a transition.
Program Flow and OnEvent
You can use GoTo commands within an OnEvent block of code. However, because OnEvent interrupts the main program, you cannot use GoTo to branch out of the event handler or into the event handler. You cannot place OnEvent…End OnEvent in the middle of program flow commands (e.g., For…Next, If…Then, etc.). You cannot declare or use local variables inside an OnEvent block.
Semaphores
Semaphores are the basis for synchronization and mutual exclusion. The difference is that the mutual exclusion semaphore is created as “full” or “1”, while the synchronization semaphore is empty “0”. If the semaphore is used for protecting mutual resources, it is taken before accessing the resource and releases at the end. A synchronization semaphore is given by the producer and taken (consumed) by the consumer.
NOTE | |
A semaphore is created as “full.” |
Global semaphore are defined with COMMON SHARED in CONFIG.PRG or from the command line. Since a semaphore's purpose is to protect data among tasks, there is no meaning to local semaphores.
A semaphore is given/released by SEMAPHOREGIVE and taken/consumed by SEMAPHORETAKE. It is possible to specify a time out of up to 5000 ms. SEMAPHORETAKE acquires a semaphore and returns before timeout or does not acquire a semaphore and returns after timeout.
NOTE | |
Mutual exclusion semaphores are taken and given by the same task. Synchronization semaphores are given by one task and taken by another task. |
Mutual Exclusion Semaphores
Mutual exclusion semaphores lock resources by taking a semaphore. Another task(s) competing for the same resource is blocked until the semaphore is released.
Example of a mutually exclusive semaphore:
‘ common shared comMutex as semaphore ‘ defined in config.prg Program Open COM2 BaudRate=9600 Parity=0 DataBits=8 StopBit=1 As #1 While 1 ‘ take semaphore lock serial port If SemTake(comMutex,5000) = 1 Then Print #1,”Hello ”; Print #1,”world” SemGive(comMutex) ‘unlock serial port End if End While End program
Synchronization Semaphores
Synchronization semaphores are essential in producer-consumer applications where task A prepares some data, while task B consumes it. In this case, the semaphore may eliminate constant polling for ready data and save considerable CPU resources.
Example of Producer:
‘ common shared syncSemaphore as semaphore ‘ defined in config.prg ‘ common shared globalA as long ‘ defined in config.prg Program Dim dummy as long ‘ Semaphore is created as “full” - flush it before first use dummy=semTake(syncSemaphore) ‘ no waiting While 1 globalA=globalA+1 ‘ produce some data semGive(syncSemaphore) sleep (100) End While End program
Example of Consumer:
' common shared syncSemaphore as semaphore ' defined in config.prg ' common shared globalA as long ' defined in config.prg Program While 1 If SemTake(syncSemaphore,5000) = 1 Then Print "A is "; globalA End if End While End program
SERCOS
The MC uses the SERCOS fiber-optic ring network to communicate with the drives. The SERCOS interface (SErial Realtime COmmunication System) is an internationally recognized specification (IEC 1491), supported by many companies around the world. SERCOS replaces analog connections with digital, high-speed fiber-optic communication. MC supports 2/4/8/16 Mbit/s baud rate speeds. The SERCOS interface is selected because of numerous technical advantages:
DeterminismSERCOS provides deterministic communication to all drives. The communication method provides complete synchronization between controller and axes, and among all axes.
International StandardSERCOS is the only digital communication method for motion control supported by an international body. It is the only standard with motion control products provided by a wide base of companies.
Reduced Wiring Between Drive And ControllerSERCOS greatly reduces wiring between controller and drives. While analog and PWM amplifiers require 10 to 15 connections-per-drive, SERCOS requires only two fiber-optic cables between the controller and the drive.
NoiseBecause SERCOS is based on fiber optics, electromagnetic noise is greatly reduced. The controller is electrically isolated from drives and feedback devices, as well as from limit switches and other I/O wired through the drives. Most grounding and shielding problems, notorious for the difficulties they cause during installation of analog motion control systems, are eliminated.
Simplifying ReplacementSERCOS allows you to download configuration parameters for all drives simultaneously via the SERCOS network. You can configure your system to automatically configure the drives after each power up. If a drive needs to be replaced, all re-configuration is automatically done.
Reliable ConnectionsSERCOS uses fiber optic connections to eliminate the tens or even hundreds of hard-wired connections between the drives and the controller. This eliminates many possibilities for intermittent or reversed connections.
Access to DriveSERCOS provides complete access to drive data. For the drive, you can even record variables realtime in the drive and send the data via SERCOS to your PC using MOTIONLINK.
Axis ModularitySERCOS relies on the drive to connect to most external signals related to an individual drive: feedback device, limit switches, and registration sensors. When an axis is added to a system, most of the wiring associated with the axis connects directly to the drive. This minimizes the changes to system wiring required to support adding or removing drives.
Communication Phases
In SERCOS, one master controller and many drives are connected with the fiber optic cable to form a communication ring.
The master attempts to establish communication in a step-by-step process. This process is referred to as bringing up the ring. Each step is defined in SERCOS as a phase. In order to bring up the ring, the system must proceed successfully through five phases (0 through 4). The MC simplifies this process by allowing you to specify at which phase you want the ring. In most cases, you simply need to set the SERCOS property phase to 4. The main exception to this is when configuring telegram Type 7 to include external encoder data, which requires that you first set the phase to 2 and then to 4.
In phase 0, the master establishes synchronization by passing the Master Synchronization Telegram (MST) to the first drive. That drive passes it to the next and so on until it is returned to the master, indicating that the ring is complete. After the master determines that 10 MST telegrams have been passed through the ring, phase 0 is complete.
In phase 1, the master sends the Master Data Telegram (MDT). Each drive is addressed individually and each drive responds with an Amplifier Telegram (AT). When all drives have responded, phase 1 is complete.
In phase 2, all drives are configured through a series of IDNs. First, the communication parameters are sent. Then, the drives are configured for operation.
Up to this point, all data have been sent via the service channel. In phase 3, the cyclic data channel is established. Configuration is completed and verified.
Phase 4 is normal SERCOS operation.
SERCOS.PHASE automatically moves the SERCOS ring through each phase. You can observe this operation by watching the 7-Segment LED display on the drive. The number displayed indicates the current communication phase. When the process is complete, an S (or 5) is displayed, indicating that the ring is up and drives can be operated.
Telegrams
All SERCOS data are organized into data packets called telegrams. Telegrams transport data and also provide protocol support and error checking. SERCOS provides three telegrams, which are issued in order:
- Master Synchronization Telegram (MST)
- Amplifier Telegram (AT)
- Master Data Telegram (MDT)
The first telegram in a communication cycle is the Master Synchronization Telegram (MST). The MST, issued by the controller. It provides a single mark in time for all the drives. All feedback and command data are synchronized for all axes via the MST.
Immediately after the MST is issued, each drive returns feedback and status data in the Amplifier Telegram (AT). This includes position and velocity feedback as well as responses to non-cyclic commands.
The final telegram in the communication cycle is the Master Data Telegram (MDT). The controller issues the MDT. It contains information transmitted from the MC, such as signals and position and velocity commands. The service channel sends signals as well as non-cyclic commands.
Telegram Types
SERCOS provides for a variety of telegram types. Different telegram types define different sets of data to be exchanged in the AT and MDT. There are seven standard telegrams in SERCOS. The simplest telegram is Type 0, which defines only the service channel. No data are transferred in the cyclic data. The most complex type is Telegram Type 7, which allows the user to configure which data are in the cyclic data (all telegrams equally support the service channel.) The other telegrams (Types 1 through 6) define different combinations of position, velocity and current in the AT and MDT. The uses only Telegram Types 5 and 7 for data communication.
Normally, the relies on the SERCOS telegram type 5. In Telegram Type 5, position and velocity feedback are transmitted by the drive in the AT cyclic data, and position and velocity command are transmitted by the MC in the MDT cyclic data. These four components are the only motion data transmitted in the cyclic data. Telegram type 5 works well unless you need to have the external encoder position brought in with the cyclic data. This is necessary when you want to slave an axis to the external encoder In this case, you need to configure a Type 7 telegram.
When you need to bring an external encoder position from a drive to the MC in realtime (cyclic data) you must configure a telegram type 7 for the drive. This telegram must contain all the motion data found in telegram type 5 (position and velocity in both the AT and MDT), with the external encoder position added.
To set up an axis for telegram type 7, you must modify the SERCOSSETUP subroutine, which is generated as part of the BASIC Moves auto setup program. You need to take the following steps:
Set SERCOS.PHASE to 0 and set the baud rateSet the axis PEXTFAC of the axis with external encoderSet the drive addresses (DRIVEADDRESS)Set the axis MASTERSOURCE, GEARRATIO, and slave properties of the slave axisSet Sercos.Phase to 2Configure the axis for Telegram Type 7 using IDN 15Configure the AT for VFB, PFB, and PEXT (IDNs 40, 51, 53)Configure the MDT for VCMD, PCMD (IDNs 36, 47)Set SERCOS.PHASE to 4
See SERCOS Setup Subroutine in Appendix A for a sample subroutine.
Cyclic vs. Non-Cyclic Communication
SERCOS communicates across the fiber-optic ring with two types of data: cyclic and non-cyclic. Cyclic data are sometimes referred to as real-time, and are updated at a regular rate (SERCOS update rate). The system supports update rates from 1 millisecond. The MC requires that the cyclic data include position and velocity command (transmitted from the controller) and position and velocity feedback (transmitted from the drives.) These data must be updated once each SERCOS update.
Non-cyclic data are updated irregularly and on a demand basis via the service channel. The service channel is roughly equivalent to a 9600-baud serial link between the drives and the controller, except that it is transferred on the fiber optic cable along side the cyclic data. Using the service channel, you can request data from the drive or set a parameter that resides in the drive. Each drive has I/O points. You can use the service channel to access this I/O or you can use a Telegram type 7 to configure the I/O as cyclic data. The service channel is non-deterministic. Consequently, non-cyclic data transmits considerably slower than cyclic data.
IDNs
SERCOS commands are organized according to an Identification Number or IDN. SERCOS defines hundreds of standard IDNs, which support configuration and operation. Manufacturers provide IDNs specific to their products. IDNs are numbered. Standard IDNs are from 1 to 32767 (although only several hundred are used to date) and manufacturer IDNs are numbered from 32768 to 65535.
If you are using a drive, you normally use only a few IDNs for special functions (e.g., for querying drive I/O or changing the peak current of a drive).
SERCOS requires that you define every IDN used on each drive. The system eliminates most of this step because the MC automatically defines all necessary IDNs for drives. This process would otherwise be tedious as there are quite a few IDNs that must be defined.
Most requests from the service channel are responded to immediately. For example, when you set the digital-to-analog converter (DAC) on the drive, the value is placed in the DAC by the drive immediately upon receipt. The drive acknowledges the command almost as soon as it is received, thereby freeing the service channel for subsequent commands. However, some functions of the drive that are accessed from the service channel require a much longer time for execution. For example, incremental encoder-based systems must be oriented on power up. The wait for verification that the process has completed successfully can take many SERCOS cycles, far too long to tie up the service channel. To support these functions, SERCOS developed procedures.
With procedures, the master starts a procedure and optionally halts and restarts it. Procedures allow processing in the service channel without blocking other communication. For example, waiting for a registration mark is a procedure. In this case, the motor is turning and the drive is searching for a registration mark. By using a procedure, the service channel remains available for other communication during the search.
Position and Velocity Commands
The MC sends position and velocity commands in the cyclic data, and drives return position and velocity feedback in the cyclic data. This allows you to configure your system as a position or a velocity loop. It also allows you to switch between position and velocity loop on-the-fly. The format of each data type is shown below:
|
|
|
Position Command | 32 Bit | One count |
Position Feedback | 32 Bit | One count |
Velocity Command | 32 Bit | 1/256 count per SERCOS update |
Velocity Feedback | 32 Bit | 1/256 count per SERCOS update |
SERCOS Support
The MC provides numerous commands within the language to support SERCOS.
Sercos.Baudrate for SERCON 410B:
The SERCOS baud rate is set to 2 (2MBits/sec) or 4 (4MBits/sec). The baud rates of all drives must be the same. To control the baud rate on the drive, find the 10-position DIP switch on top of the drive and set the switches according to the following:
Baud rate Sercos.Baudrate Drive, Switch 62 MBits/sec 2 Off4 MBits/sec 4 On
Sercos.Baudrate for SERCON 816:
The SERCOS baud rate is set to 2 (2 M bits/sec) / 4 (4 M bits/sec) / 8 (8 M bits/sec) or 16 (16 M bits/sec). The baud rates of all drives must be the same. To control the baud rate on the drive, find the 10-position DIP switch on top of the drive and set the switches according to the following:
Baud rate Sercos.Baudrate Drive, Switch 6 Drive, Switch 10 2 M bits/sec 2 Off Off 4 M bits/sec 4 On Off
8 M bits/sec 8 Off On
16 M bits/sec 16 On On
Remember that DIP Switch-6 and DIP Switch-10 are read by the drive only on power up. If you change DIP switch-6 or DIP Switch-10, you must cycle power on the drive. Some versions of drives exists SERCON816, but in compatible mode – in this case it equals to SERCON 410B. For checking drive sercon version and mode see drive product number.
For the current SERCON version, query from the terminal with:? System.SERCONversion. It returns:
- 2 For SERCON 410B Version or
- 16 For SERCON 816 Version
Sercos.CycleTime is used to either set or query the SERCOS communications cycle time - rate of updating cyclic data (rate with which to the desired phase of communication (see Cyclic vs. Non-Cyclic Communication). This property is only set in SERCOS communication phases 0, 1, and 2, transferred from the MC to drives during phase 2 and becomes active in phase 3.
sercos.cycletime = 2000 ? sercos.cycletime
Sercos.NumberAxes is used for querying the actual number of SERCOS drives detected on the ring. This value is generated during communication phase 1, when the SERCOS driver scans the ring for drives (or when the the drive addresses are explicitly set)
? sercos.numberaxes
Sercos.Power is used to set or query the SERCOS transmission power. The transmission power is governed by the SERCON interface chip and is set to one of six levels. Setting the power level too high drives the fiber-optic receiver into saturation and causes communication errors. This value should not have to change unless a very long cable is being used (>10 meters). Level 6 is the highest power.
Sercos.power = 3 ? sercos.power
Sercos.Scan indicates to the SERCOS driver whether to scan the ring for drives. If the property is set to a value greater than 0, the ring is scanned during communication phase 1. The scan value indicates the highest drive address for which to scan. For example, if the value is set to 5, the ring is scanned for drives at addresses up to 5.
Sercos.scan = 0 ‘Do not scan the ring Sercos.scan = 5 ‘Scan for drives up to address 5
Set SERCOS.PHASE to the desired phase of communication (see Enabling and Communication Phases). Normally, the command stream outlined in the procedure below is sufficient to bring up the ring. Because it takes time to bring up the SERCOS ring, you may want to speed the process by changing the phase only when it is at some phase other than 4.
Most IDNs have numeric values. After these IDNs are defined, you can read their values with IDNVALUE. To do this, you must specify the drive address, IDN, and the IDN element. For example, you can enter:
? IDNValue{5, 104, 7}
This lists the value of IDN 104, element 7, for the drive at address 5. IDNVALUE is only executed in SERCOS communication phases 3 and 4 as cyclic data, or in phases 2, 3, or 4 via the service channel (some restrictions apply for writing to an IDN). For a complete listing of IDNs supported by the drive, refer to the MC Installation Manual.
IDNs have numeric values and you can write to most of them with the WRITEIDNVALUE command. To do this, specify the drive address, IDN and the value. For example, you can enter:
WriteIDNValue Drive = 5 IDN = 104 value=1
which sets the position loop gain (IDN 104) of drive 5 to 1. WRITEIDNVALUE is executed only in SERCOS communication phases 2, 3 and 4.
Some IDNs have alpha-numeric string values. After these IDNs are defined, you can read the string values with READIDNSTRING. Specify the drive address, IDN, and IDN element. For example, you can enter:
? IDNString(5, 104, 7)
IDNSTRING is used only in SERCOS communication phases 2, 3 and 4.
Some IDNs have alpha-numeric string values. After these IDNs are defined, you can write new string values to most of them with WRITEIDNSTRING. Specify the drive address, IDN and the value. For example, you can enter:
WriteIDNString Drive = 5 IDN = 104 Element = 7 String = IDN String
WRITEIDNSTRING is executed only in SERCOS communication phases 2, 3 and 4.
IDNState returns the state of a specified procedure command from a specified drive. It is used when executing a procedure command to determine progress of that procedure’s execution. Common procedures are 99 (clear faults) and 148 (drive-controlled homing).For example, you can enter:
‘Check how procedure terminated If IdnState(a1.dadd, 99) <> 3 Then Print “Reset Faults procedure failed” End If
For more information about states of this property, refer to the MC Reference Manual.
Use MOTIONLINK to configure and operate the drive. The parameters are stored in the drive, but not in the controller. So, if you need to replace a drive in the field, you must reconfigure that drive with MOTIONLINK.
One benefit of SERCOS is that it allows you to download all drive parameters via the SERCOS link each time you power up. If you need to replace a drive, you do not need to configure it with MOTIONLINK. This is a significant advantage when maintenance people unfamiliar with the design of the system do drive replacement. For this reason, Danaher Motion recommends that you configure your systems to download all parameters on power up. BASIC Moves provides a utility that reads all pertinent IDNs after the unit is configured and the ring is up and stores them in a task you automatically download each power up.
Loops
The system supports three main loop types:
Standard position loop
Dual-feedback position loop
Velocity loop
The MC sends position and velocity commands each SERCOS update cycle. The operation of the MC is hardly affected by the loop selection because the loop selection is made in the drive.
Standard Position Loop
Position loop is the standard operating mode of the system. For position operation, set the position loop gain to a value greater than zero. Typically, you set up the position loop using MOTIONLINK. See the MC Installation Manual for more information.
Dual-feedback Position Loop
Dual-feedback position loop compensates for non-linearity in mechanical systems (inaccuracy from gears, belt drives, or lead screws, or backlash from gears and lead screws). Dual-feedback position loop adds a second feedback sensor (usually a linear encoder) to the system so the load position is directly determined. Unfortunately, the load sensor cannot be the sole feedback sensor in most systems. Relying wholly on the load sensor usually causes machine resonance that severely affects system response. Dual-feedback position loop forms a compromise: uses the load sensor for position feedback (accuracy is critical) and uses the motor sensor for velocity feedback (low compliance required). This is the dual-feedback position loop shown below.
The additional hardware for dual-feedback position loop is a second encoder connected to the drive which is running dual-feedback position loop. You configure the drive for dual-feedback position loop operation using MOTIONLINK. See the MC Installation Manual for more information. The MC does not close the servo loops and is not directly involved in dual-feedback position loop operation. In a sense, the MC is not aware that the drive is operating in dual-feedback position loop. However, when setting up the feedback system, you must configure your units for the external encoder, not the motor feedback device. In addition, you must also tell the MC to monitor the external encoder for position error. This is done with <axis>.FEEDBACK. For example:
A1.Feedback = External 'Set the axis feedback to the load
Velocity Loop
For some applications, the motor must be under velocity loop control. Maintaining a position is not important. The advantage is that the motor is more responsive (typically 3 to 5 times faster in settling time). When you configure an axis for velocity loop, you more or less fool the drive by setting gains to disable the position loop. You need to set the position loop gain to zero and the feed-forward gain to 100%. This produces the following servo loop:
Since a lot of position error can accumulate in velocity loop, it is best to configure the system to have such a large maximum position error that it never realistically generates an error.
Simulated Axes
A simulated axis is an axis that exists only inside the MC. Simulated axes have most of the functions of physical axes including profile generators, units, position and velocity commands and feedback signals, and limits. However, simulated axes do not include a drive, motor or feedback device.
An axis can only be configured as a simulated axis during Sercos.Phase 0 or before SERCOS configuration takes place in CONFIG.PRG or AUTOEXEC.PRG. To set up a simulated axis, set the axis property SIMULATED to ON:
A1.Simulated = ON
This step is inserted in the BASIC Moves auto setup program, in the subroutine, SercosSetup, just after the phase is set to zero. See SERCOS Setup Subroutine in Appendix A for additional details.
Simulated axes require about the same amount of resources from the MC, as physical axes. As a result, simulated axes are part of the total axis count of the controller. For example, a system with three physical axes and one simulated axis requires a four-axis MC. Simulated axes are used in the MC in the same way as physical axes. They are profiled with JOG and MOVE, can be geared and cammed, and can act as masters for geared and cammed axes. Variables from simulated axes such as position feedback can be used to generate events. During operation, the feedback position and velocity are set to their respective command values.
Although most commands and variables for axes work for simulated axes, there are some exceptions. Simulated axes cannot receive SERCOS commands. You cannot set drive variables such as position loop gains in simulated axes.
The units on a simulated axis are flexible. The simplest way to set the units is to set PFAC=1, which can be thought of as 1 simulated unit (eg, 1 meter, 1 inch). Set VFAC to PFAC/1000 for units-per-second or set to PFAC/60000 for units-per-minute such as rpm. Set AFAC to VFAC/1000, such as meters-per-second2. Most axis properties do work with simulated axes, including:
Position properties: command, feedback, finalVelocity properties: command, feedback, cruise, maximumAcceleration and decelerationAcceleration maximum and deceleration maximum
In addition, you can move, jog, gear, and cam simulated axes. The following axis properties do not work with simulated axes:
Position error and velocity error (assume to be zero)Velocity OverspeedTuning parametersExternal position and velocity