 # Comparing floats

I have a machine controlled by DC motors with encoders as position feedback which I am calculating in degrees.

I control the setpoint of where the motors should be with some potentiometers (in degrees). The machine position and setpoint are a float for accuracy, but I am having problems comparing the two values on when to stop the motors (which I understand why) but I have not figured out a way to get past it.

Accuracy only needs to be to 0.2 degrees. So when the machine is within 0.2 degrees of the set point, the motors can stop.

``````if (setpoint > machinePosistion) //Drive the motor up
{
digitalWrite(DnPin, LOW);
digitalWrite(UpPin, HIGH);
}
else if (setpoint < machinePosistion) //Drive the motor down
{
digitalWrite(DnPin, HIGH);
digitalWritelUpPin, LOW);
}
else if (setpoint == machinePosistion) //Stop the machine
{
digitalWrite(DnPin, LOW);
digitalWrite(UpPin, LOW);
}
}
``````

Basically because of using floats, the setpoint and machinePosistion never equal the same so it over shoots and goes back the other way all the time and hunting.

Do I convert the floats into a long and compare those or is there is more clever way to make this work?

``````if (abs(setpoint - machinePosition) < EPSILON) { ... }
``````

Define EPSILON as appropriate (but probably not less than about 0.000001…)
(a relatively standard technique.)

Orac: The machine position and setpoint are a float for accuracy,

Floats don't give you any accuracy at all! Rather inaccuracy like westfw showed with the epsilon. It you want a accuracy of 0,1 degree, just store the position and set-point as a int values of 1/10 of a degree. So for 10,5 degree you have an int with the value 105. The decimal point can be added later if you want to print it of something. But the calculation of int's is faster and no weird float inaccuracies.

Take a look at PID in the learning section it may help.

Mark

westfw:

``````if (abs(setpoint - machinePosition) < EPSILON) { ... }
``````

Define EPSILON as appropriate (but probably not less than about 0.000001…)
(a relatively standard technique.)

Ok I did try something like this, but I think I came into problems when comparing negative numbers. Ie. 0 degrees is machine dead center, --50 degrees is left and +50 degrees is to the right.

Should abs still work correctly in this scenario or maybe I did something wrong…

Cheers.

It should as it removes the sign. But you wont get rid of hunting. What are you really trying to do?

What device are you trying to control? Eg if it's a relay just get rid of the relay.

Mark

Orac: I have a machine controlled by DC motors with encoders as position feedback which I am calculating in degrees.

Tell us about these encoders. How many "units" per degree?

Also, is a full 360 degree rotation possible for your machine?

holmes4:
It should as it removes the sign. But you wont get rid of hunting. What are you really trying to do?

What device are you trying to control? Eg if it’s a relay just get rid of the relay.

Mark

Moving a solar tracker, using a H bridge to control some DC motors.

I did try your suggestion of:

``````if (abs(setpoint - machinePosition) < EPSILON) { ... }
``````

But I got erratic results.

odometer:
Tell us about these encoders. How many “units” per degree?

Also, is a full 360 degree rotation possible for your machine?

0.0014175988453013 Degrees per encoder pulse The machine will do a complete 360 degree revolution, but I don’t want it to.

Erratic results for what values input?

Orac: 0.0014175988453013 Degrees per encoder pulse

This looks like a garbage number to me.

360 / 0.0014175988453013 = 253950.545454...

That is not an integer. Get the cat off the keyboard and try again.

253950 encoder pulses for 360 degrees sounds wrong?

``````360 / 253950 = 0.00141760189...

But you said   0.00141759884...
``````

odometer:

``````360 / 253950 = 0.00141760189...
``````

But you said  0.00141759884…

That’s why if you want accuracy you never use a float. Floats are for big ranges of numbers, but they are inherently NOT accurate.

Orac:
0.0014175988453013 Degrees per encoder pulse

This number comes from where? How exactly did you get this number?

If the number appeared like this in documentation, then it is almost certainly a typo or mistranslation.

If you calculated this number, then it is almost certainly a miscalculation.

Thank you Delta! All those crappy floats all the time for people who just want to have a decimal point...

Maybe banks use floats and that's why we get screwed over by them all the time?