Arduino I/O Speed Breakdown

[Jee Labs] has worked out how long it takes for an Arduino to perform various I/O operations. Predictably, analogRead() takes the longest, followed by analogWrite(). Arduino really falls behind when it comes to digital pin I/O: digitalWrite() takes a whopping fifty times longer than a direct bit write to a port register!  This is something to take into consideration when you are looking to do some beefy I/O with an Arduino. Perhaps this I/O performance will be addressed in the future with Arduino 1.0.

45 thoughts on “Arduino I/O Speed Breakdown

  1. Yet another reason I use the plain ATMega chip and a $34 programmer…If you’ve done a few projects with the Arduino, you can handle stepping into this more cost effective (and much faster) world…

  2. Arduino is great as a beginner tool or to do some simple hacks without fiddling too much with electronics. It is worth remembering however that it is a fairly crappy ‘n cheap chip when compared to the state of the art.

    When an Arduino has too low performances for your project, it is time to open your wallet again and to wander in the $100+ world where many wonders awaits you.

  3. This might have something to do with why I couldn’t get decent Software PWM. I was looking at doing software PWM because I needed the timer for decoding IR remote signals. Never did get it going, so IR was sacrificed.

  4. @Iv: “It is worth remembering however that it is a fairly crappy ‘n cheap chip when compared to the state of the art.”

    It is not the chip (microcontroller) that is inefficient for I/O, on the contrary, the ATmega chip is extremely fast at digital bit-twiddling I/O. It is the Arduino software layers that make I/O slower with calls like digitalWrite() since it’s no longer, apparently, 1 or 2 machine instructions to perform a write.

    While I think the ATmega is a great chip, I would really like to see Arduino with a Cortex-M3 MCU instead; then it would be an even better prototyping platform.

  5. @josh, $34 for an avr programmer 0.o you paid way too much, an arduino in its own right can be an avr isp programmer (google arduino isp programmer) or you could substitute the arduino and use a $14 ftdi breakout board from sparkfun. Incredibly simple to build, doesn’t require a circuit (I’ve been using mine in a breadboard, just the xtal and appropriate caps.)

    The chip is fine, its the associated IDE/arduino libs/core code that let it down on the pure IO functions, but then if you wamt that raw speed and know why it is happening you are more than a beginner and happy to use avr-gcc etc, port manipulation/asm to speed things up a bit, and you’re probably not using the arduino IDE anymore so your chip is infinitely faster already.

  6. If you *really* want guaranteed, low-latency I/O programmable from a high-level language, you need to check out XMOS (www.xmos.com).

    Pin I/O can be controlled with static timing guarantees at ns-order resolution at compile time. Coupled with 8 hardware threads this gives you a huge degree of guaranteed-performance I/O capability.

    The Devkits are sub-$100 and SparkFun have even made their own:

    http://www.sparkfun.com/commerce/product_info.php?products_id=9428

    Would be very interested to see a comparison of I/O capabilities across Atmel/ARM/XMOS. Any takers?

  7. You can not be serious!!!
    This is a discussion as lame as software stack overflow/underflow protection.
    Just look at the code and think for yourself.
    From the arduino Google code:
    void digitalWrite(uint8_t pin, uint8_t val)
    {
    uint8_t timer = digitalPinToTimer(pin);
    uint8_t bit = digitalPinToBitMask(pin);
    uint8_t port = digitalPinToPort(pin);
    volatile uint8_t *out;

    if (port == NOT_A_PIN) return;

    // If the pin that support PWM output, we need to turn it off
    // before doing a digital write.
    if (timer != NOT_ON_TIMER) turnOffPWM(timer);

    out = portOutputRegister(port);

    if (val == LOW) *out &= ~bit;
    else *out |= bit;
    }

    Do you expect it to be fast!

  8. @skitchin: Search around for using a UART as a CIR demodulator instead. The trick is to set the baud rate such that the carrier looks like valid data, then all you have to do is mark the time difference in the UART ISR. The actual data received is irrelevant. Then you can have your timer back.

  9. @Devlyn Thyne / Hack a Day:

    I think it would be great if you guys did a tutorial on how to ditch the Arduino IDE and/or their abstraction layer. The IDE really frustrates me so I’d love if I could use Visual Studio from now on. Is it just me or does anyone else hold shift while backspacing(like if you made a typo), and then accidentally delete lines of code?

    Also, interesting blog post http://richardsphotoblog.blogspot.com/2009/09/using-winavr-with-visual-studio.html

  10. @Skitchin
    that backspace thing is the main thing that bothers me in the IDE itself… the ide bothers me in that i often have a hard time getting it to run on my 64bit linux box…

  11. Having and knowing the timings is useful.

    The discussion about what’s bad because “it’s quick” and what’s not really isn’t.

    Your job as a software engineer is to determine what trade-offs you need to do your job. If you can use digitalRead/Write (or whatever API) and make your code portable and reusable (because that’s important) then you do.

    If you need speed over portability then you have the option of direct port access.

    All computers wait at the same speed, so squeezing cycles at the cost of maintainability and portability just for the sake of it, is not the best choice.

  12. @Skitchin

    The options for the IDE allow you to use an external editor if you want.

    Or you can just code in any editor then just use the IDE to do the loading (because the liquidware version is quite nice with it loading multiple boards at once). The sketch files are just text.

  13. JCS hit it right, the Arduino software is not supposed to be fast. It only runs at 16MHz and every one of those digitalPinToPort calls uses pointers. Pointers are incredibly inefficient in the little AVRs and easily take 20 cycles just to evaluate. The point is that they can easily change hardware settings and use the same IDE by just changing the definitions of digitalPinToPort. It’s a sacrifice in speed so that you can be guaranteed your software runs on all the platforms.

  14. I did some work on the hardware core for the Illuminato (Atmega645 chip) from Liquidware to implement 6 pins of software PWM and a few other features. Working through that, I got pretty familiar with how the background stuff for Arduino code works.

    The “hardware abstraction layer” that is provided isn’t meant to be the pinnacle of efficiency, but rather to make it as easy to program as possible. That’s what people new to hardware programming love about it and, inversely, that’s what people who know a lot about direct chip programming hate about it.

    Like JCS stated, moving all of the ports/registers into arrays so that they can be easily addressed by “pin” (array index) number will never be as fast as direct port manipulation. But like nilkoproductions and TJ said, it also enables you to use the same sketch on various arduino chips. If you use direct port manipulation and change chips, you need to go to the datasheet for the chip and change the port/bit numbers to match, which can be a pain for novices.

    Arduinos are a learning/prototyping/testing tool, not a production environment. If you need production quality, best to stick with direct chip programming and avr-gcc. More work but better results.

  15. I’m surprised this needed to be measured or evaluated – if you need really fast port control, don’t use an Arduino. 4134 ns port reads are more than fine for 99% of Arduino projects, and I doubt anyone who needs faster performance would even try to use an Arduino.

  16. It depends on what you are doing I guess. I use the arduino bootloader for the sake of lazyness. Most of the times uC memory is NOT a problem for me, however the extra time digitalRead() and friends take in comparison to direct register access is.

    So, if my prototype needs fast code (capacitive input, controlling a big charlyplexed array of leds, …) I mostly disable all uC functions I don’t need (like the timer that is heavily used for delay() ) and I use direct register access instead.

    Your time matters and is valuable.. Same thing happens in computer programming. If you really need to juice your CPU, then a C program with inlined MMX/SSE asm is OK. Otherwise a python program might just fit your needs.

  17. @Brett Nothing stops you of flashing a different bootloader on arduino hardware. From there, you can program in C using avr-libc and do “fast port control”.

    Just because you own arduino hardware, it doesn’t mean you have to use the arduino programming environment, does it? We are not talking about M$ solutions here :)

  18. The real issue here is that all this pin validation takes place at runtime. That’s just incorrect. If the main Arduino developers are concerned about users failing to use output ports correctly, or portability, then their preprocessor should be boiling all that down to a direct port access before compile.

  19. Maybe somebody should put together a fast I/O library that uses only hard coded macros for the digital stuff. A pair of functions for analog reads would be nice, one to start, and another that checks to see if the process is finished, allowing other code to execute while waiting.

    Its open source, if you don’t like it, don’t complain, just fix it.

  20. @Skitchin
    Software PWM is easy if you use AVR studio, look at Atmel’s AVR136: Low-jitter, Multi-channel software PWM application note, it has example code that works great, using it to drive 4 RGB LEDs from one ATMega328p.

    Also, you don’t have to get rid of the Arduino bootloader if you want to use AVR Studio compiled code, the Arduino bootloader is avrisp compatible, so just use AVRdude to program the Arduino with your .hex file from AVR Studio. I burn the Arduino bootloader to bare AVR’s just to make uploading programs easier.

  21. @KillerSpud
    Who needs a library for fast read/write? There are port registers, use them. Any library is going to have to check to see which register and bit a pin corresponds to, so you can call FastWrite(1, HIGH). Or will fill the memory with symbols, and leave you with a large set of macros that look more like Pin1(HIGH). The first method, is exactly what the Arduino library is doing. The second is going to get you only one pin write per time interval, where the registers will give you 6 to 8, depending on the register. Plus, a library like that would have to be re-mapped for each different Arduino out there, or do a lot of compile time manipulation.

    And if you are down to the point where you are actively worrying about the speed of the Arduino read/write operations, and want it faster than the register read/write calls, then you have probably stretched it as far as it will go.

    I suspect, however, there are some people using it that do not understand why an analogue read takes more time than a binary one, and are going to read this and assume it is a problem specifically with the Arduino. That issue might call for another newbie tutorial on why analogue is such a pain in the digital realm.

  22. @Quin: The only reason to keep using a library is to preserve the abstraction layer. Sure, the library will be device specific, unless you can dig out all of the pin and port references at compile time (I have no idea how to do that). But simply requiring a different library for each of the devices would still keep your code easily portable.

    I do wonder why uC manufacturers insist on using successive approximation encoders instead of flash encoders, how much more expensive would it be? Even if it is still multiplexed? I guess it is good enough for most applications.

  23. @quin & killerspud: The SPI port is pretty good for fast single bit output if you get it going (and sacrifice the spi clock pin). It’s buffered (you can do other stuff while its sending data such as read large chunks of data from progmem) and you can transmit at up to 1/2 the clock speed (8mbps).

    I used it in a 40×20 character 1 bit per pixel serial terminal with the font stored in flash (actual res of the lcd panel was 320×240).

    I’ve recently decided to hang up the arduino and get a programmer as i’m happy plodding through data sheets to get my code to run faster. Its surprising what those chips can do if you really push.

  24. @MrX: You mean Apple…

    Actually I ordered an Arduino (i guess for 15€ it was rather a clone…) today just because I like the Hardware. No need to make a new PCB for every little project. And i think I get rid of the bootloader anyway.

  25. It is possible to do much better, but still fully maintain Arduino’s abstractions. I’ve been working on this in Teensyduino, which now has much faster I/O using the same abstractions. I’ve even tried, really tried, to contribute some of these optimizations back to Arduino. They just don’t seem so interested.

  26. @Reggie

    IMO, spending $34 for an AVR ISP mkII is well worth it.

    It’s much faster than anything else (8MHz SPI clock… actually too fast for normal AVRs) and I’ve done all kinds of horrible things to it without it breaking. Well, I haven’t plugged it into 120V mains and don’t intend to anytime soon.

  27. @KillerSpud
    The ADC question… It was explained to me in the old HC11 days (one of the first MCU’s with ADC). First combining precise analog electronics circuits in a digital chip is quite difficult (and it has only been done “recently”). Second is chip area, for a 8 bit flash ADC you need 256 comparators, 256 precision resistors and a 256 input encoder, for a 10 bit one (AVR) you’ll need 1024 of each of those. With a capacitive (or R-2R ladder) ADC you need 1 comparator (that you can afford to improve in terms of performance, stability etc), 8 analog switches (easy to do in digital logic) and 16 capacitors/resistors…

  28. I found that I needed to use direct port manipulation when doing some extensive shifting-out (~4000 toggles per update), and some software that did a lot of things in the background. ADC is also very slow, but lowering the prescaler helps quite a bit.

    I actually used AVR Studio 4 before arduino, and generally it was a pain due to the lack of extensive libaries that Arduino has. So I just switched to Arduino, and still use the original low-level commands for speed.

  29. Is anyone _really_ surprised that a platform designed for ease of use is slower than a platform designed for ‘conventional’ programming, also considering it is ‘free’?

    It seems to me that most people who use the Arduino platform are not as likely to be hindered by it’s performance, and those who are probably need to step up to the next level anyway.

    I’ve never been a big fan of gcc, I find it clunky at best. A moderate investment in a decent compiler that provides similar io libraries is the way to go imo.

  30. Uhh or just buy a $1 AVR and program it with gcc. Systems like that (Arduino or the basic stamp) are very limited and meant for beginners.

    The only justification for getting an Arduino is that it’s easier to get started with for a n00b. Or at least people think it is. My opinion is that if you’re starting out, you’re better off with getting an AVR Dragon and a breadboard. That will actually allow you to do real debugging, which is incredibly valuable, and the cost would be less than two Arduinos.

    I’ve really been puzzled by HAD’s obsession with Arduino. One would think that real hacker minded people would not fall prey to fads and hypes.

  31. gcc is not easy to setup for beginners, and it’s still a pita to find good io libraries for more experienced users.

    It’s nice to have open source alternatives – they’re certainly cost efficient – but a decent compiler like CodeVision or Imagecraft is much easier to use, generally compiles more efficiently and include nice io libraries.

    For beginners, it’s well worth looking into Bascom AVR Basic – it compiles to fast native code and has a _substantial_ io library that’s a breeze to use. The free demo compiles up to 4k code.

  32. “I think it would be great if you guys did a tutorial on how to ditch the Arduino IDE and/or their abstraction layer.”

    Google avr-libc and check out the demos. Also hop over to avrfreaks.net.

    Hardware-wise, all the Arduino is is a minimalistic ATMegaXX8 development board. The ATMegaXX8 series are VERY capable CPUs if you learn how to program in straight AVR-GCC.

    An advantage of AVR-GCC is that it’s easy to port your code up/down to a larger/smaller AVR than the Arduino IDE. I prototyped a sigma-delta modulator on a Mega168 (Older Adafruit Boarduino model – new ones are 328s) and then ported it down to a Tiny85.

    Arduino hardware is a GREAT way to start with AVR programming, even if you skip the Arduino IDE. My reccommendation is Adafruit Boarduino + Adafruit USBTinyISP, total cost for board and programmer is about $40 + shipping.

  33. It’s important to recognize just what you get for the extra cycles:
    1) The port being read is a variable
    2) the bit being read is a variable
    3) the “pin number” is variable and is mapped at runtime to the appropriate port and bit.
    Given the fundamental underlying architecture, these are relatively “expensive” features to implement. One of the reasons that faster alternatives are resisted in the core libraries is that they’d tend to make timing “complicated.”
    It would be interesting (perhaps) to take a source statement like “if (digitalRead(1))” and walk it through various stages of (de-)optimization, starting with the single instruction/2cycle SBIS and adding features until you get the existing Arfduino function…

    (meanwhile, parties are invited to check how many reads per second of, say, a parallel printer port bit, they can get from their multi-GHz P4 systems. Bet you’ll be surprised!)

    (and don’t forget that the big “competitor” of Arduino is the Basic Stamp. (so how come I’ve never seen a HaD article on something using a Basic Stamp?))

  34. @WestfW: “how come I’ve never seen a HaD article on something using a Basic Stamp?” — because they are extremely overpriced and underpowered compared to AVR/Arduino/PIC (in fact, the $99 Basic Stamp is based off of like a $5 PIC chip)

  35. Hi to everyone, i want to make an analog to digital arduino converter with delta modulation but i stuck with the code and specific with the delta modulation code.Any ideas???I send data to the computer and graph it in Processing.

  36. I have the atmega2560 arduino board. I left the arduino bootloader alone as I use avrdude to program it from the usb virtual com port using avrdude. I use a command line such as this…

    avrdude -c STK500 -p armega2560 -P /dev/tty.usbmodem621 -U flash:w:blink.hex

    I use avr-gcc direct to generate the hex files – don’t bother with the arduino IDE stuff. Look at the following page for general directions.

    http://www.nongnu.org/avr-libc/user-manual/group__demo__project.html

    and the following for info on how to do a LED blinker using timer interrupts…

    http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=50106

    I had to modify some of the register names and numbers as the articles refers to a 1MHz AVRMEGA16 as opposed to my 16MHz atmega2560. It was easy to figure out what I need to change by referring to the atmega2560 data sheet (http://www.atmel.com/dyn/resources/prod_documents/doc2549.pdf)

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.