When to move beyond Arduino

Sjors de Wit
February 27, 2020
Last updated: Jul 20, 2020

Arduino is a great platform for quick proof-of-concept development and experimenting. But at some point you might want to consider the next step. When is that point? How to know when you have reached it?

The first signs


Arduino libraries are designed for ease of use. Unfortunately, this comes at a price: with more complex projects, you will eventually hit its limits.

Consider this example: your project requires a servo motor and a small speaker. Your prototype is nearly complete: the servo is doing its thing, you have tested the speaker on a separate Arduino. But combining these two projects turns out to be difficult: either the servo moves erratically, or the speaker refuses to play its tunes.

Sounds familiar? This is certainly a problem I have often encountered. You spend hours debugging your code with the assumption you did something wrong. Only to find out later that it was not your fault at all: you have run into a library conflict.

Even though your own code may be correct, some libraries are not compatible with each other. Under the hood, libraries make assumptions about resources they can use (for example a timer peripheral). If two libraries claim the same resource, this leads to a conflict with unpredictable consequences. Arduino hides all of this stuff to make things appear easy. But in this case it actually made things difficult!

Now you have to search for a workaround. If you’re lucky an alternative library might exist. Sometimes the easy way out is simply using multiple Arduinos. At this point you are no longer working with the Arduino, but fighting against it. A clear sign that it may be time to move on.

Limited debugging

The Arduino development environment is very simple. No bells and whistles, just a few buttons. This makes it quick to get started and it is enough in the beginning. What do you do when your sketch does not work? You probably recognize this: via Serial.println() statements. You print the value you suspect is wrong, and verify it via the serial console.

But adding print statements might slow down your code. Maybe even to the point that it no longer functions. This is especially true in interrupt handlers. Now you are stuck: if only there was a way to look ‘inside’ the processor…
Did you known this actually exists? Many embedded platforms support debugging with so-called breakpoints: you can halt the program at a specified place, explore all the variables and continue the program at your command! There are even things called watchpoints: you can mark a variable and the debugger stops the program when that variable is modified. I have solved some tricky bugs with that feature!

The cost of abstraction

Arduino allows you to think at a relatively high abstraction level. This is mostly a good thing, and almost all microcontroller platforms try to provide a nice abstraction.

An example of such abstraction: digitalWrite(13, HIGH) is all you need to know to turn on pin 13. This is very convenient, and the fuction checks if you have given a valid pin number, turns of PWM if applicable, looks up where pin 13 is, and finally toggles it to high.

If you would program the ATmega328P microcontroller directly, you would have to do all of this by yourself!

This is arguably the biggest strength of Arduino: you get a nice set of well-documented functions that are easy to use. You don’t need to know the intricate details of the underlying hardware.

However, not knowing the details of your hardware can also be a limitation. Especially if you need high performance or have other special requirements (e.g. minimal power consumption). In such cases there can be a big gap between the capabilities of your microcontroller and what you can express with Arduino code.

When to switch?

You may recognize some of the signs described above. Does that mean you should abandon Arduino? No, at least not immediately. But it is good to be aware that you might be pushing its limits.

Maybe you are wondering how it all works under the hood. You might not even intend to move away from Arduino. But knowing its strengths and weaknesses is always a valuable thing to learn.

I would recommend to explore the possibilities beyond Arduino. You don’t have to learn everything at once: pick a subject and learn it step by step. Through experience, you will eventually find the right balance between prototyping with Arduino and working with other tools.

The next steps

If you are hitting the limits of Arduino, consider learning more about working directly with a microcontroller. You can even do this with an arduino board: the Arduino Uno for example, is basically a devkit for the ATmega328P microcontroller. Try bare-metal programming and learn how stuff like digitalWrite() works behind the scenes. Maybe try to build your own low-level driver for an SPI or I2C sensor.

Want better debugging? Good news: there are tools to enable this for your Arduino!

Want to try a different microcontroller? Try the super-cheap STM32 BluePill board. There are multiple ways to work with it: pick an IDE you like and lookup some examples.

Need help?

Moving to a different microcontroller can be a big step. Want help? Feel free to contact me and I’ll help you get started.


  • If you have some unix command-line experience, you might like Blinky101, a guide demonstrating low-level bare-metal firmware code from scratch.