M19 orientation drift with external encoder and orient component (LinuxCNC 2.9.4

More
03 Aug 2026 15:15 - 03 Aug 2026 15:18 #348415 by jelost
Hello,I am trying to configure M19 spindle orientation on LinuxCNC 2.9.4 using the standard orient component.My spindle is driven by an analog servo drive (0–10 V speed command) and direction is selected by a relay (CW/CCW). Because of this hardware, the PID output is converted to an absolute value and the direction is handled separately. The orientation itself works surprisingly well, but I have a strange drift that I cannot explain.Hardware
  • LinuxCNC 2.9.4C10 breakout boardParallel portAnalog servo drive (0–10 V speed reference)External incremental encoder (100 PPR, TTL, A/B/Z)Encoder position-scale = 400 (quadrature)
    encoder.0.position
    increases by exactly 1.0 per spindle revolution
HAL architectureThe orientation chain is:
  • orient
    pid
    mux2
    PID output →
    abs
    Sign handled separately by logic (
    and2
    ,
    or2
    ,
    not
    ) driving the CW/CCW relay.
The relevant HAL section is attached below.What works
  • M3 and M4 work correctly.Rigid tapping (G33.1) works correctly.M19 works mechanically.
The problemBetween different executions of the same G-code program, the spindle zero slowly drifts.1–2 degreesAdditional observationsAfter M19:
  • orient.0.is-oriented
    is always FALSE.
    spindle.0.is-oriented
    is also always FALSE.
    orient.0.poserr
    is typically around 73 degrees.
    orient.0.tolerance = 0.5
    Visually, however, the spindle is correctly oriented.
Signal values:
  • encoder.0.position = spindle.0.revs = orient.0.position
    Position is in revolutions (1.0 per revolution).
Another observationWhile debugging I discovered something unexpected.With the servo drive powered ON (motor stopped), the external encoder produces random A/B/Z pulses.The encoder is even removed from the motor and rotated by hand.If the servo drive is powered OFF, the encoder signals become perfectly clean.This may be a separate EMC issue, but I do not know whether it could also explain the orientation drift.QuestionHas anyone seen a similar behaviour with the
orient
component?In particular:
  • should
    orient.0.is-oriented
    become TRUE after a successful M19?is a
    poserr
    of about 73° compatible with a visually correct orientation?could the drifting reference be caused by the encoder/EMC issue, or is there something wrong in my HAL logic?
Any suggestions would be greatly appreciated.I can provide the HAL file if necessary.Thank you.jelost
Last edit: 03 Aug 2026 15:18 by jelost. Reason: forgotten line

Please Log in or Create an account to join the conversation.

More
03 Aug 2026 16:17 #348418 by PCW
It does sound like the issue is EMI causing miss-counts.

Software read encoder counters are more susceptible to noise
because they do no have a high enough sampling rate to allow
oversampling/ filtering of the A/B/Z signals. This means  that very
short noise pulses on the inputs can result in a miss-count

Possible fixes:

1. Use differential signaling on the A/B/Z  signals and a differential --> single ended converter
to convert the differential signals to the single ended parallel port signals.

2. Use some RC filtering of the A/B/Z signals at the parallel port end of the wiring.
The following user(s) said Thank You: jelost

Please Log in or Create an account to join the conversation.

More
04 Aug 2026 09:13 #348437 by jelost
Hello,
I have a few follow-up questions:
Is it normal for `spindle.0.index-enable` never to switch to TRUE with M19?
Is it normal for `orient.0.is-oriented` to remain FALSE even though the spindle is perfectly oriented?
Under what conditions is `ORIENT_OFFSET` actually used?

Please Log in or Create an account to join the conversation.

More
04 Aug 2026 22:52 - 04 Aug 2026 22:55 #348452 by PCW
I've not used M19 but it looks like the orient component does not use index at all.
 
Though M19 does use index:

"Spindle orientation requires a quadrature encoder with an index to sense the spindle shaft position and direction of rotation."

So I would expect spindle.0.index-enable to be set true at some point.
Last edit: 04 Aug 2026 22:55 by PCW.
The following user(s) said Thank You: jelost

Please Log in or Create an account to join the conversation.

More
05 Aug 2026 02:27 #348454 by Aciera
'orient.N.poserr' must be smaller than 'orient.N.tolerance' for 'orient.N.is-oriented' to go true ('orient.N.tolerance' = 0.5 by default)

Have a look at the man page:
www.linuxcnc.org/docs/html/man/man9/orient.9.html
The following user(s) said Thank You: jelost

Please Log in or Create an account to join the conversation.

More
05 Aug 2026 05:36 - 05 Aug 2026 05:40 #348456 by jelost
Man page Description :
The spindle is assumed to have stopped in an arbitrary position. The spindle encoder position is linked to the position pin. The current value of the position pin is sampled on a positive edge on the enable pin, and command is computed and set as follows: floor(number of full spindle revolutions in the position sampled on positive edge) plus angle/360 (the fractional revolution) +1/-1/0 depending on mode.

Do i understand that with mode 0 offset is 1, with mode 1 offset is -1, with mode 2 offset is 0 ? because during tests i seemed to find these shifts.
Last edit: 05 Aug 2026 05:40 by jelost. Reason: Text modification

Please Log in or Create an account to join the conversation.

More
05 Aug 2026 08:07 - 05 Aug 2026 11:07 #348458 by Aciera
 
linuxcnc.org/docs/devel/html/en/gcode/m-code.html#mcode:m19

I don't think that is correct.  'M19' does NOT seem to set 'spindle.n.index-enable'.
Testesd on real hardware using current master version :

 


 
Attachments:
Last edit: 05 Aug 2026 11:07 by Aciera.
The following user(s) said Thank You: jelost

Please Log in or Create an account to join the conversation.

More
05 Aug 2026 08:25 #348459 by Aciera

Do i understand that with mode 0 offset is 1, with mode 1 offset is -1, with mode 2 offset is 0 ? because during tests i seemed to find these shifts.


That man page info appears to be left over from the original code. This particular logic was then modified some time later without updating the man page info:

github.com/LinuxCNC/linuxcnc/commit/b2cd...919af6524f3b82e3eb33
The following user(s) said Thank You: jelost

Please Log in or Create an account to join the conversation.

More
05 Aug 2026 08:40 #348461 by Aciera
You might want to try 's_orient.comp', this modified version of 'orient.comp' provides an input that is to be connected to your encoder-index signal and will look for the index before orienting the spindle.
forum.linuxcnc.org/media/kunena/attachme...ient_2025-03-18.comp

- download the file and rename to 's_orient.comp'

- to install you need the 'halcompile' tool (you might need to install the 'linuxcnc-dev' package if your are on a package installation of linuxcnc)

- $ halcompile --install {your-path-to-the-file-here}/s_orient.comp
(you will need to use 'sudo' to execute this command on a package installation)
The output should look something like this:
Compiling realtime s_orient.c
Linking s_orient.so
cp s_orient.so /home/user/git/mylinuxcnc-master/rtlib/

- in your hal file change 'loadrt orient {...}' to 'loadrt s_orient {...}' and connect your encoder index signal to the orient component (you might have to modify your pin names to 's_orient')
The following user(s) said Thank You: jelost

Please Log in or Create an account to join the conversation.

More
06 Aug 2026 06:29 #348485 by jelost
Thank you for your detailed answers; i have ordered RS422-TTL converters to try everything out as soon as possible.

Please Log in or Create an account to join the conversation.

Time to create page: 7.217 seconds
Powered by Kunena Forum