When developing a project, we often overlook the importance of our chosen programming language and focus all our attention on the hardware. However, choosing the wrong programming language can seriously impact our project during the final stage when we realize that the chosen language doesn’t support the hardware being used or that a device is far too complicated to program.
For example, many I2C devices make both schematic and PCB design trivial but can be extraordinarily hard to program. Not all manufacturers provide libraries in every language, and as such, the software development stage of a project can suffer horrendously.
As such, it is essential that we choose the right programming language for our project at the very beginning. Therefore, the computer programming language that we choose should be chosen to help simplify the task needed, provide all the libraries we need, and meet the performance requirements of our project.
Determine your platform: Microprocessor vs Microcontroller
The first step in choosing a language is to determine your platform. Electronic projects can fall under all kinds of platforms, but the two that mainly apply are microprocessors and microcontrollers. Microprocessors (i.e. computers) can be windows machines, apple macs, or raspberry Pis and are primarily differentiated with their high-performance CPUs, high frequencies, large memories, and use of operating systems.
Microcontrollers can be ESP32s, Raspberry Pi Picos, STM32s, and Arduino boards that are differentiated with their fast access to I/O, lower energy requirements, limited memory, and lack of operating systems.
By understanding what kind of platform we are running on, we can start to get a picture of the requirements for our project and therefore choose a programming language that will aid in this. Microprocessors have numerous system resources, meaning they can afford to use slower languages in favour of library support and simplicity, while microcontrollers have more restrictive resources, meaning that memory usage and processor performance need to be taken seriously.
To summarise, if your platform typically runs an OS, has over 128MB of RAM, and a CPU in the GHz, then it is very likely to be a microprocessor, and if your platform has less than 1MB of RAM, a CPU speed in the MHz, and no operating system (RTOS doesn’t count), then it is very likely that it is a microcontroller.
Now that we understand how to identify our platform, we can look at how many languages there are in the following list of programming languages and their uses.
Programming Languages List:
Assembler is a programming language that deals with individual CPU instructions instead of arbitrary code that needs to be compiled (assembler needs to be turned into byte instructions, but each piece of assembler code has a matching byte pattern). Each instruction in an assembler program can be natively understood by the CPU, and as such, you know exactly what the CPU will do. Furthermore, you know the exact amount of time it takes for each instruction to execute, which makes assembler ideal for applications where timing is critical.
One example where assembler would be beneficial is VGA displays. The H SYNC and V SYNC signals require precise microsecond timing, which is easily done using assembler.
As the programmer is required to write every single instruction, assembler is extremely processor and memory efficient, making it ideal for microcontrollers with limited memory. However, assembler is a complicated language to write as it’s challenging to manage, and it takes an age to code even the most basic features (this is because CPU instruction sets are generally limited, and the only instructions available to the programmer are whatever the CPU can do).
Furthermore, very few libraries support assembler to the same degree as other languages such as C and Python. As such, every bit of code you write must be from scratch and something you develop on your own. This includes even the simplest functions, such as floating point operations and loops.
Finally, assembler is not cross-platform as the assembler code will only run on a specific processor. Thus, if you try to move your code from one microcontroller platform to another, you will have to rewrite the entirety of the code.
C was one of the first languages that became mainstream on microcontrollers after assembler and provides numerous advantages over assembler, including human readable code, simplified code, standard libraries, and a single generic language format that is cross-platform.
While C may be slower than assembler, this speed reduction is marginal, and C compilers have become good enough to produce code that runs almost as fast as assembler code while also taking up little memory space.
Additionally, the popularity of C means that there are many, many libraries available online for all kinds of devices and peripherals. This can dramatically speed up the development time of a project, especially when using a platform such as Arduino.
Even though C provides simplicity over assembler, it can still be very complicated, especially when trying to manage memory. As such most programmers who use C on a microcontroller will rarely implement memory management. Furthermore, writing programs in C on a mainstream computer is something that’s also rarely done due to its complexity (except for operating systems, game engines, and scientific simulations).
C++ is like C, except it is somewhat easier as it provides support for objects and classes. This addition of object-oriented programming made C++ one of the most popular languages in the world thanks to the ability for dynamically created objects to inherit properties from a single class, the ability to hold both data and functions inside a class object, and the dynamic memory allocation capabilities that come with the runtime.
While C++ can be used on some microcontrollers, it is often targeted at microprocessors due to the increased memory and processor requirements. As such, C++ is often slightly slower than C, but again this is marginal.
In microprocessors, C++ is commonly found in high-performance computer applications, including games graphics and AI, but can also be found in high-performance network computing, especially for servers deploying cloud-based services.
Python is arguably one of the easiest languages to use as it mostly avoids the use of symbols, it’s easy to read, has widespread library support, and is cross-platform by nature.
Unlike C and C++, Python is an interpreted language which means that instead of being compiled into native CPU code, Python code is interpreted by an interpreter. As such, if a piece of Python code can run on one interpreter, then it can run all interpreters and, by extension, any machine running any one of those interpreters.
As Python is resource intensive (due to the need for an interpreter), it’s generally found only on microprocessor systems. However, the increasing capabilities of modern microcontrollers allow for Python applications to be written on microcontrollers, with one excellent example being MicroPython.
The introduction of MicroPython onto microcontrollers has provided programmers with a coding environment that is not only easy to use but cross-platform. This means that microcontroller applications (which have historically been device specific) can now be easily ported to other microcontrollers. Additionally, most MicroPython systems use a drag and drop system for programming, which also trivializes development, but this depends on whether the microcontroller in question supports this feature (it is typically recognized as an external USB flash disk).
Java is an unusual language as it’s very similar to C++ in that it supports objects classes and structures and uses a similar coding format, but while C++ is compiled, Java is first compiled into Java byte code that is then interpreted by a virtual machine. This use of a virtual machine makes Java a cross-platform language and, as such, has seen large amounts of popularity through platforms such as Android.
However, one of the challenges faced by Java is its performance. Even though Java may be significantly faster than Python, its support is generally limited to microprocessors. One classic example that demonstrates the performance issues faced by Java is Minecraft.
The original creator of Minecraft likely chose Java because of its cross-platform nature, but for a game that has limited graphic capabilities and consists of cubes, it struggles significantly on low-end machines, often requiring a high-end machine and graphics card to run. In fact, there are multiple examples of YouTubers rewriting Minecraft in C++ where they demonstrate a significant performance increase which is why many video games are written in C and/or C++.
Today, Java is frequently found in mobile development and specifically in Android, but Java was also found frequently on online applications. However, Java has now mostly been overtaken by web apps and web assembly.
The last language we all looked at (which is a guilty pleasure of mine) is visual basic. While visual basic can only run on a windows machine through the .NET Framework, it is one of the simplest languages to use when creating a GUI application. Not only is the language easy to use, but it also has full access to windows resources, including file folders, the explorer and serial ports.
Of course, visual basic has some serious performance issues as it is not designed for heavy data usage as well as being an interpreted language. As such, Visual Basic is designed to work with event-based applications that involve button clicks and drop-down menu changes. This is why visual basic with the.net framework is often used to make applications that communicate with a microcontroller over UART ports, such as a device flasher or debug window.
So, what programming language should you choose?
So, now that we’ve looked at the different types of programming languages, it’s time to answer the question, “which one should you choose?”. There are other languages available (such as rust, C#, Objective-C, Ruby etc.), but the languages we have focused on in this video are ideal for working with or on microcontrollers.
For projects that require small microcontrollers with limited resources, designers should consider using assembler. Additionally, projects that require real-time processing of GPIO should also consider using assembler as routines can be programmed that respond in the fastest time, and the programmer can calculate the exact time it takes to respond to a signal. One such example would be a VGA controller where carefully timed V sync and H sync signals are needed.
Projects that are looking to add lots of different peripherals to a microcontroller would do well to use the Arduino platform and, by extension, the C programming language. Additionally, it would also be a good idea for an engineer planning to use an Arduino-compatible platform to consider peripherals with pre-made libraries as this will save significant amounts of time. Such peripherals with pre-made libraries include touch screens, weight sensors, servo controllers, environmental sensors, accelerometers, and cryptographic functions.
Projects that are using 32-bit microcontrollers with larger memories and higher operating frequencies can consider using C++ as it gives easy access to strings, objects, and classes. However, such platforms can also look at the Python programming language if performance isn’t a serious issue as the use of Python can dramatically speed up the development time of a project, and the large number of libraries available online can help to accelerate development as well.
Finally, projects that intend to do heavy network traffic should consider using larger machines such as a Windows PC, a server rack, or a Linux system and avoid microcontrollers altogether. Using an operating system provides the designer with multiple resources, including network handling, sockets, multithreading, multitasking, file access, and APIs that can help abstract, complicated protocols.
Furthermore, microprocessor systems allow for the use of most programming languages which grants the greatest degree of flexibility. However, if the speed of operation is an issue, C++ should be considered, and if the speed of development is essential, then consider using Python.
Overall, it can be seen that choosing the correct language is essential for the success of a project, but it is also tough to choose the right one. It requires us to look into the future to figure out what we need in our project, which could also affect the hardware design.
It should also be stated that no programming language is better than any other language as each language has its own unique applications at niches. Fundamentally, when choosing a language, you will have to consider one of three things; library support, speed, and size.
If you’re looking for hardware parts for your next project and are currently deciding what language to use, head over to our Electromaker store to see our full range of platforms that will be available to you!