Math equations with decimals

Hello! I’m working on my first stepper motor/ballscrew project and am now dealing with decimal numbers in an equation for the first time. For testing I’m using an inexpensive stepper/ballscrew setup but the final project will require precision movement, thus my question. In the code there is an equation that starts with a decimal number (cutLength) divided by another decimal number (the pitch of the ballscrew) that eventually generates the required number of steps to reach that distance. If I do the math I get a result of 70528.9673 steps but I’m not sure what the Adruino result is. If anyone can tell me what that result would be with the equation as written I’s appreciate it and any suggestions on how to better do the calculation are welcome. Thank you! EDIT: Although the cutLength currently in the code is 2 decimal places it will likely be 3 or 4 in actual use if that makes any difference in how I should approach this.

unsigned long Steps = 0;
float cutLength = 8.75;
unsigned long requiredSteps;
void setup() {
  
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  digitalWrite(8, LOW);
  digitalWrite(9, LOW);
requiredSteps = ((cutLength / .1985) * 1600);
}

void loop() {
  
digitalWrite(9, HIGH);
delayMicroseconds(83);
digitalWrite(9, LOW);
delayMicroseconds(83);
Steps = Steps + 1;
if (Steps == requiredSteps)
{
  if (digitalRead (8) == LOW)
  {
    digitalWrite (8, HIGH);
  }
  else
  {
    digitalWrite (8, LOW);
  }
  Steps = 0;
  delay (5000);
}
}

Why not print out the result of the calculation, using Serial.println()?

As you have declared requiredSteps to be an integer, the fraction will be dropped.

jremington:
Why not print out the result of the calculation, using Serial.println()?

Honest answer? Because I never thought of doing that. and need to better learn how to use that. Thank you!

Another poster seems to have a similar setup, but is using a nut with his leadscrew. I believe his problem relates to the thrust bearings on his leadscrew. How are you controlling the end thrust on your leadscrew?

Also when your calculation is all done to compute the steps, you need to round up or down to an integer number of steps. You have 70528.9673 as a step result and stepper motors are able to do complete steps. But, I am sure you already know this.

Paul

Paul,
I am not building the ball screw assembly. For testing purposes I am using this: https://www.amazon.com/gp/product/B016MC2W3C/ref=oh_aui_detailpage_o02_s02?ie=UTF8&psc=1

The project is to replace a pneumatic feed which uses mechanical limit switches with a servo drive controlled by an Arduino. This is on a $100,000 plus machine so the final product will use a high end, sealed ball screw slide along these lines: http://www.bell-everman.com/sls and a ClearPath Serve system: https://www.teknic.com/model-info/CPM-SDSK-2310P-RLN/

Regarding rounding the calculated number of steps, it appears that in the result the fractional (decimal) step is simply dropped by the Arduino. While there are some scenarios where this might be a problem I'm using a microstepping controller with 1600 "steps" per revolution on a ball screw with a lead of .5cm so even if it drops a .9999 that is only about .00012" in linear travel which is about 10 times the accuracy I need from the system. My original concern was that it might be dropping, or rounding, numbers in the middle of the equation which would multiply the error I got in the final result but thankfully that's not the case.

If you want any kind of accuracy at all, you better steer clear of floats, as they will give you, at best, only 6-7 digits of precision, and the more calculations you do, the more errors you will accumulate. Instead, use large (32- or 64-bit) integers, using "fractional integer" math for all calculations. i.e. - keep all numbers as integer counts of ten-thousandths, hundred-thousandths, or millionths of an inch. Also, work in the native units of the ballscrew (if it's a metric screw, do all calculations in mm, if it's an inch screw, do all calculations in inches) and convert to different units ONLY when interacting with a human.

Regards,
Ray L.

My usual advice is: always treat floating-point numbers as approximations accurate to about 6 places. If you need absolute precision, as is usually the case when you are working with units of time or currency or when you are fooling about with stepper motors, then work out the smallest unit you wish to deal with and do your calculations using integer quantities (int, long, long long) of that unit.

BillMurphy:
Paul,
I am not building the ball screw assembly. For testing purposes I am using this: https://www.amazon.com/gp/product/B016MC2W3C/ref=oh_aui_detailpage_o02_s02?ie=UTF8&psc=1

The project is to replace a pneumatic feed which uses mechanical limit switches with a servo drive controlled by an Arduino. This is on a $100,000 plus machine so the final product will use a high end, sealed ball screw slide along these lines: http://www.bell-everman.com/sls and a ClearPath Serve system: CPM-SDSK-2310P-RLN | torque = 112 oz-in, speed = 4000 rpm

Regarding rounding the calculated number of steps, it appears that in the result the fractional (decimal) step is simply dropped by the Arduino. While there are some scenarios where this might be a problem I'm using a microstepping controller with 1600 "steps" per revolution on a ball screw with a lead of .5cm so even if it drops a .9999 that is only about .00012" in linear travel which is about 10 times the accuracy I need from the system. My original concern was that it might be dropping, or rounding, numbers in the middle of the equation which would multiply the error I got in the final result but thankfully that's not the case.

Looks like you are all set! Good way to debug your code.

Paul

Three points

  1. the Arduino does not drop (or in deed have) any decimal points.

  2. when you convert (CAST) from float/real to int you get the whole part of the number and it always rounds down eg 2.1 to an int gets you 2 (no . ) ans 2.99999 also gets you 2

  3. Floats do not have a number of decimal places. The print method/function decides on how many places to print the number too. The default is 2 decimal places.

Mark