How it Works
Audience for this section
This section is useful for users two classes of audience
Users that wish to wish to create custom homing sequences from the existing snippets. A deep understanding is not required but will show how the sequences are built up.
Developers wishing to contribute to the project and add their own snippets and / or callback functions. For this, good grasp of the concepts on this page is required.
Generating PLC Code
The output code is generated using a root jinja template called plc.pmc.jinja.
The render is passed a Plc object which has been generated by the definition code. For example, consider the following definition code:
from pmac_motorhome.commands import group, motor, plc
from pmac_motorhome.sequences import home_hsw
with plc(
plc_num=12, controller="GeoBrick", filepath="/tmp/PLC12_SLITS1_HM.pmc",
):
with group(group_num=3):
motor(axis=1)
motor(axis=2)
home_hsw()
Executing the above will create the following structure to be passed to the render.
a
Plc
object which has groups that contains a singleGroup
objectGroup
also has templates which contains a list ofTemplate
objects that represent the sequence of snippets of PLC code to be inserted for the enclosing group.
The templates list is created by the function home_hsw
which is a
sequence of calls to Snippet Functions.
When the Plc context completes Plc.__exit__ is called and this will invoke a render of the root jinja template.
The core of plc.pmc.jinja looks like this:
{# Loop through the Groups in the Plc #}
{% for group in plc.groups %}
{% if group.group_num == 1 %}
if (HomingBackupGroup = 1)
{% else %}
if (HomingBackupGroup = 1 or HomingBackupGroup = {{ group.group_num }})
{% endif %}
and (HomingStatus = StatusHoming or HomingStatus = StatusDebugHoming)
HomingGroup={{ group.group_num }}
;Clear home flags
{% if group.htype != "NOTHING" %}
{{ group.clear_home() }}
{% endif %}
{# Loop through snippet templates in the Group #}
{% for template in group.templates %}
{% if template.function -%}
{{ group.callback(template.function, template.args) -}}
{% else %}
{% include template.jinja_file+'.pmc.jinja' %}
{% endif %}
{% endfor %}
endif
This loops trough all of the groups held by Plc and though each of the snippet templates held by each of those groups. For each templates the jinja file associated with it is included into template, or the callback function is executed with arguments from the template object.
Note that the current group object and current template object are in scope for the included jinja template and thus it will have access to their members e.g. the child jinja template will be able to see template.args.
Included snippet templates may in turn include other templates and in most cases will also include callback functions. The following typical example is the snippet which searches for the home mark.
{% include "debug_pause.pmc.jinja" %}
;---- {{template.args.state}} State ----
if (HomingStatus = StatusHoming or HomingStatus = StatusDebugHoming)
HomingState=State{{template.args.state}}
; Execute the move commands
{{ group.pre if template.args.state == "PreHomeMove" }}
{% if template.args.restore_homed_flags %}
{{ group.restore_home_flags() }} {{ group.set_large_jog_distance(homing_direction=template.args.homing_direction) }}
{% else %}
{{ group.set_large_jog_distance(homing_direction=template.args.homing_direction) }}
{% endif %}
cmd "{{ group.jog_to_home_jdist() }}"
{% include "wait_for_done.pmc.jinja" %}
endif
This jinja template follows these common patterns:
Uses arguments from template.args to insert literals e.g. {{template.args.state}}
Also uses arguments for flow control e.g. {% if template.args.restore_homed_flags %}
Includes further levels of jinja templates e.g. {% include “wait_for_done.pmc.jinja” %}
Calls a callback function in the group object to output a command that actions all of the group’s axes on a single line e.g. {{ group.jog_to_home_jdist() }}
The second level jinja includes are typically used in most snippets. They are:
‘debug pause’ inserts code that will wait for user intervention when in debug (see Homing API).
‘wait for done’ loops while the motors are completing the current move command.
Templates and Functions
Generating PLC Code describes a process that uses several levels of templates and callbacks. Here we will outline those levels separately to make the distinction clear.
The rendering uses a mixture of Jinja Templates and callback functions. The decision as to which is used for each part of the PLC is made on this basis:
Any block of code that can be represented easily in Jinja and might be used more than once goes into its own Jinja template
Occasional variable substitutions and flow control are acceptable in Jinja as long as it is reasonably readable
Where the Jinja would be unreadable we substitute in a callback function to output the relevant code
At present the only callback functions are for lines of PLC code that perform an operation on all axes in a group on a single line (also all axes in a PLC for some cases)
The following headings are in order of hierarchy with the root first.
Root Jinja Template
Template plc.pmc.jinja is the root template. Rendering this template with a Plc object generates the entire PLC. This template may directly use any of the below headings.
The root Jinja Template is rendered automatically when a Plc context ends in the definition code.
Snippet Jinja Templates
These templates are directly included by the root template in its inner loop that iterates over groups’ contents. These templates may directly use any of the following headings.
These templates represent one block of functionality in the PLC and typically take the form of:
Pause for debug if debugging
Setup some axis parameters
Initiate a move of all axes in the group
Wait for all axes to complete the move
Every snippet template has a corresponding snippet function whose name is the same as the jinja file prefix (See Snippet Functions). Calling this function in the context of a Group object causes the snippet to be instatiated in the render.
Further Jinja Templates
Repeated functionality from Snippet Jinja Templates may be implemented in a further template. These templates can use Callback Functions below.
The most common examples are debug_pause.pmc.jinja and wait_for_done.pmc.jinja.
Callback Functions
Callback functions exist in the Plc
class and Group
class. These are
used to output a line of code that operates on all axes in the Plc
or
Group
.
For example The function home()
will output code to
home all the axes in a group. Assumimg the group has axes 1, 2, 3
then the output of the command home()
will look like this:
#1hm #2hm #3hm