Arduino · 12 September 2013 0

Optimize the sketches

When we talk about the sketch optimization, not only we refer to the need of writing good code but also to use specific tools, to optimize the microcontroller’s resources. As we have said several times, the memory of the ATmega328P of out Arduino boards is limited, and a good programming practice is to save it as more as possible.

Let’s start analizing the “Blink” sketch from the IDE…

It’s certainly the most famous sketch. Here it is (without the initial comments):

int led = 13;

// the setup routine runs once when you press reset:
void setup() {                
    // initialize the digital pin as an output.
    pinMode(led, OUTPUT);     
}

// the loop routine runs over and over again forever:
void loop() {
    digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(1000);               // wait for a second
    digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
    delay(1000);               // wait for a second
}

It works and does its job. Memory occupation? 1,072 bytes of Flash. Not a lot of space, you will say. Too many, for the few things it has to do!

The problem resides into the predefined functions of the Arduino core, pinMode e digitalWrite. They simplify the code writing hiding at the user some thing that they need to be done. For example, pinMode has to convert the pin number into the corresponding phisical pin of the microcontroller. Furthermore, digitalWrite not only makes this convertion but also checks if it is a PWM-capable pin and, if yes, deactivates the PWM signal on such pin, even if that signal isn’t present.

All of these controls are translated into instructions to be compiled and stored into Flash. Now, if we direclty manipulate the logic ports of the microcontroller, our “Blink” can be lighter:

int led = 13;

// the setup routine runs once when you press reset:
void setup() {                
    // initialize the digital pin as an output.
    //pinMode(led, OUTPUT);     
    DDRB |= (1<<5); 
}

// the loop routine runs over and over again forever:
void loop() {
    //digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
    PORTB |= (1<<5);
    delay(1000);               // wait for a second
    //digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
    PORTB &= ~(1<<5);
    delay(1000);               // wait for a second
}

This sketch when compiled occupies 654 bytes of Flash, 418 bytes less! A gain of 39%, thanks to the fact that 3 of the 5 instructions of the program referred to the ports’ manipulation. If we optimize longer programs surely the gain won’t be so significant but we will be able to recover some hundreds of bytes that, on sketches with sizes close to the limit of the Flash of our 328P can have their importance.

A last notice about the sketch. The original “Blink” does use the “int” type for the variable led. Well, that’s not a sintax error per se but it can lead to a RAM waste. It is better to use the “byte” type, that uses 1 byte of SRAM instead of the 2 bytes of the “int” type.