Arduino output delay - Page 1
Forum section: electronics / general

author: IvoS
author_rank: Frequent Contributor
timestamp: February 27, 2014, 04:44:31 pm
content: A Rookie question, delay question.All I have seen in a book so far is a delay of digital output written something like this:"digitalWrite (neg, LOW);delay (500);"which means the number is in milli-seconds. This brigs it down to 1ms, the lowest number I can write.?Now, how can I write or what would be the fastest achievable frequency output (duty cycle 50%) between high and low of the pin set as an output, and pin set as an input? How fast frequency can I feed to ATMEGA328P input to be able to distinguish between logic "1" and logic "0" ?

author: mariush
author_rank: Super Contributor
timestamp: February 27, 2014, 07:12:21 pm
content: Use PWM feature of the microcontroller...If you want to do it manually... you're limited by the complexity of the Arduino functions.In theory with a 16 Mhz clock, you have 16 million cycles per second. So in theory you hav 16.000 cycles per ms.Some instructions take 1 or 2 cycles to execute, a few take 3, going into a function and getting out of one takes 4 cycles.The DigitalWrite function will take a few microseconds to run by itself.If you go and look at the definition of the DigitalWrite function (it's in arduino\hardware\arduino\cores\arduino\wiring_digital.c) you will see that it's quite complex and does a lot of checking and calls some functions every time it runs.The compiler may optimize those checks away in some cases, but in the worst case it still take 10+ cycles just to set a pin high or low, something you could do in the main code of your program with just one instruction (1 cycle)Anyway... the point is that if you know how many cycles each instruction takes you can add 1 cycle instructions into a loop to get a really accurate pulse width modulation.

author: sigxcpu
author_rank: Regular Contributor
timestamp: February 27, 2014, 07:18:45 pm
content: For output, you can use this:https://code.google.com/p/digitalwritefast/. It is much faster than usual digitalWrite(), the single drawback being that you need to know the pin at the compile time (it is either #define-d or a const).

author: klr5205
author_rank: Regular Contributor
timestamp: February 27, 2014, 08:32:43 pm
content: Quote from: IvoS on February 27, 2014, 04:44:31 pmThere is also a delayMicroseconds() function, but maybe it's still too slow for your application? mariush's explanation is probably going to be as accurate as you can get.It might be worth noting that delays are ok if your program has nothing better to do while its waiting, but lots of times it is preferable to setup regular "ticks" in the program, whether that is by using timer interrupts or just polling millis()... although this won't be as accurate as code that forces an exact number of clock cycles between events.

author: westfw
author_rank: Super Contributor
timestamp: February 28, 2014, 12:58:44 am
content: There was a detailed discussion on this issue over in the Arudino forums (surprise! Did you know that Arduino has its own forums? They're actually pretty good.)http://forum.arduino.cc/index.php/topic,4324.0.htmlThis is several years old now, and so the exact timing quotes for digitalWrite() may be somewhat out of date (and don't include the newer ARM-based chips at all.) But the upshot is:1) the Arduino digitalWrite() function is quite slow (20-30x) compared to the maximum pin toggle speed you can achieve via other means.2) This is not because digitalWrite() is horribly written. It genuinely does a number of things that are useful and relatively difficult given the architecture. I would probably be very difficult to write a function that does the same things and runs significantly faster.3) The digitalWrite() pin-toggle rate is greater than 100KHz, and no one in the Arduino hierarchy is particularly interested in supporting more special-case versions that go significantly faster. (In particular, there is a lot of worry that it would be a bad thing if performance changed drastically depending on (say) whether the arguments were compile-time constants.)

author: dannyf
author_rank: Super Contributor
timestamp: February 28, 2014, 01:38:29 am
content: QuoteThe fastest you can get, under 16Mhz crystal and 1:1 prescaler is 8Mhz.and pin set as an input? Unknown, depending on the capacitance on that pin.QuoteUpto 20Mhz, depending on how you code it.

author: Dave
author_rank: Super Contributor
timestamp: March 02, 2014, 02:40:57 pm
content: Quote from: dannyf on February 28, 2014, 01:38:29 amNope.The fastest way to make it work is by writing the code in assembly.You would need two consecutive OUT commands (both taking 1 clock cycle), one to turn the output on, one to turn it back off, and a RJMP command to take the program back to the top (2 clock cycles).The maximum frequency would therefore be 4MHz (1/4 of the main processor clock). The duty cycle wouldn't be ideal, either (25% or 75%, depending on the order of the two OUTs). If you wanted it to be 50%, you would need to put two NOPs between the OUTs, reducing the frequency further (2,67MHz - 1/6 of the main clock).Quote from: dannyf on February 28, 2014, 01:38:29 amAgain, no.

author: dannyf
author_rank: Super Contributor
timestamp: March 02, 2014, 03:38:59 pm
content: QuoteHere is a simulation for 8Mhz. You can burn the attached code into your avr to verify.Code::100000000C9434000C943E000C943E000C943E0082:100010000C943E000C943E000C943E000C943E0068:100020000C943E000C943E000C943E000C943E0058:100030000C943E000C943E000C943E000C943E0048:100040000C943E000C943E000C943E000C943E0038:100050000C943E000C943E000C943E000C943E0028:100060000C943E000C943E0011241FBECFEFD8E04C:10007000DEBFCDBF0E944A000C944D000C940000DE:10008000259A82E584BD81E485BD17BC8AB180666E:0E0090008AB908950E944000FFCFF894FFCF78:00000001FFQuoteThe above code was entirely written in C.QuoteThere are quite a few ways to get it done.The dumber of those approaches requires just one avr instruction. I can post that as well if you so desire.QuoteAgain, the fact that you cannot get it done doesn't mean it cannot be done.

author: dannyf
author_rank: Super Contributor
timestamp: March 02, 2014, 03:57:55 pm
content: I just wanted to add that that one instruction / statement is written entirely in C,Hopefully you can figure out how it is done.

author: mariush
author_rank: Super Contributor
timestamp: March 02, 2014, 04:27:59 pm
content: You can fill the full flash memory with a pin = not pin instruction and right at the end you can do a jump to the beginning.You'll have a close to ideal 10 Mhz square wave (if you use a 20 mhz oscillator, because the atmega can do it).

author: Dave
author_rank: Super Contributor
timestamp: March 02, 2014, 04:41:28 pm
content: I won't bother disassembling the hex code, but I'm going to make an educated guess, that you are using the timer to get your 8MHz signal. I have to admit it, I did not think of that, I thought of toggling entirely through code.Quote from: dannyf on February 28, 2014, 01:38:29 amQuote from: dannyf on March 02, 2014, 03:38:59 pmThat AVR only goes up to 20MHz in normal conditions. The sampling frequency needs to be at least double of the sampled signal, if you want to detect all of the high and low states (slightly higher, if you take into account clock jitter and other inconveniences). That is just sampling, you would also need code that uses that sampled data to do something useful.

author: dannyf
author_rank: Super Contributor
timestamp: March 02, 2014, 04:58:59 pm
content: QuoteBingo!That's in the ballpark, with two crucial details yet to be figured out:1) which pins?2) which avrs? This approach works with a small collection of avrs only.QuoteThat's still a guess.QuoteThere are other ways to do it as well.QuoteWithout the code, it wouldn't be toggling those pins so it is definitely toggling entirely through code.

author: dannyf
author_rank: Super Contributor
timestamp: March 02, 2014, 11:37:18 pm
content: There are lots of ways to generate high frequency signal out of an avr or a mcy:. Bit banging the output data register.. But banging the input data register.. Use a timer.. Use a pwm generator.. Use hardware spi, either the sck or mosi. Works well on mcus with TX buffers. It can also be used as low resolution pwm or one - wire device.. Use hardware uart. Similar to spi.. Use internal oscillator plus clock out pin.. Use nco or onboard logic (pic)....