Question about the length of commands (how many microseconds...)

Hey there,

I'm working with an infrared transmission at the moment and asking myself which delay instruction I should give the arduino when pulsing the led. It's about the thing that an ir led has to be pulsed at a high frequency so that the sensor is able to read the signal, in this case 38 kHz.

38 kHz is 26,31.. microseconds. So I want the led to turn on/off every 13 us. I use this code:

while (time+3>millis()) {
        digitalWrite(6, HIGH);
        delayMicroseconds(13);
        digitalWrite(6, LOW);
        delayMicroseconds(13);
      }

at the moment and it works. But I read at http://www.ladyada.net/learn/sensors/ir.html#testing_your_ir_detector that this has to look like this:

while (time+3>millis()) {
        digitalWrite(6, HIGH);
        delayMicroseconds(10);
        digitalWrite(6, LOW);
        delayMicroseconds(10);
      }

In this guide they used 10 us insted of 13 us with the explanation that digitalWrite() needs 3 us itself. Unfortunatley there is are further comments to this topic.

Can you confirm that? Is 10 us better than 13 us or something in between? Is there a reference for the duration of commands?

I would be very thankful if you could give me a hint.

Greetings

Alex

let the Arduino give you the answer herself… (assuming Arduino is female :wink:

void setup()
{
Serial.begin(115200);
uint32_t start = micros();
for (int i = 0; i< 1000; i++) digitalWrite(6, LOW);
uint32_t duration = micros() - start;
Serial.println(duration);
}
loop()
{}

assuming Arduino is female

I think that would be Arduin[u]a[/u].

Hello Alex,

If your application is time critical, try having a look at those things:

First, digitalWrite() is costly in time. Better to use direct port writing to fasten your app!

Second, if you want to be accurate within thime, maybe you should have a look at the Arduino Interrupt capability. You can configure one of the Arduino Timer to count, and to generate an action each time it reaches a specific value. I use this technique to do a task every 50us precisely. This has several advantages, the highest being to allow the main loop to continue abother task while the interrupt, executed every 50us. The example I used is given here, ate the bottom of the page.

robtillaart: let the Arduino give you the answer herself...

Thank you, I've tried this method and it turned out that I need 9 us to achieve 13 us with digitalWrite().

D4p0up: First, digitalWrite() is costly in time. Better to use direct port writing to fasten your app!

Thanks for the hint, I'll check this out now.

D4p0up: if you want to be accurate within thime, maybe you should have a look at the Arduino Interrupt capability

That would be a great method, but I think it will not work with my project. Correct me if I'm wrong but as far as I know you can turn on/off interrupts only for all the pins (with cli() and sei()). So I cannot get any ohter interrupts while my IR led is not transmitting (which I would need for a sensor in my circuit). (yeah I know, I could use a transistor for example, but this would be one more pin). So I think I better don't use interrupts.

Thank you both

This is the pain I'm currently trying to deal with. But from the AVR datasheet it appears that you can reenable Interrupts manually during an interrupt, in order for a higher priority interrupt to interrupt the previous one. Let me quote the AVR manual here:

When an interrupt occurs, the Global Interrupt Enable I-bit is cleared and all interrupts are disabled. The user software can write logic one to the I-bit to enable nested interrupts. All enabled interrupts can then interrupt the current interrupt routine. The I-bit is automatically set when a Return from Interrupt instruction – RETI – is executed.

However I never tryed it, and will this week. Shall this work, I'll come back with info on it :)

a_lehmann: Correct me if I'm wrong but as far as I know you can turn on/off interrupts only for all the pins (with cli() and sei()). So I cannot get any ohter interrupts while my IR led is not transmitting (which I would need for a sensor in my circuit). (yeah I know, I could use a transistor for example, but this would be one more pin). So I think I better don't use interrupts.

Thank you both

Consider yourself corrected. cli() and sei() are used to disable/enable the global interrupt flag, and if you do so that will disable/enable ALL interrupts. However, all individual interrupts have the ability to be enabled/disabled themselves as well. If you were to use a timer to generate your signal for your IR LED, you first have to enable this timer (since all timers are disabled by default, excluding what Arduino configures automatically). That timer could then easily be disabled and re-enabled at your discretion, all while leaving global interrupts enabled and functional.

In fact, I highly recommend utilizing a timer to generate your IR carrier signal and handling the timing for generating the command pulse trains yourself (though without the use of delay(), but that's an entirely different issue). This is the best case scenario for issuing command without blocking any other activities. If the Arduino's only task is to issue IR commands, then it isn't really an issue, but it's generally a good practice to develop code with this mindset because more often then not, you will be multi-tasking with the Arduino, and learning how to do that early on will not be wasted effort.