Es muy sencillo, en cuatro lineas de HAL code lo tienes.
Te paso mi archivo HAL y si no entiendes algo me lo dices.
# Generated by Pablo Enguita. Grupo Volund S.A
#
http://grupovolund.com/es# loadrt threads name1=pablo period1=40000
loadrt trivkins
loadrt [EMCMOT]EMCMOT base_period_nsec=[EMCMOT]BASE_PERIOD servo_period_nsec=[EMCMOT]SERVO_PERIOD num_joints=[TRAJ]AXES
loadrt probe_parport
loadrt hal_parport cfg="0x378 out "
setp parport.0.reset-time 5000
loadrt stepgen step_type=0,0,0 ctrl_type=p,v,p
loadrt encoder num_chan=1
loadrt pid num_chan=1
addf parport.0.read base-thread
addf stepgen.make-pulses base-thread
addf parport.0.write base-thread
addf parport.0.reset base-thread
addf encoder.update-counters base-thread
addf stepgen.capture-position servo-thread
addf motion-command-handler servo-thread
addf motion-controller servo-thread
addf stepgen.update-freq servo-thread
addf encoder.capture-position servo-thread
addf pid.0.do-pid-calcs servo-thread
# loadrt threads name1=pablo period1=100000
# net spindle-cmd <= motion.spindle-speed-out
# net din-00 => motion.digital-in-00
# net din-01 => motion.digital-in-01
net xstep => parport.0.pin-02-out
setp parport.0.pin-02-out-reset 1
net ystep => parport.0.pin-03-out
setp parport.0.pin-03-out-reset 1
net ydir => parport.0.pin-04-out
net zstep => parport.0.pin-05-out
setp parport.0.pin-05-out-reset 1
net xdir => parport.0.pin-06-out
net zdir => parport.0.pin-07-out
# net din-01 <= parport.0.pin-10-in
# net din-00 <= parport.0.pin-11-in
setp stepgen.0.position-scale [AXIS_0]SCALE
setp stepgen.0.steplen 1
setp stepgen.0.stepspace 0
setp stepgen.0.dirhold 50000
setp stepgen.0.dirsetup 50000
setp stepgen.0.maxaccel [AXIS_0]STEPGEN_MAXACCEL
net xpos-cmd axis.0.motor-pos-cmd => stepgen.0.position-cmd
net xpos-fb stepgen.0.position-fb => axis.0.motor-pos-fb
net xstep <= stepgen.0.step
net xdir <= stepgen.0.dir
net xenable axis.0.amp-enable-out => stepgen.0.enable
setp stepgen.1.position-scale [AXIS_1]SCALE
setp stepgen.1.steplen 1
setp stepgen.1.stepspace 0
setp stepgen.1.dirhold 50000
setp stepgen.1.dirsetup 50000
setp stepgen.1.maxaccel [AXIS_1]STEPGEN_MAXACCEL
# net ypos-cmd axis.1.motor-pos-cmd => stepgen.1.position-cmd
# net ypos-fb stepgen.1.position-fb => axis.1.motor-pos-fb
net ystep <= stepgen.1.step
net ydir <= stepgen.1.dir
net yenable axis.1.amp-enable-out => stepgen.1.enable => pid.0.enable
# Parafernaria made in volund
net ypos-fb axis.1.motor-pos-fb <= encoder.0.position => pid.0.feedback
net ypos-cmd axis.1.motor-pos-cmd => pid.0.command
net ypos-out pid.0.output => stepgen.1.velocity-cmd
# Parametros del PID
setp pid.0.Pgain 15
setp pid.0.Igain 0
setp pid.0.Dgain 0
setp pid.0.bias 0.0
setp pid.0.FF0 0.0
setp pid.0.FF1 0
setp pid.0.FF2 0
setp pid.0.deadband 0.01
setp pid.0.maxoutput 140
#Visualizar encoder en mm
setp encoder.0.position-scale 200
net faseA encoder.0.phase-A
net faseB encoder.0.phase-B
net faseA <= parport.0.pin-11-in
net faseB <= parport.0.pin-10-in
setp stepgen.2.position-scale [AXIS_2]SCALE
setp stepgen.2.steplen 1
setp stepgen.2.stepspace 0
setp stepgen.2.dirhold 50000
setp stepgen.2.dirsetup 50000
setp stepgen.2.maxaccel [AXIS_2]STEPGEN_MAXACCEL
net zpos-cmd axis.2.motor-pos-cmd => stepgen.2.position-cmd
net zpos-fb stepgen.2.position-fb => axis.2.motor-pos-fb
net zstep <= stepgen.2.step
net zdir <= stepgen.2.dir
net zenable axis.2.amp-enable-out => stepgen.2.enable
net estop-out <= iocontrol.0.user-enable-out
net estop-out => iocontrol.0.emc-enable-in
loadusr -W hal_manualtoolchange
net tool-change iocontrol.0.tool-change => hal_manualtoolchange.change
net tool-changed iocontrol.0.tool-changed <= hal_manualtoolchange.changed
net tool-number iocontrol.0.tool-prep-number => hal_manualtoolchange.number
net tool-prepare-loopback iocontrol.0.tool-prepare => iocontrol.0.tool-prepared
---------------------------------------------------------
Este sistema solo tiene hecho el lazo cerrado en el eje Y. Los demas actuan en pulso direccion sin retroalimentacion de posicion.
Un saludo.