A few random tips for Arduino programmers. We cover saving RAM by storing text in program memory, making your programs easier to read, a technique to avoid being held up in delays, the C++ ternary operator and the watchdog timer.

Putting text strings in program memory saves ram

When you write:Serial.println("Hello World!");
the text ‘Hello World!’ is stored in two places:

Program memory

Random access memory (RAM)

The contents of RAM are lost every time the Arduino is reset, or the power is lost. Program memory is retained through reset and power loss, so at the start of each program, normal strings are copied from program memory into RAM so they can be used by your program.

Many Arduino boards don’t have much RAM though: there’s only 2 kb on the 328 chip used in the Uno, for example. So it is easy to run out of RAM if your program uses many strings or other variables.

When you write:Serial.println(F("Hello World!"));
the println function gets the text from program memory directly, using a temporary buffer that doesn’t eat up lots of precious RAM.

Constants make programs easier to read

Let’s say you want to annoy your little brother: attach a buzzer to one of the digital outputs of your Arduino and have it beep every few seconds. If the buzzer is attached to port 6, you’ll need to enter the 6 in three places:

setting the pin mode as an output,

turning on the buzzer, and

turning off the buzzer.

Instead, define a constant at the top of your program: const int BuzzerPort = 6;

C++

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

/*

Beeper

Makes a noise every few seconds.

*/

// A constant for the port that the buzzer is connected to.

constintBuzzerPort=6;

// These constants define how often the beeper sounds, and how long it sounds for.

constintBuzzerPeriod=5000;// [milliseconds]

constintBuzzerOnTime=100;// [milliseconds]

voidsetup()

{

pinMode(BuzzerPort,OUTPUT);

}

// the loop routine runs over and over again forever:

voidloop()

{

digitalWrite(BuzzerPort,HIGH);

delay(BuzzerPeriod);

digitalWrite(BuzzerPort,LOW);

delay(BuzzerOnTime);

}

Now, when you plug the buzzer back into port 7 (after your little brother has ripped the wires out to shut the thing up), you have to change the port in only one place.

Even better, the code is clearer. Straight away we know that digitalWrite(BuzzerPort, HIGH) should turn on a buzzer; with digitalWrite(6, HIGH), we need to remember what is connected to port 6.

So why use a constant instead of just a variable? Wouldn’t int BuzzerPort=6; work just as well?

Sort of: you still only have one number to change when the port changes. But when the ‘variable’ is declared as a constant, the compiler, the tool that turns your program into something the Arduino can use, won’t let you change it accidentally. So if you have const int BuzzerPort=6, and you try to change is value:

C++

1

2

3

4

5

voidsetup()

{

BuzzerPort=7;

pinMode(BuzzerPort,OUTPUT);

}

The compiler will report an error. So with constants, you can rely on the value never being changed after it is set.

No little brothers were harmed in the writing of this tip.

Delays are boring

The delay function stops your program dead. The classic blink program spends most of its time doing absolutely nothing:

C++

1

2

3

4

5

6

7

voidloop()

{

digitalWrite(LedPin,HIGH);

delay(1000);// yawn. Nothing is happening here.

digitalWrite(LedPin,LOW);

delay(1000);// zzz. Or here!

}

Think of all the great things you could do in that dead time: reading sensors, making noise, driving motors. Delays can be useful, but often they are just a waste of time.

There’s an easy way around it, but we’ll need a few variables:

C++

1

2

3

4

5

6

7

8

9

10

11

// Time stamp when the LED was last turned on or off.

longLastLEDToggleTime=0;

// Current state of the LED; true =&gt; on; false =&gt; off.

boolIsLEDOn=false;

// Time between turning the LED on or off

constintLEDTogglePeriod=1000;// [milliseconds]

// The pin the LED is connected to

constintLEDPin=13;

And the loop becomes:

C++

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

voidloop()

{

// This will toggle the LED on and off every second, with no waseful delays

if((millis()-LastLEDToggleTime)&gt;LEDTogglePeriod)

{

LastLEDToggleTime=millis();

if(IsLEDOn)

{

IsLEDOn=false;

digitalWrite(LEDPin,LOW);

}

else

{

IsLEDOn=true;

digitalWrite(LEDPin,HIGH);

}

}

// Do something else here.

}

Ternary Tricks

C++, the language the Arduino platform uses, includes a handy expression for selecting between two values:(expression) ? (true-value) : (false-value).

This is called a ternary operator…because it has 3 arguments:

(expression), a test which is true or false

(true-value), the result if (expression) is true

(false-value), the result if (expression) is false

It lets you write things like:

C++

1

2

IsLEDOn=!IsLEDOn;// toggle value of IsLEDOn

digitalWrite(LEDPin,IsLEDOn?HIGH:LOW)

Instead of:

C++

1

2

3

4

5

6

7

8

9

10

if(IsLEDOn)

{

IsLEDOn=false;

digitalWrite(LEDPin,LOW);

}

else

{

IsLEDOn=true;

digitalWrite(LEDPin,HIGH);

}

It is easy to create code that is hard to follow using this tip. Use it wisely!

Taming runaway programs with the watch-dog timer

The Arduino’s microprocessor includes a watch-dog timer. The watch-dog timer is a sort of dead-man’s switch: if your program doesn’t keep telling the timer all is well, it will blow up the Arduino.

Actually, it just resets the micro: what you do on reset is your own responsibility.

To use the watch-dog timer, you’ll need to:

include a library

enable the watch-dog

tell the watch-dog that all is well

This example should work on any Arduino that uses a microcontroller from Atmel, including the Uno, Mini and Mega. Note, older Mega’s had a problem in their bootloader. If you set the watch-dog timeout too low, you won’t be able to reprogram the Arduino using the serial bootloader. Update to the latest Mega bootloader to fix that.

C++

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

// Include the watch-dog library functions

#include

unsignedCountDown=10;

voidsetup()

{

Serial.begin(9600);

// enable the watchdog timer and set a timeout.

// if we don’t call wdt_reset() before the time is up, the program will reset automatically.

wdt_enable(WDTO_1S);// WDTO_1S =&gt; 1 second timeout.

}

voidloop()

{

// the program is alive...for now.

wdt_reset();

while(CountDown&gt;=0)

{

Serial.println(CountDown);

CountDown=CountDown-1;

delay(30);

}

Serial.println(F("Kaboom!"));

}

This program contains a bug which means the countdown will never finish. Can you spot it?

The program will get stuck in the while loop. Because that means wdt_reset() is only called the first time into loop, the watch-dog timer will eventually timeout and the program will get reset.

Got a thorny question on Arduino development? Post your question below and we’ll try to cover it in our next tip.

11 comments on “5 tips for Arduino programs”

you wanna save space, lose the pinMode, digitalWrite/read and if you wanna use delays, use delayMicroseconds instead. yay 1kB saved. you can use assembly instructions like DDRD 0b00001111, will set pins PD7 to PD4 to input and PD 0 to PD3 outputs, safes around 500 bytes. I used this with attiny chips it didnt work with my UNO yet I think you gotta lose the bootloader for that

I have some qestions about your “Note, older Mega’s had a problem in their bootloader. If you set the watch-dog timeout too low, you won’t be able to reprogram the Arduino using the serial bootloader. Update to the latest Mega bootloader to fix that.”
How can I check my bootloader version?
What version fixes this bug?