Notifications
Clear all

Stepper acceleration

Page 2 / 2

Will
 Will
(@will)
Reputable Member
Joined: 3 months ago
Posts: 368
 

Why not simplify the whole thing by using step counts instead of angles in the first place ? For instance 45 degrees is 25 steps and 270 degrees is 150 steps. If you convert all of the required positions into steps (or the closest integer) then all you need to do is move by steps from one location to the other.

That way to move from 45 degrees to 270 degrees means moving from 25 steps to 150 steps, so the calculations becomes: move (150-25) = 125 steps.

The stepper can only move in steps, so why not use that as the basis ? You'll only need to convert the angles into steps and define them once as literals.

 

But also keep in mind davee's warning about choosing the right data type. It WILL come back to bite you eventually.


ReplyQuote
robotBuilder
(@robotbuilder)
Prominent Member
Joined: 2 years ago
Posts: 883
 

@will

Why not simplify the whole thing by using step counts instead of angles in the first place

I actually suggested this and used it in my own version in the original thread.

https://forum.dronebotworkshop.com/help-wanted/questions-about-changing-to-array-from-buttons/paged/7/#post-18412

Still any budding C++ programmer does need to understand how numbers are represented.

 


ReplyQuote
Will
 Will
(@will)
Reputable Member
Joined: 3 months ago
Posts: 368
 

@robotbuilder

Sorry to plagiarize, I didn't realize that this was a continuation of that thread.


ReplyQuote
robotBuilder
(@robotbuilder)
Prominent Member
Joined: 2 years ago
Posts: 883
 

@will

You didn't plagiarize you just had the same idea, brilliant minds think alike 🙂 

This isn't a continuation of the same thread just a continuation of Gam's project in a new thread.

 

 

This post was modified 2 months ago by robotBuilder

ReplyQuote
DaveE
(@davee)
Estimable Member
Joined: 4 months ago
Posts: 138
 

Hi @gam,

 Sorry this is turning out to be a 'heavy' session on a tiny point.

I should also like to emphasise that I haven't analysed your program generally, it was just a case of glancing down and seeing a 'howler' glaring at me ... and from bitter experience, I know how hard they can be to find when you have a program that just won't play nicely.

So without judging your program as whole, this reply just homes in on the specific point... as it happens you effectively set yourself a bear trap to fall into, but then "fortunately" walked around it!!

The fragment of code that could be affected is:

n = ((na - ca) * 5 / 9);

(and also the rather similar line in 2nd Scenario)

You will notice that your line uses '5 / 9' explicitly, even though you had already declared yourself a handy variable:

  int stepPerAngle = 5 / 9; // full step = 1.8 or could have used "*1.8"

In 'normal' circumstances, declaring something like this would be good practice, since numbers like the 5 or the 9 might need to be changed, and it is much better to just declare them in one place, so any modifications are easy. Also, if you use stepPerAngle instead of '5 / 9', then the division only has to be done once, not every time stepPerAngle is used.

So your above program line 'should' simplify to:

n = ((na - ca) * stepPerAngle);

However, if you had done this, it would have stopped working!! 'n' would always be zero, because stepPerAngle is itself zero!

............

So why does   n = ((na - ca) * 5 / 9);  work and n = ((na - ca) * stepPerAngle); fail?

Let's imagine na = 45 and ca = 35 to have numbers to play with:

Looking at the first one you will see:

  • subtraction
  • multiplication
  • division

The compiler breaks it down to these 3 'simple' calculations, and the order is important.

It starts with the subtraction because it is in the innermost brackets.  na - ca, which in this example would be 45 - 35 = 10

Next it has a choice of multiplication or division to do next. There are no brackets, so it picks the multiply first ... for this example it is 10 * 5 = 50

Finally it does the divide ... 50 / 9 = 5 

So n receives the value of 5.

-----------------------------

Had you used stepPerAngle instead of '5 / 9', then n would be 0.

Similarly, if the compiler had decided to do the division before the multiplication, because 5 / 9 would have resulted in a zero,

----------------------------

I realise that in a parallel discussion you have found a way of simplifying the whole program, which is brilliant. The way to go!

---------------------------------------

However, if in a different situation you still needed to do this calculation, then the best approach would be:

  1. Use the variable initialisation that you had, albeit with problems discussed previously fixed
    float stepPerAngle_float = 5.0 / 9.0; // full step = 1.8 or could have used "*1.8"
  2. Use this variable in your 'main code' e.g.
                                                 n = ((na - ca) * stepPerAngle);

------------------------------------------------------

I hope that makes some sort of sense.


ReplyQuote
GAM
 GAM
(@gam)
Trusted Member
Joined: 8 months ago
Posts: 58
Topic starter  
Posted by: @davee

I realise that in a parallel discussion you have found a way of simplifying the whole program, which is brilliant. The way to go!

If I have done something brilliant please let me know what it was! I'm starting to understand what your telling me, but I not getting why declaring 1.8 and using that in the math would result in N=0?

Other suggestions were to just use steps and forget about degrees. I think I would lose the ability to take the shortest route (CW/CCW).  At this point I don't know that is a big advantage and steps would be simpler.

@will also mentioned going to a geared stepper motor for more torque and I may need to do that. Perhaps I need a better understanding of how to read specs and calculating what I need. 

Don't give up on me yet it is sinking in slowly.

 

PS

Posted by: @robotbuilder

brilliant minds think alike 🙂 

Following this logic, the person who thinks like me is in trouble! 🤪   

 


ReplyQuote
GAM
 GAM
(@gam)
Trusted Member
Joined: 8 months ago
Posts: 58
Topic starter  

@robotbuilder Is it OK that I started a new thread?  I thought it should be different since I thought we resolved the first one dealing with arrays.  This one was meant to be just about the torque issue but sort of worked it way back to the other. Please let me know if I did this incorrectly. 😀 


ReplyQuote
Will
 Will
(@will)
Reputable Member
Joined: 3 months ago
Posts: 368
 
Posted by: @gam

Other suggestions were to just use steps and forget about degrees. I think I would lose the ability to take the shortest route (CW/CCW).  At this point I don't know that is a big advantage and steps would be simpler.

The stepper has 200 steps per revolution, so if ca = current angle and ta = target angle then if the absolute difference of (ca-ta) is greater than 100, then you need to move in the opposite direction.

As an example ta=25 (45 degrees) and ca=150 (270 degrees) ...

(ta-ca) = (25-150) = -125 which suggests 125 steps CW.

However, since the absolute value -125 is 125 which is greater than 100 (i.e. MORE than half a turn) then we can calculate the shorter route as 200 (i.e. a full turn) plus the calculated difference as:

200 (full turn CCW) - 125 (steps CW) = 75 CCW.

So you haven't lost any shorter turn efficiency by using steps.

Does this explanation work for you ?


ReplyQuote
Will
 Will
(@will)
Reputable Member
Joined: 3 months ago
Posts: 368
 
Posted by: @gam
Posted by: @robotbuilder

brilliant minds think alike 🙂 

Following this logic, the person who thinks like me is in trouble! 🤪   

As long as you're thinking, you're not in trouble, you're learning.


GAM liked
ReplyQuote
Will
 Will
(@will)
Reputable Member
Joined: 3 months ago
Posts: 368
 
Posted by: @gam

If I have done something brilliant please let me know what it was! I'm starting to understand what your telling me, but I not getting why declaring 1.8 and using that in the math would result in N=0?

What robot builder is trying to explain is a concept which is inherent in the representation of numbers in a computer.

Computers understand integers (int, long, uint, etc) as being the integer (whole number if you prefer) value which is the sum of the powers of two.

1001 (decimal) means 1x(10^3)+0x(10^2=100)+0x(10^1=10)+1*(10^0=1) = 1000+1

In other words, the digits represent the power of ten values at the position (starting from the right and moving back). So, it indicates the number of 1s,10s, 100s, 1000s, ... and the value is the sum of these powers times the digit in the corresponding position in the number. Because the decimal system as the digits 0,1,...9 each multiplier can assume any one of these digits.

Similarly, binary representation has only two digits (0 and 1) and it uses the powers of two 1,2,4,8,16,etc to represent. Ignoring negative numbers for simplicity, the representation:

1001 (binary) represents the integer formed by adding 1x(2^3=8)+0x(2^2=4)+0x(2^1=2)+1x(2^0=1)

= 8+1=9 in binary representation.

Similarly, 7 (binary) = 1x(2^2=4)+1*(2^1=2)+1x(2^0=1) or 4+2+1;

Computers also understand floating numbers (float, double, etc), but these are stores as an INTEGER binary number with one or two bytes reserved to hold an exponent. So, for instance

27.55 would be stored as (exponent =-2, number = 2755).

So, if we tell the computer that a value is an integer, then we must realize that it will always hold only an integer value. So if we try to add 1.8 to an INTEGER value of, say 14, the computer will usually convert the 1.8 to 1.0 and then add it to get the result 15.

Depending on your compiler, if you declare int n=2 and then try n *= 1.8, you will never get n=5.6 because it will either cut the 1.8 to 1 or do a floating multiplication of 2x1.3 to get 3.6 which it will then cut back to 3.

On the other hand, if you declare the value to be floating point value, it all happily add either integer or float values. Sometimes (like for stepper steps0 it's handy to always have the value in whole numbers because steps are aways integers. BUT it is important to do the calculations in floating point to get the maximum precision and then save the vale into an integer step value.

Is this helping ?


ReplyQuote
robotBuilder
(@robotbuilder)
Prominent Member
Joined: 2 years ago
Posts: 883
 

@gam

@robotbuilder Is it OK that I started a new thread?  I thought it should be different since I thought we resolved the first one dealing with arrays.  This one was meant to be just about the torque issue but sort of worked it way back to the other. Please let me know if I did this incorrectly. 😀 

I don't set the rules.  I can't see why you shouldn't have started a new thread to talk about the torque issue.

With the other coding issue that came up. 

An integer variable type can only hold whole numbers. If you have a number requiring a decimal point you must use some other data type. If you mix them you need to know the consequence. Look for Arduino c++ data types for more information. You cannot store 1.8 in an int type.

 

 


GAM liked
ReplyQuote
DaveE
(@davee)
Estimable Member
Joined: 4 months ago
Posts: 138
 

Hi @gam,

  If I have done something brilliant please let me know what it was!

Finding a way of simplifying the problem is one of the hardest, but also often most productive, tricks when trying to improve a program. In your case it probably makes sense to use steps rather degrees. Using degrees is 'familiar' to humans, but thinking in multiples of 1.8 degrees is harder for both humans and computers compared to 200 steps for a complete revolution.

Whilst '4 steps' is obviously easier than '7.2 degrees' for humans, it may not be obvious to you that this also applies to computers, but as you come to understand what words like 'int' and 'float' imply to a computer, then all will become clearer!

I not getting why declaring 1.8 and using that in the math would result in N=0?

@will and @robotbuilder have already provided some excellent replies. (Thanks - much appreciated by me!)

I hope it is becoming clearer and you are starting to figure it out.

Just to emphasise the points, I thought I would go back to your particular line of code. As it had two errors, albeit related errors, I'll deal with them one at at time.

----------------------------------------------------------------------

If we use a calculator, we can find 5 / 9 = 0.55555555555.

So you might have written:

int stepPerAngle = 0.55555555555;

This would fail because "int" tells the compiler to create a 'box' called stepPerAngle that can only hold an integer ... and 0.55555555555 is a floating point number not an integer number.

(Maybe imagine "integer number" is a square peg and "floating point number" is a round peg ... and we all know you can't fix a square peg in a round hole!! So you have to request a box of the right shape.)

(Depending upon the compiler, this is likely to either cause an 'error' or put "0" into stepPerAngle.)

------------------------------------------------

The fix is to replace "int" with "float", which tells the compiler to create a 'box' that can hold a "floating point" number instead of an "integer" number.

float stepPerAngle = 0.55555555555;

This should work fine!!!!

----------------------------------------------

But maybe you would like to write it as fraction (keeping the "float" fix from above), so you might try:

float stepPerAngle = 5/9;

Unfortunately, that will fail as well ... as the compiler will use "integer" division instead of "Floating point" division. This will put a "0.0" in stepPerAngle.

(It will probably not 'error', so you will not get a warning... just a program that doesn't work.)

-----------------------------------------------

To explain why, I'll start by inventing a slightly different line, which I hope will be easier to follow:

float abc = 13 / 5;

You might remember "Integer" division from your childhood ... think back a 'short while' to before you learnt about "decimals" and you only knew about "whole numbers"!

The calculation on the right hand side of the equals sign says  "13 divided by 5"

Now you would have been taught something like:

"13 divided by 5" is equal to "2 remainder 3"

So this implies the 'answer' has two parts:

  "2"          the number of "5"s in 13

  "3"          the remainder

However, the compiler has only one 'box', called "abc", so it can only accept one part.

Hence abc will be set "2.0", and the remainder "3" will be discarded.

(Note: it stores "2.0" in "abc", not "2", because "abc" can only hold a floating point number. That is the compiler automatically converts the integer answer of "2" from the right hand side, to the nearest floating point equivalent "2.0")

-----------------------------------------

Returning to your case:

float stepPerAngle = 5/9;

The 'sum' on the right hand side is:

"5 divided 9" is "0 remainder 5"

Following the same rule as above, the "0" is converted to the floating point "0.0", which is then stored in the left hand side 'box' called "stepPerAngle", and the "remainder 5" is discarded.

Hence, if your program had used stepPerAngle in a subsequnt line, it would have the value "0.0"

------------------------------------------

So how do you fix "float anglePerStep = 5/9;" to do the mathematics correctly?

The easiest way is to make "5" and "9" floating point numbers .. "5.0" and "9.0", which tells the compiler to use the "floating point" divide.

So the following line should work correctly:

float stepPerAngle = 5.0/9.0; 


HURRAH ... we have the line you thought you wrote!!!

---------------------------------------------------------------------------------------------

So why does the compiler have two (actually more than two.. another discussion!) ways of doing division?

The first reason is that "Integer" division is a lot easier and quicker than "Floating point", so reduced execution time and improved efficiency, if your task can live with the limitations.

A second reason, (yet another discussion!), is sometimes the the actual task or algorithm is easier to code. 

-----------------------------------------------------------------------------------------------

I hope that helps a little .. persevere .. it's really hard to start with but with a little effort and practice the 'fog' will gradually melt away. The precise rules vary with different programming languages, but the principles are near universal.

Best wishes!


ReplyQuote
GAM
 GAM
(@gam)
Trusted Member
Joined: 8 months ago
Posts: 58
Topic starter  

@davee, @will, and @robotbuilder,   Thanks to all,  Starting to understand and the last example with remainders and "float stepPerAngle = 5.0/9.0;" kind of cleared it up some.  Now I think I will try to code it in steps as suggested by many others but @will explanation was very clear. 

 

Then I will be back to figuring out the correct stepper to use for the torque I need.

Thanks again 

 


ReplyQuote
Page 2 / 2