First introduction

Programming is used to bring rudimental intelligence into your projects. Basically, you tell a computer or micro controller in a basic language in easy words how to react on certain inputs. Nowadays, especially micro controllers can be found everywhere – there are billions of them produced per day, and with Internet of Things and Industry 4.0 both household items as well as industry production processes become smarter- Albeit not that much – programming can be seen just as an elaborated decision path between yes or no. With this microcontroller becoming cheaper and cheaper even tasks where you could use discrete electronic circuits (blinking leds for example) are replaced with programmable circuits. As a result, the circuit will become more flexible (e.g. variable blink frequency) and even easier to design and reuse.

Practical relevance

– This is what you will need the knowledge and skills for

After reading this module, you’ll understand the fundamentals about programming and how to write your first programs – in this case especially for a microcontroller.

Overview of learning objectives and competences

In this module, you will first learn about different programming languages and programming environments. You will learn how to program a microcontroller and learn about the programming basics with short examples.

Required skills for this module

Basic computer skills and electronic skills learnt in module 7: Electronic 1

Programming languages for Microcontroller

Why programming skills are useful: Programming lets you put intelligence into your projects, either by making programs for a computer or for their smaller sibling, the microcontroller as a machine brain. This allows you to make your life easier – if you program useful things – or just make cooler fun projects. In the end, while using open-source CNC tools and software, you will be able to adapt and improve this tool for you in the long run.

Combining a beer mug with a cuckoo clock for long distance toasting. Not necessarily one of the useful examples for programming a microcontroller.

Different types of programming languages

With programming you want a computer to do certain things. Similar to humans, different (programming) languages and dialects exist, the main difference is that the programming languages are less complex than your normal speech, and the computer will follow its instructions letter by letter, even if these instructions might be faulty, run forever or even destroy the system.
What do these computer languages look like? A computer understands basically just power or no power – or 0 and 1. Programs consist therefore just of long lines, these zero and ones, the machine code.

Machine Code: Executable Code, understandable for the machine. A list of zeros and ones for data and instructions.

This is of course a bit uncomfortable for us humans (and might look completely different if you want to use the same program on another system), so over time developers of programming languages tried to make life easier for the human programmer. A first step was Assembler language, translating blocks of zeros and ones to data and command mnemonics. So a machine code like 11 1110 00100110 can be divided into an operation and operand, resulting in a better readable ADDLW k (replacing the 11 111 as the operation and k as the operand 000100110).

Assembler: Direct translation of the machine code into better human readable symbols(words).

Punch cards, a very close-to-machine art of programming. It directly represents the 0s or 1s of the machine code, a staple of cards representing the whole program.

Better understandable than the assembler language,  high level programming languages allow more natural text forms and more complex constructs like data control structures. They are independent from the machine (It will be translated into machine code for execution). C is a language which is still relatively close to assembler – nice for time critical programming. C++, Java, C#Python allows for even better readable code and additional features, while faster computing power, more memory and efficient interpreter (for translating it into machine code) make up for the slightly lower efficiency.

Another variant is Visual programming by using connections between logical blocks to describe a program. This is mostly used for flow control programs e.g., for test benches.

High level programming language: Machine independent (needs to be interpreted/translated) with more complex structures, easier to use for humans.

Of course, there exist also more exotic programming languages for special purposes with a different structure: Logical programming (e.g., Prolog) and functional programming (e.g., Haskell). They have its benefits in special use cases like database search and can be more efficient there – but are in general not used in terms of maker spaces and fab labs.


Turing complete: The theoretical mathematical model of modern computers is a turing machine. The programming language is the set of rules for data manipulation. This set of rules has to be turing complete to be able to simulate a general purpose machine. There exists a similar problem in real world languages: If a concept doesn’t exist in a language, and can’t be described through other worlds, e.g. “possession” doesn’t exist, it might be hard to set up a market economy. 
But as a result, you can simulate any turing complete general purpose computer with a different one (albeit it might take some time). Translations allow this rule to be broken down into machine code for a certain machine. Fun fact: The game Magic:The Gathering is turing complete and therefore also a valid programming language.

Integrated Development Environment

The programming language is a bunch of text which needs to be translated before a machine can execute it. An integrated development environment will do this translation and will give additional support for the user like spell checking and even simulating the execution of code to find errors.

  • The text editor is used for writing the code, with spell checker and auto completion as additional bonus.
  • The compiler (or interpreter) will translate the text into executable machine code
  • A debugger allows a step-by-step execution of the code to find errors

They are basically a set of tools to make your life easier.

Arduino IDE: A programming environment for a microcontroller.

In the next parts you will write your own first programs. It will start with  the basics, including more and more complex parts.  The resulting programs will run on a microcontroller, in this case one of the most popular ones for beginners: An Atmega 32U4 on a Pro Micro PCB. It can be programmed with the Arduino IDE as a programming environment for this type of microcontroller.

The other option would be a program which can run directly on your computer. The basics will be the same,  but would be a little bit less hands-on (main difference is that we can easily add additional electronic hardware on the microcontroller, while the computer would allow using a bigger screen and inbuilt input options (keyboard, touchpad, mouse). 

Actually, the Arduino IDE used here is based on another IDE named Processing, developed as an entry level programming environment on the computer which will be covered later – as mentioned before, the advantage of high level languages is that the language stays the same independent of the used hardware.

The Arduino is missing a debugger as well as some other features – it only has a text editor with spell checking as well as the interpreter. But it is open source, free available, works on different platforms and allows easy communication with the controller as well as a special language for easier access for starters.

The IDE can be found under – after the download the program can be installed and started.

After starting the program, there are different menu options found in the menu bar on the top of the screen:

After starting the program, there are different menu options found in the menu bar on the top of the screen:
Here you will find (later) your saved own programs
A collection of example projects for different topics, a good starting point to find and learn about already existing solutions
Of course, you can load and save programs, print them etc.
An important part of programming is commenting on your code to help you and others understand it. This can be done here either with a // before a text line or a /* before and */ after a text block to tell the compiler to ignore this part while translating it for the machine. With this menu points you can either add or delete // before activated lines
Increase/decrease indent
To structure the code, one will use indentions to distinguish different blocks of code
Meaningful names within the code for functions and variables allow a better readability and understanding, and also to easily search for this part of code for debugging (finding errors)
Of course, you have also the usual editing functions like text formatting and other options allows better reading
Here we check the code for functionality and compile it. Beside this menu point you will also have the button on the code window top left for this function. It will also save the code.
Upload (using programmer)
This entry will upload the code on the controller for execution, again with a button at the code window right next to the compile button.
Include Library
This will allow libraries (existing code parts) to be included into your code to simplify your life.
Other options like export a binary are not used that often
Manage Libraries
Here you can search for existing libraries with the library manager and add them onto your computer for usage
Serial Monitor/Plotter
A serial connection allows data sent from the controller to your computer and back, here we can display it in text form (works also for sending data) or graphically. Useful for testing.
Select the used controller board. A board manager allows to add additional boards
Select a data connection where the board is connected to your computer
Bootloaders are used to easily load code onto the controller via USB, the Arduino boards have them already included. Other options in this menu part are mostly cosmetic and less important
The code window with the basic example project: Blink

The most important parts which are regularly used can be found in the code window shown above (created either with file->New or by opening an existing own or example project). At the top you can find the Compile button (1), the button next to it uploads the code(2). Then you can make a new file (project) (3), load (4) or store code (5) and then, on the right you can open the serial window (6) for testing. Below you find a tab structure (7) (with adding/organizing tabs on the right(8)) to organize a project into different files. Then you have the text editor window with syntax highlighting (9). At the bottom you got a feedback window for compiler messages (the black part (10)) with additional information at the lowest part of the window. 
With this setup done and understood, you can start learning programming.


Hello World vs. Blink: Learning programming languages for a computer starts normally with showing a window with a  “Hello World” string on the computer screen. For microcontrollers – without a screen, but with the feature to easily add electronics to the controller the start is to let a LED blink as starter circuit and program. Both cases represent the simplest possible program with an visible output as entry into programming.

Basic Programming

First some basic remarks due to our hardware related learning approach: The classic starter setup for the Arduino is the Arduino UNO . It consists of an Atmega328 microcontroller with the necessary hardware for programming (namely an USB interface to connect with your computer) and easy access for its input/output pins.  It has the most community projects and biggest community, which allows easy to find answers for questions online. Furthermore, both are developed for beginners to make life easier. Shields with electronics circuits- which are to be put on top of the board to extend it with further hardware and therefore functions are useful to circumvent the development of own hardware for complex systems. Without complex circuits in the following lessons we don’t need shields, therefore we can use an Arduino Leonardo clone, the Pro Micro (another microcontroller board). It is breadboard friendly, and its Atmega32U4 controller allows some additional features like using it as a HID device on your computer (acting as a mouse, keyboard or joystick).  Besides the HID features the program code can be used as well for the other boards like the Arduino Uno and its derivatives.

Hardware components like LEDs, Buttons and Motors  allow to develop interesting projects but add an additional error risk: Components and connections can fail. But they are necessary to connect the microcontroller with the real world – a computer would be also hard to operate without keyboard and display, and this additional hardware allows the construction of automated farming, robots cars and so on both on maker level as well as in the  industry. The hardware oriented approach will therefore connect this programming unit with the electronics unit before – and allows an entry into developing your own machines.

Don’t forget the most important rule: It is not necessary to reinvent the wheel. Look on the internet and in libraries for existing examples to see if someone has already solved your problem or if there are at least parts that can be reused. Also try to create good documentation (comments) and structure (functions, classes, …) so that you can reuse your own code (or even let others use your code).

You will use (and need) the following parts in the following examples for the hardware part. The resulting circuits allow you to execute the program on a microcontroller and get optical and motorized feedback as well as different data input variants. They are relatively common and not expensive.

  • Breadboard
  • Arduino Pro Micro
  • a Micro-USB-wire
  •  Jumper wires
  • A Botton
  • 2* LEDs (red, green)
  • Photoresistor
  • Buzzer
  • 1* 10 kΩ resistor
  • 1* 150 Ω resistor
  • WS2812 Strip
  • Bluetooth Module HC 06
  • Ultrasonic distance sensor HC-SR04
  • Position Sensor MPU6050
  • Servo Motor
  • Temperature Sensor DS18B20

Digital Output

You start the Arduino IDE. Thereafter you connect the Pro Micro (seen on the right side of the picture above) with the computer and select the right USB port under Tools > Port and the right Board (in this case selecting the Arduino Leonardo works fine). Now you can make a new sketch under File > New, creating a new file named O1_Digital_Output seen on the right side of the picture above. 

A void setup () {} und void loop () {} is already included with a few comments (text after // is a comment and will be  ignored by the compiler). A program will be executed chronologically, with the setup() one time at the start, and then the loop() will be repeated forever. Both are functions which we will introduce later, for the moment it is enough to know that your code will be written inside the woven brackets ({}). Since nothing is within the brackets at the beginning, when you upload the code to the controller (Upload-button) the following will happen after the upload and a bunch of blinking: Nothing. 

That’s obviously a bit boring. Therefore you will start by turning an integrated LED at pin 17 in the Pro Micro on. Also not that interesting, but at least now an additional LED should light up permanently. Pins are connections from the microcontroller to the outside world, in this case the rows which are sticking physically out of the board and can be fitted later on into the holes of the breadboard. On the backside of the board you can find numbers (for input/output pins, controlled by the microcontroller) and descriptions 4V, GND for power pins. In this case we use a pin of the microcontroller itself (the black box in the center of the board), which is only connected to a led on the board and not to the row of pins on the side of the boards – there is no pin marked with 17.

To achieve this goal, you need to define pin 17 as an output and put it on 5V to let the LED glow.

Since you want to do it just one time at the moment and let the LED run forever (until the controller is shut down), you put it into the setup-brackets.

With pinMode (17, OUTPUT); you will define the pin as an output, and digitalWrite (17, HIGH); will set this output on 5V.

Here you can already see the main advantage of higher programming languages (the ones above writing direct machine code and Assembler), the code is relatively good to read and understand for us humans. The controller will see at the end some 0 and 1 stored on the chip (unreadable for humans). Our micro controller and computer run on these bits (0 or 1) as basic number systems, resembling ground or voltage (LOW and HIGH) and logic (FALSE and TRUE). 

pinMode () and digitalWrite () are basically shortcuts for a bunch of commands to make things easier for the user – one important part of programming: Be smart and try to reuse code snippets  as often as possible and make it as easy to understand as possible (to foster reusability). 

Another important part (which tends to give problems due to being easy to forget) is the semicolon at the end of each command, which structures the program into understandable parts for the computer.


Just a glowing integrated LED is of course a bit boring, we will start upgrading both hardware and software.  For the hardware side we will put the controller on a breadboard and add an external LED as shown in the picture. 

You can also see an additional 150-Ohm-Resistor between LED and power supply to limit current through the LED. Furthermore, polarization of the LED is important, since current can only flow in one direction through the LED: the long led belongs to +. Otherwise, she will stay dark.

The LED is now on Pin 10, we could just change the number in pinMode () and digitalRead (), but even in this short program we need to already change two numbers, contradicting the lazy paradigm. Better use variables e.g., you add even before the setup () an int led = 10; afterwards you can exchange 13 through led. 

For variables you need to define a type – in this case int for integer. This type defines storage size and number range: E.g., Boolean is just a single bit (0 or 1), float is used for floating point values. led is the chosen name of the variable, try to find useful names. Afterwards you initialize the variable with 10. 

The advantage of variables is not only that you can easily exchange its values at the beginning, but also later within the program or even by the program itself.

Another possible variant in this case would be a #define LED 10 instead of the int led = 10; . The #define tells the compiler to exchange in a first step all led later with 10 before the actual work (no semicolon necessary) – a latter manipulation of the value within the program is therefore not possible. 

Code conventions are that variables are written in small letters (besides dividing words), while defines are using only capital letters (to easily distinguish them within the code).

Pausing the controller

To make life a bit more interesting you will now begin to use the loop () and learn a new function: delay (milliseconds). With this function the controller will do nothing for a certain amount of time, with a number of milliseconds within the brackets as holiday time.

On the hardware side you will replace the LED with a buzzer as shown in the picture above.

Furthermore, you can also replace in digitalWrite (led, HIGH) the HIGH (5V) with LOW (0V). In this case the buzzer has both pins on ground (LOW, 0V) – therefore nothing will happen due to the missing voltage difference.

You write now within the loop ():
digitalWrite (buzzer, HIGH); delay (1);
digitalWrite (buzzer, LOW); delay (1);

This will turn the Buzzer on and off and generate a tone. With different duration within the two delays, you can adjust the frequency.

And if you have a look at Examples -> Basics -> Blink, here you can find a very similar program… examples and program code found on the internet are also a perfect starting point to develop your programs.

Loops: Repeat things

You will continue to make your program a bit more complex and learn about loops. loop () {} is one, albeit one which is a derivative of the regular loop functions of higher programming languages: while and for. In both cases we need a certain rule on how long such a loop should be done. E.g., while(true) {} will repeat the parts in the brackets forever, just like loop () itself. Of course, you can and want to use other logical expressions instead of just inserting “true” in the round brackets as an argument to make life more interesting. This will be covered later in the Logic section, here we will just continue using the loop() – which you can also replace with while(true) and focus on another kind of loop:

Another type of  loop is the for-loop: for (int i=0; i<10, i++) {… blink program…} will let the LED blink 10 times. i is a counter in this case, which will be initialized as an integer with 0 (and works as a local variable). It will be increased by 1 after each execution of the blink program (i++ is a short form for i = i+1). i<10 finally is the rule which needs to be correct to further continue execution of the program. When the counter reaches 10, this statement will not be correct anymore (10 is not smaller than 10), and the execution will stop. 

You need to keep in mind that this statement will be reached at some point, otherwise the program will stay within the for-loop forever, e.g., if you replace i++ with i=i. Interesting part: If you use i=i-1 (or i–) you could assume that the program will also run forever since the number will get smaller every time. Actually, at some point the value will become smaller than the assumed data storage for the value (determined by the integer) – after this point you will get an overflow and the number will switch to the highest possible number.

For a hardware test you can use now two LEDs anti-parallel, long leg of the red LED connected with the short leg of the green one and a controller pin, and the other legs on a second pin (with a resistor in between): With the LED only lighting up with current flow in one direction, depending which Pin is high and low will determine which LED will light up – or, when you put both pins on the same level, no LED will light up at all.

Analogue Output

As described before our microcontroller (and most of nowadays computers) has only a limited binary logic, running on zeros and ones, either something is on or off. But if you played around with the delay time in the loop part before, you might have noticed that you can’t see the blinking anymore with short delay times. Instead, you can variate the brightness of the led by varying the ratio between on and off time. This is called pulse width modulation and gives a (pseudo) analogue output value. Pseudo because with faster vision we could still see the blinking pattern – but our slow working eyes will only perceive an average value determined by this ratio.

Instead of using this software built with the delays there is also a hardware implementation on certain pins of the microcontroller (sometimes these pins are marked with a ˜ symbol in the Arduino world, normally you need to check the microcontroller datasheet, where descriptions and functionality for each pin is described). There you can use instead of digitalWrite () also analogWrite (pin, Wert); for analogue output.

Since pin 10 has been used in the led circuit before we can use the same circuit, but instead of digitalWrite (led, HIGH) you will use analogWrite (led, value), with value initialized as an integer value between 0 and 1023, e.g., int value = 300;

You can combine it furthermore with the for-loop from the lesson before:

for (int i=0, i<1023, i++) {

   analogWrite (led, i);

   delay (100);


for (int i=1023, i>0, i—) {

   analogWrite (led, i);

   delay (100);

Now the led slowly will get brighter (first loop, counting up) and darker (second loop, counting down). Here we don’t use the delay for blink frequency or brightness – bit for the duration how long each brightness is shown. Without delay, the program will just run so fast through both for loops that we can’t see a change in brightness at all.

Logic: Booleans and the if-loop

To make the microcontroller a little more intelligent, you need to teach it some basic logic so that it can make decisions for itself. First, you need a so-called Boolean variable:

bool state = 0; This variable can be either 0 (oder False) oder 1 (True)

For decisions, we use an if-then loop in which the controller can decide which function to execute depending on the truth of a statement:

if (a) {do something}

else if (b) {…do something different}

else {…otherwise do another thing…}

Within the curly brackets you can put the normal program code as before, while you put logical statements into the round brackets. In the simplest case it can be a Boolean variable which is changed somewhere within the code (if(true) {…} works also, but then you can also remove the decision 🙂

The comparison of different (integer) values is also common, checking if one value is smaller (<), bigger (>) or equal (==) than another one.

As an example, you can program your own delay. Just let the microcontroller count a number up, if this number is then bigger than another one (the delay time), the led is switched afterwards. You can achieve this goal with an if loop (if the old state is true, then…, else …). But there is also an easier version for this: A ! before the Boolean state will act as a logical note, inverting the value (true becomes false and vice versa). The line state = !state; will therefore change the state into the opposite.

Afterwards, the timer is set back to zero again and counting up will start again. 

It works because the microcontroller still needs a small amount of time to execute each command, the repetition for a million times therefore produces a long enough delay to produce a visible blinking pattern.

Digital Input

Now you will learn about the input possibilities of the microcontroller. On the hardware side you can extend the led circuit with a button, which is connected with another pin of the controller, in this example pin number 9. 

A button will create a short circuit between two of its pins if pressed. Otherwise these pins will have no connection. The button in the circuit here has 4 pins, with each pair of pins internally connected, counting as one logical unit.

In the example the pressed button will connect pin 9 with Ground. If the button is left unpressed, we still want a stable input (otherwise the pin will be left “floating”, basically catching random noise). Since Ground is already taken, it should be 5V. A direct connection between the button and 5V will result in a short circuit between Ground and 5V while pressing, this will heat things up a bit: Short circuits produce heat due to high currents and might damage things and should be avoided. Therefore, you want to limit the current with a resistor: With 10 kΩ the current will be I = U/R = 5V/10kΩ = 0,5 mA; a nice value, a bit better than 5V/0Ω without the resistor (resulting in infinity current, luckily limited by the available power of the USB port). 

Within the program you need to tell the micro controller that this pin should be used as an input. This is done with pinMode(button, INPUT); 

The variable button is defined beforehand in line 2  as pin 9.

Within the loop you can now check if the button is pressed with digitalRead(taster);  – it will return the state of the button, either true or false (for detecting 5V or 0V).

Next you need a variable to store the internal state for switching the led on or off, perfect for a boolean value:

bool state = false;

This variable will be switched with each button press, as in the lesson before with the ! function.

Another point to consider: You want to check for button presses fast to detect each press, but while pressing the button might flicker a bit between contact and no contact, resulting in a bunch of detecting button presses when checking all the time. With a small delay after a press is detected you circumvent this so-called bouncing.

if(digitalRead(taster)==0) {

state = !state;


digitalWrite(led, state);


Analog Input

Similar that not only digital output but also analog output exists, the same pairing exists for the input side.

Again, the statements are quite similar: for the analogue input you would use

pinMode (analogPin, INPUT); as declaration at the beginning. You don’t need to do that, but it looks better (for having an overview over used pins)

analogRead(analogPin); will give back an integer value between 0 and 1023 (The analog input of the arduino works with 10 bit accuracy – it has to be stored in zeros and ones again, 10 bit allows 1024 values, which start with 0, resulting in 1023 as maximum value): Usually pins on Arduinos which are analogue input capable are numbered with prefix A (most of them can be also used as digital in-or output).

Internally, the controller will compare the voltage on that pin with a reference voltage, either 5V or another internal reference voltage or an external voltage at pin ARef. With 5V reference voltage the analogue voltage on this pin would be the measured integer value/ 1024 *5V.

With analogReference(EXTERNAL) you can check for an external reference voltage at the ARef pin. Otherwise, you can also use INTERNAL.

As an example, you can now control the buzzer with a light dependent resistor (LDR)

analogWrite(buzzer, analogRead(ldr));

This will control the volume of the speaker; another option would be changing the frequency with the LDR by adapting a very short delay through the analogue input:





Should be enough to drive other people nuts.

Serial Communication

You might have noticed that being able to read the values would be helpful in the last lesson about analog input. In the end, the micro controller is not alone in the world and already connected with your computer for programming. Here you will learn to use the serial interface, using the USB connection from the microcontroller to the computer.

As always, the programming environment tries to make your life as easy as possible. First, you need to tell the microcontroller that you want to use two pins for the serial connection, one for sending and one for receiving data. A hardware supported version (with the connection to the USB bridge) can be found at pin 0 and 1.

Furthermore, you need to tell the controller how fast you want to speak and listen, the so-called baud rate – number of bits per second. Combined, you can start the serial communication with Serial.begin(9600); with 9600 as relative slow baud rate. Baud rate says how many bits can be sent within a certain time, with certain values possible. To see which values are allowed, you can open the serial monitor. A drop down menu on the bottom shows the available baud rates. 

Afterwards, you can send data with Serial.print(…Data…); . This could be the taster or photo resistor values but also pure text, which is identified by before and after a string or before and after a single character (char). For a more structured output you can use line break, either through the command \n within a string or by replacing the Serial.print(…) through Serial.println(…) , producing a line break after the send data.

After uploading a corresponding code onto the microcontroller, you can watch the output either in text form with the serial monitor or as a graph in the serial plotter, both found in the tool menu in the Arduino IDE. 

Hint: If you receive a weird looking letter you might want to check if you use the same baud rate on the controller and the IDE window.

You can also use the serial communication the other way around: With the serial monitor you can type in things and send them to the controller. Here,; will return a sent byte (basically one single letter, strings are therefore a bit more complicated, going letter by letter). But since you don’t know if anything is sent at all, you could check beforehand with Serial.available()) if the controller received anything at all. E.g., with 

if (Serial.available()) byte=; you will only write something in a variable byte if the controller actually received something.

Libraries: Simplify your life

Communication is of course not only limited to computers and microcontrollers, and not only not only to the serial connection. It is also possible to communicate with another microcontroller. There exist e.g.  intelligent LEDs (WS2812), where a small controller within the led housing drives the three red, green and blue (RGB) led. You can even see these parts as discrete parts if you look closely. It receives a bunch of RGB values on input data lines, takes one RGB value and displays it and sends the rest of the values through a data output line to the next led. As a result, you only need the 5V/GND power supply line and a data line from LED to LED to drive a bunch of led (at some point power might become an issue). 

Here we connect a strip of leds (multiple LEDs chained in a row) to our controller, data pin of the first LED to pin 10, power to 5V and GND to GND. Now we only need to tell our microcontroller to send color values for each LED.

Of course, to send these RGB values in the first place the microcontroller needs to understand the communication protocol of these LEDs, in this case you don’t have hardware support, and the Arduino IDE doesn’t know these protocols either.

Now you could start programming this protocol by yourself, at the end it’s just zeros and ones sent with the right timing, which you already know. But that might be a bunch of work, and somebody else already did it. These services can be wrapped in so-called libraries, where the actual code is nicely packaged. First you need to find the right libraries. Two relatively popular libraries are the Neopixel and FastLED libraries. With the library manager in the Arduino menu you can search for libraries and install them – in this case you would look for the name of the LED, WS2812. Install them once for this and future use cases, afterwards you can use this library into your programs, additionally you can find examples under … examples.

Having a look into the examples should normally guide you into using it, otherwise you need to look up the internet for additional information. 

In this case if you have a look into the “simple” of the Neopixel library you can see the basic steps to use this library.

The most important part is the  #include <Adafruit_NeoPixel.h> at the beginning, where you tell the program to use this library and include their functionality.

Afterwards you work as before, with #define you add some basic (non-volatile) values like number of LEDs and which pin is used. Similar to variable definitions you can afterwards initialize an object named pixels with these values: Adafruit_NeoPixel pixels = Adafruit_NeoPixel(…); Thereafter you can start the communication with the LEDs. pixels.begin(); works similar to the Serial.begin() before, it will start the communication. Thereafter you can set the color of each pixel pixels.setPixelColor(…); and display it with;

As you can see, libraries easily extend the use case of your controller, and in best case it works and is programmed very similar to known structures.


At some point with a bunch of values it might get a bit more complicated if you need to name and initialize each value. A more efficient approach is bundling similar values into arrays. Strings which you use for sending and receiving text in the Serial communication are a kind of arrays of characters (char), an even easier example is an array of integer values, e.g., for controlling a bunch of LEDs as in the lesson before.

With int leds[7] you can initialize an array of seven integer values under the name leds. Each value inside the array can then either set leds[i] = x on a certain value or get a value at one position with leds[i].

The most important part to remember is that i is in this case the position within the array, starting with 0 and not 1 for the first position.

With this, you can easily control a bunch of leds with a for loop:

for (int i=0; i<numberOfLEDs, i++) {

digitialWrite(leds[i], HIGH);


But since you already know how to use the intelligent LED you might not need to use it (they are just counted by numbers/position). But with this type of array, you can also control the color of each led. If you have a look at the color palette example of the FastLED-library you can see that the colorPalette are a kind of array, getting each color for the led with the array access (currentPalette[0]). 

Besides this you can see and learn something different: You can define your own functions to simplify your life.

The basic structure is returnvalue functionname (int inputvalue, …) {…} . One simple example would be your own definition of the basic sum:

int mySum(int value1, init value2) {

return value1+value2;


So mySum will return the sum of the two values within the brackets. Therefore, often used functions need to be written only once and can be reused.

Bluetooth Communication

Nowadays the wired connection to the computer is a bit outdated, wireless connections e.g with Bluetooth are more and more used. One simple way is using the cheap and simple HC 06 modules, a small bluetooth sender/receiver for serial communication. The easiest way is to connect it with power and the serial connection on pin 0 and 1 – then you can use the same code and circuit from the serial connection before. Just connect the computer via Bluetooth with this module. Factory password should be 1234, and a baud rate of 9600 for the serial connection. You could change it with so called AT-Commands, but in our basic usage you can just keep the factory settings. If you want to use it for safety relevant things, you should of course need to change it. Instructions for using the AT-commands can be found online (e.g.

and switch within the Arduino IDE from the USB port to Bluetooth, afterwards you can use the serial port as before. 

But there is one major disadvantage: Since Bluetooth runs parallel with the USB connection, uploading and using the serial connection via USB won’t work anymore with the module plugged in.

Alternatively, you can use the SoftwareSerial-Library, found within the Arduinos Library manager again, where you can use a bunch of pins for a serial connection. As you already know, you first need to include the library with #include <SoftwareSerial.h> 

Thereafter you can use pins 8, 9, 10, 11, 14, 15, 16 as additional serial pins on the Arduino Micro.

Similar to what you already know you will first define an object SoftwareSerial addonSerial(pin1, pin2); The name is of course your choice, addonSerial is only one example. Thereafter you can use the same commands as for the normal serial connection, just change Serial to your name e.g.addonSerial.begin(9600); in the setup and so on.

Thereafter you can talk both over Bluetooth with the microcontroller as well as over USB in parallel.

With so called AT commands you can even change the setup of the Bluetooth module through the serial connection, in case you need a different baud rate etc. A list of commands can be found – as always for questions – in the depths of the internet, but for basic usage you won’t need this.

Simplification:  Special functions

In this part of the learning unit we will use an ultrasonic distance sensor, which will send out a sound impulse and measure the time until it receives the echo. So you need one pin as an output to trigger an impulse (put on ground and set for a short time delayMicroseconds(10);  on 5V for sending the impulse). A second one is used as input to measure the echo. So far nothing new. Now you need to somehow measure the distance. As before you could start measuring the time and then calculate the distance from it. As always, somebody else might have already done this. 

But instead of looking for libraries,  in the arduino programming language there are also a bunch of not so obvious functions. In this case the pulseIn(echoPin, HIGH)*0.034/2; is useful for measuring the length of the echo. This value is then multiplied by 0.034 for speed of sound of 340m/s and divided by 2, because the pulse will travel first to the object and then back, resulting in the double distance.

Similarly, you can use another function to control tone: tone(pin, frequency) Here you can modify the sound frequency directly.

As you can see, the structure is always similar, the most important part is checking where you can find the easiest way to solve your question, especially through already implanted code. 

1) Check the implemented functions of the programming language (for the Arduino IDE, examples are a good starting point). 

2) Check the libraries through the library manager, where you can search for keywords and which will also include examples for their functionality. 

3) Look up open-source projects found on the internet ( might be interesting, for more complex programs also, and for code snippets and questions forums like, but normally just typing in a description of your idea or  hardware should direct you to the right pages). This might get perfect solutions for a special problem, but might not be as cleaned up. The nice thing is since you use clean code and compile it for yourself, there should normally be no viruses or other malicious attempts possible.

I2C Communication

Another useful part of the Atmega32U4 is that it can be used as a so-called HID (human interface device) for your computer, which means you can use it as a mouse or keyboard replacement. Combined with a sensor you can build your own input device.

You start with the HID functionality; in this case you will use the mouse function. As usual you include the corresponding #include “Mouse.h” at the beginning. Thereafter you can start this functionality with Mouse.begin();. With Mouse.move(x,y, wheel); you can send both direction and mouse wheel movement to the computer, and; sends the signal that a mouse button is pressed. You could use the well-known button with a combination of photo resistor and ultrasonic distance sensor for mouse movement.

In the following paragraph you will learn to use another sensor, a combined acceleration and gyroscope with another protocol, I2C.

This is a popular protocol used for a bunch of sensors and other extensions of your microcontrollers’ functionality. Each module has a certain address, under which it could be found on the bus structure, where each module is put in parallel on a data and clock line, with the microcontroller as central.

The sensor module used is a GY-521 or the MPU6050 sensor. As always, there are appropriate libraries, e.g. from Adafruit, the Adafruit_MPU6050 where you can find examples such as basic_readings for orientation. Beside the MPU6050 library there are two other libraries included: Adafruit_Sensor – which is a support library for general sensor functionality, and Wire. The latter is the library which allows you to use I2C on your controller.

After inclusion of the libraries with #include <Adafruit_MPU6050.h> #include <Adafruit_Sensor.h> and #include <Wire.h> you can make an new object Adafruit_MPU6050 mpu;  which can be started with mpu.begin(); Afterwards you can take the data of the module with mpu.getEvent(&a, &g, &temp); for storing them in sensors_event_t a, g, temp; and feed them into the mouse Mouse.move(g.gyro.x, g.gyro.y, g.gyro.z);

You might notice one point: I2C needs an address for each sensor, which you didn’t use in this example. This address is hidden within the Adafruit_MPU6050 library. If you look up the Arduino folder within your documents, and then under libraries and Adafruit_MPU6050 you can open the so-called header file, which shows the sort of general functionality of the library (implemented within the other files) – some parts like #define you might already understand, some are more advanced features (which you should just ignore if it doesn’t look necessary for your code). At some point you will find the public interface parts like getEvent(), which you used in the example. Followed by a private integer value _sensorID, which is the before mentioned I2C address of the sensor module. Classes, and public and private access to functions and variables of a class is a more advanced method for structuring your program, not featured in this course. If you are interested in these concepts, you will already get into advanced programming techniques.


Apart from sensors you can also control motors with your controller, one small motor module is the servo motor. If you tear such a servo motor (which you can find in different sizes in electronics part stores) apart you can find a small controller, a DC motor with a mechanic and finally a changeable resistor for position control inside. The nice thing for this kind of motor is that due to its integrated controller you don’t need an external driver. Other motors are power hungry, too much for direct power supply through controller pins – besides other electrical problems due to the motor inductance. The disadvantage of a servo is that it generally only rotates within a certain area of degrees due to mechanical limitations

For controlling the servo you can use the corresponding library and examples, which are in this case directly installed within the IDE: You can find under examples the Servo with two example programs.

Here we will learn about the basic timing of the controller. You already know about delays. Here you learn about millis(); . This function returns the time in milliseconds since the start of the microcontroller. With this timer (and ideally the start time of the controller) you can build your own clock. Millis() will count up since the start of the program, getting bigger and bigger (that’s why millis() uses not integer but a bigger data format, long, for more storage space for bigger values). 

For this you need to think if your servo should display hours, minutes or seconds: You need to change millis(); into the right value through division with a corresponding value. A normal division won’t work, but you can use a so-called modulo operator %, which gives the whole number the rest of a division. Millis()/1000)%60 results in the seconds for our clock with a reset to zero after sixty seconds through the modulo operator. 

If you want to use your servo as a digit for seconds, and with the servo moving between 0 and 180 degree, you only need to multiply the result of the calculation before with three, resulting in values between the 0 and 180: myservo.write(((millis()/1000)%60)*3);


The chapters beforehand give you basic knowledge about programming a microcontroller, but this is obviously just a first step. Another interesting field for programming is of course writing programs directly on and for your computer.

For this purpose, you can use – among other environments – an IDE called Processing. After download and installation, you can start the program and might notice that it looks very similar to the Arduino IDE. In fact, the Arduino IDE is based upon this IDE. As a result, programming is very similar, furthermore you can easily communicate between Microcontroller and this IDE with the serial connection.

If you want to test it you can first get a list of serial connections of your computer with

import processing.serial.*;

for (int i=0; i< Serial.list().length; i++) {

    print(i + “ : “ );



This will print out all available serial connections in the processing window. Now you only need to remember the number of the serial connection in the Processing IDE which matches the serial connection of the microcontroller in the Arduino IDE. A bit more complex is the comparison between this list entries and a corresponding partstring:

if(Serial.list()[i].substring(0,17).equals(„/dev/cu.usbmodem1″))  or similar (depending on the actual connection on your computer)

In any case, after detecting the same serial connection for microcontroller and program in Processing you can start a serial connection with this list entry similar to the program on your microcontroller.

Serial myPort;

String portName = Serial.list()[portNumber];

myPort = new Serial(this, portName, 9600);

Infinite Possibilities

From this point onwards you can use the serial connection to send and receive data. You can do this by text or with a graphical interface. This is of course a topic of its own, but Processing makes your life easier. Under Topics -> GUI -> Buttons you can find a nice example as a basis. Here you can include the serial connection and within mousePressed() add a Serial.print(“N“);.

When you start this example program you will see a small window, and if you press the button on the screen within the program window while hovering with the mouse pointer over one of the two figures, Processing will send a letter N over the serial connection to the computer. Now you can program the microcontroller that if it receives something through Serial e.g., a LED is turned on or off.

Similar to the Arduino IDE beforehand, Processing gives you a bunch of possibilities to develop your own programs. Other Programming languages like HTML can be used for website programming.. In the end, the basics remain the same and with each programme you learn something that makes your life easier for the next programme. And don’t forget to check on which existing open-source projects you can build upon.


Programming tells a microcontroller or computer what to do. Broken down on a machine code level these machines only understand binary language – True and False. To make life easier for programmers, higher programming languages exist which are closer to our human language. These languages are translated into machine code through a compiler

In this unit we use the Arduino IDE to program code and compile it for a small microcontroller board, the Pro Micro.

Digital/analogWrite allows direct manipulation of output devices, while the corresponding Read-Functions allow the usage of input devices. Variables, delays, time, logic are used to create a program flow.

Different communication protocols like Serial, I2C, 1Wire  can be used with the help of libraries. They further expand the options of communication with other devices, as well as enabling communication with the computer. To understand their functionality, you can use onboard examples or look them up on the internet.

Processing is a similar programming environment as the one used to program the microcontroller, but in this case for making programs for a regular computer. In General there exist a bunch of different programming languages either optimized for hardware (C), use case (HTML for websites) or general usage on different platforms (Java). 

The basic structures are similar, since all of them can be broken down at the end on a general machine code level.

The most important lesson is that you should always try to reuse code: Use examples as a basis, reuse already programmed code parts (especially libraries through the library manager), as well as open source code as a basis for your own (hopefully also open-source) programs. It is not necessary to invent the wheel a second time.