Encoder steps.. Issue with returning sprocket to 12 o'clock after precise number of links fed out... again

I posted this in my Holey Calibration thread, but figure I would start a new thread.

I tried to speed up my calibration process and feed out an integral number of links when I reset the chain. With my 12 foot motor mount, I found a distance of 2032 would feed out precisely 320 links (2032/6.35 = 320). Since that’s divisible by 10, the zero tooth should return to 12 o’clock. However, it didn’t. It returned a bit past 12 o’clock. This happened for both motors. When I went to set the chains back to zero, I pressed automatic and the sprocket moved the zero tooth back to 12 o’clock. So, for some reason, 2032 mm isn’t feeding out the correct amount and Maslow knows it’s not where its supposed to be.

Chain tolerance is turned off (it’s not even used in SingleAxisMove routine that is used to feed out the chain. distPerRot is set to 63.5 mm for both left and right motors). The only thing I noticed from the log was that the encoder steps per revolution was reported as $12=8113.73046875 whereas GC reports it as 8113.73. I know when we had an issue last year, it was with the encoder steps value we were using… I think we used 8113.7 (which is still listed as the default in the firmware even though it gets updated by GC). So I think there may be an issue with how the values are sent from GC to the controller and how the controller parses it. I’ve not touched anything regarding encoder steps so not sure why it’s off.

1 Like

I modified the firmware to hardcode it to 8113.73 and now it reports as $12=8113.72998046 (main steps per revolution).

There are some flies on the way that Arduino handles floats and prints them. You’ll find the same situation for every value printed by the $$ command.

I just redid the process with encoder steps hard coded as 8113.73 in the firmware and got the same results. it went a little past 12 o’clock and when I hit automatic on the zero page, it went back to 12 o’clock. Somehow it seems that 2032mm isn’t coming out as 2032mm

This is floating point math in operation, it can’t accurately represent 8113.73,
so it comes ‘close’

we would have to switch the math to use a fixed point library instead of
floating point math to fix this (we probably should due to other issues we are
running into with single precision floating point). We do know from a prior
test that this will slow things down a little bit (the prior test was trying to
do this to speed things up)

David Lang

Well, the hardcoded value of 8113.73 produced the same results… ended a tick past 12 o’clock but would return to zero when the command was issues.

Edit… oh I guess I already posted that.

You might be/likely are hitting the limits of the arduino’s single precision floating point. Maybe isolate the necessary calculations into a small sketch and see if you can duplicate it. Wonder if you can duplicate it on a PC, didn’t look to see if the number of exponent/mantissa bits are the same. Or worse, maybe the Arduino library plays tricks to up the speed; something’s fishy if it beats fixed point

https://www.arduino.cc/reference/en/language/variables/data-types/float/

B09 L2032 turned to 12 o’clock. That’s good news.

I reran the B02 command that feeds out the chain length from GC and at the end, it printed the final location (in the log). It reported 2030.91 mm. This is rather striking since it is supposed to report 2032…

1 Like

I then went to set the sprockets to zero and when I used the automatic command, the program reads the current chain distance and figures out how much to subtract from it to get the zero tooth back to 12 o’clock. Well, when it read it, it read: [Measure: 2032.95] in the log… So first, FW is reporting it short by 1.09 mm when it’s done and then later reports 2032.95 (0.95 mm long). I believe the second value is more correct because the sprocket had rotated too far.

When I do the G09 L2032 command and go to set zero, it reported a distance of 2032.01 mm (can’t complain about being off .01 mm).

So, I think I know what’s up. The originalChainLength (the value that holds how much chain to feed out… my case it’s 2032) is an unsigned int. I think we either have a problem with it getting assigned a float value in settings.cpp (maybe gets rounded down or up?) or a problem when that value is passed to singleAxisMove…

1 Like

void singleAxisMove(Axis* axis, const float& endPos, const float& MMPerMin)

Could it be because with the B02 command, a uint gets passed for endPos (and results in an issue) whereas in a G09 command, a float gets passed (and works)?

I did notice that the MMPerMin in the B02 command is set to maxFeed*0.9 whereas in the G09 L2032 command, a speed of 800 mm/min is used (default return value in firmware subroutine).

So, could a differing speed be the problem?

I modified the firmware to print endPos and it comes out at 2032.00mm as desired. I changed the firmware to use maxFeed*1.0 to see if it results in a difference and it didn’t… still overshot.

1 Like

void singleAxisMove(Axis* axis, const float& endPos, const float& MMPerMin)

Could it be because with the B02 command, a uint gets passed for endPos (and results in an issue) whereas in a G09 command, a float gets passed (and works)?

That is one good reason for the difference

I did notice that the MMPerMin in the B02 command is set to maxFeed*0.9 whereas in the G09 L2032 command, a speed of 800 mm/min is used (default return value in firmware subroutine).

So, could a differing speed be the problem?

If you are actually loosing pulses, it would probably happen more at high speed.

David Lang

I’ll look at it more tomorrow… the same command is issued (singleAxisMove) and it looks as if the same values are sent to it… but the results differ. The only difference I see (assuming the controller is in relative mode, which I believe it is) is that the B09 command reads the axis and then adds the distance to it whereas the B02. just sends the distance (I guess because it assumes the axis is at zero). If the axis has just been zero’ed, then shouldn’t axis report zero when read?

1 Like

I’ll stop spamming for the night.
I modified the firmware to report the values in singleAxisMove. For both commands, the values were identical:

endPos = 2032.00
moveDist = 2032.00 (hence startingPos = 0.0)
MMperMin = 800
stepSizeMM = 0.13

I’m a bit dumbfounded why the results are different. The main difference I see with the B02 behavior is at the end, the axis read reports a value less than 2032 but it actually overshoots 2032 and the firmware knows it because when the axis is read later, its shown to be greater than 2032.

This is very interesting, I am excited to see what you learn. I don’t have anything to contribute other than that everything you said seems logically sound and I agree that both commands should have the same behavior under those conditions. I agree that it sounds like a software bug to me.

Just wish I could find it. Nothing is making sense. The fact that an axis.read happens after the singleAxisMove reports a value less than the target distance but one that happens a little later (when you go to automatically reset the sprockets) reports a distance that is greater than the target … and representative of actually where the sprocket is.

I would say it doesn’t matter since the controller truly knows how long the chain is and that’s what matters. But if there’s a glitch here, I just get worried there’s a glitch somewhere else that results in overshooting the target during a cut (out of round circles, for instance). I’d say it might be because the distance moved is so high (2032 mm) in the singleAxisMove, but issuing a B09 for the same distance works fine… It’s baffling.

I guess one question I have is this isolated to something in my setup?

1 Like

Here’s the logs. First I did an set zero on the sprockets (I had already did auto adjustment to 12 o’clock), followed by an adjust left chain. The brackets variables indicate the print statements I added to report the variables of singleAxisMove.

Sent: B06 L0 R0
B06 L0 R0
Setting Chain Lengths To:
Left: 0.00mm
Right: 0.00mm
ok
Sent: B02 L1 R0
B02 L1 R0
Measuring out left chain
2032.00mm [endPos]
800.00mm [MMPerMin]
2032.00mm [moveDist]
15239steps [finalNumberOfSteps]
0.13mmpermin [stepSizeMM]
2030.67mm [value reported from axis.read at end of calibrate chain lengths]

Then I did another automatic and set zero. The error from 12 o’clock was 1.17 mm

Sent: B10 L
B10 L
ok
Sent: B10 R
B10 R
ok
Sent: G91
G91
ok
Sent: B09 L-1.17
B09 L-1.17

2032.00mm [endPos]
800.00mm [MMPerMin]
-1.17mm [moveDist]
8steps [finalNumberOfSteps]
-0.13mmpermin [stepsizeMM]
ok
Sent: B09 R-0.0
B09 R-0.0
ok
Sent: G90
G90

Sent: B06 L0 R0
B06 L0 R0
Setting Chain Lengths To:
Left: 0.00mm
Right: 0.00mm
ok
Message: Notice: Exiting the calibration process early may result in incorrect calibration.Sent: ~
ok

finally, sent a B09 L2032:

Sent: B09 L2032
B09 L2032
2032.00mm [endPos]
800.00mm [MMPerMin]
2031.94mm [moveDist]
15239steps [finalNumberOfSteps]
0.13mmpermin [stepSizeMM]

this time, there error was only 0.01 mm

If there isn’t any rounding going on with how the variables are being reported to the log, it makes no sense for the same values to provide differing results.

1 Like

I figured out how to print out more digits and the numbers are truly identical. stepSizeMM is 0.1333333333.

2 Likes

Well, I’m moving on from this since I can’t figure it out. I’ve changed GC to do a B09 command instead:

chainLength = App.get_running_app().data.config.get(‘Advanced Settings’, ‘chainExtendLength’) self.data.gcode_queue.put(“B09 L”+str(chainLength)+" R0 ")

1 Like

I find that B02 comes up short on my setup too. B09 is quite accurate.

1 Like