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 ?
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.
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.
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.
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.
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.
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.
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.