Learn C++ via Arduino? - Page 1
Forum section: electronics / general

author: KSP
author_rank: Regular Contributor
timestamp: March 27, 2014, 10:17:20 am
content: Hello allBasically my current area of profession is electronic test and measurement, and obviously automating the process where possible is going to increase productivity. For certain applications I would like to be able to write software to control my kit.The problem is I am a hands-on kind of guy, so when it comes to trying to get my head around programming I get totally lost! I cannot sit and try and figure out tutorials and example code written in books, the way I learn is to set an objective and try and reach it. Trying to figure out someone elses applications is just arduous.So for the sake of learning, is the Arduino microcontroller a good starting point? It seems like a good way to get to grips with software talking to hardware, if you see what I mean. Or would this only apply a limited area of C++'s cabapility, therefore blinding me to how powerful C++ can be?I am not suggesting using an Arduino to control my kit, simply a learning exercise. I have no need to write software apps, my only interest is programs which talk to hardware so learning C++ the usual way tends to be off-putting for me.I have had a basic introduction to C++, so I am relatively familiar with it (doesn't mean I'm any good at it, just that I understand certain parts of it).What do you all think of this? I may not have explained myself very well but give feedback or ask more questions, all input is welcome

author: Galenbo
author_rank: Super Contributor
timestamp: March 27, 2014, 10:58:15 am
content: Quote from: KSP on March 27, 2014, 10:17:20 amNot at all. Try eventually an 8-bit Atmel AVR or an 32-bit Atmel ARM microcontroller.Quote from: KSP on March 27, 2014, 10:17:20 amLearn the huge difference between C++, C and C for embedded applications.

author: Psi
author_rank: Super Contributor
timestamp: March 27, 2014, 11:05:09 am
content: For some people a good way to learn is merging existing code examples into one project and connecting them together in some way.A simple example could be merging a blinky light example with a ADC reading example so that the light blinks only when the ADC value is in a preset range.This sort of glue-logic style of joining working bits of code stops you from getting totally lost.If the example stops working you always have a working 'start point' you can go back to.As you get good at doing this you quickly find you can build lots of cool stuff simply by connecting bits of code from various sources.

author: Galenbo
author_rank: Super Contributor
timestamp: March 27, 2014, 11:07:20 am
content: Quote from: KSP on March 27, 2014, 10:17:20 amThere are several ways to 'learn' embedded programming.They all contain:-working basic complete kit/experimental board/programmer/cables/software/license/power supply-information (forum articles videos books helpfunction examples documentation text whatever)-time and effortAfter some time, you will expierience that there's no such thing as 'knowing embedded programming'What's SPI what are the exceptions when using the one-wire BS18B20 what protocol to use for communication, is CAN better than RS485 than ethernet than bluetooth than zigbee what's better, implementing the complete modbus instruction set or partual how to use the interrupt of a port expander in combination with the already existing interrupts (add 10.000 words here)

author: iceisfun
author_rank: Regular Contributor
timestamp: March 27, 2014, 11:16:23 am
content: Arduino "C++" is not C++ at all, if you want to learn C++ there are a lot of great books and development tools, I personally use MSVC 2012 for everything right now and it works well.I don't know of any beginner books as I gave those away long ago but once you understand the core concepts there are 3 must have books by Scott Meyers.You should get them and read all 3Effective C++More Effective C++Effective STLhttp://www.amazon.com/Effective-Specific-Improve-Programs-Designs/dp/0321334876/ref=sr_1_1

author: ecat
author_rank: Frequent Contributor
timestamp: March 27, 2014, 11:30:03 am
content: If you wish to learn it is better to do something than it is to do nothing, Arduino C++ is as good a place to start as any.Assuming your user name and BOOM quote refers to Kerbals, you may enjoy playing with a little C# while making or poking around with mods for the game.

author: KSP
author_rank: Regular Contributor
timestamp: March 27, 2014, 12:20:52 pm
content: Quote from: Psi on March 27, 2014, 11:05:09 amThis is actually how I have done things in the past. I find I can understand and debug better than I can code myself (I guess most people can...). Bolting together working code and trying to understand what is going on is a good way of learning for me. This will be particularly useful in an embedded application such as this where you can see teh lights blinking etc. and see the code working, whereas writing actual software doesnt always allow for you to see the inner workings in action.Quote from: ecat on March 27, 2014, 11:30:03 amYeah that was my mentality. I have to start somewhere and it is better to start with something that interests me.As for the BOOM quote, that is actually a line from a song. It's an innuendo, but I am using it as a reference for my tendancy to blow stuff up. And KSP is simply my initials

author: ecat
author_rank: Frequent Contributor
timestamp: March 27, 2014, 12:34:46 pm
content: Quote from: KSP on March 27, 2014, 12:20:52 pmMy mistake.The other KSP, fyihttps://kerbalspaceprogram.com/... highly recommended

author: Jarrod Roberson
author_rank: Regular Contributor
timestamp: March 27, 2014, 12:42:21 pm
content: The Arduino environment is specifically aimed at getting the most functionality for the least amount of effort.That is to say it isn't targeted at teaching canonical C++.It definitely isn't going to be the first place you turn for idiomatic C++ examples and tutorials as much of the code can't/doesn't use modern idiomatic C++ because it doesn't need to and the majority of the people submitting code to the internet collective aren't professional programmers much less C++ experts.They have an itch to scratch and good enough is good enough.There is nothing wrong with this approach, matter of fact it is the most pragmatic approach.The important thing to learn software development is to learn the logical constructs, the patterns they create and how to apply them. Really no different than EE. The rest is syntax and syntactic sugar that is specific to a given language and its features.The Processing language, which is the default Arduino environment language is a better choice for learning software and programming at a higher level. When you need the power of lower level construct languages you will "know it" and will be able to recognize when they are require and more appropriate.There is really no such thing as "basic introduction to C++", there might be a naive introduction to the syntax and some claims that it is a "superset of C" and other over-simplications, it is a much more complex topic than anyone expects given the ridiculous amount of subtlety and nuance in the specifications and implementations and the shear amount of "traps for young players" to quote Dave.People think they struggle with pointers, which I find very intuitive, wait until they start having to deal with the degenerate behavior of not implementing "the rule of 3" correctly and now with C++11 it becomes "the rule of five" which is even more subtly and more complexity!http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)Guido created Python to automate test case customization for engineers because working with C was a complete PITA. There are much more appropriate solutions than low level languages like C++, for what you are probably doing.Unless you are writing device drivers, operating system kernels C and C++ aren't appropriate, if you need to interface with hardware, a very thin C library layer exposed to a higher level language like Python or Processing will be more productive and more maintainable and teach just as much about software design than struggling with nuances of something like C++ that are just distractions from solving your problem, you are solving C++s problems.

author: KSP
author_rank: Regular Contributor
timestamp: March 27, 2014, 01:13:31 pm
content: Thank you Jarrod, there is a lot of info there!I realise that C++ is very powerful and may not be the best language for my basic needs, the only reason I chose it is because the electronics course I am doing has a C++ module which I have to complete, so I wanted a side project to sort of complement this, as I am currently struggling. I should maybe have mentioned this at the start...The module is not one of the core modules, therefore it is pretty basic and quite frankly not structured very well.Although I will only be writing simple embedded programs, having a baseline knowledge of C++ is useful due to its widespread usage, so if I do choose to branch out in the future I will have that foundation knowledge.I am yet to delve in to the differences between C and C++, but of the two it seems that people are suggesting that C is better for my needs, and from my understanding C code is compatible with C++ anyway (for the most part) so would you suggest I focus my efforts there? Because for what my course covers I'm pretty sure the objectives can be met with either

author: Galenbo
author_rank: Super Contributor
timestamp: March 27, 2014, 01:45:04 pm
content: Quote from: KSP on March 27, 2014, 01:13:31 pmForget all this, if you're past the if-statement and loop-structures.Time to focus on the target. How to configure an input/output/pwm/I2C port.What is an interrupt and how to use it.

author: zapta
author_rank: Super Contributor
timestamp: March 27, 2014, 04:54:42 pm
content: KSP, if your goal is to lear programming for embedded microcontrollers than Arduino is an excellent choice. Easy to install the toolchain, top notch compiler that runs the world (gcc), tons of examples, large user community and forums, and a wide variety of compatible hardware, including bare bone boards like this onehttp://www.ebay.com/itm/Arduino-PRO-MINI-ATMEGA328-5V-16M-MWC-avr328P-Development-Board-/131150711724?pt=LH_DefaultDomain_0&hash=item1e89310bacthat you can use as a module in your project or a tiny board that plugs directly into your computerhttp://digistump.com/products/1BTW, I don't know why people say that Arduino does not use C++, when you call 'Serial.begin(57600)', this is C++ and I often use classes namespaces, etc.The only thing I can think that you may miss is a debugger. As a learner, being able to single step though your program and examine variables may give you better understanding of what's is going on. Without it, you will need to find other ways to expose internal information about your program for example by blinking a led or printing to a serial terminal. Atmel has a free IDE called Atmel Studio and from what I heard it has a debugger. It is not as friendly IMO as the Arduino IDE.

author: IanB
author_rank: Super Contributor
timestamp: March 27, 2014, 05:03:40 pm
content: If you are not (yet) very familiar or comfortable with programming and are trying to learn, then you don't need to focus on learning a specific language like C++, you need to learn about the general concepts of programming, and how your programs interact with the hardware, and how you make programs do useful things.This means that starting with an Arduino would indeed be an excellent choice. You will eventually find the Arduino environment hides away certain gory and technical details that you eventually might need to learn about, but that's good since it removes some clutter and allows you to focus on programming.Once you gain experience with programming in general, you will start to see how specific features of a language like C++ are useful, and why they are there. Until then, don't worry too much about language details, try to get familiar with concepts.

author: Jarrod Roberson
author_rank: Regular Contributor
timestamp: March 27, 2014, 05:40:48 pm
content: "from my understanding C code is compatible with C++ " this is what I am talking about misconceptions. Resistors and Voltage regulators can do the same thing sometimes, but you can't conflate them to be the same thing. Software and languages are much more subtle even more so, there is no fire or smoke when you get it wrong, at least not most of the time ... :-)This is fundamentally incorrect and will lead to nothing but pain. C and C++ unfortunately get conflated because they have the character C as part of their name, much like Java and JavaScript get conflated for the same reason, both cause endless confusion and problems to "young players". There are many traps when naively compiling C programs with C++ compilers, yes it might compile with a bunch of warnings, but it may also not behave like the same code compiled with an ANSI C compiler.When people write C/C++, it implies that one is a superset of the other or that they are related in some way that they aren't. There is no such language as C/C++. The use of this terminology is a sticking point with most experienced software developers as it illustrates a lack of comprehension of both the subjects by conflating them. Using a straw man example: If I was to say Verilog/VHDL; that makes about as much sense semantically and would show I don't know the difference between the two.The OO part of C++ was to scratch an itch of maintainability at scale of hundreds of thousands of lines of code. Something that C doesn't excel at because it is by convention at best. I haven't seen any embedded systems with hundreds of thousands or millions of lines of code. All that memory overhead and indirection of the OO paradigm is just that overhead if it doesn't bring any kind of tangible benefits.Most embedded systems have limited space even if the CPU is powerful, Vtables and all the other C++ runtime plumbing is eating up valuable bits of memory, there is a major space tradeoff here.C++ is a red herring to beginners of all software development, embedded or not. It has way too much overhead and complexity to deal with to get simple things done quickly and easily and too many traps that don't manifest themselves in non-subtle ways, even if you think you are "not using the advanced stuff" it is still there to bite you in the ass from ignoring it.

author: mtdoc
author_rank: Super Contributor
timestamp: March 27, 2014, 06:00:53 pm
content: Quote from: KSP on March 27, 2014, 10:17:20 amIf you want hands on learning of embedded programming I can highly reccomendTHISfree online embedded systems course. It may be too late to register for a grade but all the course material is there. It's focused on teaching C programming for ARM on the TI Tiva C launchpad but the principles would be the same for C programming of any MCU.

author: zapta
author_rank: Super Contributor
timestamp: March 28, 2014, 12:33:54 am
content: Quote from: Jarrod Roberson on March 27, 2014, 05:40:48 pmSaying that the syntax and semantic differences between Verilog and VHDL are the same as between C and it's corresponding subset of C++ is a very surprising statement, to say the least.In understand that you want to make a point that there are subtle semantic differences between C and it's corresponding subset of C++ and that technically it is not a subset in the purist mathematical sense of the word but the comparison above is still strange.Anyway, Arduino is a good choice for starting learning C/C++ in the context of microcontrollers.

author: vvanders
author_rank: Regular Contributor
timestamp: March 28, 2014, 12:45:33 am
content: As someone who's spent most of his professional career writing C++(with some C mixed in) I'd recommend against learning it in a uC environment. Iteration time, logging/debugging capabilities are all reduced in an embedded environment which can lead to frustration.IMO if you're looking to learn programming concepts I'd recommend Python over C++, however if you're interested in dealing with memory, allocations and all the fun stuff that comes with C++ then I'd grab a copy of Visual Studio Express 2012 and learn on a desktop where you can poke & prod with the watch window, memory view and host of other things that make debugging the gnarly C++ issues easier(not to mention much faster link, deploy and debugging time).

author: andyturk
author_rank: Frequent Contributor
timestamp: March 28, 2014, 02:07:26 am
content: Wow. Lotsa C++ hate here.Personally speaking, I'm vastly more productive writing embedded code in C++ (compared to straight C). Virtual functions, constructors and references work really well together, especially when most of your objects/variables are statically allocated (as is typical for embedded code).To each his own, I suppose.

author: vvanders
author_rank: Regular Contributor
timestamp: March 28, 2014, 02:28:45 am
content: I wouldn't say hate, just that if the goal is an understanding of C++ I think that it's a bit heavyweight for micro environments, esp AVRs.I've also seen a tendency to associate C++ = speed from people coming from managed languages(not saying that's the case here) without a solid understanding of caches, data flow and the fact that many C++ features drive you towards anti-patterns if performance is what you are concerned about.IMO C++ fills this weird niche of software that needs to be highly performant but also scale to tens of thousands of lines of code. That's not really the domain of microcontrollers, at least in the 8bit space.If you're picking up C++ to be more productive than C I would say that many other languages(C#, Python) fill that area much better and let you not worry about circular references, memory corruption and all of the other things that makes C++ time consuming to work with. They have frameworks and concepts that will let you be 20-30x more productive than C++ and can still interface with native code when speed is needed.I love C++, it's one of the languages I'm most proficient in, it has features that can't be found in any other languages while giving the right balance of control, abstraction and wide portability across a multitude of platforms. However I also think that it's important to pick a language/tool that fits a domain space appropriately and not just blindly use what's most comfortable for each problem encountered.I should also add that I spend most of my day debugging via printf() and other limited means due to platform restrictions of the things I work on. While micros are better, the debuggers are still fairly constrained and I think that's a horrible way to learn a language. With something as complicated as C++ having a modern IDE with data breakpoints, watch window, memory window and standard heap/stack corruption tracing mechanisms can vastly increase the ability for someone to enjoy learning a language.

author: andyturk
author_rank: Frequent Contributor
timestamp: March 28, 2014, 03:41:20 am
content: Quote from: vvanders on March 28, 2014, 02:28:45 amI haven't worked with 8-bit processors since the Z80A, but it seems like the main issue there is doing whatever is necessary to fit your application into the cheapest silicon. That's definitely not the realm of (interesting) C++, and even straight C is pushing it sometimes.But 32-bit mcus (ARM in particular) are where C++ shines, IMO. They're not terribly expensive, and the GNU toolchain is free. It's a really powerful combination.That said, if someone wants to learn proper C++, it's probably better to start with Linux or a PC. That's where most of the educational material is focused, and you won't have to deal with issues specific to bare metal builds. Once you can do a few tricks in C++ on a bigger system, then that's the time to figure out what parts to stay away from for mcu projects.

author: zapta
author_rank: Super Contributor
timestamp: March 28, 2014, 04:55:43 am
content: Quote from: andyturk on March 28, 2014, 03:41:20 amThese are the C/C++ source files of my last Arduino project and they all compiled into 7,640 bytes, including libraries like vsnprintf. This is less than 25% the flash size of the 8 bit Atmega328P.https://github.com/zapta/linbus/tree/master/injector/arduinoI must say, this thread brings very interesting assertions ;-)

author: andyturk
author_rank: Frequent Contributor
timestamp: March 28, 2014, 05:25:49 am
content: Quote from: zapta on March 28, 2014, 04:55:43 amClearly that processor is too big. Have you tried the Atmega82P? ;-)That's some nice code you have there. Very clean and easy to read. Namespaces! Woo!

author: zapta
author_rank: Super Contributor
timestamp: March 28, 2014, 06:00:57 am
content: Quote from: andyturk on March 28, 2014, 05:25:49 amThe Atmega328P is cheap enough that I standardize on it. More or less I have pieces of software and schematic that I just copy/paste/customize from project to project. Things move faster this way ;-)

author: KSP
author_rank: Regular Contributor
timestamp: March 28, 2014, 07:58:04 am
content: Thank you all for your input. There may be some conflicting views here but it has given me a lot to think about!Quote from: mtdoc on March 27, 2014, 06:00:53 pmI didnt look into it in great detail because I am not at home, but on the surface this looks almost exactly what I want! And its free!!! Thank you very much, I will look into it in detail at some point. The only reason I chose Arduino was because I am new to microcontrollers in general and Arduino is just a name I have heard a lot, figured due to its popularity that it would have the most supporting information around. Turns out that is not the case, and there is a multitude of places to start at. But now I have a starting point

author: zapta
author_rank: Super Contributor
timestamp: March 28, 2014, 11:26:48 am
content: Quote from: mojo-chan on March 28, 2014, 09:58:39 amCan you provide a reference?To my knowledge, C++ static variables within the same file are guaranteed to be initialized by the order they are defined.

author: andyturk
author_rank: Frequent Contributor
timestamp: March 28, 2014, 03:54:36 pm
content: Quote from: mojo-chan on March 28, 2014, 09:58:39 amFor a given class, the order in which member constructors and superclass constructors is well defined. And within a particular source file, *static* objects will be initialized in the same order that they occur in source. However, you're correct that there is no defined order for the construction of static objects defined in separate files.As a hack, GCC lets you put an initialization priority on a declaration that will be used by the linker:Code:MyClass __attribute__ ((init_priority(200))) my_instance;The big thing to remember about static constructors is that they run before main(). For a variety of reasons, it's not good practice to do any computation so early. Basically all you want to accomplish in a constructor is setting up pointers (that won't be changed later) and initializing member variables to constants. If you've got an init() function that does something interesting, you should still call it explicitly.So why use constructors at all in an embedded project?Well, I use them to link up objects at run time that need to know about each other. For instance, an I2C device driver will need to know which I2C peripheral it should use for I/O. However, you probably don't want to hard code the driver to require a specific peripheral. Different chips have different numbers of I2C peripherals to choose from, and based on your board design, you might have to pick one over another based on pinout. None of that should affect the coding of your device driver though.Some real-life static initializers:Code:I2CBus i2c_bus(I2CD1);MPU9250 mpu_9250(i2c_bus, I2C_ADDR_MPU_9250);MPL3115A2 mpl_3115a2(i2c_bus, I2C_ADDR_MPL_3115);The first line declares the I2C bus object. It doesn't need to know which devices are attached. The next two lines declare device instances. Each device needs a bus on which it'll communicate and an id. Because this information comes in through the constructor, the driver code itself doesn't change *at all* if you decide to remap your IO lines (or if your board design tweaks the device ids).These three lines of code came from one .cc file (so the order of the constructors is well defined), but the principle works just as well if they were in separate files where the initialization order could change. The reason is that the constructors are only initializing values to constants. Sure, there's a pointer in each I2C device to its bus, but the pointer itself is constant defined by the linker.To further nail things down and emphasize that relationships between objects don't change, the device driver code uses a C++ reference to "point at" the bus object:Code:class MPU9250 {I2CBusBase &bus;const uint8_t address;public:MPU9250(I2CBusBase &bus, uint8_t address);...}This is a very different style of C++ compared to what you'd do on a system with virtual memory, but I think it works really well for embedded projects.

author: zapta
author_rank: Super Contributor
timestamp: March 28, 2014, 08:22:42 pm
content: Quote from: mojo-chan on March 28, 2014, 03:42:14 pmI like your sense of humor.Anyway, looks like C++ guarantees more than just "they all execute in a random order".

author: zapta
author_rank: Super Contributor
timestamp: March 28, 2014, 08:39:54 pm
content: @Andyturk, very nice explanation. I am using classes like this with the Arduino IDE and static construction.Code:class InputPin {public:InputPin(volatile uint8& port, uint8 bitIndex):pin_(*((&port)-2)),bit_mask_(1 << bitIndex) {volatile uint8& ddr = *((&port)-1);ddr &= ~bit_mask_; // inputport |= bit_mask_; // pullup}inline boolean isHigh() {return pin_ & bit_mask_;}private:volatile uint8& pin_;const uint8 bit_mask_;};And then statically construct:Code:static InputPin in1(PORTB, 0);static InputPin in2(PORTC, 7);And use like thisif (in1.isHigh()) {...}Tried to make it to work with class templates instead (making port_ and bit_mask_ compile time constants) but could not make it to work yet. ;-)

author: vvanders
author_rank: Regular Contributor
timestamp: March 29, 2014, 01:42:38 am
content: Quote from: andyturk on March 28, 2014, 03:41:20 amAgreed, I spend most of my time on the higher end 32bit ARMs and that's where C++ does really well, I still wouldn't want to learn it on that platform. I made all my my mistakes(oh so many) on the PC where data breakpoints were a god-send, among other things.

author: vvanders
author_rank: Regular Contributor
timestamp: March 29, 2014, 01:46:19 am
content: Quote from: zapta on March 28, 2014, 08:22:42 pmIt's still a horrible thing to depend on, all you need is form someone not familiar to refactor your code into multiple files and then you've broken any behavior that you are depending upon.Like mentioned earlier constructors should set default values only and not execute any code. A separate init/cleanup function provides much better and clearer lifetime control then the ordering of static constructor/destructors.

author: zapta
author_rank: Super Contributor
timestamp: March 29, 2014, 03:34:57 am
content: Quote from: vvanders on March 29, 2014, 01:46:19 amThat a valid point.

author: zapta
author_rank: Super Contributor
timestamp: March 31, 2014, 03:52:15 pm
content: Quote from: mojo-chan on March 31, 2014, 01:46:43 pmThat specific Arduino project has about 20 .h and .cpp files.Quote from: mojo-chan on March 31, 2014, 01:46:43 pmI avoid semantic that is not guaranteed by the language. In this case, the order is guaranteed only within the same compilation unit and this is all I rely on.