Integer and Floating Point Math on the Arduino UNO

I'm trying to avoid floating point math while trying to maintain as high a level of precision as possible. Here's the scenario:

I have built a event timer that will compute events per hour (along with other production related metrics). I'm running into an issue with the computation for the events per hour.

I'm storing the running time in milliseconds as an unsigned long and the event count as an unsigned int.

The formula I initially had was

(unsigned long) veh_per_hour_x10 = (10UL * 3 600000UL * ((unsigned long) timing.count)) / timing.msec_count ;

organized in such a way the division was performed last. Unfortunately I found it could only count 119 events before the divisor was too big for an unsigned long. (103600000199 > unsigned long)

While I'm working through rewriting the formula myself to avoid the 119 event limit, what other options do you all know of to minimize the floating point math and maintain the accuracy.

For what you are doing, exact milliseconds almost certainly have no real meaning.

First divide the number of milliseconds by 100 to get the number of tenths of a second. Then use the number of tenths of a second in your "vehicles per hour" formula. This will allow you to squeeze two more digits out of your formula.

Remember to check for division by zero. You might not want to use your formula unless at least a few seconds have elapsed: calculating vehicles per hour from less than one second of data does not seem to make much sense.

Vehicles <> automobiles.

The original design was to measure carriers (called vehicles by the conveyor manufacturer) per hour in a production line. Luckily I built the program with more capacity than for that one instance. The line was capable of 3000 vehicles (carriers, events, etc) per hour. Built just to handle that rate, then measuring in tenths of a second would be sufficient (program capability = 10x event rate). Now I am looking to use the program at upwards of 80,000 events per hour (or one event less than every 45 milliseconds). Milliseconds will now become the last significant digit in the calculation. Unfortunately reducing to tenths of a second or tens of milliseconds will impact the accuracy.

There is a whole sequence around starting and sequencing the sensor that prevents the divide by 0.

Something is wrong with your math.

There are 3600 seconds in one hour.

8000 events per hour is equivalent to one event every 0.45 seconds (about 1/2 second).

Timing to 1/10 second should be more than adequate.

jremington:
Something is wrong with your math.

There are 3600 seconds in one hour.

8000 events per hour is equivalent to one event every 0.45 seconds (about 1/2 second).

Timing to 1/10 second should be more than adequate.

Nothing wrong with your math or reasoning. Probably an issue with my typing. Not 8,000 but 80,000. That is starting at 80,000 and increasing and must also be able to handle bursts exceeding 200,000 events per hour but for only a short time (ie., a few minutes).

Floating-point result without floating-point arithmetic:

long top =  123456L;
long bottom = 7890L;
// bottom must not exceed 214 million !!!
// (otherwise there is danger of overflow in the loop)

Serial.println(top);
Serial.println(bottom);

int count;
for (int i=0; i<=7; i++) {
  count = 0;
  while (top >= 0) {
    top -= bottom;
    count++;
  }
  top += bottom;
  count--;
  Serial.print(count);
  top *= 10;
  if (i==0) {
    Serial.print(".");
  }
}
Serial.println();

Source: Original Odhner - Division & Decimals - YouTube (skip to 2:58 to see the actual process of division)

Note also that multiplication by 3600000 (or by 36000000) can be easily faked: multiply by 36 instead, and just display the decimal point in a different place.