Email: Password: Remember Me | Create Account (Free)

Back to Subject List

Old thread has been locked -- no new posts accepted in this thread
???
02/24/09 21:32
Read: times


 
#162780 - more step-by-step
Responding to: ???'s previous message
I don't think I would let any pulse reset anything. But you may consider resetting the timer on every display update - but normally you can keep it freerunning.

Let's say you have a timer ticking an 8-bit value at 5kHz. The resolution of this timer is then 200us. Let's say that each overflow of the timer will trig an interrupt that increments an overflow counter. This would give you one interrupt every 256*200us or 50ms. If your timer is 16-bit instead, then you only have to worry about an overflow interrupt every 13 seconds which means that you don't even need to store an overflow counter (since you are expected to produce a displayed value much more often than 13 seconds).

Let's say you use a pin interrupt on every pulse.

Every interrupt, you increment a pulse counter. And you also check the total time that has passed since the previous time you updated the display.


If you drive at 100mph, you get about 220 interrupts/second. That means that you get a pulse every 4.54ms.

After the first interrupt, you have 1 pulse, but your timer should only have ticked 22(.7) ticks. This is too short time for you to be happy, so you do not update the display.

After the second interrupt, you have 2 pulses, and your timer have ticked 45 ticks. Still too little for you to be happy.

On your 100th interrupt, you have 100 pulses, and your timer have ticked 2272 ticks - getting close to the 2500 ticks that represents 0.5 seconds.

On your 110th interrupt, you have 110 pulses, and your timer have ticked 2500 ticks. Bingo. Enough time. Let your interrupt store the count of 110 pulses and 2500 ticks into two variables and set a flag to your main program that it should update the display.

You have 110 pulses in 0.5 seconds so you have 110 * 5000 / 2500 = 220 pulses / second. And your formula says that 2.2 pulses/s is 1mph. So the speed to display is then 220 / 2.2 = 100mph.

Let's say you instead drive at 37mph. If the vehicle produces 2.2 pulses/mph, that means that at 37mph it will produce 81.4 pulses/s or one pulse every 12.3ms.

On your first interrupt, you have one pulse, and your timer have ticked 61 ticks.
On your second interrupt, you have two pulses, and your timer have ticked 122 ticks.
On your 40th interrupt, you have 40 pulses, and your timer have ticked 2457 ticks.
On your 41th interrupt, you have 41 pulses, and your timer have ticked 2518 ticks.
OK. We have reached or passed 0.5 seconds, so time to emit a speed reading.
Let the interrupt save the count of 41, and the timer count of 2518 and flag main to display.
41 * 5000 / 2518 is 81.4 pulses/second and your speed is 81.4/2.2 = 37.0 mph.

Let's say you drive at 3mph. Expected pulse frequency would then be 6.6Hz.
Pulse irq 1: 1 pulse, 5kHz/6.6Hz means that the timer have ticked 757 ticks.
Pulse irq 2: 2 pulses, 1515 ticks.
Pulse irq 3: 3 pulses, 2272 ticks
In this case, your interrupt may do a rough estimate (it knows time and tick count) that the next tick will be way outside 0.5 seconds, so maybe you should stop here, instead of waiting for the 4th pulse at 3030 ticks (=3030/5000 s = 0.6 seconds).
Floating point division is no fun in an interrupt. So make it easy. Just do a couple of quick integer tests. Use a 11-entry table with precomputed constants
Entry 0: not used.
Entry 1: If you need more than 1250 ticks for 1 pulse -> display directly.
Entry 2: If you need more than 1700 ticks for 2 pulses -> display directly.
Entry 3: If you need more than 1875 ticks for 3 pulses -> display directly
...
Entry 10: If you need more than 2291 ticks for 10 pulses -> display directoy.

When you have received more than 10 ticks, then the tick frequency is high enough that 0.55s instead of 0.5s update interval isn't noticeable.

For the example with 3mph speed, the suggested table would then give:
if (start_counting) {
    current_pulses = 0;
    reset_current_ticks_or_memorize_current_value_as_offset;
} else {
    current_pulses++;
    current_ticks = read_ticks_somehow;
    if (current_pulses <= 10 && current_ticks > limits[current_pulses]
    ||  current_ticks >= 2500) {
        // Either have measured at least 0.5 seconds, or speed is slow. Emit now.
        measured_ticks = current_ticks;
        measured_pulses = current_pulses;
        have_speed_data_to_display = TRUE;
        current_pulses = 0;
        reset_current_ticks_or_memorize_current_value_as_offset;
    }
}

Quick and easy, and no need to wait for the fourth pulse that would have slowed down the display update interval to 0.6s.

You may decide to let the pulse interrupt clear the timer at the same time it clears the pulse count after having flagged main. Or you may copy the current timer value to a t0 time reference, that you subtracts on every reading.

The main loop can just wait for one of two things.
Either it sees the flag that the timer interrupt have supplied a pulse count and a tick count. Compute and display.

Or looks at a clock somewhere (possibly the timer overflow) and if the pulse interrupt have not supplied any measurement for more than 0.6-0.8 seconds, you grow tired and decide that the speed is too slow to measure. Display 0 and set a flag that the pulse timer on next interrupt should clear itself and start counting from zero.

Note that at low speeds, it is important that you only start the timing on a pulse interrupt, since you don't know how long into the pause you are if you start at a random time, and that may affect the reading quality.

And once more: You do not need 5kHz timer resolution, since your display update intervals speed is so slow. Easiest is if the timer is so slow that it does not turn around between two pulses until the speed is so slow that you can switch to display 0.

With 2ms tick frequency, an 8-bit timer overflows after 512ms. This gives a number of advantages. Clear the timer on the first pulse. If you get a timer overflow interrupt before the pulse interrupt, you can display 0. If you get a pulse interrupt first, you can sample the timer and decide (using my table suggestion) if you should continue waiting for more pulses or use the number of pulses you already have for displaying the speed.

Your worst case reading would be a speed that passes 128 ticks for the first pulse. In that case, a 2ms/step 8-bit counter would still give you 1% precision. Quite acceptable for a car.

The reason why I don't talk specifics about the timers is that I know practically nada about the 8051 timers. I can a lot about the timers for a number of other processors, but for the last 15 years, I have only needed to fix minor bugs in 8051 applications. Besides, there are too many 8051 variants out there with bigger or smaller improvements since the old classic 8031 chips I once spent my time with.

List of 49 messages in thread
TopicAuthorDate
Tip for Speed sensor via External Interrupt            01/01/70 00:00      
   Fresh thoughts.            01/01/70 00:00      
      Try measuring time instead of count for slow pulse trains            01/01/70 00:00      
         The highest frequency would be            01/01/70 00:00      
            Once more - think time instead of frequency            01/01/70 00:00      
            Rough estimation...            01/01/70 00:00      
         On the teatering edge......            01/01/70 00:00      
            Is that not good enough?            01/01/70 00:00      
               I was having issues with that.....            01/01/70 00:00      
                  Did you read this post?            01/01/70 00:00      
                     I think that's the bullseye, I was forgetting....            01/01/70 00:00      
                     Yes, and your solution is in my code...perfect!            01/01/70 00:00      
                        Happy that it works            01/01/70 00:00      
                           I'm using this model.....at least            01/01/70 00:00      
                           I'm using this model.....at least            01/01/70 00:00      
                           Looks like I was blind to the obvious.            01/01/70 00:00      
                              All depends on the input scale            01/01/70 00:00      
                                 That will be the next step.......            01/01/70 00:00      
                                 Per,            01/01/70 00:00      
                                    Would this work for a Random() Seeding?            01/01/70 00:00      
                                       Thermal noise from a diode            01/01/70 00:00      
                        Bisection.            01/01/70 00:00      
                           I was a bit hasty ...            01/01/70 00:00      
   PLL ?            01/01/70 00:00      
      Stability            01/01/70 00:00      
         Yes, for a car            01/01/70 00:00      
            Are you sure?            01/01/70 00:00      
               your math is correct            01/01/70 00:00      
                  Ok, can you please explain...            01/01/70 00:00      
                     Should be minute not seconds, typo            01/01/70 00:00      
                        Two questions...            01/01/70 00:00      
                           Yes, 3.3V is right and works correctly            01/01/70 00:00      
                              Have you read...            01/01/70 00:00      
                                 In more detail...            01/01/70 00:00      
                                 It would take forever to go through all the combos            01/01/70 00:00      
                                    This is no log function, ...            01/01/70 00:00      
                                       This is my solution, and almost there            01/01/70 00:00      
                              do you read datasheets???            01/01/70 00:00      
                                 Yes/No            01/01/70 00:00      
                                    better perfomance if ...            01/01/70 00:00      
         The PLL approach isn't that hopeless...            01/01/70 00:00      
   period measurement            01/01/70 00:00      
      Here is an image of what I think you mean?            01/01/70 00:00      
         what derivative do you use?            01/01/70 00:00      
            I'm using the NXP LPC936            01/01/70 00:00      
         Your drawing is still in the frequency domain            01/01/70 00:00      
            Yes, you're correct, and I undestand, connecting...            01/01/70 00:00      
            Where I'm at and software recap            01/01/70 00:00      
               more step-by-step            01/01/70 00:00      

Back to Subject List