# Dividing longs and displaying decimals on an OLED

I am creating a digital rolling measuring wheel (I know I can buy these, lol)... I am using an optical encoder that gives me 200 pulses per rev and an arduino to read the pulses, and display the distance on an OLED display in meters and feet.

Everything is working, but I am wondering if there is a better approach to displaying the distances:

I am using unsigned longs to hold my pulse count as this number could easily exceed 32,768.

I created a calibration routine where I enter a pre-determined distance (say 10 meters for example) and then roll the counter over that distance. i do this a few times and store the average number of pulses. (I realize I could just hard-code this based on wheel diameter, but I don't know what size wheel I will be using, yet - or might want to make my code work on different sized devices).

I then perform mathematical calculations to divide the pulses into the calibration distance to get a "meters per pulse" figure that is later multiplied by the number of pulses traveled when the wheel is actually being used to measure.

Because I am using longs, I don't know a great way to get numbers with decimals to properly display the metric and imperial measurements on my display.

What I have done is create a "long division" function I based off what I fund on Post #7 on this page: How can I divide two longs in an accurate double? - Programming Questions - Arduino Forum

When I calculate the distance, I am concatenating the "whole number" from my calculation with a decimal point and then the "remainder digits" into a string that I then display on my OLED.

It works, but it is kind of a "hack" way of doing this and I was wondering if there was a better / more correct / simpler way of getting a decimal result from dividing longs that I can show on my display.

J

roboscan:
I created a calibration routine where I enter a pre-determined distance (say 10 meters for example) and then roll the counter over that distance. i do this a few times and store the average number of pulses.

It’s not so great to have a measuring tool that gives different results when measuring the same thing unless you are talking about fractions of a unit or use of poor measuring techniques.

How about putting a scratch on the edge of the wheel and rolling the wheel once from scratch mark exactly on the bottom to the same to get closer than 200/360 degrees?

If you put a known dia roller on a larger wheel, the roller will turn the same distance as the large wheel covers ground. To be practical the roller has to be big enough to roll easily, not 1cm or less dia. You don’t want the roller turning 3000RPM on a wheel turning 60RPM.

When I calculate the distance, I am concatenating the “whole number” from my calculation with a decimal point and then the “remainder digits” into a string that I then display on my OLED.

You do put leading zeros on the remainder digits where needed? Like 101 % 100 = 1 but the decimal is .01.

If you want faster /10 and %10, check this old thread out, it’s amazing how fast they got it.

GoForSmoke:
How about putting a scratch on the edge of the wheel and rolling the wheel once from scratch mark exactly on the bottom to the same to get closer than 200/360 degrees?

I think you mean 360/200 degrees.

Right.

roboscan:
I created a calibration routine where I enter a pre-determined distance (say 10 meters for example) and then roll the counter over that distance. i do this a few times and store the average number of pulses. (I realize I could just hard-code this based on wheel diameter, but I don't know what size wheel I will be using, yet - or might want to make my code work on different sized devices).

GoForSmoke:
It's not so great to have a measuring tool that gives different results when measuring the same thing unless you are talking about fractions of a unit or use of poor measuring techniques.

How about putting a scratch on the edge of the wheel and rolling the wheel once from scratch mark exactly on the bottom to the same to get closer than ( 360/200 ) degrees?

Indeed, the whole "try several times and take an average" makes more sense for a pedometer than for a measuring wheel.
If the diameter of the wheel is known, then to get the circumference, you can multiply by 355 and then divide by 113. Milü - Wikipedia Just make sure that, when you do the multiplication, that you use `long`s rather than `int`s, because the result of the multiplication will probably be too big to fit in an `int`.

GoForSmoke:
It's not so great to have a measuring tool that gives different results when measuring the same thing unless you are talking about fractions of a unit or use of poor measuring techniques.

How about putting a scratch on the edge of the wheel and rolling the wheel once from scratch mark exactly on the bottom to the same to get closer than 200/360 degrees?

If you put a known dia roller on a larger wheel, the roller will turn the same distance as the large wheel covers ground. To be practical the roller has to be big enough to roll easily, not 1cm or less dia. You don't want the roller turning 3000RPM on a wheel turning 60RPM.

Thank you for your reply. Well, my thinking for this device is that my encoder would have a fixed wheel on it and it might attach to another object (say the wheel of a bicycle, scooter, handtruck, remote controlled vehicle, etc) in a way where my "encoder wheel" rubs against an existing wheel of whatever I attach it to (a friction drive).

The idea behind my calibration setup was that I wouldn't need to know the circumference of the wheel I attach it to, I could simply roll the "vehicle" (once the the system is attached) over a known distance to calibrate the measuring tool "on the fly." This would also account for any unexpected variables (for example, tire over / under inflation).

GoForSmoke:
You do put leading zeros on the remainder digits where needed? Like 101 % 100 = 1 but the decimal is .01.

If you want faster /10 and %10, check this old thread out, it's amazing how fast they got it.
divmod10() : a fast replacement for /10 and %10 (unsigned) - Libraries - Arduino Forum

What I actually changed to is using some division, mod and multiplication to "disassemble" and "reassemble" my real number...

``````  uint32_t dM = virtualCounter * mpc;   //meters per count figure from calibration routine * actual encoder counts
uint32_t dMrr = virtualCounter * mpc * 1000; //enlarge the number to avoid a decimal (3 places is enough)
int decimal = dMrr%1000; //get rid of the whole number leaving just a remainder

sprintf(distanceMetric, "%" PRId32 ".%03d M",dM,decimal);  //put it all together for display on OLED
``````

(I actually just got help with the sprintf portion of this code - I had the wrong format for the "integer" so the numbers were there, but they wouldn't display.

As for leading zeros - I will admit, I didn't originally come up with a solution for that, but "%03d" above forces the leading zero so I don't think I need to go back and bother with it (at least not until I decide I need to optimize my code )

roboscan:
The idea behind my calibration setup was that I wouldn't need to know the circumference of the wheel I attach it to,

You don't need to know the diameter of the vehicle wheel if you put a roller on it. The outside of the wheel will move over the top at the same speed that it moves along the ground, how could it be different? You only need know your roller dia.

(I actually just got help with the sprintf portion of this code - I had the wrong format for the "integer" so the numbers were there, but they wouldn't display.

As for leading zeros - I will admit, I didn't originally come up with a solution for that, but "%03d" above forces the leading zero so I don't think I need to go back and bother with it (at least not until I decide I need to optimize my code )

If you run out of flash, you know what to do. Sprintf is -FAT- and slower.