Help with Arduino idexer

Home Model Engine Machinist Forum

Help Support Home Model Engine Machinist Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.
https://photos.app.goo.gl/Pow7kkDphG3jxf5r8[/URL [/URL

One thing you might want to try for my 21 division version ist to change the i=0 to i=1 in the void rotation section. I think I made a mistake. The zero is doing one step.
(that will damage the function for the even divisions. Just to check the correction once. Because I see now that it shows 763 steps on the video.

To how many steps per revolution did you set on the stepper driver now? as per video 400 ?
The motor shoud rotate 20 full turns, when the display shows 360°.

I see 763 steps on the display, which results in 1/2° on the rotary table, but 40 times more on the motor.

void rotation(float tm, int d, int cut)
{
for(int i = 1; i < tm; i++)
{
digitalWrite(stp, HIGH);
delay(stepdelay);
digitalWrite(stp, LOW);
delay(stepdelay);
}
cut = int(tm);
Remainder= tm-cut;
}

You can also try to set the stepdelay = 1 to stepdelay = 2, just to have a little more "observation time".

Greetings Timo[/url]
 
Last edited:
I apologize that I have not read through the sample code thoroughly, but based on the last post above, here is a suggestion (coming from prior years of working in embedded systems): Don't use floating point at all. Instead, use two integers to hold the required ratio. IOW, work out the math on the basis of integer dividend (stepper pulses per required division) plus integer remainder. As you step through the steps, add in the dividend and remainder to a running count, and whenever the latter crosses a threshold, add an additional pulse and reset the remainder.

A quick glance at Timo's last post suggests that he may be headed in that direction, but I note that the variable tm is still using float. Again, I may be speaking out of turn for not having read through this thoroughly, and don't have the time to do so right this minute, so my suggestion above may be as clear as mud ... but in general, if you need something to come out to a specific whole number (e.g., if you need 16000 stepper pulses for one complete revolution), you will never be absolutely sure of avoiding a rounding error if you use floating point. Use integers throughout, and you will gain speed as well as accuracy.
 
One thing you might want to try for my 21 division version ist to change the i=0 to i=1 in the void rotation section. I think I made a mistake. The zero is doing one step.
(that will damage the function for the even divisions. Just to check the correction once. Because I see now that it shows 763 steps on the video.

To how many steps per revolution did you set on the stepper driver now? as per video 400 ?
The motor shoud rotate 20 full turns, when the display shows 360°.

I see 763 steps on the display, which results in 1/2° on the rotary table, but 40 times more on the motor.

void rotation(float tm, int d, int cut)
{
for(int i = 1; i < tm; i++)
{
digitalWrite(stp, HIGH);
delay(stepdelay);
digitalWrite(stp, LOW);
delay(stepdelay);
}
cut = int(tm);
Remainder= tm-cut;
}

You can also try to set the stepdelay = 1 to stepdelay = 2, just to have a little more "observation time".

Greetings Timo[/url]
I am totally amazed! It works really good now. I tested it on many different divisions (odd ones & even) and my dial indicator comes up on "Zero" after a full 360 degree rotation. I noticed that the steps counter always reads + 1 from what the controller is actually moving?? 20 Division = 801 instead of really 800. Thank-you for your help with this!
 
Last edited:
I apologize that I have not read through the sample code thoroughly, but based on the last post above, here is a suggestion (coming from prior years of working in embedded systems): Don't use floating point at all. Instead, use two integers to hold the required ratio. IOW, work out the math on the basis of integer dividend (stepper pulses per required division) plus integer remainder. As you step through the steps, add in the dividend and remainder to a running count, and whenever the latter crosses a threshold, add an additional pulse and reset the remainder.

A quick glance at Timo's last post suggests that he may be headed in that direction, but I note that the variable tm is still using float. Again, I may be speaking out of turn for not having read through this thoroughly, and don't have the time to do so right this minute, so my suggestion above may be as clear as mud ... but in general, if you need something to come out to a specific whole number (e.g., if you need 16000 stepper pulses for one complete revolution), you will never be absolutely sure of avoiding a rounding error if you use floating point. Use integers throughout, and you will gain speed as well as accuracy.
Hello, thank you for entering the discussion.
That might make sense, just have to understand the concept a little better.
Just started today looking into this code for the first time and trying to figure out a good way to handle division and remainder in a good way.
Now Mike reports the "bodge code" I made works? So that is good and not so good at same time.

@Mike: Happy to hear that works now. What did you change, only used the loop from 1 instead of zero or also slow down the pulses?

Maybe I will try to play around with suggestions from Andy.


Greetings Timo
 
Last edited:
I am totally amazed! It works really good now. I tested it on many different divisions (odd ones & even) and my dial indicator come up on "Zero" after a full 360 degree rotation. I noticed that the steps counter always reads + 1 from what the controller is actually moving?? 20 Division = 801 instead of really 800. Thank-you for your help with this!
Another thing that I discovered is that I need to do reset before each test & zero out my indicator at the starting point
 
Another thing that I discovered is that I need to do reset before each test & zero out my indicator at the starting point
I would like to leave it at that for today :cool:, I think the remainder is not properly put back to zero by the keyboard actions for all scenarios.
I hope you can proceed with what you were trying to do as is. Still I suggest you change the resolution a bit finer on the motor. (it will slow down the things)
If I will have any better version (no promise) I will post it here.

Greetings Timo
 
Hello, thank you for entering the discussion.
That might make sense, just have to understand the concept a little better.
Just started today looking inot this code for the first time and trying to figure out a good way to handle division and remainder in a good way.

Greetings Timo

I am totally amazed! It works really good now. I tested it on many different divisions (odd ones & even) and my dial indicator comes up on "Zero" after a full 360 degree rotation. I noticed that the steps counter always reads + 1 from what the controller is actually moving?? 20 Division = 801 instead of really 800. Thank-you for your help with this!
I reset the driver to 800 steps & updated the sketch accordingly. It still works great & runs at a more reasonable speed now. Thanks again!
 
I apologize that I have not read through the sample code thoroughly, but based on the last post above, here is a suggestion (coming from prior years of working in embedded systems): Don't use floating point at all. Instead, use two integers to hold the required ratio. IOW, work out the math on the basis of integer dividend (stepper pulses per required division) plus integer remainder. As you step through the steps, add in the dividend and remainder to a running count, and whenever the latter crosses a threshold, add an additional pulse and reset the remainder.

A quick glance at Timo's last post suggests that he may be headed in that direction, but I note that the variable tm is
still using float. Again, I may be speaking out of turn for not having read through this thoroughly, and don't have the time to do so right this minute, so my suggestion above may be as clear as mud ... but in general, if you need something to come out to a specific whole number (e.g., if you need 16000 stepper pulses for one complete revolution), you will never be absolutely sure of avoiding a rounding error if you use floating point. Use integers throughout, and you will gain speed as well as accuracy.
Thanks for looking at this. It is working good now. Timo made some changes to the sketch & now the missing steps have been added into the code.
I would like to leave it at that for today :cool:, I think the remainder is not properly put back to zero by the keyboard actions for all scenarios.
I hope you can proceed with what you were trying to do as is. Still I suggest you change the resolution a bit finer on the motor. (it will slow down the things)
8

Greetings Timo
 
Taxing my memory somewhat, but I think I solved this problem with mine by using integer division, and more importantly, by doing each tooth calculation from scratch. Thus no accumulated error. But I am going back quite a few years now, so I could be remembering wrong.
 
Taxing my memory somewhat, but I think I solved this problem with mine by using integer division, and more importantly, by doing each tooth calculation from scratch. Thus no accumulated error. But I am going back quite a few years now, so I could be remembering wrong.
I know there have been several years of discussion about building a digital dividing head using a Arduino on HMEM. I think I read every post at least twice over the last few days. I started out with a Arduino Sketch that was written in 2015, it had a few bugs in it. Chuck Fellows (passed away now) had made revisions to the code that fixed the problem, unfortunately the link to his Sketch isn't available to download anymore. Timo looked at the Sketch I posted yesterday & helped me make it work really good now. There may be a few minor things to tweak, but it works now. Thank for your interest in this project.
 
I know there have been several years of discussion about building a digital dividing head using a Arduino on HMEM. I think I read every post at least twice over the last few days. I started out with a Arduino Sketch that was written in 2015, it had a few bugs in it. Chuck Fellows (passed away now) had made revisions to the code that fixed the problem, unfortunately the link to his Sketch isn't available to download anymore. Timo looked at the Sketch I posted yesterday & helped me make it work really good now. There may be a few minor things to tweak, but it works now. Thank for your interest in this project.
Might I suggest posting the good, working sketch somewhere/in the download files section, so it's available as the original seems to be gone?
 
Thanks for looking at this. It is working good now. Timo made some changes to the sketch & now the missing steps have been added into the code.
If it ain't broke, don't fix it! :) But since I have a bit more time today, I'll sketch out below what I mean by using integers only - in case the need arises for either more speed or more accuracy in the future.

First, let's illustrate the potential problem. Suppose you have a stepper motor with 200 steps per revolution, driving a dividing head with a 40:1 worm gear. This setup will need 8000 steps on the stepper motor (200 x 40) to make a single complete revolution of the dividing head. This is the number we need to get back to every time - not 8001, not 7999, or else we will start to drift further and further away from a true 0.

Let's say you want to make a gear with 36 teeth (or 36 evenly spaced holes in a plate, or 36 sides, or any other evenly spaced feature). You will need to step the motor by 8000 / 36 steps for each tooth. But 8000 / 36 = 222.2222222 .... note that this number repeats forever, but our calculators and computers have definite limits on the precision they can keep.

Let's suppose our micro-controller is using the equivalent of 222.22 - rounded to two decimal places. If we use this 36 times, we get back to our zero point with a total of 36 x 222.22 = 7999.92. Close enough, since this will round up to 8000 - yay! But what if we need 10 passes to cut each tooth or other feature? If we rotate the table 10 times, our count comes out to 36 x 222.22 x 10 = 79,999.2 rather than the desired 80,000 - and now the rounding works against us, and we are a count short.

Honestly, this is still probably "good enough" for most of what we do; after all, there is going to be a single step of "jitter" every time, depending on whether the count rounds up or rounds down. And there are ways to reduce the error - using double precision floating point, or micro-stepping, or using a 90:1 worm gear, or so on. Each of these comes with a cost - loss of speed for double precision; loss of torque for micro-stepping; increase of size or loss of strength (due to having to increase the diameter or use smaller teeth in the worm gear) for a greater worm ratio.

And beyond all of that, this is but one example out of countless possibilities. 36 teeth is pretty benign, but what if you need 37 or 59 or 127 teeth? And we haven't factored in the steadily accumulating error that will result from every floating point addition along the way as we keep track of the movement.

continued in the next post ...
 
Might I suggest posting the good, working sketch somewhere/in the download files section, so it's available as the original seems to be gone?

:) Maybe vk7krj can find his version and is willing to share it?
What was done yesterday is maybe a little of a "bodge repair". I am not to proficient with that stuff, and I guess it might be not good enough.
If it ain't broke, don't fix it! :) But since I have a bit more time today, I'll sketch out below what I mean by using integers only - in case the need arises for either more speed or more accuracy in the future.

First, let's illustrate the potential problem. Suppose you have a stepper motor with 200 steps per revolution, driving a dividing head with a 40:1 worm gear. This setup will need 8000 steps on the stepper motor (200 x 40) to make a single complete revolution of the dividing head. This is the number we need to get back to every time - not 8001, not 7999, or else we will start to drift further and further away from a true 0.

Let's say you want to make a gear with 36 teeth (or 36 evenly spaced holes in a plate, or 36 sides, or any other evenly spaced feature). You will need to step the motor by 8000 / 36 steps for each tooth. But 8000 / 36 = 222.2222222 .... note that this number repeats forever, but our calculators and computers have definite limits on the precision they can keep.

Let's suppose our micro-controller is using the equivalent of 222.22 - rounded to two decimal places. If we use this 36 times, we get back to our zero point with a total of 36 x 222.22 = 7999.92. Close enough, since this will round up to 8000 - yay! But what if we need 10 passes to cut each tooth or other feature? If we rotate the table 10 times, our count comes out to 36 x 222.22 x 10 = 79,999.2 rather than the desired 80,000 - and now the rounding works against us, and we are a count short.

Honestly, this is still probably "good enough" for most of what we do; after all, there is going to be a single step of "jitter" every time, depending on whether the count rounds up or rounds down. And there are ways to reduce the error - using double precision floating point, or micro-stepping, or using a 90:1 worm gear, or so on. Each of these comes with a cost - loss of speed for double precision; loss of torque for micro-stepping; increase of size or loss of strength (due to having to increase the diameter or use smaller teeth in the worm gear) for a greater worm ratio.

And beyond all of that, this is but one example out of countless possibilities. 36 teeth is pretty benign, but what if you need 37 or 59 or 127 teeth? And we haven't factored in the steadily accumulating error that will result from every floating point addition along the way as we keep track of the movement.

continued in the next post ...

The zip is what we ended with yesterday. The known issue is that it requires a reset at start in certain conditions (I think the remainder is not zeroed properly in all paths). Because I count the loop in the "void rotation()" from 1 to smaller tm, the LCD is off by one, but not the motor.

Greetings Timo
 

Attachments

  • arduinorotary.zip
    2.2 KB · Views: 0
So the above post illustrates the problem; what is the solution? Let’s see if we can do everything with integers only. Note that even using long integers (64 bits) will be vastly faster on the typical 8-bit microcontroller such as in the basic Arduino. (Less of an advantage on a 32-bit ARM with a floating-point unit, but still integers will be faster.)

So let’s do our math using dividend and remainder. For each tooth on our 36-tooth example, we need to step 8000 / 36 steps, which comes to 222 steps plus a remainder of 8. To say this another way, we will usually need to perform 222 steps per tooth, but 8 times over the 36 teeth, we will need to add an extra step.

There is more than one way to code this, but here is a Q&D version that accomplishes the task:
Code:
long int  steps_per_revolution, n_teeth, steps_per_tooth, remainder, previous_step_count, step_count, remainder_count, n_steps;
int       i;

steps_per_revolution = 8000;     // calculated by the mechanics of the table and stepper motor
n_teeth = 36;                    // set by the user as the desired number of divisions

steps_per_tooth = steps_per_revolution / n_teeth;                // will come out to 222 in this example
remainder = steps_per_revolution - steps_per_tooth * n_teeth;    // will come out to 8 in this example

previous_step_count = 0;
step_count = 0;
remainder_count = 0;

for ( i = 0; i < n_teeth; i++ ) {
    step_count += steps_per_tooth;
    remainder_count += remainder;

    if ( remainder_count >= n_teeth ) {
        step_count++;
        remainder_count -= n_teeth;
    }

    n_steps = step_count – previous_step_count;

    { send n_steps pulses to the stepper motor }
}
 
Last edited:
So the above post illustrates the problem; what is the solution? Let’s see if we can do everything with integers only. Note that even using long integers (64 bits) will be vastly faster on the typical 8-bit microcontroller such as in the basic Arduino. (Less of an advantage on a 32-bit ARM with a floating-point unit, but still integers will be faster.)

So let’s do our math using dividend and remainder. For each tooth on our 36-tooth example, we need to step 8000 / 36 steps, which comes to 222 steps plus a remainder of 8. To say this another way, we will usually need to perform 222 steps per tooth, but 8 times over the 36 teeth, we will need to add an extra step.

There is more than one way to code this, but here is a Q&D version that accomplishes the task:
Code:
long int  steps_per_revolution, n_teeth, steps_per_tooth, remainder, previous_step_count, remainder_count, n_steps;
int       i;

steps_per_revolution = 8000;     // calculated by the mechanics of the table and stepper motor
n_teeth = 36;                    // set by the user as the desired number of divisions

steps_per_tooth = steps_per_revolution / n_teeth;                // will come out to 222 in this example
remainder = steps_per_revolution - steps_per_tooth * n_teeth;    // will come out to 8 in this example

previous_step_count = 0;
step_count = 0;
remainder_count = 0;

for ( i = 0; i < n_teeth; i++ ) {
    step_count += steps_per_tooth;
    remainder_count += remainder;

    if ( remainder_count >= n_teeth ) {
        step_count++;
        remainder_count -= n_teeth;
    }

    n_steps = step_count – previous_step_count;

    { send n_steps pulses to the stepper motor }
}
Hello,

If I multiply the number of steps per revolution, by the tooth count here (j [1..36]), then divide by the total number of teeth by the (Division [36]),
I get the total number of steps from zero to the tooth number j.
The number of steps to send to the subroutine rotation( ToMove ) is total number for tooth number (j) - total number for tooth (j-1).

Code:
void loop() // MAIN LOOP
    {
    for( int j = 1; j<(Division+1); j++)
    {
   moved = ((j-1)*StepsPerRotation*TableRatio)/Division;
   ToMove = (j*StepsPerRotation*TableRatio)/Division - ((j-1)*StepsPerRotation*TableRatio)/Division;
}
}

Greetings Timo
 
Last edited:
Hello,

If I multiply the number of steps per revolution, by the tooth count here (j [1..36]), then divide by the total number of teeth by the (Division [36]),
I get the total number of steps from zero to the tooth number j.
The number of steps to send to the subroutine rotation( ToMove ) is total number for tooth number (j) - total number for tooth (j-1).

Code:
void loop() // MAIN LOOP
    {
    for( int j = 1; j<(Division+1); j++)
    {
   moved = ((j-1)*StepsPerRotation*TableRatio)/Division;
   ToMove = (j*StepsPerRotation*TableRatio)/Division - ((j-1)*StepsPerRotation*TableRatio)/Division;
}
}

Greetings Timo

Yes, that will work as well. That approach does not track the total steps to date, but rather calculates them, and from that calculates the steps needed for the given tooth.

I had a couple of minutes free to work up the attached Excel sheet to show how my previous code would work, and as I was doing it, I realized that I too didn't really need to keep the step_count; I could work solely from the remainder_count to generate either 222 or 223 steps.

If one is needing to speed the code up as much as possible, working only with the remainder_count would allow use of short integers (16 bits), perhaps even down to individual bytes (8 bits) - the remainder is never going to be a number larger than the number of teeth. (Note that this approach would not speed anything up on a 32-bit processor, but would make a difference on an 8-bit Arduino Uno or Nano.)

The approach you have shown above could also possibly fit into 16-bit integers, so long as the steps_per_rotation and table_ratio do not get too large. However, division is always much more "expensive" than addition, so having to divide each time would add a bit of overhead. And of course, I'm probably trying way too hard to speed up what is already fast enough. (Can you tell that I used to work in an environment where we had to count every microsecond?!)

One possible advantage to the approach I showed in the earlier code is that you would have a record of the total number of steps actually taken, so that you could verify coming out exactly right (e.g., 8000 steps back to the zero position). Whether or not that would be a number one would actually want or need to track/report is another matter.

Again, there is always another way to skin the cat, as the saying goes ...
 

Attachments

  • step count example.xls
    13 KB · Views: 0
Yes, that will work as well. That approach does not track the total steps to date, but rather calculates them, and from that calculates the steps needed for the given tooth.

I had a couple of minutes free to work up the attached Excel sheet to show how my previous code would work, and as I was doing it, I realized that I too didn't really need to keep the step_count; I could work solely from the remainder_count to generate either 222 or 223 steps.

If one is needing to speed the code up as much as possible, working only with the remainder_count would allow use of short integers (16 bits), perhaps even down to individual bytes (8 bits) - the remainder is never going to be a number larger than the number of teeth. (Note that this approach would not speed anything up on a 32-bit processor, but would make a difference on an 8-bit Arduino Uno or Nano.)

The approach you have shown above could also possibly fit into 16-bit integers, so long as the steps_per_rotation and table_ratio do not get too large. However, division is always much more "expensive" than addition, so having to divide each time would add a bit of overhead. And of course, I'm probably trying way too hard to speed up what is already fast enough. (Can you tell that I used to work in an environment where we had to count every microsecond?!)

One possible advantage to the approach I showed in the earlier code is that you would have a record of the total number of steps actually taken, so that you could verify coming out exactly right (e.g., 8000 steps back to the zero position). Whether or not that would be a number one would actually want or need to track/report is another matter.

Again, there is always another way to skin the cat, as the saying goes ...
The approach you proposed is probably better with larger step per revolution counts.
The problem is that the "digitalWrite" function of the Arduino is too slow to allow for a reasonable high step frequency, so switching of the pin is the bottle neck here.
The calculation of the steps to move is probably not time critical, it is anyway initiated by a manual button push.


Greetings Timo
 
Sorry guys to be a dunce here, as I am electronically challenged
So is there a way to round off counts and still get back to exactly 360 ?
It sounds like there is no "sure Fire" method
I cut gears manually , but have a Arduino powered Indexing head (80/1) set up
but the old Fellows ( great Guy, rest his soul) program is not working so I need to update
Rich
 
Back
Top