I Don’t ‘Do’ Arduino
mattmillman.com
mattmillman.com
And I don't care! A few years ago I got an Arduino starter kit at a garage sale. I have kids now and not much geek time. I finally plugged the thing in, and literally 5 minutes later I was running code on it. Who cares that it's inefficient. It makes the difference between a project built and one not built. I already posted my most recent one the other day, but why not again...
https://github.com/MarkusWandel/battery-tester
The code is right there. It's simple, it's readable, anyone could understand it in half an hour and change it. Not as heroic as my biggest MCS-51 assembly language project, whose source code is here:
http://wandel.ca/homepage/rom.asm.html
But tell me which of these is going to get someone over the "I can do this!" threshold?
I'd say this blog post is the real hindrance.
It's ridiculous to suggest that people should always start at the very lowest level; that newcomers to a space are somehow "hindered" by not doing everything the hardest way possible from the get-go. It's like saying Basic was a hindrance to game programming because the people who cut their teeth on it were shielded from the concerns that "real game developers" have to deal with in C and C++. Quite the opposite! Anything that opens things up and helps more people discover an interest is good for that field in the long run, even if they have to learn more as they progress (who doesn't?).
This just reads as a big, tasteless, "look how much smarter and more experienced I am than you"
When I start a project with an STM32 microprocessor, I don't start by digging into the hundreds of pages of data sheet and bit twiddling each register. I start up the STMCube tool and specify what peripherals I need on which pins and let the tool configure the registers correctly. If I need better performance than it provides, then I start tweaking bits.
There is rarely any benefit to making things harder on yourself. I use C++ in embedded systems because it makes things easier to abstract than C does. Hell, I've seen people basically recreate concepts like polymorphism in C because they were on a CPU that didn't have a good C++ compiler.
I feel like all the lessons learned in desktop programming over the decades are struggling to find a foothold in the embedded world.
The unfortunate part is, I think he has a some good underlying points, especially about hidden details; and I agree that for many serious use cases, Arduino libraries are just too fickle and unreliable.
If only he had not written that whole piece from a place of professional insecurity...
Look at this, for crying out loud![0] All of that assembly for no good reason. The pin mode only requires one or two instructions. If there's no timer config needed, a digital write is a single instruction, as is a digital read.
Even my amateurish attempts[1] (granted, with a C++17 feature) resulted in a better performing, less error-prone result, which is also easier to read.
The Arudino developers are not trying to write slow code on purpose. Mocking them on hackernews doesn't solve anything. I'm sure they would greatly appreciate you pointing out how slow this code is and offering your improved implementation.
You honestly think they'd accept changes that would break literally every single library using these functions? Somehow I find that hard to believe.
> The Arudino developers are not trying to write slow code on purpose.
Of course they didn't. No reasonable person goes out of their way to make a terrible API. That's why I'm confused and irritated about how they managed to do such a bad job.
All the inputs are bare integers, pins and mode/state, so you get no warning whatsoever when you get it wrong. I've seen posts from people confused because they tried to digitalWrite pins A6 or A7 on a Nano which is accepted by the compiler and runs, but doesn't work correctly because those pins aren't on a digital port. The other analog pins are on a digital port, so work fine.
It gets better. Let's say I digitalWrite with a pin number higher than 19 on a Nano, what happens? Well, it will start off by doing lookups in its pin tables [0]. How does it do the lookup? It just adds the user's value to the lookup tables' addresses [1], and reads that address. On the Nano, these tables are 20 items long [3]. It's going to read god knows what from your flash, and use whatever gibberish it received to decide what to do!
And, because of the need to use inline assembly for the lookups, the compiler can't reason about the data in the tables, and so can't optimize out the lookups, nor can it properly optimize code that relies on those lookups. So the result is it ends up needlessly consuming your limited flash space.
And this is an API that's supposed to be used by beginners! Beginners are the ones most likely to get it wrong because they don't know better.
They're using a C++ compiler in C++11 mode, they're not stuck in the dark ages! Why use a bare integer to represent the pin, a pin's IO mode, or the pin state, or the analog reference voltage source (which, by the way, also makes no attempt to ensure it's a valid value [4])? At the very least they could have used enum classes instead of bare integers so users get a compiler error when they fuck up.
[0] https://github.com/arduino/ArduinoCore-avr/blob/master/cores...
[1] https://github.com/arduino/ArduinoCore-avr/blob/master/cores... [2]
[2] Because of the separate memory spaces, it has to use inline assembly to do this. The pgm_read_byte macro from the AVR header is what does that here.
[3] https://github.com/arduino/ArduinoCore-avr/blob/master/varia...
[4] https://github.com/arduino/ArduinoCore-avr/blob/master/cores...
He is correct about the code size, and certainly about the abstraction hiding details, but those things don't matter for 99% of the cases. Many 'makers' are using something Arduino based to do a few simple tasks that in years past could have been done with a $1 PIC but required significantly more skill to build.
Even more so, with the advent of the ESP32 you have an incredible, fast, cheap platform with wifi that you can use to solve real world problems that those old PICs could never do - and Arduino makes that in reach for more people.
Sure, those of us that are more serious tend to do things more efficiently and directly. We also dig more into those hardware details and the underlying architecture, but the reason those boards are $5 is because of everyone else that buys them to use with the Arduino environment.
Note: I have used the Arduino environment for many years, as well as almost all of the direct platform tools. One could write a book about the compromises in the Arduino platform.. a book that few would read. For anything serious I tend towards to OEM tools and compilers, and like the author I have my own collection of libraries that I have developed, some that are pretty cool, and some that a really terrible. Sounds pretty standard for software development.
Many Arduino users don't care about these points, they'll never need to know the difference between the 16kb part and the 64kb; they'll never care about the higher performance available with tighter code either. When some of them do hit a situation where it becomes relevant, articles like this will help them figure out where they need to go.
I recently got into hardware during the past year. The learning curve (especially on the software side of hardware) is quite steep. Also the toolchains suck. Coming from a webdev world it is night and day as to the amount of open source code out there that helps you get started. Arduino helps chip away at that steep learning curve and I wish there were more projects like it.
While he fears Arduino, he does not see the bigger picture. He should be celebrating the demise of C that is coming for his livelihood.
> It’s never too early to start thinking about the long term prospects of the product you’re building.
- it's practically the opposite of what on higher level of software development is called YAGNI - "you ain't gonna need it". In other words, it's actually detrimental to "optimize too early", in more than one way.
At the same time it would be nice to have an alternative way to develop software for microcontrollers, without Arduino's unwanted features, like those described.
I mention fast feedback, because it's so important to new entrants to a field. I tried to build some MCU project way back in the early 2000s, which involved soldering together a parallel port based programmer, and attempting to drive a blinking light as the first project.
It didn't work. I have no idea why. Maybe I had blew some components up or put one in backwards. I don't know what I did wrong, and I didn't know enough to debug it. I didn't know enough to know what questions to ask.
When I came back to MCU programming many years later, I picked up an Arduino kit. A small part of me felt like it was cheating, but it let me get started. It let me iteratively play around with and learn concepts piece by piece. Ironically, I feel like now I'd actually now have a chance of debugging and fixing that parallel port programmer.
So, the battery needlessly dies in a day.
If you want a true low-power system, you probably need to use STM or something else.