high precision micro second timer

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

Hi
Im using Timer0 for a high precision microsecond timer I need.
Im using the mega2560. And AVR-GCC.
My setup is here;

	TCCR0A |= (1 << COM0A1) | (1 << WGM01);
	TCCR0B |= (1 << CS00); // no prescale
	TIMSK0 |= (1 << OCIE0A);
	OCR0A = 15;
	sei();

In the ISR I am just incrementing uSeconds flag;

The defintion of the variable is in the header file:

extern volatile int uSeconds;

and initiated in the .c file:

volatile int uSeconds= 0;

I store its value to a struct variable of type int:

		ATOMIC_BLOCK(ATOMIC_FORCEON)
		{
			map[count].time = uSeconds;
		}

Then I print the value to my terminal. I have two buttons that are pressed almost at the same time and I want to know exactly how long it is between them.
The above seems to work however I get a lot of negative values.
I tried having the uSeconds variable being unsigned, but it didnt seem to make much difference.
Here are the values I have spaced them to show presses of the buttons:

-20502
-13850

-31218
-25919

30040
-30243

20034
26217

18671
25051

So the first value of each pair is the first button being pressed, the second, is the seconds button being pressed.
Why are some values negative?

Oh and when the timer does overflow, is there a way to know that, so that when I minus the second values from the first, I dont get a negative number?

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

I can measure 20ths of a microsecond with a 20MHz xtal. Just turn on the timer and let it run. Read t1=TCNT1 at the beginning and t2=TCNT1 at the end and deltat=t2-t1 in 20ths of a microsecond, up to 65535 of em.

Imagecraft compiler user

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

Quote:

Why are some values negative?

How are you printing? If a printf variant use u not d.

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

Quote:

   TCCR0B |= (1 << CS00); // no prescale
   TIMSK0 |= (1 << OCIE0A);
   OCR0A = 15;

You can't run interrupts at that rate. Even with a single rjmp+reti you will spend almost all CPU time in the interrupt handling.

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

OK changing from % d to % u solved the negative issue. Thanks - should uSeconds variable be int or unsigned int?

Lastly what interval is ok to have a timer running at? 10uS? 100uS?

Any ideas on how to handle when it overflows?

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

As bobgardner notes, you've already got what you need in the hardware, no need to choke the AVR with 10^6 interrupts every second. Decide what resolution you need (any more than the jitter it takes you to read the buttons is wasted), set the prescaler accordingly, and grab the timer value for each button event. As long as the 2 events are < 65536 prescaled clocks apart, you will always get the right interval by subtracting the first value from the second value, as unsigned 16-bit integers. The result will be correct even if the timer overflows between the first and second event.

The reason you're seeing negative numbers is because you're using a print routine that thinks it's looking a signed values. You need to tell it that the values are unsigned.

Last Edited: Thu. Feb 21, 2013 - 09:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Why are some values negative?

Because >>you<< told the compiler to use a signed variable, and are probably printed in signed format.

Note that the AVR has facilities to aid in what you are doing, called Input Capture (ICP). Then you don't need to try to maintain a microseconds counter.

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

theusch wrote:
Quote:

Why are some values negative?

Because >>you<< told the compiler to use a signed variable, and are probably printed in signed format.

To expand on this a bit for the OP, if you have the bit pattern 10110111 01101101 in two consecutive bytes of memory, is there any way to know if it represents a signed 16-bit int, an unsigned 16-bit int, 2 8-bit values, 2 8-bit characters, a bunch of 1-bit flags, etc?

The only way to know is for you to specify correctly and consistently. If your program writes some data as ASCII characters, and then later tries to print that data as a 32-bit signed value, you're going to get garbage (for the rare exceptions you can use C unions or equivalents). A subset of this is that you can't be sloppy between signed and unsigned, or you'll get bitten exactly as you did.

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

a.mlw.walker wrote:
OK changing from % d to % u solved the negative issue. Thanks - should uSeconds variable be int or unsigned int?

Well, depends how you want to understand ticks counted by timer. Anyway, time between two events is just a relative difference of two absolute times, so I bet time between evens would always be positive.

a.mlw.walker wrote:

Lastly what interval is ok to have a timer running at? 10uS? 100uS?

Do you mean at what interval to have the timer running at, or what interval have it generate overflow interrupts? How precisely you need to measure time?

a.mlw.walker wrote:

Any ideas on how to handle when it overflows?

Use a larger variable? If previous time is larger than current time, there must be an overflow. But it still does not tell you how many overflows has occured, unless you use a larger variable.

I don't think counting by increasing a variable in timer interrupt at 10us or 100us rate is very sane. Normally you would run the timer as fast as you need and read the timer counter value when button is pushed. The overflow interrupts would only handle timer overflows. This way, you can have the timer running at 20MHz, but generating overflows every 65536 ticks or only about 305 times per second.

Can you use input capture feature for this?

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

Are you suggesting that the polling algorithm that is checking the buttons sets a flag to 1 when any button is pressed, then when the second button is pressed record the value from the timer? I understand how that could work. Im not exactly sure what you mean by this and how exactly that gives you high precision timings:

Quote:

This way, you can have the timer running at 20MHz, but generating overflows every 65536 ticks or only about 305 times per second.

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

What precision do you need? Formula 1 is timed down to a millisecond.

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

What are you timing? The time between the falling edge of one input? Here's how I do it:

char but,butos,butl;
unsigned int t1,t2,dt
.
.
. //somewhere in the main while loop
  but=(PINB & 0x01)==0; //button is pressed
  butos=but && !butl;   //oneshot of button pressed
  butl=but;             //remember last pass
  if(butos){
    if(t1==0){
      t1=TCNT1;
    }else{
      t2=TCNT1;
    }
    dt=t2-t1;
    t1==0;
    //print dt here
  }

Imagecraft compiler user

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

The whole problem seems ill formed. Timing down to the microsecond? What about switch bounce?

Martin Jay McKee

As with most things in engineering, the answer is an unabashed, "It depends."

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

How does switch bounce affect it? Even if the gap between the two button presses was an hour apart, it may be necessary to have microsecond resolution.
Anyway, as I mentioned, for a keymatrix, where the user may press more than one key at a time, what is a good interval between polls? 10uS?

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

Surely you want to bring some common sense into this topic.

I am guessing that your key-matrix is a PC keyboard. i.e. something similar to what I am typing on.
Typically, you want to detect when a key is pressed and when it is released. e.g. so I can type different letters.

You might scan the matrix every 10ms.
You might regard 50ms as a valid state.
i.e. the matrix reads the same value for 5 consecutive scans.
You might regard 500ms as an intentional 'repeat' i.e. 50 consecutive scans.

Most physical switches will bounce to a certain extent. Most human beings can only type at certain speed. Incidentally, I am a human being.

I very much doubt that anyone can manage to press a key in 10us. Obviously machines can.

Note that you may need to vary your scan interval, debounce period, etc if you have heavy switches or gloved hands.

If you want to measure with microsecond resolution, you use a 16-bit timer's prescaler. e.g. div8 for 8MHz.
If you really want to measure intervals of an hour, you count overflows.

Most apps will have a regular 1ms or 10ms interrupt. Everything can work off of this.

David.

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

Now that we know what this is used for, let me ask you how fast do you think a person is able to push two buttons?
So this is only about reading buttons, instead of precision microsecond timing?

I would start by polling the buttons every 1ms, and most likely if a human wants to push two buttons at the same time, the AVR should wait at least 10ms after the first button to wait if there really is only one button pushed or is there going to be a second button too. Then you can tweak the values.

I think if the software reacts 100ms after pushing a button, I feel it does not respond fast enough.

Most likely a timer of 10ms is enough to read buttons. But if you have a button matrix, perhaps increase the row scanning rate so that you read all buttons once within 10ms, and process them only once when whole matrix is read.
How big is your button matrix?

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

If you want to measure the time between two switch closures to the microsecond (period of a shaft perhaps?) its a cinch you cant sit around rereading the switch trying to decide if the contacts are really closed. If they are closed this microsecond and they were open one microsecond ago, they are closed. Read the timer. Now wait for em to open up. Now wait for em to close again.Read the timer. How come EVERY question about switches on AVRfreaks immediately derails into a discussion of switchbounce? If the mechanical switch cant operate fast enough to read something going real fast, use an opto sensor. How bout someone write a program that proves switch bounce is a problem? Here's the setup: get a big ol milspec toggle with a big spring. Good candidate for bouncing. Write a program that looks for closure events with a variable delay between reads. A human cant actuate that switch faster than every 20ms or so, so no sense in looking for the edge more often that that. Program should report same number of closure readings as actuations. No errors. I have an 8x8 matrix that I read right from two ports. I read a row every 100usecs, so I scan the whole keypad every 800usecs.

Imagecraft compiler user

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

Quote:

So this is only about reading buttons, instead of precision microsecond timing?


Indeed, quite confusing, since it was re-iterated that
Quote:

Even if the gap between the two button presses was an hour apart, it may be necessary to have microsecond resolution.

So the question still remains in my mind: >>Why<< might it be "necessary" to have this microsecond resolution? To what purpose? Reaction-time testing, perhaps?

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

Quote:
How does switch bounce affect it? ... what is a good interval between polls? 10uS?
Consider that switch bounce can take milliseconds.

Regards,
Steve A.

The Board helps those that help themselves.

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

Why is switch bounce important? Because, as mentioned above, it can be on the order of milliseconds ( which would totally swamp the microsecond signal ) and it cannot even be "calibrated out" because switches do not bounce exactly the same with every press. Bounce is important because it marks a limit on how repeatable ( and, therefore how valid ) the "pressed" measurements can be. What, precisely, is the application. It may be that to get the required resolution ( i.e. down to microseconds ) multiple samples, duly filtered, may be required. It simply isn't reasonable to force microsecond timing on a human actuated button. Physical buttons aren't that consistent, and neither are people.

Martin Jay McKee

As with most things in engineering, the answer is an unabashed, "It depends."

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

Whether or not switch bounce is important depends on the application. If you want to know the time of the initial press, then you can mark the time of the first "on" and ignore any subsequent "on"s (at least until a predetermined reset condition is met). For instance, with an emergency stop button, you might not want to wait around until the button stabilizes. Or it might be a "who hit their button first" game show type thing.

Regards,
Steve A.

The Board helps those that help themselves.

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

Right. I have a keyboard, not like David's infact. I mean a piano keyboard. Its broken - atleast the electronics is.
Each key of the piano keyboard has two buttons. When you press the note down both buttons are pressed, but one very slightly after the other. The time difference tells me how hard the buttons were pressed down. If I press it down very fast, then the gap is microseconds.
I have adjusted my code to poll every 100uS. My ISR now looks like

ISR(TIMER0_COMPA_vect) {
		flaguS += 100;
		if (flaguS == 1000) {
		flaguS = 0;
			flagmS++;
		}
}

My polling loop now looks like:

void KeyMatrix::pollKeys() {
	uint8_t count = 0;
	for (uint8_t mask = 1; mask != 0; mask += mask) {
		PORTK = ~mask; //low one col with all others pull-up
		_delay_us(10); //after setting the state of a pin there may need to be a delay
		map[count].state = ~PINH;
		ATOMIC_BLOCK(ATOMIC_FORCEON)
		{
			map[count].time = flagmS + (int) flaguS/1000; 
		}
		count++;
	}
}

you can see the sort of times Im getting with a 100uS interrupt running here: (the values are in groups of 4 - two for down, two for release)

Quote:

0x80:0x0:6662
0x80:0x0:6860
0x0:0x80:9573
0x0:0x80:9808

0x80:0x0:15926
0x80:0x0:16216
0x0:0x80:18363
0x0:0x80:18554

0x80:0x0:28146
0x80:0x0:28475
0x0:0x80:32610
0x0:0x80:32977

0x80:0x0:39231
0x80:0x0:39565
0x0:0x80:43205
0x0:0x80:43643


The hex values just show me current state of PINH and last state of PINH. The last value is the time in microseconds.
So now just the millisecond counter will overflow. Do those numbers seem right however? They seem a little large for a number in mS?
Apart from that, I actually think they look ok - in terms of delta (6860-6662) = number of milliseconds between button presses ~ 200 uS.

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

So now you are going to do 88 channels of this simultaneously?

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

No, 25 notes.
I assume you mean an 88 key keyboard. If I were doing that, do you see a problem?

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

That would mean 176 inputs.

Regards,
Steve A.

The Board helps those that help themselves.

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

Its not a force sensing keyboard, its a velocity sensing keyboard. Short time between actuations is faster velocity (implies more force, more volume, more hi freq in the waveform). Have any data on the time diff between a pianissimo press and a sforzando press?

Imagecraft compiler user

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

Quote:
Right. I have a keyboard, not like David's infact. I mean a piano keyboard. Its broken - atleast the electronics is.
Each key of the piano keyboard has two buttons. When you press the note down both buttons are pressed, but one very slightly after the other. The time difference tells me how hard the buttons were pressed down. If I press it down very fast, then the gap is microseconds.

Tell us exactly how your keypad is wired.

It would have made the discussion a lot easier.

Yes, of course you can read the difference in time between a pair of keys.

What do actually want to do? Read it as a piano keyboard. i.e. identify key and 'speed'.

David.

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

Geez. I ask a question and..... crickets. OK, I'll act like a crazy man and try to answer my own question. "Hey Bob! How many usecs between key halfway down and key all the way down?". "Well Bob, lets say I'm playing 16th notes at 120 beats per minute. (Flight of the BumbleBee?) Thats 2 beats per sec, 32 notes per sec, 31250 usec between notes. Lets say the "press" takes the first third of the interval between notes, about 10000 usecs. If f=ma, and deltav = a*deltat and v += deltav, whats the v when t gets to 10000 usecs?" "Well Bob, I'm just a microcontroller programmer, not a physicist. If you ask this question on AVRfreaks, maybe some smart dude will tell you how many usecs between key halfway down and key all the way down when All the way down takes 10000usecs.".

Imagecraft compiler user

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

Thanks Bob. Nothing like having some hard numbers on which to make a decision. Alex, if you had told us that you were doing a piano keyboard first up we could've zeroed in on a solution much quicker. Don't get me wrong, we're happy to help, but just treat your resources a bit more carefully. You made a few posts and we're seeing a pattern emerging.

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

Except that what those numbers will be rely heavily on the hardware. Switches very close together will result in numbers much lower than switches farther apart. And I see no real reason to know actual force or velocity. Simple experimentation would be a better way to determine what values should produce a fortissimo or pianissimo.

Regards,
Steve A.

The Board helps those that help themselves.

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

But you need to know SOMETHING. If you play softly, the time between switch closures is x. If you hit the key 4 times harder, I'd want the note to be 12dB louder. I'd also expect the time to be 1/4th x. Is x 10usecs? 100usecs? 1ms? 10ms? 100ms? Certainly we should be able to get within a couple of decades of what it really is?

Imagecraft compiler user

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

We still don't even know what Alex wants to do.

It is straightforward to do a keypad, piano keys, event recorder, ...

But they are all different applications that require different solutions.

Yes, numbers are necessary for each app. However, you just write for the general case. Then adjust the parameters for reaction time, speed, frequency, ...

Good to see you are in fine health, Bob !

David.