group-icon
Arduino + Raspberry Pi Lovers
Discussion and Q&A about Arduino and Raspberry Pi projects.
186 Members
Join this group to post and comment.
Kunal Gokhe
Kunal Gokhe
Mechanical
01 Feb 2019

Speed up I/O Access for Arduino

On every AVR based Arduino board, the clock speed is 16MHz. Each instruction on the controller completes under 4 cycles, so theoretically, you can do 4 million instructions in one second. However, the I/O speed is much slower. That's because of the digitalWrite and digitalRead functions. Each time you execute them, a lot of additional code executes also. The additional code is responsible for detecting & mapping the numerical pins to a output port. On every microcontroller, the I/O devices are mapped in groups of 8 pins to ports, which are special registers in the controller.

So the question arises, how slow is it then? In my measurements, the maximal output speed of the following program is around 116-117KHz:

void setup() 
{    
   pinMode(13, OUTPUT); 
}

void loop() 
{    
   digitalWrite(13, LOW);    
   digitalWrite(13, HIGH); 
}

We can improve our program by wrapping the loop code in an infinite loop. It will speed up the execution a litle bit, because the CPU has to do less function calls. The improved loop: 

void setup() 
{    
   pinMode(13, OUTPUT); 
}

void loop() 
{    
   while (1)    
   {        
     digitalWrite(13, LOW);        
     digitalWrite(13, HIGH);        
     //required if you do serial communication       
     if (serialEventRun) serialEventRun();    
   } 
}

In my measurements, the output speed was around 126-127KHz, which is 8.6% faster, but we can improve it. To really top the output speed, we will have to use low level port access. To use low level poor access, we will have to read the details of the microcontroller used on the board, but it just takes away the beauty of the Arduino platform. So I wrote a library for that purpose, that speeds up I/O access.

It has some limitations. Mainly that it only supports the Uno, Nano, Leonardo, Mega, and Attiny45/85/44/84 models. The code for the library can be found webmaster442/ArduinoExtensions.

void setup() 
{    
   pinMode(13, OUTPUT); 
}

void loop() 
{    
   while (1)    
   {        
     //WriteD13 writes Pin 13. D means digital.        
     //to write to pin 8 use WriteD8 function.        
     WriteD13(HIGH);        WriteD13(LOW);        
     //required if you do serial communication        
     if (serialEventRun) serialEventRun();   
   } 
}

It provides inline functions for fast I/O access. The following example produces an output signal around 1Mhz, which is really nice. But, if you put the code in the earlier discussed infinite loop, it gets even faster. With it, you can produce an output signal around< 2,4MHz.