So I’ve been messing around with Arduinos a lot lately, and I figured I should take some time to explain why I feel that Arduino is one of the best ways to program microcontrollers(with some caveats, of course).
Pro #1: Libraries
This is probably the best part about Arduino, so I figured we should lead with this. There are literally thousands of libraries that exist for Arduino already, so there’s already plenty of support for various things.
Right now, I’m working on a project do display data on a 16×2 LCD display, play MP3 audio files from an SD card, listen for button presses, and read CAN messages at the same time. So what libraries am I using? Well, at least the following:
- ACAN2517 to receive/send data
- SdFat for reading data from micro SD card
- LiquidCrystal for the basic interface to the LCD display
- LiquidMenu for the menus on the LCD display
- AnalogMultiButton for decoding the button presses(all the buttons go to one analog input with different resistor values)
If I was doing this project using some sort of dev kit, there would be no way to get up and running so fast with all of the libraries. I would have to build most of the interfacing libraries pretty much from scratch, which is always annoying to do.
Don’t forget that these libraries are also not tied to a specific chipset, so in general libraries are applicable to multiple Arduino cores, making it super easy to switch out processors.
The fact that these libraries can be built by so many people though brings us to the next point
Pro #2: Simple API
How many times have you looked at the vendor-provided libraries for a microcontroller? Have you ever felt overwhelmed by what they’re trying to do?
Let’s look at how to set a pin in Arduino:
digitalWrite(12, LOW);
Compare this to what you need to do with an STM32:
- Configure the pin via the configuration GUI
- Have the code configurator run
- Hope that you don’t have any custom code that gets overwritten by the newly generated code
- add the correct code(HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin);)
Clearly, the Arduino code is much simpler. What if we want to do a SPI transfer? Well, that’s super easy using an Arduino too!
m_spi.transfer(command);
It’s not as powerful as a full OS, but it’s just so much easier to work with. And honestly, most of the time you don’t need all of the fancy features that the low-level hardware libraries provide you.
Pro #3: Headless builds
Did you know that you can do headless builds with Arduino, so you can build them on a build server? It’s true!
A few months ago at work, I had to do some headless builds of some microcontroller firmware, some using Silicon Labs’ Simplicity Studio, and some using TI CCSTUDIO. Both of these IDEs are Eclipse based, but it’s quite difficult to get them to work in a headless build.
While it is possible for both of these IDEs to build in a headless manner, it’s not easy to do. Moreover, the IDE often needs to have the exact version of a dependent library installed on the system in order to build properly. Compare this to the Arduino CLI again, and there’s a lib install command that I haven’t used before, but that should work for easily building in a CI environment.
The Cons
Alright, I’ve talked about a few of the pros, but what are the cons of the Arduino environment? Well, here’s a quick list:
- It’s hard to do complex projects where you have multiple source files and/or you want some kind of folder structure. The sketch idea is really geared more towards single file projects.
- Similar to the above, the fact that it’s not easy to create a new board somewhat limits the usefulness of the platform. The other embedded IDEs that I’ve used before(e.g. STM32CubeIDE, MPLABX, probably others) get around this by having you define “pin 23 is SPI SCK” for example. This goes way to far to the ‘complex’ side of configuration in my mind, since it also makes it very difficult to switch processors, as the pin numbers may change and there’s often not a great way of having different configurations for different boards.
- There’s no way to dive deep into the configuration for libraries that can be common. What would be great would be a simple way in Arduino to have global defines as part of your project.
Overall though, the simplicity and ability to do things quickly with an Arduino greatly outweigh the cons in my experience.
An idea for library configuration
Could we perhaps implement configuration on a per-library basis for Arduino? I don’t see why not.
Let’s imagine a simple library configuration file:
name=M95_EEPROM
version=0.4.1
author=Robert Middleton
sentence=A library for talking with the M95 series of EEPROM chips from ST. May work with chips from other vendors as well.
paragraph=
category=Data Storage
url=https://github.com/rm5248/m95-eeprom-arduino
maintainer=Robert Middleton
What if we wanted to be able to configure this at build time? We could do something like:
name=M95_EEPROM
version=0.4.1
author=Robert Middleton
sentence=A library for talking with the M95 series of EEPROM chips from ST. May work with chips from other vendors as well.
paragraph=
category=Data Storage
url=https://github.com/rm5248/m95-eeprom-arduino
maintainer=Robert Middleton
option.foo=string
option.bar=int
option.baz=bool
Simply defining options that the library could have and setting them to one of 3 values would be simple enough for Arduino I think. These options would then be turned into preprocessor defines when the library is built, something like <name>_<option>=<value>. In the above example, if bar was set to 5 this would result in a preprocessor directive of M95_EEPROM_bar=5.
These could be easily configured through the Arduino IDE. There’s already a keywords.txt file, why can’t that same idea be expanded somewhat to do configuration?
A bit of a rant on board configuration
Having used a bunch of different embedded IDEs before, I really wonder if the people who create the product actually use it. The code generation is absolutely terrible and pretty much useless half the time. Please stop making me edit auto-generated code that I can only edit between certain VERY SPECIFIC lines(looking at you STM32CubeIDE). If you want to generate code, that’s great, but let me call the autogenerated code myself, stop trying to generate a main for me.
Seriously, has any company who provides these IDEs for use with their microchips actually done anything before with CI/CD or even modern software development practices? I don’t want to configure an obscure XML file or have required libraries in specific places in order to get my firmware to build. The fact that every single embedded IDE is just different enough is incredibly frustrating, in addition to most of them having hardcoded paths in their configuration files that need to be manually changed to be relative in order to make it easy to share between people. Yes, this is a problem that I have run into before.
Conclusion
As an embedded engineer, I’ve used multiple different embedded processors and their associated IDEs before. I’ve found that every company seems to have their own version of how to program their devices, which is super annoying to have to deal with. Some IDEs/tools are more stable than others, which is also not fun to deal with. The STM32 that I’ve been using lately has been pretty stable, so I’ve been happy with it. It’s definitely on the better side of embedded support.
Overall though, the simplicity of Arduino is perfectly fine for the vast majority of software that I have written for microcontrollers. It may be using a blocking API most of the time, but this is generally not an issue because the microcontroller is running fast enough to move on to the next task once the previous one is done. You don’t get a high amount of control(e.g controlling DMA tasks, multi-level IRQs, specific chip-level features, etc) but if you need that level of control you should be using something like Zephyr instead.
What would be great would be for microcontroller providers to create Arduino cores/bootloaders for their chips, so that even on a custom board you can quickly bring up a new project. For those people who need more control, standard Zephyr drivers would make it easier to make new firmware. The current situation of everybody providing their own set of “libraries” that are generally not well designed is super frustrating to me as a developer.
Leave a Reply