Yes, it’s symmetrical. I used the cal routine to get the zero tooth back to tdc, exited out of it, wiped eeprom, issue the L635 and the zero tooth went a little past tdc (not as much as the first time though…sigh). I issued L0 and it retracted back to tdc.

I did it one more time with the left motor and it repeated to the same position and the right motor had gone to the same amount of “error” as the left. I’m just eyeballing it, but they look close. Not sure if there was something wrong with the first time.

The code to extend 635mm is B09 L635 and the code to retract is B09 L0.

Interesting, I’ll try to repeat it here in an hour or so. Is the error cumulative? Does it double if you go twice as far, halve if half as far? Can you measure the actual amount it is off?

1270mm distance puts the zero tooth about twice as far past tdc. I measure 1277mm of chain being fed. If I divide 1277mm/1270mm and multiply what maslow measured my motor spacing to be (2888.6mm) I get 2904mm… which is practically what I measured the motor spacing to be (2905mm)

Please wxcuse the “newbiness”, but… As the left motor unwinds chain, does the point at which the chain becomes tangent to the sprocket (i.e. is no longer wrapping around the sprocket) change?
I haven’t delved into how GC calculates chain length, but does it account for the fact that chain length will change depending on how far the chain wraps around the sprocket, even if the motor does not move even a single step?

Thanks to the efforts of @rjon17469 , PR #492 in GC and PR #337 in Firmware bring this to triangular Kinematics in the Firmware and the Simulator. Thanks @rjon17469! Load it up and take it for a spin.

Digging into the code to look for potential sources of error (namely rounding) I see this is called:

void Axis::write(const float& targetPosition){
// Ensure that _pidSetpoint is equal to whole number of encoder steps
float steps = (targetPosition/_mmPerRotation) * _encoderSteps;
steps = steps * 2;
steps = round(steps);
steps = steps /2;
_pidSetpoint = steps/_encoderSteps;
return;
}

I don’t see how this routine accomplishes what the comment wants (ensure that the _pidSetPoint is equal to a whole number of encoder steps) Multiplying a floating point number by 2, rounding it and then dividing it by two will result in either a whole number or one that ends in .5.

Regardless, if calculating _pidSetpoint is how the controller ultimately tells the motor where to turn, the round function there will introduce error.

I’m issuing a manual command that, I think, results in a singleAxisMove that appears to just reel out the chain a set distance. There’s no specific x,y coordinate being moved to, so there should be no calculation of how much chain is wrapped around the sprocket.

Does it seem like the error would be reversible, like you observed? It would be a pretty easy change to try.
I got sidetracked on this issue looking for a way to accurately measure the chain payed out, and I’ve found that one of my chains seems to be stretched, about 1.4mm in 2600mm. I ran out of time to dig deeper, but an interesting thing anyway.

Is there a way to write something to backup and restore the eeprom from a command line? I suspect A- something randomly corrupts some of the values, B- a write is missed. I’m a problem solver, not a Python programmer. I’m willing to learn.

There should be a .1 per link difference. I support the scientific method. Do you have a pen/pencil mount for your router or sled? Try running calibration twice, running a g-code file in between same original position of origin. Measure any variance in X & Y, Roll back and Repeat. I’ve seen your posts, you so know what your doing. My the force be with you.

I created a branch that implemented both calculation sets in parallel, they came up with the same values. I had a PR ready with the other calculation, but now it’s not necessary. Many ways to skin that cat
Did this calculation method seem reasonable to you?

Well, I haven’t calibrated it yet because I can’t get an accurate measurement of motor spacing so I haven’t gotten the machine to “run” again.

I kept going back to that code I posted with the round function, but it appears sometimes you “gain” some on the rounding and other times you “lose” some, so it all seems to average out in the end.

Will attempt more troubleshooting tomorrow. Will roll back to the previous version that didn’t include the PID controller changes and see if I get any different result…

Hmmm… this morning I downloaded firmware 1.00 as the latest release… now it looks like its 0.99… maybe a rollback?

yes, but as you unwind only the left chain, the sled moves in an arc around the right sprocket (because the right chain is a fixed length and therfore acts as the radius of that arc). In doing so, the sled is unwrapping the left chain from the left sprocket (i.e. the point of tangency between left chain and left sprocket is moving closer and closer to the 12o’clock position). This effect adds a bit more chain to the chain length that your G code command unwinds, hence you end up with a longer chain than you specified in the G code.

The latest firmware release is v0.99. The development master is at v1.00, and you might have grabbed that to match the GC development master v1.00. No rollbacks at present

In the rounding logic, there doen’t seem to be an advantage to ensuring that Steps is set to a whole number of encoder steps… that doesn’t really do anything. What we should be looking for is that the output of the PID loop be rounded to the nearest number of whole encoder steps. That output is what’s used to govern motor motion, and it would be more stable (and better controlled accuracy) if it was whole number of steps.

(I also hope the round() function in the code above simply truncates rather than rounds up or down otherwise the logic will give inaccurate results…but that’s another discusiion. I can go look up the function reference myself).