How long to toggle an output pin?

I want to send a timed pulse out.. I'm trying to figure out how many microseconds to subtract from my "pulse" value to be as accurate as possible.

Subtracting the time for code overhead.

Anyone figured this out in the past?

digitalWrite(pulsePin, HIGH);      // Start pulse
delayMicroseconds(pulse);          // wait for it..
digitalWrite(pulsePin, LOW);       // End pulse.

Many thanks in advance.

-jim lee

Just an idea... To be as accurate as possible one would have to look at the assembler code I guess... Wouldn't it be simpler to just use an oscilloscope and calibrate the delay by directly measuring the pulse width ?

Direct port manipulation would reduce latency

What about setting up a timer together with direct port manipulation ? (that's a question rather than a suggestion, though)

I don't mind about latency that much, as long as I can calculate it out. I'd figured someone had, at some point, hooked a scope upto something like this and had the measured number handy.

Sigh, these things I wish for..

-jim lee

You mean something like "to obtain a 5ms pulse, use a delay of xx usecs" ?

Exactly, 5000 - offset for a 5ms pulse. I'm looking for that elusive offset value.

-jim lee

jimLee:
I want to send a timed pulse out.. I'm trying to figure out how many microseconds to subtract from my "pulse" value to be as accurate as possible.

Use a hardware timer. That's what they are there for. Then it will be exactly accurate. They can toggle output pins.

I did some posts about timers here:

Near the bottom (at present) is a one-shot timer used for a camera shutter.

The thing is, trying to adjust for microseconds in the way you describe overlooks the overhead (maybe 20 uS) which happens when Timer 0 fires to update the millis() counter.

Hi,

As many others have suggested, use the timers, these are implemented in hardware and are directly driven from the system clock, they are not effected by any code that may be running. If you try and implement the same in software, even if you had the correct offsets for the overhead your pulses might still be wrong because your code is not able to take account of any interrupts that might occur, your code will be stopped while these interrupts run leading to inaccuracy in your timing, the hardware timers are not effected by this.

If your look up Timer1 and the output compare registers OCR1A OCR1B in the datasheet you should be able to work out how to toggle a pin very precisely. If you want a steady pulse rather than a one off pulse, look up the waveform generation modes again these are in the Timer1 section of the datasheet.

Duane B

rcarduino.blogspot.com

Ughh.. I didn't want to get down and dirty into the assembly level. The bit that attracted me to the Arduino was it talked in c++.

-jim lee

Hi,
Its actually much easier than you might think. There are only three or four registers involved, you set them up once and then forget about them. If you give us some details of what you are actually trying to do, there may even be an off the shelf library available to do the dirty bits for you.

Duane B

rcarduino.blogspot.com

jimLee:
Ughh.. I didn't want to get down and dirty into the assembly level. The bit that attracted me to the Arduino was it talked in c++.

-jim lee

You didn't follow that link did you? There's no assembly there.

Hi,
To be fair, the concept of having direct access to and the syntax for setting the bits in the registers can look a bit unfamiliar if you are coming from a high level language.

Back to the OP, its so much easier than it looks, but again if you let us know what you ultimately want to achieve there is almost certainly a similar example such as nick's or an off the shelf library.

Duane B

rcarduino.blogspot.com

Well I went to the trouble near the bottom of my post to make a few functions to make it more C++ like. For example:

 // Mode 4: CTC, top = OCR1A
  Timer1::setMode (4, Timer1::PRESCALE_1, Timer1::CLEAR_A_ON_COMPARE);

That's setting a mode, a prescaler, and an action (clear pin on compare) all in one function call.

I'm trying to figure out how many microseconds to subtract from my "pulse" value to be as accurate as possible.

Accuracy and "really easy to do" tend to be mutually exclusive. We are trying to show you an accurate way, that is reasonably simple as well.

See this thread
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1230286016

How many pages? Ah well, it's an old topic. But a good one.

I did follow the link and looked at your code. Just sort of buzzed through it in a hurry and -thought- I saw assembly in there. I re-looked and realized I was wrong.

All I'm doing is playing around with my R/C servo library. And before every one jumps in, I KNOW there is one I can use already. I just like mine better. The code seems to be working fine, I was just thinking that the overhead time would be a well known value and would improve the accuracy. I guess its not.

-jim lee

The thing is there is no easy answer. It depends on a lot of things like what pin is used and what the state of the interrupts are at the time you are trying it. If you look at the source code for digital write you will find about 60 machine code instructions with all sorts of conditional jumps. So there is not a simple, or even a complex answer.

If you need precision then there are other techniques but simply compensating for the speed by adding a fudge factor is not going to work all the time. To take the simplest reason, it depends on if the millis() timer interrupt fires during your time in digitalWrite, if it does you get one fudge factor you need to use, if not there is another.