Code Craft-Embedding C++: Hacking The Arduino Software Environment

The Arduino software environment, including the IDE, libraries, and general approach, are geared toward education. It’s meant as a way to introduce embedded development to newbies. This is a great concept but it falls short when more serious development or more advanced education is required. I keep wrestling with how to address this. One way is by using Eclipse with the Arduino Plug-in. That provides a professional development environment, at least.

The code base for the Arduino is another frustration. Bluntly, the use of setup() and loop() with main() being hidden really bugs me. The mixture of C and C++ in libraries and examples is another irritation. There is enough C++ being used that it makes sense it should be the standard. Plus a good portion of the library code could be a lot better. At this point fixing this would be a monumental task requiring many dedicated developers to do the rewrite. But there are a some things that can be done so let’s see a couple possibilities and how they would be used.

The Main Hack

As mentioned, hiding main() bugs me. It’s an inherent part of C++ which makes it an important to learning the language. Up until now I’d not considered how to address this. I knew that an Arduino main() existed from poking around in the code base – it had to be there because it is required by the C++ standard. The light dawned on me to try copying the code in the file main.cpp into my own code. It built, but how could I be sure that it was using my code and not the original from the Arduino libraries? I commented out setup() and it still built, so it had to be using my version otherwise there’d be an error about setup() being missing. You may wonder why it used my version.

When you build a program… Yes, it’s a “program” not a “sketch”, a “daughter board” not a “shield”, and a “linker” not a “combiner”! Why is everyone trying to change the language used for software development?

When you build a C++ program there are two main stages. You compile the code using the compiler. That generates a number of object files — one for each source file. The linker then combines the compiled objects to create an executable. The linker starts by looking for the C run time code (CRTC). This is the code that does some setup prior to main() being called. In the CRTC there will be external symbols, main() being one, whose code exists in other files.

The linker is going to look in two places for those missing symbols. First, it loads all the object files, sorts out the symbols from them, and builds a list of what is missing. Second, it looks through any included libraries of pre-compiled objects for the remaining symbols. If any symbols are still missing, it emits an error message.

If you look in the Arduino files you’ll find a main.cpp file that contains a main() function. That ends up in the library. When the linker starts, my version of main() is in a newly created object file. Since object files are processed first the linker uses my version of main(). The library version is ignored.

There is still something unusual about main(). Here’s the infinite for loop in main():

	for (;;) {
		loop();
		if (serialEventRun) serialEventRun();
	}

The call to loop() is as expected but why is there an if statement and serialEventRun? The function checks if serial input data is available. The if relies on a trick of the tool chain, not C++, which checks the existence of the symbol serialEventRun. When the symbol does not exist the if and its code are omitted.

Zapping setup() and loop()

Now that I have control over main() I can address my other pet peeve, the setup() and loop() functions. I can eliminate these two function by creating my own version of main(). I’m not saying the use of setup() and loop() were wrong, especially in light of the educational goal of Arduino. Using them makes it clear how to organize an embedded system. This is the same concept behind C++ constructors and member functions. Get the initialization done at the right time and place and a good chunk of software problems evaporate. But since C++ offers this automatically with classes, the next step is to utilize C++’s capabilities.

Global Instantiation

One issue with C++ is the cost of initialization of global, or file, scope class instances. There is some additional code executed before main() to handle this as we saw in the article that introduced classes. I think this overhead is small enough that it’s not a problem.

An issue that may be a problem is the order of initialization. The order is defined within a compilation unit (usually a file) from the first declaration to the last. But across compilation units the ordering is undefined. One time all the globals in file A may be initialized first and the next time those in file B might come first. The order is important when one class depends on another being initialized first. If they are in different compilation units this is impossible to ensure. One solution is to put all the globals in a single compilation unit. This may not work if a library contains global instances.

A related issue occurs on large embedded computer systems, such as a Raspberry Pi running Linux, when arguments from the command line are passed to main(). Environment variables are also a problem since they may not be available until main() executes. Global instance won’t have access to this information so cannot use it during their initialization. I ran into this problem with my robots whose control computer was a PC. I was using the robot’s network name to determine their initial behaviors. It wasn’t available until main() was entered, so it couldn’t be used to initialize global instances.

This is an issue with smaller embedded systems that don’t pass arguments or have environment values but I don’t want to focus only on them. I’m looking to address the general situation that would include larger systems so we’ll assume we don’t want global instances.

Program Class

The approach I’m taking and sharing with you is an experiment. I have done something similar in the past with a robotics project but the approach was not thoroughly analyzed. As often happens, I ran out of time so I implemented this as a quick solution. Whether this is useful in the long run we’ll have to see. If nothing else it will show you more about working with C++.

My approach is to create a Program class with a member run() function. The setup for the entire program occurs in the class constructor and the run() function handles all the processing. What would normally be global variables are data members.

Here is the declaration of a skeleton Program class and the implementation of run():

class Program {
public:
	void run();
	static Program& makeProgram() {
		static Program p;
		return p;
	}

private:
	Program() { }
	void checkSerialInput();
};

void Program::run() {
	for (;;) {
		// program code here
		checkSerialInput();
	}
}

We only want one instance of Program to exist so I’ve assured this by making the constructor private and providing the static makeProgram() function to return the static instance created the first time makeProgram() is called. The Program member function checkSerialInput() handles checking for the serial input as discussed above. In checkSerialInput() I introduced an #if block to eliminate the actual code if the program is not using serial input.

Here is how Program is used in main.cpp:


void arduino_init() {
	init();
	initVariant();
}

int main(void) {
	arduino_init();
	Program& p = Program::makeProgram();
	p.run();
	return 0;
}

The function initArduino() is inlined and handles the two initialization routines required to setup the Arduino environment.

One of the techniques for good software development is to hide complexity and provide a descriptive name for what it does. These functions hide not only the code but, in one case, the conditional compilation.

Redbot Line Follower Project

redbotThis code experiment uses a Sparkfun Redbot setup for line following. This is a two wheeled robot with 3 optical sensors to detect the line and an I2C accelerometer to sense bumping into objects. The computer is a Sparkfun Redbot Mainboard which is compatible with the Arduino Uno but provides a much different layout and includes a motor driver IC.

This robot is simple enough to make a manageable project but sufficiently complex to serve as a good test, especially when the project gets to the control system software. The basic code for handling these motors and sensors comes from Sparkfun and uses only the basic pin-level Arduino routines. I can’t possibly hack the entire Arduino code but using the Sparkfun code provides a manageable subset for experimenting.

For this article we’ll just look at the controlling the motors. Let’s start with the declaration of the Program class for testing the motor routines:

class Program {
public:
	void run();
	static Program& makeProgram() {
		static Program p;
		return p;
	}

private:
	Program() { }
	static constexpr int delay_time { 2000 };

	rm::Motor l_motor { l_motor_forward, l_motor_reverse, l_motor_pwm };
	rm::Motor r_motor { r_motor_forward, r_motor_reverse, r_motor_pwm };
	rm::Wheels wheels { l_motor, r_motor };

	void checkSerialInput();
};

There is a namespace rm enclosing the classes I’ve defined for the project, hence the rm:: prefacing the class names. On line 11 is something you may not have seen, a constexpr which is new in C++ 11 and expanded in C++14. It declares that delay_time is a true constant used during compilation and will not be allocated storage at run-time. There is a lot more to constexpr and we’ll see it more in the future. One other place I used it for this project is to define what pins to use. Here’s a sample:

constexpr int l_motor_forward = 2;
constexpr int l_motor_reverse = 4;
constexpr int l_motor_pwm = 5;
constexpr int r_motor_pwm = 6;
constexpr int r_motor_forward = 7;
constexpr int r_motor_reverse = 8;

The Motor class controls a motor. It requires two pins to control the direction and one pulse width modulation (PWM) pin to control the speed. The pins are passed via constructor and the names should be self-explanatory. The Wheels class provides coordinated movement of the robot using the Motor instances. The Motor instances are passed as references for the use of Wheels. Here are the two class declarations:

class Motor : public Device {
public:
	Motor(const int forward, const int reverse, const int pwm);

	void coast();
	void drive(const int speed);

	int speed() const {
		return mSpeed;
	}

private:
	void speed(const int speed);

	PinOut mForward;
	PinOut mReverse;
	PinOut mPwm;
	int mSpeed { };
};


class Wheels {
public:
	Wheels(Motor& left, Motor& right) :
			mLeft(left), mRight(right) {
	}

	void move(const int speed) {
		drive(speed, speed);
	}
	void pivot(const int speed) {
		drive(speed, -speed);
	}
	void stop() {
		mLeft.coast();
		mRight.coast();
	}

	void drive(const int left, const int right) {
		mLeft.drive(left);
		mRight.drive(right);
	}

private:
	Motor& mLeft;
	Motor& mRight;
};

The workhorse of Wheels is the function drive() which just calls the Motor drive() functions for each motor. Except for stop(), the other Wheels functions are utilities that use drive() and just make things easier for the developer. The compiler should convert those to a direct call to driver() since they are inline by being inside the class declaration. This is one of the interesting ways of using inline functions to enhance the utility of a class without incurring any cost in code or time.

The run() method in Program tests the motors by pivot()ing first in one direction and then the other at different speeds. A pivot() rotates the robot in place. Once the speed is set it continues until changed so the delay functions simply provide a little time for the robot to turn. Here’s the code:

void Program::run() {
	for (;;) {
		wheels.pivot(50);
		delay (delay_time);

		wheels.pivot(-100);
		delay(delay_time);

		checkSerialInput();
		if (serialEventRun) {
		}
	}
}

Wrap Up

The Redbot project is an interesting vehicle for demonstrating code techniques. The current test of the motor routines demonstrates how to override the existing Arduino main(). Even if you don’t like my approach with Program, the flexibility of using your own main() may come in handy for your own projects. The next article is going to revisit this program using templates.

THE EMBEDDING C++ PROJECT

Over at Hackaday.io, I’ve created an Embedding C++ project. The project will maintain a list of these articles in the project description as a form of Table of Contents. Each article will have a project log entry for additional discussion. Those interested can delve deeper into the topics, raise questions, and share additional findings.

The project also will serve as a place for supplementary material from myself or collaborators. For instance, someone might want to take the code and report the results for other Arduino boards or even other embedded systems. Stop by and see what’s happening.

72 thoughts on “Code Craft-Embedding C++: Hacking The Arduino Software Environment

    1. That’s a bit of a grey area. AVR’s use FLASH (not ROM) and many of them have ‘self write’ capabilities (write to FLASH). It’s (used to be) in the parametric parameters on the Atmel site.

  1. Author: ‘The arduino movement was able to simplify embedded programming to the point where it was readily accessible to non-programmers–as a competent programmer I can’t stand these simplifications so lets go back and add all of the complication back in and try to convince the community to use that’

    The reason there is such a vibrant community around the arduino is that it is simple, if you want something complicated why even bother starting with the arduino in the first place? There is nothing magic about the dev board (even the bootloader is just a standard chip45 and they use avrdude for programming), the existing toolchains still work just fine. If you want all of your libraries written in C++ in a ‘proper’ form so that you could run them on a complete linux machine then go and write them yourself. If you really wanted to contribute to the non-arduino embedded community you should go and write some automated scripts to take arduino code or even whole libraries and convert them to standard C++

    1. Well I find it anything but simple. I cannot get my head round this “setup” “loop” thing and can’t make sense of how it fits together. I am not a C programmer, I am firmly in the assembler and machine code arena where I can keep track of stuff rather than being dependent on over complicated macros decided on by someone I don’t know. I do use C when I have to for things that need ethernet or wifi where the assembler path is way too complicated so I can do a bit of “main()” without many problems but the arduino just seems to take something that is understood by lots of people and make another way to do it for no reason. Anyone that wants to go forward in the programming arena must learn ansi C as their starting point. Why move away from that.

  2. Great, so you’ve introduced vast swathes of content free boiler plate just to make your program “more real”.

    All of this is a massive impediment to instant gratification, one of the most important attributes when making something newbie friendly – undoubtedly why Arduino did it the way they did.

  3. I have spent more time prying the lid off the Arduino environment than using it. Many things said in this article ring very true. Before I abandoned AVR microcontrollers for the ESP8266, I spent a lot of time setting up an AVR Makefile, but once I did I was happy as a pig in mud using vim, gcc, and makefiles. It was a lot easier to get to this same place with the ESP8266. Why do things this way? Well two reasons. One is that I refuse to code with some lame editor that is part of some sugar coated GUI. The other is that I want to know what is going on at the deepest levels without obstacles. I enjoy learning how things works as much as making things work. I am skeptical of C++ in general, but especially think it is out of place in embedded software (call if firmware if you want).

      1. I am always happy when I can leapfrog entirely over some technology. C++ is one of those. I can give two reasons though. One is that C++ is a higher level language. If you use OO features like inheritance and such, there is extra baggage the compiler has to generate. Another is garbage collection – a high level “nicety” that can play hob in a real time system. I have a pretty good idea with plain C of what the assembly code looks like for any statement I write. If I want an OO language, I reach for ruby — but not in an embedded system.

          1. True, but “proper” C++ does tend to lead to other forms of automatic memory management (smart-pointers etc) which invariably results in programmers becoming lazy and you wind up seeing many of the same issues regardless.

      2. I once tried to write embedded code in C++. Initially I was excited, but then I started to look at the generated assembly, and was shocked at the mess it made out of simple things. So I started to learn how to improve the C++ code so that the compiler would be able to optimize it better. After a while, I noticed that I spent more time on figuring out how to write efficient C++ than it would have taken to write the program in C in the first place. That’s when I switched back to C.

      3. I agree C++ is not the best choice in embedded systems. The abstractions of C++ are helpful in large projects with multiple developers. In embeddes systems where the code size is counted in KB instead of MB, a single developer can write all the code.
        And, speaking from experience, it is easier to become a good C programmer. Using advanced C++ features like templates, constexpr, etc is hard.
        C++ has lots of gotchas that can mess things up. One example I’ve seen many times is someone’s library that has a method that doesn’t modify the object but wasn’t declared const. Developers on a deadline can’t wait for the library to be fixed, then kludge a cast of a const object to non-const.

        You also introduced another potential gotcha without warrnimg about the danger. The order of global static initialization is difficult to control, and can lead to serious problems that are hard to debug.

        1. I did mention the global initialization problem. It is one of the motivations for the class Program. Instead of globals they become class members.

          General comment to others, the previous articles in the series addressed why C++ is usable in embedded systems, including small ones.

          1. Static initialization order is indeed a problem. But from an efficiency point of view, making things non-static isn’t a very desirable solution on architectures like AVR where static data can be accessed quickly and non-static data incurs considerable overhead to manipulate pointers.

            This is the sort of design decision that gives C++ such a poor reputation among embedded firmware types who care deeply about efficient code generation!

  4. As soon as it turns C++, I am confused. classes, instances, inheritance: it just does’nt make sense to me. and the code turns unreadable for me. I’ve tried at least 5 times from 1996 up and Its just not sticking. So turning everything C++ is a show stopper for me. And i don’t think I’m the only one. keep that in mind.

    1. If you want to understand and enjoy OO programming, get the book “Programming Ruby”. It turned the light on for me. Before that book it was all pointless BS to me, compounded by self-righteous OO advocates annoying me. Ultimately it is organizational sugar coating. Nobody (that I know of) is writing operating systems using C++

      At least none that I know of, and you can go read what Torvalds has to say about C++ (and I agree with him). I don’t see that C++ or an OO programming style allows anything really new. It can be a useful way to tidy up big projects though.

    2. It’s the exact same way for me (disclaimer – I’m an embedded guy, of the “what’s an operating system?” / “libs? what libs? just give me the register definitions file and the datasheet!” type). I can do assembly no problem, I’m fine using C – but as soon as C++ and OOP comes along I can’t understand anything at all, even after having tried multiple times to break that barrier. Technically I am aware of the various concepts and none of them is impossible to understand alone, but the whole thing falls apart at the first instantiation or inheritance and I start staring at a bunch of meaningless words (like most of the code in this article is for me). Maybe there’s such a thing as OOP dyslexia…? I certainly know I have it. In C, I have a perfect idea of what’s going on, because _I’m the one doing it or it’s not happening_. In C++, I have no idea what’s firing when – and in an embedded system where _I_ am solely responsible for a thing that _must_ work (no such thing as “sorry, out of memory”: dynamic allocation has no place in embedded stuff if you want 100% reliability – and yes, such a thing absolutely does exist) that prevents me from being able to accept that responsibility.

      The Arduino toolchain can’t even tell you whether your code will run at all – the official advice is to just “don’t use too much memory and pray”. Seriously? My code never used to have that problem – when you have one page of RAM set aside as stack in the linker file, never more than 5-6 levels of call depth, few to no parameters in calls, few to no local variables and no dynamic allocation you _know_ you _cannot_ run out of RAM, ever, as soon as your code compiles. If you also take care never ever to block on anything, service everything in a timely fashion and never create states that cannot be exited, your code can run for _decades_ without ever crashing crash or any “unresponsiveness” (over a decade of service, currently about a year of continuous uptime only due to the last mains power outage, never became unreachable due to firmware update, never failed to respond to communication immediately, never failed to turn the light on or off when you hit the button). For me at least, using OOP and/or an OS makes guaranteeing anything like that, uhhh, unfeasible…

  5. now need one tutorial, where an Arduino board is used and all code is standard C/C++, which uses AVR registers directly.

    So, using Arduino for the sake of the HW board and not the library or the IDE, as the Arduino IDE might provide an easy and good platform for learning, better learning (specifically for engineering students) can only come when they are exposed to the 8-bit registers.

    Maybe Assembly even.?

    I know AVR registers can be accessed and written in Arduino IDE and even Assembly, but what would be your choice, Arduino IDE or some other way, i had started a project, AVR on Arduino to make an extension for Atmel Studio allowing uploading of code to Arduino boards from within Atmel Studio, but then they updated the Atmel Studio to v7 and I did not have the new VS2015 – until yesterday. Link: https://hackaday.io/project/7428-avr-on-arduino

  6. There is an interesting paradox in the article that goes further than arduino.
    ‘Bluntly, the use of setup() and loop() with main() being hidden really bugs me’ versus
    ‘One of the techniques for good software development is to hide complexity and provide a descriptive name for what it does’

    some need a simple interface with a lot hidden from view, and some need to be able to get at or at leas see the nuts and bolts.
    It’s not easy to placate both types. I guess Arduino went for type I users, and their success causes type II users to be unhappy.

      1. That’s a lot like saying “everyone’s farts smell.. except mine.”
        If the aim is to teach people how to be “real” programmers, one should not start out with a contradiction like that. “Do as I say, not as I do” does not give learners good vibes.

        1. I agree with you. I’m explaining the contradiction. People writing the code, understand how it works, so they naturally want to hide stuff. People not familiar with the code get confused by hidden code, because it forces them to switch back and forth to build a complete picture.

          In general, people tend to overdo the level of abstractions and code hiding. That’s why my recommendation would be to get rid of the Program class (but also the setup() and loop() functions), and just put everything in main(). It’s only a handful of lines, and everything is in plain sight, making it easy to understand.

  7. In an ideal world we wouldn’t be using either language. C was specifically designed for low-level high-performance implementation on Von Neumann architectures and requires things like the ugly PROGMEM hack to shoe-horn it into working with Atmels. C++ on the other hand was developed, at least partially, to exploit things like embedded hardware caches which the Arduino Atmels don’t have. Both languages require a semi-decent optimizer with at least a cursory understanding of the system being targeted, which in the case of Arduino is sorely lacking. One could try to claim that it at least provides good learning platform for C++ beginners but it’s not a particularly compelling argument for a system that lacks even integrated source-line debugging.

        1. That’s a concern yes. But 8 bits are already too small for the single address space of the RAM. That’s why they have 16 bit registers. And 16 bits is already too small for the bigger flash versions, so they use 24 bits for extended flash access. There are ways to work around this.

          They could have put the RAM in the 24 bit address space, at least. And they could have put part of the flash in the 16 bit space to provide for a small constant pool, and provide some generic load instructions.

    1. I blame the ugly mess with PROGMEM on the compiler and not so much on the architecture. Most of the other embedded C compilers (commercial or open source e.g. SDCC) have proper extensions for the embedded target. Once you have declared the data structure to be in FLASH program space, it is up to the compiler to use the proper code sequence to access it and there should not be silly macros and work around required on the C code.

      1. If you want to make the use of RAM/program space transparent to the user, it means that the memory space needs to be encoded in the pointer type, and that every dereference of a generic pointer needs to check the memory space and use the right access instruction. That’s a lot of overhead.

        1. That’s a big “if”. By sharing a common bus you immediately incur a sizeable performance hit irrespective of which language you choose. The real issue is that Atmel simply didn’t have the novice-programmer market in mind when designing the Atmels, and factoring in such ease-of-use at the time would have seriously impeded their market competitiveness. Like it or not, novice programmers remain to this day a very small segment of their market, and if there was any mistake made it was the one made by the Arduino team in choosing the AVRs in the first place.

          This entire argument is of course complete and utter BS in view of the fact that had they gone down any other route (e.g. PIC) we’d be having this exact same conversation in a slightly different form. I’m the first to concede that it’s a lot easier to trash design decisions, particularly historic ones, than to come up with viable alternatives.

          1. “By sharing a common bus you immediately incur a sizeable performance hit irrespective of which language you choose.”

            You don’t have to share a common bus. You just need to share the address space. ARM CPUs have separated data and program buses, but they can still read data from program space with the same instruction, without incurring a performance hit.

          2. Moderators: I accidentally hit “report” to Artenz’s comment, sorry!

            Artenz: I still don’t see how this would get around the performance hit. At the point an instruction is fetched you would still need an extra clock cycle to determine which bus the address correlates to, even if you were to grab them both you would still need an additional cycle for a multiplexer to choose the one you’re after. It might be possible to alleviate some of the performance hit later on down the pipeline but that would double the fabric required for every instruction that accessed memory. That said my hardware experience is limited to playing around with FPGAs, so please do enlighten me if I’m missing something.

          3. @Myndale: it is true that you need some extra logic, but it wouldn’t necessarily require an extra cycle, as it can be done combinatorically. The data paths from RAM to core, and from flash to core are already present, and there’s already a multiplexer to choose between the two based on opcode (LD vs LPM). All you need to do is operate the multiplexer based on address range instead. The ARM proves it can be done without performance penalty.

          4. Even if you are incurring performance hit, you are looking at a very small percentage of the code in an execution sequence that access data in memory space. You code would normally do a few operations with the data in *registers* beside the actual memory access.

            Some chips prefetch instructions by using a double wide bus for the FLASH or use a cache. On chips that are made with smaller geometries (i.e. non 5V parts) in a more modern process, they can afford more transistors and still come out with a smaller chip size.

        2. AVR GCC implementation is really too anal with desktop ANSI syntax for embedded C. I have done enough of 8051 code on both Keil and SDCC that use language extension to know what I am talking about.

          These *other* compiler would not need to implement generic pointers if you specify the type of memory during declaration with memory modifier extensions and they treat “const” as something you want in FLASH. Try to statically initially something more complex than a char array in FLASH and your AVR GCC code becomes a mess. You would think that a compiler can keep track of variable types and allow for transparent access and not require you to use “silly macro” such as pgm_read_word() to access FLASH.

          Thankfully that ARM chips these days are competitively priced, so i wouldn’t bother with AVR parts in my projects once I use up the rest of my stock.

          1. The problem is when you call a generic function like printf() or strcpy() with a char* argument, which could point to a location in RAM, or to a location in program memory. The code inside the strcpy() needs to know whether the pointer points to flash or RAM, and use different instructions to dereference.

          2. You can recompile or tailor your library for the particular memory by declaring it with memory modifier in the *parameter* declaration too if you need to avoid the penalty of generic pointers for critical code. You will need to have special code with those macros in AVR GCC anyway.

            The other compilers let you do that without the BS or can handle it with a generic pointer. You would use a typedef in a single file to make a pointer to FLASH and just by changing that file, the higher level code can be ported to other architecture. If you are sharing routines for accessing RAM and FLASH spaces, then the generic pointers can save some space and not having to duplicate otherwise similar code.

          3. I agree that adding some extra features in the compiler could help to manage this issue a bit, but it’s no panacea. Large projects that use mixed pointers to RAM and flash objects still require the programmer to be aware of different memory areas, use the right keywords for each, or suffer a performance penalty for universal pointers.

  8. Tangential point, but anyone who doesn’t like the term ‘sketch’ can stop using the term ‘script’ for code executed by an interpreter. You know.. like ‘shell script’.

    The practice of applying new names to specific sub-groups of programs is old and well-established. ‘Sketch’ denotes a program built on top of the Arduino core libraries exactly the way ‘bash script’ denotes a program written using built-in functions from a specific shell.

    1. The term “sketch” always served a useful purpose for me; a warning that this was not a road I wanted to go down.

      The decision to use language like this is clearly part of the game to pitch the Arduino to artists. Artists are apparently the poster children of the non-computer savvy people who (at least in the minds of the Arduinoinians) would be frightened by the word “program”. I guess a shield is supposed to sound less scary than a daughter-board. But there are only a handful of terms it would seem, and it is easy to learn the mappings and then ignore them.

      But do they really call the linker a “combiner”? What do they say about inline assembly language?
      All this sugar coating is contributing to my tooth decay.

  9. “When you build a program… Yes, it’s a “program” not a “sketch”, a “daughter board” not a “shield”, and a “linker” not a “combiner”! Why is everyone trying to change the language used for software development?”

    For someone who is as interested in educating as you seem to be, you’re astoundingly dense to the concepts within education in regards to mass adoption. The terms ‘program,’ ‘daughter board,’ and ‘linker’ all have deep-rooted meanings in the computer science world, and are often so broadly or technically defined that an interested party just getting started with an Arduino, say, a 50-something architect wanting to integrate electronics into his next presentation, would be daunted to the point of discouragement at the prospect of having to dig deep into decades of culture to find out the ins and outs of the esoterica that we have collectively built, just to find what should otherwise be straightforward definitions. Put another way, by NOT using the terms that you say they should use, they’re free to define their own terms simply; a sketch as a piece of code which runs on Arduino-compatible hardware, a shield as a piece of add-on hardware which fits into the Arduono’s particular pinout, and a combiner as a program which combines multiple parts of a sketch into a single unit.

    Perhaps, if the prospect of an evolving language around how we describe our electronics is too much for you to stomach, you should find a new hobby, rather than lecturing on why your singular and restrictive ideology is better than anyone else’s. Clearly, if you let this degree of lexical nonsense bother you, you are too set in your ways to be a terribly good teacher to the true beginner. It would be like trying to teach introductory-most music classes by declaring that the only proper way to compose music is to do it the way that Franz Liszt did it, and that every other composer is wrong.

    1. To me, it sounds like people talking to their toddlers about toot-toots and woof-woofs, instead of cars and dogs. It’s an attempt to make it easier, but it only means more work for the child who later has to unlearn the bad word, and learn the good one. It’s simpler to start with the correct words in the first place.

      For the 50-something architect, who is not familiar with any of the deeply rooted meanings, the word ‘linker’ is just as easy or hard as ‘combiner’.

  10. […]it’s a “linker”, not a “combiner”[…]
    :
    :
    […]the linker then combines[…]

    Then I wanted to stop reading because I feared what was coming, but curiosity kept me reading on.
    It got worse than my fearings.

    I agree that the ‘duino crew did a mediocre job implementation wise (libs code quality + run-time behaviour) but they did a VERY respectable integration job (tying all the stuff together AND still are in biz since a decade).

    I agree that the IDE is “overly simplified” for people chewing code even before breakfast (so do I, too) but they got it right for entry level without suffering feature creeping (again: sice a decade).

    I disagree with Ruds line in his article: he pleads for replacing “hidden stuff” with other, more complex (but standard!) “hidden stuff”. To me this feels “same shnip, different tase” but not helping novices.
    The point in ‘duino style (albeit not perfect) is that it applies ABSTRACTION + ENCAPSULATION (albeit in more loose way than strict OO) for the newcomers, SO TO ATTAIN A SIMPLIFICATION, whereas Ruds style exposes ALL OF C++ “FEATURITIS”, including all tar pits and hatches coming with for free.
    If you leech for OO, why can’t you accept the abstraction (albeit not OO, nor perfect) set by Arduino “programming model”?

    I understand that “colorful paintings” are more impressive, but learning to draw starts with just a pencil.

    Therefore: Arduino ist (mostly) right for what it’s aimed at. And appreciate it FOR THIS.

    You aim further? Then leave Arduino aside, pull the straps of your safety boots and wade the full mud of C++. You’ll appreciate THAT TOO.

    “loop();” vs. “p.run();” – you must be kidding…

    PS:
    Not “p.run(); exit(0);”
    But “exit(p.run());”

    1. To add some weight to this. I am a HW engineer aswell as a hobby enthusiast. This Arduino bashing by SW people is really getting old. Can you please accept this facts once and for all.

      We don’t want to learn how to write clean efficient code.
      We don’t need to learn how to write clean efficient code.
      I just wan’t that sensor to give me readings asap so I can verify that it does what it’s supposed to do.

      How many small just for fun blinking LEDs projects do think justifies the effort of learning how to set up an environment and go through datasheets to find all the registers you need and how to configure them and so forth? It takes a newb like Me days or even weeks.

      Get Arduino going:
      Download and install – google protocol to be used and name of sensor – read the example and tutorial – run example – get sensor data rolling in serial monitor – done in 10 minutes.

      Sketch: A simple code snippet to test stuff or do simple tasks.
      Program: A complete firmware.

      PS
      Reporting PaulS comment was unintenional, please move button or implement “are you sure”

      1. Funny you should say that – my experience somewhat differs:

        Get Arduino going:
        Plug in / hook up Ethernet2 shield – read the example and tutorial – fail to run example – scratch head like an idiot – spend hours continuing to fail to run example – start to realize that the chip on the shield is not actually the one they seem to be talking about everywhere, and that just because everything in Arduino world has eleventy billion revisions yet stays compatible with itself doesn’t in any way imply Ethernet2 shields (the only kind sold currently at the outlets I’ve seen) are actually usable with the standard Ethernet library – start to realize Ethernet2 shields DON’T HAVE SUPPORT AT ALL in the traditional Arduino IDE (the arduino.cc one) – finally dawning on me that I’m only supposed to use that hardware with the alternative Arduino IDE (the arduino.org one) unless I’m willing to hunt down and grab a special Ethernet2 lib from wherever I can – a mere workday later finally get a response to ping – done in 8 hours! Woohoo! Plug and play, baby!

        1. I feel your pain when it comes to things that should just work out of the box and don’t :)
          I had this funny experience with a Wiz820io module which would work on every arduino but the one I chose (MINI).
          Neither WizNet nor Arduino (forums) were able to give me an answer, which turned into several days of circuit analysis (at the time I knew even less than I know now, of course).
          I found out that there was a 100Ω resistor on the designated clock pin, which was playing funny tricks no matter the speed I chose for my ISP communication.
          Had to go through the schematics (some version of the MINI did not have that resistor on pin D13 [ PB5 ]) but I figured it out and it was great :)

          we can safely say that “out-of-the-box” can have different meanings

      2. Far as comment reporting goes, far as I know it goes to a human being, who isn’t going to remove it unless there’s a good reason. So don’t worry too much, people are always pressing the wrong button.

        Maybe that should go in the FAQ, also HAD should have a FAQ.

      3. Also… great point! Writing software for little gadgets with 16K ROM has very different requirements from writing apps, for an interactive user with a screen and a mouse.

        There’s some elements of good practice that make you less likely to fall into traps, or get confused. But really the result is 95% of what matters.

        With Arduino even moreso, where easy access, being able to bang in a bit of code and have it WORK without entirely understanding what you’re doing, is the most important thing by far. The integration of standardised hardware and software libraries is a triumph of open-sourcing. Although some of the libraries work better than others.

        There’s also a few libraries that are over-general, messing about getting a matrix keypad working I was tempted to use a library, but there were kilobytes of code to cover every possible case. In the end a dozen or two lines of code did it. What I learned: you can’t use the RX/TX pins for general I/O while you’re trying to send debug messages to the serial terminal. Doh!

        Also tried an infra-red remote control library, which wanted 10K of my 16K space, and couldn’t give the same result twice for the same key. If I decide to do more with IR, I think I’m gonna have to do it myself.

    2. nicely put.
      I have learned most of what I know today thanks to my encounter with Arduino, and although in my daily µC life I use SublimeText to code and ISP programmers to write my firmware to AVR chips, I still teach Physical Computing using Arduino.
      It is one of the best things out there to start.
      Of course I also explain how these things work behind the hood, and invite my students to look at other means of doing the same things (registers manipulation) and teach them how a serial port works.
      It would be so much harder without having the chance to download a single package, plug a USB cable in, push a button and see the results.

      Before meeting Arduino I tried BasicStamp and also bought a Wiring Board (https://en.wikipedia.org/wiki/Wiring_(development_platform) – precursor of Arduino, someone will remember Wiring.h) but none of these attempts were fruitful.
      Once I had an Arduino board and could play with it I ended up following web links until I was able to understand how that worked behind the UI.
      I could turn an Arduino NG into an ISP programmer, learn AVRDUDE, mess up fuses, pick the wrong crystal, learn about HV Programming, buy an STK500, then a Dragon.
      Later I ended up learning how to read Intel HEX and so on.
      This whole process is to me a never-ending adventure, and allowed me to become a better teacher with much more insight to share on the world of computing.

      That said, people tend to forget that Arduino was created because ID students already knew about Processing, and the folks at IDII (https://en.wikipedia.org/wiki/Interaction_Design_Institute_Ivrea) thought it would be easy for their students to use the same UI (which I honestly don’t enjoy using a single bit) to write code for their physical computing projects.
      Before then you had to resort to Phidgets (http://www.phidgets.com), and be forced to have a computer attached to your installation.

      What I mean is that Arduino was created for a specific task and took over the world, which I haven’t seen many more projects succeed at.
      If you are an “artist” who wants to blink lights or spin motors, that’s all you need.
      If you want more, like me and other million more advanced users, you start there and move forward.

      I really enjoy this series, as it’s been clearing up some concepts, but there’s no particular reason to bash Arduino.
      I’d rather stay constructive and teach to the interested parties how things work behind the curtain :)

  11. “The if relies on a trick of the tool chain, not C++, which checks the existence of the symbol serialEventRun. When the symbol does not exist the if and its code are omitted.

    If serialEventRun is undefined, the liker would (correctly) fail. It will be initialised to zero (NULL) somewhere in the generated object files. Only once though,

    “If you look in the Arduino files you’ll find a main.cpp file that contains a main() function. That ends up in the library. When the linker starts, my version of main() is in a newly created object file. Since object files are processed first the linker uses my version of main(). The library version is ignored.

    If the linker sees two definitions of main in the global scope it would also fail. There will be a (clever/hacky?) mechanism somewhere in the Arduino build environment to prevent these linker errors.

    1. Exactly. Increasingly complex frameworks are going to become more and more relevant as the capabilities of micocontrollers advance. Furthermore, we will be advancing towards a “universal” language which could be applied to numerous forms of hardware. It is a form of redundancy/reusability. This kind of agnostic hardware/software will be mission critical for things like a trip to Mars for example.

  12. I always find it mind boggling how often professional programmers pick up the Arduino platform, instantly scowl in disgust, then attempt to rip it apart and re-craft it into the way their experience dictates. That is quickly followed by rants about how trash it is, and “all these things need to change or…” rather than just going straight to the AVR GCC and doing it the way they want to.

    The environment does not exist to make professional developers happy. It’s purpose is not to subscribe to anyone’s version of the ‘correct’ way to implement C or C++ as firmware. It’s purpose is to be easier to understand, quicker to learn and implement. Notice I say nothing about the experience level of the programmer. Beginners and professionals should be capable of putting it to use.
    It is it’s OWN thing, and should be treated as such.

    Don’t get me wrong; I think it is great to pull it apart and look under the hood. How did the developers get from there to here? What are these macros doing? How does that library actually work? I think it is great to hack on it, modify it, and try other ways of making it play. If something does not work exactly how you’d like.. go ahead and change it.

    But your version of it is not anymore ‘right’ than how it was before you touched it. It is not called “C++duino”. There is no law that says it must conform to any preexisting notion.

    Every language goes through the same sort of comparisons to other languages. But eventually people always come around to the fact that the language stands on it’s own feet and merits. Each language either finds it’s niche and adopters or dies. The Arduino environment and language are solidly routed. There is not much point in the continuous arguing about it.

    Its great to explore it and look more deeply..
    But I can’t wrap my head around why anyone would want to zap setup() and loop() in favor of main(). They are cornerstones of the language. If you are going to go that far, you might as well go all the way; Forget about the Arduino environment and language all together and go right back to AVR GCC. In fact, I think an extensive tutorial series on Atmel development from the ground up bypassing Arduino entirely would be a far better use of the author’s experience and HAD resources. Why unscrew a working light-bulb?

    Better yet, take AVR GCC, add a bunch of macros, new keywords and libraries, and craft a competitor to the Arduino language with the same goals; Easier to read/understand than bare naked C/C++, fast to learn, easy to implement, and a better model people to get into embedded hardware. But one which addresses all the complaints of professional developers. If you don’t like it, make a new one. Either of the two above options would be highly valuable tutorials for HAD readers.

    And for the guy who says he cant wrap his head around setup and loop… they are far more intuitive than main is. Setup runs first, once. After which loop runs continuously. What further confusion could there possibly be?

    1. If you don’t need to call init();, using main() saves a few bytes over setup() and loop(). Also, if you don’t want to default construct variables shared between setup() and loop(), then using main() is better.

  13. I think with all the potential hardware SNAFUs you can get putting electronics together, introducing OOP as another source of bugs and confusion doesn’t make it better.

    I’ve always been happier with good ol’ C. I see the point of C++, but C was probably the wrong language to try and add OOP to. C was designed for low-level systems stuff, “All the advantages of asm, with all the disadvantages of asm”. Anything with pointers should stay the fuck away from objects and orientating. Add a ++ to COBOL or something.

    There’s also the relative lack of sneaky stuff going on in the background, in C compared to C++. Theoretically you don’t need to know what’s going on behind the scenes, but in practice it’s sometimes the answer to a problem, or at least points you down the right path.

    So I don’t use OOP on Arduino, except with other people’s libraries. And if I ever meet Bjarne I might consider punching him.

    Currently trying to think of functions to add to a toy with RGB LEDs, for a 3 year old who likes pressing buttons. So I thought I’d give him some buttons.

      1. I gots a piezo beeper. Damn quiet unless I press it against something, will have to superglue it to the case it will end up in. I looked up middle C and the associated notes, so got that now. Was thinking about reusing a 32 ohm headphone, but probably his mum wouldn’t thank me for making it any louder.

        Since I’m sending the LEDs a much less bright set of colours, current consumption will have gone down, good for it’s eventual batteries, and less chance of blinding anyone, it’s quite hard to look at 12 of the WS2812 LEDs on full bright.

        A mate suggested a Simon-type game, but I dunno… Got 16 buttons, 8 of them do the colours of the rainbow plus 1 random. Others do a few things I thought of, but nothing spectacular. Mostly just a matter of software now, and the ‘weeno it’s going to end up on is a 32K model, so plenty of room. Might stick it on .IO as a project…

    1. Before you meet BS and attempt to punch him, you might ask if he thinks C++ is object oriented. Or, you could actually read a book. In any case, you will find his answer is most emphatically *NO*, *NO WAY*, *NO HOW” – (Although you can use it that way if you choose.) Same for any other member of WG21. You might also get ahold of the Subcommittee 22 2005 DTR on C++ as the premier system language. Or, since you like firmware, try “Real-Time C++: Efficient Object-Oriented and Template Microcontroller Programming 2013th Edition” (http://www.amazon.com/Real-Time-Efficient-Object-Oriented-Microcontroller-Programming/dp/3642346871/ref=sr_1_1?s=books&ie=UTF8&qid=1453412050&sr=1-1&keywords=real+time+c%2B%2B). It starts with “purchase a breadboard”, and some very old components.

      Just keep in mind that anyone can write bad Fortran in any language – including C++.

  14. The truth about arduino is it is a killer app that allows the mainstream to make the leap into physical computing, to assume it’s purpose is to help people learn programming is a bit narrow minded. IMHO Arduino allows “noobs” such as myself to create then share useful products that without the simple arduino IDE and simple example sketches, would never be made.
    Just as there are many people now making a huge impact on social media that don’t have a clue how networking protocols work (eg. The Kardashian effect), race car drivers that don’t know what an ignition coil is, and jockeys without vetranary degrees…It is important to keep in mind that it is not critical to know everything about how something works to make something work.

    And now for my rant….

    I do believe there will always be a place for experts that can dive deep into the workings of a useful system and make it better, I just think these experts would be better off if they understood that just because it may be more efficient to use a boolean argument to blink an Led, digital write high/low does the same thing and when that led is being used as a fake car alarm light, who really cares about OHM’S law anyways?

    PS. RC networks are even more efficient ☺

    1. It brings people into messing with electronics, which means there’s enough demand for components and boards that we can get stuff dirt-cheap. That’s fantastic!

      Also means more people are learning programming and electronics, thereby making them more logical, and much easier to put up with sharing a world with.

      Schools should use Arduinos, although knowing most schools they’ll be paying $50 a board from some specialist educational supplier, that talks the right talk to get teachers to trust him. There’s tons of money in selling shit to schools for 4x the market price, if you offer the right sort of handholding for idiots, and a few worksheets.

      Butanyway… With Arduino boards, perfectly good ones, for $3, breadboards cheap, all the shields and the like, there’s a lot that smart kids could do, and even average kids could achieve something practical, with the smarter ones helping them along. Doing so would empower them, give them a feeling of ownership over technology, rather than being it’s consumers / slaves.

      It would be more useful just for effect it might have on society and people, than for producing future engineers and scientists. Making people logical and rational. Might even have a longer-lasting effect than the English lessons kids have, and then forget completely after they grow up and get Facebook accounts.

  15. I understand the problem, the people complaining about the software arduino ide, c, c++ etc… They are trying to use a “maker educational system” to do professional work. Why because it works, and they are to lazy to create their own microprocessors for professionals ide. You would not buy a ford focus then complain it did not come with a ferrari engine, a porsche suspension etc…or would you? Why should the people that are leaning or the makers of the world have to have a PHD in programming just to read a temperature sensor? Maybe the people who get paid to do these things I loosely call professionals should learn the hardware side and how to read the datasheets and make their own code and directly load it to the atmel chips themselves without a ide like a real electronics engineer would. This system was intended to be a educational, maker, proof of concept system not a finshed product for the masses from professionals. Not that it can not be used that way. Come back here in a year and say I made a C++ only ide for micro controllers including Arduino’s then i wont think of you as a over educated CRY BABY.

  16. I’m working on some other documentation of C++ and wandered back through some of these articles for fun. Reading the comments in late 2018 is quite interesting. I still like the concept of Program and have used it in some PC based robotics work. But didn’t use it at other times so I’m not 100% sold on it myself. One of the reasons for writing this article was to generate some discussion on it.

    A number of comments here say Arduino is for educational purposes and for enticing people into developing on computers. That is a valid statement and I support it. Unfortunately, Arduino experience is going to lead to some bad habits and ideas. When professionals criticize the Arduino it is based on long experience. I recently did a non-trivial Arduino project using multiple different I2C sensors that started using the Uno but because of memory requirements I switched to the Due. The Due’s main I2C pins are not in the same location as the Uno’s. The libraries from one vendor handled this through parameter changes. Libraries from another vendor required edits. The former is professional; the latter is not.

    Experience over these 3 years shows that the Aruduino is not just an educational or hobby system. Actually the boards like the Due being available years ago were a good indicator even then. They are too powerful for just blinking LEDs. The newer boards are even more powerful and well suited for professional use. The software should be equally professional. Unfortunately there is a lot of non-pro software and that isn’t likely to change unless a massive open-source project takes on the task.

Leave a Reply to MRECancel reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.