Command line examples are presented in bold typewriter
font. Responses from the computer will be in typewriter font.
As of early 2006, there are no longer commands that require root privileges,
so all examples will be preceded by the normal user prompt, $.
Text inside square brackets [like-this] is optional. Text
inside angle brackets <like-this> represents a field that
can take on different values, and the adjacent paragraph will explain
the appropriate values. Text items separated by a vertical bar means
that one or the other, but not both, should be present. All command
line examples assume that you are in the emc2/ directory,
and you configured/compiled emc2 for the run-in-place scenario. Paths
will be shown accordingly when needed.
All HAL entities are accessed and manipulated by their names, so documenting
the names of pins, signals, parameters, etc, is very important. HAL
names are a maximum of 41 characters long (as defined by HAL_NAME_LEN
in hal.h). Many names will be presented in a general form, with text
inside angle brackets <like-this> representing fields that
can take on different values.
When pins, signals, or parameters are described for the first time,
their names will be preceeded by their type in (SMALL CAPS)
and followed by a brief description. A typical pin definition will
look something like these examples:
At times, a shortened version of a name may be used - for example
the second pin above might be referred to simply as .output
when it can be done without causing confusion.
- (BIT) parport.<portnum>.pin-<pinnum>-in -
The HAL pin associated with the physical input pin <pinnum>
on the 25 pin D-shell connector.
- (FLOAT) pid.<loopnum>.output - The output
of the PID loop.
General Naming Conventions
Consistent naming conventions would make HAL much easier to use. For
example, if every encoder driver provided the same set of pins and
named them the same way it would be easy to change from one type of
encoder driver to another. Unfortunately, like many open-source projects,
HAL is a combination of things that were designed, and things that
simply evolved. As a result, there are many inconsistencies. This
section attempts to address that problem by defining some conventions,
but it will probably be a while before all the modules are converted
to follow them.
Halcmd and other low-level HAL utilities treat HAL names as single
entities, with no internal structure. However, most modules do have
some implicit structure. For example, a board provides several functional
blocks, each block might have several channels, and each channel has
one or more pins. This results in a structure that resembles a directory
tree. Even though halcmd doesn't recognize the tree structure, proper
choice of naming conventions will let it group related items together
(since it sorts the names). In addition, higher level tools can be
designed to recognize such structure, if the names provide the neccessary
information. To do that, all HAL modules should follow these rules:
- Dots (``.'') separate levels of the heirarchy. This is analogous
to the slash (``/'') in a filename.
- Hypens (``-'') separate words or fields in the same level of the
- HAL modules should not use underscores or ``MixedCase''. typeset@protect
Underscores have all been removed, but there are still a few instances
of mixed case, for example ``pid.0.Pgain'' instead of ``pid.0.p-gain''.
- Use only lowercase letters and numbers in names.
Hardware Driver Naming Conventionstypeset@protect
Most drivers do not follow these conventions as of version 2.0. This
chapter is really a guide for future development.
Hardware drivers should use five fields (on three levels) to make
up a pin or parameter name, as follows:
The individual fields are:
- The device that the driver is intended
to work with. This is most often an interface board of some type,
but there are other possibilities.
- It is possible to install more than one
servo board, parallel port, or other hardware device in a computer.
The device number identifies a specific device. Device numbers start
at 0 and increment.typeset@protect
Some devices use jumpers or other hardware to attach a specific ID
to each board. Ideally, the driver provides a way for the user to
specifically say ``device-num 0 is the board with ID XXX'', and
the device numbers always start at 0. However at present some drivers
use the board ID directly as the device number. That means it is possible
to have a device number 2, without a device 0. This is a bug and will
be fixed in version 2.1.
- Most devices provide more than one type of
I/O. Even the simple parallel port has both digital inputs and digital
outputs. More complex boards can have digital inputs and outputs,
encoder counters, pwm or step pulse generators, analog-to-digital
converters, digital-to-analog converters, or other unique capabilities.
The I/O type is used to identify the kind of I/O that a pin or parameter
is associated with. Ideally, drivers that implement the same I/O type,
even if for very different devices, should provide a consistent set
of pins and parameters and identical behavior. For example, all digital
inputs should behave the same when seen from inside the HAL, regardless
of the device.
- Virtually every I/O device has multiple channels,
and the channel number identifies one of them. Like device numbers,
channel numbers start at zero and increment.typeset@protect
One glaring exception to the ``channel numbers start at zero''
rule is the parallel port. Its HAL pins are numbered with the corresponding
pin number on the DB-25 connector. This is convenient for wiring,
but inconsistent with other drivers. There is some debate over whether
this is a bug or a feature. If more than one device is installed, the channel numbers on additional
devices start over at zero. If it is possible to have a channel number
greater than 9, then channel numbers should be two digits, with a
leading zero on numbers less than 10 to preserve sort ordering. Some
modules have pins and/or parameters that affect more than one channel.
For example a PWM generator might have four channels with four independent
``duty-cycle'' inputs, but one ``frequency'' parameter that
controls all four channels (due to hardware limitations). The frequency
parameter should use ``0-3'' as the channel number.
- An individual I/O channel might have
just a single HAL pin associated with it, but most have more than
one. For example, a digital input has two pins, one is the state of
the physical pin, the other is the same thing inverted. That allows
the configurator to choose between active high and active low inputs.
For most io-types, there is a standard set of pins and parameters,
(referred to as the ``canonical interface'') that the driver should
implement. The canonical interfaces are described in chapter .
- - the position output of
the third encoder channel on the first Motenc board.
- - the state of the fourth digital input
on the first Servo-to-Go board.
- - the carrier frequency
used for PWM channels 0 through 3.
Hardware drivers usually only have two kinds of HAL functions, ones
that read the hardware and update HAL pins, and ones that write to
the hardware using data from HAL pins. They should be named as follows:
- The same as used for pins and parameters.
- The specific device that the function will
- Optional. A function may access all of the
I/O on a board, or it may access only a certain type. For example,
there may be independent functions for reading encoder counters and
reading digital I/O. If such independent functions exist, the <io-type>
field identifies the type of I/O they access. If a single function
reads all I/O provided by the board, <io-type> is not used.typeset@protect
Note to driver programmers: do NOT implement separate functions for
different I/O types unless they are interruptable and can work in
independent threads. If interrupting an encoder read, reading digital
inputs, and then resuming the encoder read will cause problems, then
implement a single function that does everything.
- Optional. Used only if the <io-type>
I/O is broken into groups and accessed by different functions.
- Indicates whether the function reads the
hardware or writes to it.
- - reads all encoders on the first
- - reads the second 8 bit
port on the first generic 8255 based digital I/O board
- - writes all outputs (step generators,
pwm, DACs, and digital) on the first ppmc board
Canonical Device Interfacestypeset@protect
As of version 2.0, most of the HAL drivers don't quite match up to
the canonical interfaces defined here. In version 2.1, the drivers
will be changed to match these specs.
The following sections show the pins, parameters, and functions that
are supplied by ``canonical devices''. All HAL device drivers
should supply the same pins and parameters, and implement the same
Note that the only the <io-type> and <specific-name>
fields are defined for a canonical device. The <device-name>,
<device-num>, and <chan-num> fields are set based
on the characteristics of the real device.
The canonical digital input (I/O type field: digin)
is quite simple.
- (BIT) in - State of the hardware input.
- (BIT) in-not - Inverted state of the input.
- (FUNCT) read - Read hardware and set in
and in-not HAL pins.
The canonical digital output (I/O type field: digout)
is also very simple.
- (BIT) out - Value to be written (possibly
inverted) to the hardware output.
- (BIT) invert - If TRUE, out
is inverted before writing to the hardware.
- (FUNCT) write - Read out
and invert, and set hardware output accordingly.
The canonical analog input (I/O type: adcin). This
is expected to be used for analog to digital converters, which convert
e.g. voltage to a continuous range of values.
- (FLOAT) value - The hardware reading, scaled according
to the scale and offset parameters. Value
= ((input reading, in hardware-dependent units) * scale)
- (FLOAT) scale - The input voltage (or current)
will be multiplied by scale before being output to value.
- (FLOAT) offset - This will be subtracted from the
hardware input voltage (or current) after the scale multiplier has
- (FLOAT) bit_weight - The value of one least significant
bit (LSB). This is effectively the granularity of the input reading.
- (FLOAT) hw_offset - The value present on the input
when 0 volts is applied to the input pin(s).
- (FUNCT) read - Read the values of this analog input
channel. This may be used for individual channel reads, or it may
cause all channels to be read
The canonical analog output (I/O Type: adcout).
This is intended for any kind of hardware that can output a more-or-less
continuous range of values. Examples are digital to analog converters
or PWM generators.
- (FLOAT) value - The value to be written. The actual
value output to the hardware will depend on the scale and offset parameters.
- (BIT) enable - If false, then output 0 to the hardware,
regardless of the value pin.
- (FLOAT) offset - This will be added to the value
before the hardware is updated
- (FLOAT) scale - This should be set so that an input
of 1 on the value pin will cause 1V
- (FLOAT) high_limit (optional) - When calculating
the value to output to the hardware, if value + offset
is greater than high_limit, then high_limit will
be used instead.
- (FLOAT) low_limit (optional) - When calculating
the value to output to the hardware, if value + offset
is less than low_limit, then low_limit will be
- (FLOAT) bit_weight (optional) - The value of one
least significant bit (LSB), in volts (or mA, for current outputs)
- (FLOAT) hw_offset (optional) - The actual voltage
(or current) that will be output if 0 is written to the hardware.
(FUNCT) write - This causes the calculated value
to be output to the hardware. If enable is false, then the output
will be 0, regardles of value, scale, and offset.
The meaning of ``0'' is dependent on the hardware. For example,
a bipolar 12-bit A/D may need to write 0x1FF (mid scale) to the D/A
get 0 volts from the hardware pin. If enable is true, read scale,
offset and value and output to the adc (scale * value)
+ offset. If enable is false, then output 0.
The canonical encoder interface (I/O type field: encoder
) provides the functionality needed for homing to an index pulse and
doing spindle synchronization, as well as basic position and/or velocity
control. This interface should be implementable regardless of the
actual underlying hardware, although some hardware will provide ``better''
results. (For example, capture the index position to +/- 1 count while
moving faster, or have less jitter on the velocity pin.)
The ``index-enable'' pin is bi-directional, and might require
a little more explanation. If ``index-enable'' is False, the index
channel of the encoder will be ignored, and the counter will count
normally. The encoder driver will never set ``index-enable'' True.
However, some other component may do so. If ``index-enable'' is
True, then when the next index pulse arrives, the encoder counter
will be reset to zero, and the driver will set ``index-enable''
False. That will let the other component know that an index pulse
arrived. This is a form of handshaking - the other component sets
``index-enable'' True to request a index pulse reset, and the
driver sets it False when the request has been satisfied.
- (S32) count - Encoder value in counts.
- (FLOAT) position - Encoder value in position
units (see parameter ``scale'').
- (FLOAT) velocity - Velocity in position
units per second.
- (BIT) reset - When True, force counter
- (BIT) index-enable - (bidirectional) When
True, reset to zero on next index pulse, and set pin False.
- (FLOAT) scale - The scale factor used
to convert counts to position units. It is in ``counts per position
unit''. For example, if you have a 512 count per turn encoder on
a 5 turn per inch screw, the scale should be 512*5 = 2560 counts
per inch, which will result in ``position'' in inches and ``velocity''
in inches per second.
- (FLOAT) max-index-vel - (optional) The
maximum velocity (in position units per second) at which the encoder
can reset on an index pulse with +/- 1 count accuracy. This is an
output from the encoder driver, and is intended to tell the user something
about the hardware capabilities. Some hardware can reset the counter
at the exact moment the index pulse arrives. Other hardware can only
tell that an index pulse arrived sometime since the last time the
read function was called. For the latter, +/- 1 count accuracy can
only be achieved if the encoder advances by 1 count or less between
calls to the read function.
- (FLOAT) velocity-resolution - (optional)
The resolution of the velocity output, in position units per second.
This is an output from the encoder driver, and is intended to tell
the user something about the hardware capabilities. The simplest implementation
of the velocity output is the change in postion from one call of the
read function to the next, divided by the time between calls. This
yields a rather coarse velocity signal that jitters back and forth
between widely spaced possible values (quantization error). However,
some hardware captures both the counts and the exact time when a count
occurres (possibly with a very high resolution clock). That data allows
the driver to calculate velocity with finer resolution and less jitter.
There is only one function, to read the encoder(s).
- (FUNCT) read - Capture counts,
update position and velocity.