Counting in decimal fractions....

Go To Last Post
18 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So my bicycle wheel rotates 3150 times in 1 mile. I want to build a mileometer that shows distance to an accuracy of 0.01 miles.

I get one pulse from a sensor on my wheel every time it rotates one revolution.

So I need to increment my display every 31.5 pulses.

I want to offload the counting to an 8-bit AVR counter to minimise my CPU load - it's a clever mileometer that does loads of other things as well !

I can't set the counter to 224 or 225, let the pulses increment the counter, detect the overflow, increment my display by 0.01, reset the counter and start again, because either value won't show exactly 1.00 on the display after exactly one mile.

So what do I do?

Answers on a Christmas post card please!

Best Regards, Martin

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How about:

counts = (n * counter) / q;

255 / 255 = 1.

find a value of n and q that will give a value of 1/10 mile on each roll-over of the counter.

So, I've already had many "Brain Farts" today! I could be full of S^*t, so go with caution. But do at least look into the concept.

Merry Christmas!

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You could alternate the count between 31 and 32. Then only every other 0.01 of a mile would be slightly off, but not enough to matter.

Or, if your sensor is with a magnet on the rim as a trigger, then you could put another magnet at 180 degrees from the first, so you end up with 63 pulses per 0.01 mile. Then you wouldn't have that 1/2 rotation to worry about.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

my bicycle wheel rotates 3150 times in 1 mile.

Quote:

So what do I do?

Get a bicycle with a wheel diameter larger than 6.4"/16.26cm.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The extra magnet is the easiest sollution, in fact more than one extra would increase resolution again and again. There's really no need to have that high a level of resolution accept to more easily simulate an acurate .01 mile counter, (or smaller) 4 or 8 sensors should be pretty easy to put on.

-Curiosity may have killed the cat
-But that's why they have nine lives

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't know, I still lean toward getting a bigger bicycle. Would be a hell
of a lot easier to ride, too.

Tom Pappano
Tulsa, Oklahoma

Tom Pappano
Tulsa, Oklahoma

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Circumference is (Pi)*diameter

6.4" * 3.14 = 20.1"
( 20.1" * 3150 )/12 = 5275 feet

Tom Pappano
Tulsa, Oklahoma

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Not to make things more diffficult but the effective circumference actually changes with speed because centrifugal force pulls the tire away from center, also low/high tire pressure will change the effective circumference.

-Curiosity may have killed the cat
-But that's why they have nine lives

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Nice replies!

Trouble is I don't have a bike at all 8) - my application solves a different problem but the bike analogy is perfect!

I realised after I'd posted that I'd made it too easy - what if it did 3173 revolutions per mile...that would stop the solution that alternates the count between two whole numbers :cry:

I have a perfect solution using interrupts - each pulse increments a variable by 100, when the variable exceeds 3173, I add one to the display and subtract 3173 from the variable. So the variable goes 0, 100, 200 ... 3100, 3200, (increment display), 27, 127, 227 etc. The last click over from 0.99 miles to 1.00 miles occurs exactly after 3173 pulses and each increment is as accurate as possible

...but it uses CPU time, more memory and an interrupt - is there a counter-oriented solution?

Best Regards, Martin

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you use a 16-bit timer as a counter (use external timer input pin) and throw it into compare match, you could do the input and compare completly in hardware. That way, when the counter reaches your requested value, it would throw a compare match interrupt and reset the counter automatically.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MartinM57 wrote:
I want to offload the counting to an 8-bit AVR counter to minimise my CPU load - it's a clever mileometer that does loads of other things as well !

There ist absolutely no reason to fear calculations, in opposition, the µC like to do calculations for you.

E.g. to be ergonomic the display should no faster show a new value as every 200ms (because the human must be able to read it !).

Then assuming 1ms for the calculations, result in only 1ms/200ms = 0.5% CPU-load.

1ms = 16000 cycle = many time for the µC to do many things.

Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dean...but the whole point is that I can't put 31.73 (the number of revolutions needed to increment the display by 0.01) into a counter :(

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
want to offload the counting to an 8-bit AVR counter to minimise my CPU load - it's a clever mileometer that does loads of other things as well !

I agree entirely with danni, How much processing power to you think it will take? Or are you running the AVR at 1KHz to save power?

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I assume you mean readout resolution of 0.01 mi, not accuracy. Can't help you with the accuracy or precision of your sensing method.
Since your readout is in centimilies, let's calculate in that. Your wheel circumference is thus 0.031746 cmi.
If this was floating point, one would add 0.0317.. to an accumulator, and transfer 1 to the odometer whenever there's one. In integer math this becomes:

interrupt (wheelpulse)
{
int32 = int32 + 68174084; // 68174084 is from 2^31*0.031746
if (int32<0) { centimilecounter++; int32^=0x8000000; }
}

Depending on what additional accuracy error can be tolerated, int16 may be sufficient.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are missing danni's point. What he is saying is to use a 16 bit counter to count the pulses. But the interrupt to display is not based on that counter, it's on a second counter triggered to interrupt at a certain time interval. At that time you calculate the distance based on the 16 bit timer value and display it. Also at that time, if the 16 bit timer is over 3173, you subtract 3173 and add one to your whole mile count.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I agree with that.
Basically, you dont even get a pulse at the 0.01 mile step.
So all you can do is to count the number of pulses up to 1 mile and use timervalue/3173 to display the digits after the decimal point. Of course the display wont switch by 0.01 at exactly that distance but this isnt possible anyway.

But your overall accuracy (in miles) is as good as you can get it.

Additionally, this wont need a lot of resources, when you use a compare interrupt.
Every solution that counts in fractions is a bad thing as the error grows with every revolution.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi.
If i understand right, Martin, you can't count 1/2 of wheel pulse.
And i think that you mast use one bit as FLAG, and flip this flag anytime when counter overflow, and set the counter to 224 or 225. And you can minimised error of count.

Best Regards.
Merry Christmas! And ...
ArTih.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think the thread is almost over - thanks for the replies and I'm sure I can't use a single counter alone, however I manipulate it. The idea of using a timer every, say, 0.2 seconds is interesting, but becomes more complex than the solution I've now designed, built and which seems to be working great

Just to restate the problem using a bicycle analogy (but it isn't actually a bicycle!)...

I need maximum accuracy at ALL times, and a resolution of 0.01 miles. I only get one pulse per revolution of the wheel and the number of revolutions per mile is fixed but can be anything - let's say from 100 to 9999 (and as it's not a real bicycle, then it really can be 100 revolutions per mile in this analogous world!!)

My solution is as previously outlined by me - and suggested by others here - to use an interrupt (INT0, positive rising edge, on a ATMega8515) and each pulse increments a variable by 100. When the variable exceeds, say, 3173, I add one to the display (ie click over to the next 0.01 mile increment) and subtract 3173 from the variable. So the variable goes 0, 100, 200 ... 3100, 3200, (increment display), 27, 127, 227 etc.

The last click over from 0.99 miles to 1.00 miles occurs exactly after 3173 pulses - so the accuracy and resolution at the end of a mile is perfect. Also each and every increment on the way to 1.00 miles is as accurate as possible - not exactly accurate, of course, but as accurate as it can be

Thanks all!
Best Regards, Martin