Maslow Home Maslow Community Garden

Holey Triangular Calibration


These are my results.

cal.SP_chainOverSprocket=0 I did not know what to set this as so left it default my chain is over the top then down the side

My sled weight is 21lb 14.1Oz. I put this at 22lb because of the vac hose weight. (1.0 KB)

mishle6@openbox:~$ python /home/mishle6/Documents/GroundControlUpdate/
Optimized Errors
Index : 0
Points Span : 1 to 2
Measured Distance : 957.659375
Calibrated Distance: 960.41531595
Distance Error : -2.75594095023
Index : 1
Points Span : 2 to 3
Measured Distance : 957.659375
Calibrated Distance: 959.780032929
Distance Error : -2.12065792933
Index : 2
Points Span : 4 to 5
Measured Distance : 959.64375
Calibrated Distance: 960.413809634
Distance Error : -0.770059634469
Index : 3
Points Span : 5 to 6
Measured Distance : 959.64375
Calibrated Distance: 959.784713788
Distance Error : -0.1409637879
Index : 4
Points Span : 1 to 4
Measured Distance : 703.2625
Calibrated Distance: 703.938865093
Distance Error : -0.676365093027
Index : 5
Points Span : 2 to 5
Measured Distance : 701.675
Calibrated Distance: 703.502821741
Distance Error : -1.82782174126
Index : 6
Points Span : 3 to 6
Measured Distance : 704.05625
Calibrated Distance: 705.036766522
Distance Error : -0.980516522331
Index : 7
Points Span : 2 to 4
Measured Distance : 1191.815625
Calibrated Distance: 1190.21767503
Distance Error : 1.59794997213
Index : 8
Points Span : 1 to 5
Measured Distance : 1193.00625
Calibrated Distance: 1191.05839771
Distance Error : 1.94785229198
Index : 9
Points Span : 3 to 5
Measured Distance : 1194.196875
Calibrated Distance: 1191.91986869
Distance Error : 2.27700631203
Index : 10
Points Span : 2 to 6
Measured Distance : 1189.89230769
Calibrated Distance: 1188.98366025
Distance Error : 0.908647441925

Distance Between Motors:

Motor Y Offset:

Left Chain Tolerance:

Right Chain Tolerance:


I am not sure how to interpret this. I am just going to type as I think.

  • The calibration is better than the first one I got with the TriangularCalibration.
  • Overall, if this accurately represents the quality of the calibration, it might not be all that bad.
  • All your measurements are short in comparison to “Ideal”
    • This could be due to the machine’s starting calibration/setup, or it could be due to your measurements.
  • What concerns me is:
    • The measurements are short, AND the calibration defined a positive left and right chain tolerance.
    • I would think the calibration should go the other way. If all the measurements are short, it should define a negative chain tolerance, so that the controller would feed out more chain.

I am having a difficult time with this one. I would like to see if I can reproduce the result. Then I will get back.


Should I measuring between the holes or from the center to center of the holes


The intent is to measure the distances, center-to-center. The most practical way to do this is to measure to the edges of the holes (left-edge to left-edge) or (right-edge to right-edge) or (top to top) or (bottom to bottom)


that’s what I did the first time but then you put the words in between in the instructions so maybe that needs to be changed to say Center to Center


OK. I will change it. I apologize.


Hi @Joshua
I was reviewing how I get accurate results and it seems the chain stretch factor is possibly one that could be used to tune up the calibration. My value is 8.1x10E-6 m/m/N. It is the only parameter acting on the top workspace edge dip while changing almost no curve on the bottom edge. It is difficult to estimate and I don’t know how variable it is across various chain supplies.
So I summarized my criticality / measurability analysis and decided to bump a (short) zombie thread just to avoid duplicating that topic or otherwise highjack your topic.


OK. I figured out what is going on. On the calibration/code side, everything worked correctly. I would recommend re-measuring the center-to-center distance between the holes, but other than that, everything is OK.

The chain tolerances are implemented in the kinematics.inverse function. They are implemented such that positive chain tolerance results in a shorter chain. This is a mistake, but it is fully functional and valid. The intent was for a positive chain tolerance to correspond to a stretched chain, however it is the other way around in this implementation.

Moving forward, you’ll just have to be careful. If this is switched in a future version, and you update your software, you’ll have to switch these numbers to negative values. If this happens, I will have to do this, and so will @c0derpr1sm.


To me the chain tolerance is a statement of how much the chain is longuer that expected.
So a positive value tells the firmware how much to shrink it so can be used accurately.


That was my interpretation, too. However, it is the opposite in this implementation. This factor is implemented in the kinetics.inverse function. When the firmware calculates the chain-length, a positive tolerance results in a longer requested chain length. This effectively is equivalent to the chain being shorter than it should be.


Indeed, review of the code shows a positive chain tolearnce value increases the effective chain length considered to reach a (x,y) coordinate.

firmware’s Kinematics.cpp lines 244 to 246

And the chain tolerance value is straight what is sent by GroundControl.

firmwarw’s Settings.cpp lines 400 to 405

So the chain tolerance is a statement of how much longer the chain needs to be to really match the chain link nominal length. So a positive value tells the firmware how much to extend the chain length so the deployed length is accurate.


So, this is consistent with the main GC and Firmware branch. I wonder if this is the reason why they were having a difficult time implementing chain-tolerance measurement/calibration a while back, when they originally recognized chain tolerance as a potential source of error. The value they were measuring was effectively negative what was happening in the software.


Wow… I think that’s a great catch. When I worked on it, I was originally just multiplying the chain tolerance by the chain length and my value for chain tolerance was less than 1 (e.g. 0.998743). The original implementation by @bar used a postive small value (e.g. 0.003346) to increase the circumference of the sprocket using the formula you see in the kinematics (i.e., 1+chain tolerance/100)… applying chain tolerance factor to every calculation. When a PR was eventually made so that it was applied only to the straight chain length, I changed my implementation to use the same formula so people’s existing positive small values wouldn’t have to be changed to match my way of using values less than 1, but as you found, the sign of the chain tolerance should have changed from + to -. I think it should be (1-chainTolerance/100) so that it comes out with a number smaller than 1. Mea culpa.

Does everyone agree that the sign should change?


Hi @Joshua
I think tuning chain (elastic) stretch parameter might come into play to reach accurate positions.

Did you consider optimising chain stretch factor in the Holey Triangular Calibration parameter optimisation tool?

ref post 187


My understanding is that because the chain is “stretched” you want to “let out” less chain and therefore you need to reduce the straight chain length. I think the virtually larger sprocket diameter does the same thing… reduces the amount of chain that’s feed out.


:astonished: OUPS! I just realized that my firmware version indeed divides (1+tolerance factor).

Let me apologize and take back this idea of changing the definition.

About chain stretch… I see what you mean.
Now chain manufacturing is not perfectly producing a 6.35mm pitch. That is a manufacturing error expressed by the tolerance parameter.

On the other hand, steel is elastic and stretches under tension. That is a length change depending on chain tension expressed by the chain stretch parameter.
The later is missing in the current MasloCNC firmware.

For an example of possible chain calculation improvement, I invite you to look at this version of Kinnematics.cpp:

  • Starting at line 278 it computes chain stretch correction,
  • Line 291 makes chain tolerance adjustment where I use a parameter meaning (1+tolerance).
  • And starting at line 209, you can review the complete triangular inverse function that I use.


I did consider this. However, the resulting correction is only a few mm in any direction. This magnitude of correction can be difficult to measure with a tape-measure. I put this into the same category as a chain-sag correction factor. In @madgrizzle’s original Holey Calibration, a chain-sag correction factor was included, that calibrated to a sled-weight that was half of what it should be. I struggled with this for a while, but eventually realized that if one of the ~6 ft measurements was just 1mm shorter, the result would have been very different. The elasticity of a part is a function of material properties and part shape. Since both material and shape are largely equivalent for all chains, I thought elasticity would be pretty consistent for all chains. I thought this was best left out of the optimization.

Both of these phenomenon are in my fork of GC and the firmware. I haven’t reviewed your implementation in detail, though.

Collectively, I think we’ve learned quite a bit this weekend.

I am not sure. Since everything is functional, it is not urgent.


I made a PR but instead of changing the sign, I changed the whole terms operator from a * to a /. I think that’s the correct way.


I just realize that @Joshua should also update his firmware because it is the beta test version for holey calibration solution!


I think we are ready to integrate one more Holey Calibration step improvement into the firmware: the chain tension calculation and chain stretch compensation.

I propopse to do it so that users get immediate vertical scale improvement of their center upper workspace. That would at least improve the standard calibration results.

The proposed implementaiton adds 4 slots into the EEPROM table: sled weight and chain stretch would have default values, plus two reserved slots. Bumping EEPROM table to version 6.

This way, a default value is applied, and macros of the type $4X=YY would allow advanced users to tune manually. Then it would be ready for a later update GC to offer GUI based adjustments.

I prepared a firmware version for review before triggering a pull request. I will test it in the coming days. (Arduino IDE compiles fine)

It is based on the current firmware and integrates these specific items from Joshua’s proposal.
Please review and comment.