Click here to Skip to main content
13,832,223 members
Click here to Skip to main content
Add your own
alternative version

Tagged as


12 bookmarked
Posted 13 Aug 2016
Licenced CPOL

Faster and More Efficient GPIOs on Arduino Without Modifying the Sketch

, 13 Aug 2016
Rate this:
Please Sign up or sign in to vote.
I am presenting a new implementation of Arduino GPIO functions which are faster and more efficient than the original functions.


Arduino comes with built-in GPIO functions which serve the purpose well. But it becomes clear that these functions are bulky and slow, after we compare their performance with other more efficient implementations. The argument that is often presented in favor of these inefficient functions is that they are primarily meant to be used by the hobbyists, which often value ease-of-use more that efficiency.

Here, I am not presenting the fastest implementation, but rather an implementation that is efficient while maintaining the same ease-of-use of the original Arduino functions.


A couple of years ago while I was in university, I did a research to make Arduino libraries more efficient. Although I did succeed, but it was never used outside the laboratory. But now I have cleaned up the code, to make its use easier.

Using the Code

Using this code is fairly easy. All you have to do is copy the FastIO.h and FastIO.c to the Arduino core directory ([Arduino Folder]\hardware\arduino\avr\cores\arduino) and include the header file in your sketch.

#include <FastIO.h>

How It Works

Every pin on Arduino is attached to a pin of AVR microcontroller. These pins are divided among different ports. These ports are memory mapped at different addresses inside AVR's memory. In order to manipulate these pins, we have to write to these specific memory regions.

So, how does Arduino access its pins just by using a pin number? Actually, Arduino has saved all the required information to its memory. So, when you call digitalWrite on a specific pin, Arduino software searches its memory for the required information (the address of the port to which the pin belongs, and its place on the port). Arduino software also requires some additional information about whether the pin is also attached to a timer or not, if it is then, which timer and at which place.

All this overhead makes the Arduino's built-in function very slow. My implementation tries to ease off this overhead, by making all the required information readily available to the function. So that the function could start manipulating the pins as soon as it is called instead of searching for the information.

It works by storing the information in an array of 4 bytes.

  • The first byte contains the location of the pin on a specific port.
  • The second byte contains the address of the port to which the pin belongs.
  • If the pin also has a timer attached to it, then the third byte contains the timer pins which controls the pin function.
  • The fourth byte contains the address of the timer which is attached to the pin.

In case the pin doesn't have a timer attached to it, both the third and fourth byte will be equal to zero.

At function calls, a reference to this array is passed to the function, instead of simply passing the pin number.


The built-in digitalWrite function takes about 5us to change the pin state which is very slow for a microcontroller running at 16MHz (62.5ns period). My implementation makes this function 20 times faster by reducing the time to about 250ns. All this performance boost is achieved without making any changes to the sketch code, which is the main aim of this implementation.

As a bonus, the size of compiled sketch is also smaller when using my code (two kills in one shot).

As you can see here, near native speeds could be achieved without making any changes to the sketch.


Currently, this code is incompatible with the Arduino mega based boards. This is because I have reserved only one byte for the port address in the pin definition array, but in Atmega2560, some ports are located at addresses greater than 0xFF. This limitation could easily be avoided by reserving 2 bytes for port address and timer address. These changes will be made in a subsequent version once my implementation has been thoroughly tested on Atmega8/168/328P based boards.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Mohiuddin Awan
United States United States
No Biography provided

You may also be interested in...


Comments and Discussions

QuestionInteresting but have you seen this Pin
Jan Dolinay24-Feb-17 3:08
memberJan Dolinay24-Feb-17 3:08 
AnswerRe: Interesting but have you seen this Pin
Mohiuddin Awan25-Feb-17 4:08
memberMohiuddin Awan25-Feb-17 4:08 
GeneralRe: Interesting but have you seen this Pin
Jan Dolinay27-Feb-17 0:20
memberJan Dolinay27-Feb-17 0:20 
GeneralRe: Interesting but have you seen this Pin
Mohiuddin Awan27-Feb-17 14:33
memberMohiuddin Awan27-Feb-17 14:33 
GeneralRe: Interesting but have you seen this Pin
Jan Dolinay28-Feb-17 0:25
memberJan Dolinay28-Feb-17 0:25 
GeneralDoing something similar Pin
Chad3F18-Aug-16 12:46
memberChad3F18-Aug-16 12:46 
GeneralRe: Doing something similar Pin
Mohiuddin Awan19-Aug-16 3:48
memberMohiuddin Awan19-Aug-16 3:48 
GeneralRe: Doing something similar Pin
Chad3F19-Aug-16 18:43
memberChad3F19-Aug-16 18:43 
QuestionCareful in the future ! Pin
marcus obrien15-Aug-16 9:47
membermarcus obrien15-Aug-16 9:47 
AnswerRe: Careful in the future ! Pin
Mohiuddin Awan15-Aug-16 10:37
memberMohiuddin Awan15-Aug-16 10:37 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web02 | 2.8.190114.1 | Last Updated 14 Aug 2016
Article Copyright 2016 by Mohiuddin Awan
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid