Possible error in logic of LinuxCNC homing with leadscrew compensation

More
13 Feb 2019 03:29 #126323 by Richard J Kinch
My current project is to automatically characterize leadscrew error and compensate with an automatically generated LinuxCNC COMP_FILE. This has been utterly successful, converting my rough leadscrews from +/- 0.003in positioning errors into +/- 0.0005in repeatability and linearity, including compensation for a sloppy 0.050in of random backlash in the screw and bearing mechanics.

I've gotten everything in place to automatically tabulate leadscrew errors by logging DRO scale readings in a G-code program that moves an axis along stepped locations. The DROs are accurate to 5 microns. I also configured automatic homing of the axis to employ the DRO index, so the homing and error readings are all mutually consistent and automatically repeatable across machine shutdowns, and across characterizing versus compensating startups. Here are plots of the characterization readings:



And the backtested compensation performance:



The backtest plot shows an offset of no consequence; what matters is that the curve maintains an unvarying mean response to commanded position, and the magnitude of random deviations from that unvarying mean. Moving in the opposite direction, though, results in compensated moves that are slightly off. This fault seems to be either in my logic, or LinuxCNC's logic, or possibly a faulty assumption or interaction.

I know the characterization data is accurate, because I backtest it in a separate G-code program that logs errors with my compensation data applied by the G-code values, and no compensation in LinuxCNC. The characterization and backtesting are run with LinuxCNC compensation disabled.

This all works grandly when LinuxCNC is given the compensation characteristic, when moving in the same direction as the LinuxCNC homing approach moved. Moving in the opposite direction, though, is not. I have not been able to find the source of this unexpected behavior.

What I suspect is that LinuxCNC should not be applying compensation during the homing process, but it is. The compensation characteristic is necessarily known from uncompensated configuration, based on an uncompensated home location. If LinuxCNC applies compensation during homing, then that defeats all the predicates of the measurements.

Inspecting the source code from control.c it appears that this is the case. The compensation is loaded before the homing action, and the compensation is applied to all motion from the startup. Thus the homing location is always relatively off from its true physical reference by any non-zero compensation function provided in COMP_FILE at the home coordinate. That would seem to be a logical error in the compensated motion logic. Instead LinuxCNC should disable compensation during homing. As a workaround, I suppose one could rework the COMP_FILE error characteristic function to be zero error at the physical home, but that's a whopping lot of algebra.

Here's the G-code magic that reads and logs uncompensated leadscrew errors, for those that are interested in this facility:
( DRO sampling of axis realized response to motion commands			)
( Creates or appends to file _.log in the configuration directory		)
( RJK 02/2019									)
(										)
( This program requires the LinuxCNC HAL-reading feature, which exposes		)
( realtime HAL values to G-code programs as G-code parameters.  To enable that	)
( feature, before launching LinuxCNC, edit the FEATURES mask in the .ini	)
( configuration file to assert the value 8, or to add 8 to an existing value,	)
( thus:										)
(										)
(   [RS274NGC]									)
(   FEATURES = 8								)

( ----------------------------------------------------------------------------- )
( Manually configure the constants in this section for the desired sampling run	)
( Observe the consistency directed in the comments; this program does not check	)
( the values for consistency.							)
( ----------------------------------------------------------------------------- )
#<_gmin> = -3.875	( Minimum G53 coordinate to be sampled, < _gmax		)
#<_gmax> = 1.375	( Maximum  "       "     "  "     "   , > _gmin		)
#<_samples> = 256	( Number of samples to be taken across the range, >= 2	)
#<_home> = 0.0		( G53 axis home coordinate, _gmin <= _home <= _gmax	)
#<_feedrate> = 6	( Feedrate most practiced in precise stopping, > 0.0	)
#<_dwell> = 0.5		( Seconds of dwell time to settle mechanically, >= 0.0	)
#<_backlash> = 0.050	( Worst-case estimate of backlash magnitude, >= 0.0	)

			( Additional configuration required:			)

			( Change the configuration-dependent "_hal" names below	)
			( to reflect the appropriate HAL pins for the HAL .ini	)
			( configuration of the machine under test for the	)
			( sampled axis.						)

			( To select which axis is sampled instead of X, edit	)
			( each appearance of capital "X" below to the target	)
			( axis.							)

			( To change the output log file name, edit "_.log"	)
			( below.						)

( ----------------------------------------------------------------------------- )
( Subroutine: log the current realtime sampling state and DRO measurement	)
( Format of log file lines emitted:						)
(     <commanded> <actuated> <dro> <diff>					)
( Where:									)
(   <commanded> = the G53 coordinate						)
(   <actuated> = the coordinate actuated by the realtime motion controller	)
(   <dro> = the DRO reading							)
(   <diff> = <actuated>-<dro>, which is the error at the <commanded> location	)
(	This diff value is logged to aid human inspection of raw results and to	)
(	make plotting a log file such as in gnuplot simpler.			)
(										)
( Note: each sample's commanded and actuated values should be identical,	)
(   *unless* a prior backlash value or compensation table is configured into	)
(   HAL, in which case the values will differ by the position-dependent		)
(   interpolated compensation as applied by the realtime motion controller.	)
(   To temporarily turn off such compensation, comment out the BACKLASH or	)
(   COMP_FILE settings in the .ini file configuration, and restart LinuxCNC.	)
(   LinuxCNC may involve other offsetting factors in the actuated motor		)
(   position for a given commanded position, so the actuated value is not	)
(   necessarily significant other than to confirm whether "something", perhaps	)
(   unexpecting, is going on in the motion control.				)
(										)
( All prior compensation must be turned off to read the basic or uncompensated	)
( error characteristic of the mechanism.  Conversely, a compensation table	)
( processed from a reading of the basic error characteristic must be turned	)
( on, and the now-compensated error characteristic read again, to evaluate the	)
( effectiveness of the compensation.						)
(										)
( This program uses G53 moves, which is the machine coordinate system in which	)
( any compensation table is referenced. In short, this works as close to the	)
( "bare metal" as a G-code program can, which is critical to getting valid	)
( and repeatable characterization of the mechanical response and error.		)
( ----------------------------------------------------------------------------- )

o100 sub
g4 p#<_dwell> ( Dwell )
m66 p0 L0 ( Queue-buster with no other effect )
#<commanded> = #1
#<actuated> = #<_hal[xpos-fb]>
#<dro> = #<_hal[sum2.0.out]>
#<diff> = [ #<commanded> - #<dro> ]
(LOG,#<commanded> #<actuated> #<dro> #<diff>)
o100 endsub

( ----------------------------------------------------------------------------- )
( Subroutine: Step the range #1 .. #2 of axis position, logging the experiment	)
( ----------------------------------------------------------------------------- )

o101 sub
#<start> = [ #1 ]
#<end>   = [ #2 ]
o103 if [ #<start> gt #<end> ]
    (LOG,NEGATIVE-GOING)
    #<min> = [ #<end> ]
    #<max> = [ #<start> ]
    #<incr> = [ - #<_step> ]
  o103 elseif [ #<start> lt #<end> ]
    (LOG,POSITIVE-GOING)
    #<min> = [ #<start> ]
    #<max> = [ #<end> ]
    #<incr> = [ + #<_step> ]
  o103 else
    (LOG,NON-GOING)
  o103 endif
#<loc> = [ #<start> ]
o102 while [ 1 ]
  o104 if [ #<loc> gt #<max> ]
    o101 return
    o104 endif
  o105 if [ #<loc> lt #<min> ]
    o101 return
    o105 endif
  g53 g1 f#<_feedrate> X#<loc>
  o100 call [ #<loc> ]
  #<loc> = [ #<loc> + #<incr> ]
  o102 endwhile
o101 endsub

( ----------------------------------------------------------------------------- )
( Main program									)
( ----------------------------------------------------------------------------- )

(LOGAPPEND,_.log)
(LOG,# Axis error sampling)

( Emit all configuration parameters and conditions to the log output, for use	)
( by post-processing programs							)
(LOG,GMIN #<_gmin>)
(LOG,GMAX #<_gmax>)
(LOG,SAMPLES #<_samples>)
(LOG,HOME #<_home>)
(LOG,FEEDRATE #<_feedrate>)
(LOG,DWELL #<_dwell>)
(LOG,BACKLASH_WORST_CASE_ESTIMATE #<_backlash>)

( Provisional step = the step length that integrally divides full range )
#<_step> = [ [ #<_gmax> - #<_gmin> ] / [ #<_samples> - 1] ]
( Adjust step such that one sample will be taken at G53 home, which will maintain )
( phase with any axis compensation table deduced from one-time error readings )
( taken when calibrated to the automatic homing location. )
( Scaffold: we don't handle the case where _home is within a provisional _step )
( away from _gmax )
#<_step> = [ #<_gmax>/FIX[ [ #<_gmax>-#<_home> ]/#<_step> ] ]
( Adjust backlash up to the next integer multiple of the step )
( This keeps the sample locations aligned in both directions )
#<_backlash> = [ FUP [ #<_backlash> / #<_step> ] * #<_step> ]
(LOG,STEP #<_step>)
(LOG,BACKLASH_ADJUSTED #<_backlash>)
#<_logitem1> = [#<_gmax>/#<_step>]
#<_logitem2> = [[#<_gmax>-#<_gmin>]/#<_step>]
(LOG,POSITIVE_INTERVALS #<_logitem1>)
(LOG,OVERALL_INTERVALS #<_logitem2>)

( Starting move to most-positive end )
g53 g0 X#<_gmax>
( Sample the full range in the negative-going direction )
o101 call [ #<_gmax> - #<_backlash> ] [ #<_gmin> ]
( Sample the full range in the positive-going direction )
g53 g1 f#<_feedrate> X[#<_gmin>+#<_backlash>]
o101 call [ #<_gmin> + #<_backlash> ] [ #<_gmax> ]

( Return to G53 home on the sampled axis )
g53 g0 X[#<_home>+#<_backlash>]
g53 g1 f#<_feedrate> X#<_home>

(LOG,# FINISHED)
(LOGCLOSE)
(MSG, DONE)
m30
Attachments:
More
13 Feb 2019 13:48 #126342 by pl7i92
did you also check the switch hystereses
it may trigger not the same point
More
14 Feb 2019 00:55 #126421 by andypugh

Richard J Kinch wrote: What I suspect is that LinuxCNC should not be applying compensation during the homing process, but it is. The compensation characteristic is necessarily known from uncompensated configuration, based on an uncompensated home location. If LinuxCNC applies compensation during homing, then that defeats all the predicates of the measurements.

Inspecting the source code from control.c it appears that this is the case. The compensation is loaded before the homing action, and the compensation is applied to all motion from the startup.


That's an interesting observation, and might warrant raising as an issue in the issue tracker:
github.com/LinuxCNC/linuxcnc/issues
Time to create page: 0.096 seconds
Powered by Kunena Forum