Arduino IDE Linux Install

Installing the Arduino IDE for an Arduino UNO on Ubuntu 20.04 LTS

In this guide I will install the Arduino IDE for use on a PC with Zorin OS 16 (an Ubuntu 20.04 LTS Based Linux Distribution).

I am using an Arduino UNO (ELEGOO UNO from the ELEGOO Most Complete Starter Kit). For installation and test of the Arduino UNO board we only need the Arduino UNO (ELEGOO UNO) and its USB 2.0 Type A to B cable.

Downloading the ELEGOO Documentation

The ELEGOO Documentation can be downloaded from:

To the left hand side select UNO R3 Starter Kits and then to the right hand side, select ELEGOO UNO R3 The Most Complete Starter Kit:

Select ELEGOO UNO R3 Project The Most Complete Starter Kit V2.0:

Right click the extracted zip file and select Extract to…

Select Documents and select Select:

You will now have the ELEGOO Documentation:

You will have three folders:

  • ##Read Me First – Contains a Copy Me First folder which has Arduino Sketches which will be discussed later. The other pdfs are for Windows Drivers and not relevant for a Linux Install.
  • ##DataSheet – Has the Datasheet for each electrical component in the Kit. It is worth browsing through these later before you begin using the electronics components.
  • English – Has English Tutorials. This guide will complement Part 1 Preparation which contains 1.1 Packing List and 1.2 First Look Arduino. 1.3 Setting the Arduino IDE Up for Windows and 1.4 Setting up the Arduino for Linux are not covered too well and this guide will expand on 1.4. This guide will also cover 1.5 Blink.

Installing the Arduino IDE on Linux

Download the latest Arduino IDE from:

It will be available as a .tar.xz file.

You should be able to right click it and extract it.

Select, Downloads and then select Seclect:

Open the extracted folder and subfolder:

We are going to install the Arduino IDE using the install.sh. To do this right click on some empty space within the folder and select open in terminal:

Input:

sudo ./install.sh

Because the command begins with sudo (super user do), you will be prompted for authentication. Input your password to proceed:

The Arduino IDE will be installed.

You can now add the Arduino IDE to favourites:

Insert the USA Type A to B cable into your computer and Arduino UNO. You should see a green power LED illuminate. You can now launch the Arduino IDE:

A blank sketch will display. This essentially has two functions a setup function and a loop function. Code in the setup will only be carried out once and code in the loop function will be looped indefinitely:

void setup(){
   // put your setup code here to run once:
}
void main(){
   // put your setup code here to run repeatedly:
}

For now we won't modify this blank sketch and just attempt to upload it to the Arduino. There are a number of Arduino boards. We are using the most standard beginner board, the Arduino UNO. Before uploading a sketch to the Arduino we must select the correct Board Type by selecting Tools → Board → Arduino Uno:

We should then make sure the correct Port is selected. In this case it is /dev/ttyACM0 and as it is recognised as an Arduino Uno, /dev/ttyACM0 (Arduino Uno) is shown.

To upload a sketch to the Arduino UNO, select the Upload button:

Linux Serial Port Permissions

During first time run you are likely to get the following error:

An error occurred while uploading the sketch avrdude: ser_open: can't open device "/dev/ttyACM0": Permission Denied.

This is because the user does not have permissions to dialout to the Arduino using the Serial Port.

We are going to use user mode (usermod) to append the user Philip to the Group called dialout (which have permissions to dialout).

sudo usermod -a -G dialout philip
  • -a means append
  • -G Group
  • philip should be replaced with your user name (shown at the start of the prompt in the console).

We are then going to change the mode (changemod) for the specific port to be all options including read and write:

sudo chmod a+rw /dev/ffyACM0
  • a (all options)
  • rw (adds read and write permissions)
  • /dev/ttyACM0 is the name of your device (this may vary if you have multiple Arduinos, replace with the desired device).

Finally to apply the changes we need to reboot and we can use this by typing in:

sudo reboot

When the computer reboots we can try to upload our sketch. Now we see no error message and our sketch gets uploaded to our Arduino Uno. As the sketch gets uploaded the two lights incited in the orange square will briefly illuminate for about 0.5 s:

The Example Blink Sketch lets you test whether you can communicate with your Arduino to control an inbuilt test LED.

To access this select File → Examples → Basics → Blink

Then upload the sketch. When this sketch is ran you should see the test LED blink on and off for every second:

Let's have a look at the code. In the setup we have a single statement. This uses the Arduino inbuilt pinMode class, note the automatic yellow color-coding for an inbuilt class. This class takes two input arguments the pin to be used; in this case LED_BUILTIN and whether than pin is used as an INPUT or OUTPUT. Note the capilization of these constants and automatic green color-coding for an inbuilt constant.

void setup(){
   pinMode(LED_BUILTIN, OUTPUT);
}

This setup is only ran once. Once we have selected this pin, we are not changing our selection.

The loop uses the inbuilt digitalWrite class. This once again is color-coded in yellow and takes two positional input arguments. The first is the pin and the second is the state of the pin which can be HIGH or LOW (which can be thought of as ON or OFF respectively for the LED). Note once again these constants are capitalized and color-coded in green.

void loop(){
   digitalWrite(LED_BUILTIN, HIGH);
   digitalWrite(LED_BUILTIN, LOW);
}

These commands will be carried out in a less than a ms which is too quick for the eye to register. In order to see something we can add a delay using the inbuilt delay function which takes an int input which specifies the number of milliseconds to wait (1000 ms = 1 s).

void loop(){
   digitalWrite(LED_BUILTIN, HIGH);
   delay(1000);
   digitalWrite(LED_BUILTIN, LOW);
   delay(1000);
}

The duration of the delay can be changed to specify a custom ON and OFF time for the test LED.

Hello World with the Serial Port

Note that the syntax used within the Arduino IDE is essentially C++. Let's have a look at one of these empty functions:

void setup(){
   // put your setup code here to run repeatedly:
}

The first word void is the return type of the function. void means the function has no return type. i.e. there is no return statement in the functions body.

setup is the name of the function.

( ) enclose the functions input arguments. This particular function has no input arguments.

void setup( ) is known collectively as the functions head.

{ } are used to indicate a code block that belongs to the function. This code block is known as the functions body.

// is used to indicate a comment.

In C++ we cannot use spaces in object names and therefore we tend to capitalize adjoining words. We tend to use two conventions which are often confused by beginners; PascalCase and camelCase. The difference between these can be depicted using a camel. When the Camel has its HeadUp we are using Pascal Case and when the camel has its headDown we are using camelCase:

caseexample string
English SentenceThis is a string
Pascal Case (HeadUp)ThisIsAString
Camel Case (headDown)thisIsAString
Upper CaseTHISISASTRING

In C++ we use camelCase to name functions. We have used the functions pinMode, digitalWrite and delay for example. These are all recognized and automatically highlighted in yellow by the Arduino IDE.

In C++ we use UPPERCASE for constants. A constant is a data type with a fixed value. Constants are normally defined at the top of the Arduino sketch/ There are some inbuilt constants such as OUTPUT, INPUT, HIGH and LOW which we have used before and are automatically highlighted in green by the Arduino IDE.

In C++ we use camelCase for variables. A variable is a data type with a value. This value may be updated to a new value at a later point in the Arduino sketch but the data type of the variable cannot be changed.

In C++ we use PascalCase for a class. A class can be thought of as a collection of data variables, constants and functions which work on the data variables. To access an object belonging to a class we type in the class name followed by a dot .

The first class you are likely to use with the Arduino is the Serial class which contains a number of functions that are used for serial communication.

Let's have another example sketch, by going to File→Examples→Communications→SerialEvent:

Within the setup() function we see use of the Serial class.

The begin function of the Serial Class is used to initialize or set the beginning conditions of the Serial port. The input argument 9600 corresponds to the speed of the serial port.

Note the form:

Class.function(arg);

Serial.begin(9600);

The . means we are accessing the function begin which belongs to the Class Serial.

We also see the use of the Serial classes println (ln an lower case abbreviation for line, not to be confused with capital i as in) function which can be used to print a string followed by a new line to the Serial Port.

We can modify the setup of an empty sketch to initialize the Serial Port and we can use the print function to print a string. A string is a collection of characters. The collection of characters to be printed must be enclosed in double quotations.

void setup(){
   Serial.begin(9600);
   Serial.print("Hello"); 
}
void loop(){
   // put your setup code here to run repeatedly:
}

In the C++ programming language, indentation isn't as critical however it can make the code easier to read:

The Arduino IDE can autoformat your sketch to make it readible:

The activity from the Serial Port can be monitored by using the Serial Monitor. This can be accessed by selecting Tools→Serial Monitor:

The baud of the Serial Monitor should match the value defined when the Serial Port was initialized:

The sketch can be uploaded to the Arduino using the Upload Button:

As this is the first time running this sketch you will be prompted to save the sketch. The default location is in Documents/Arduino

If there are no errors in the Sketch, the Sketch will successfully upload

Code in the setup function should only be carried out once however sometimes in Linux when the sketch is uploaded, it is carried out twice. The output can be cleared from the Serial Port and the reset button can be used on the Arduino to relaunch the currently uploaded Sketch:

We have so far looked at the data type string which is enclosed in double quotations " ". We also have the character or char datatype which is a single character enclosed in single quotations ' '. Another important datatype is the integer or int datatype which is a whole number. We can update our sketch to include these:

void setup(){
   Serial.begin(9600);
   Serial.print("Hello"); 
   Serial.print('H');
   Serial.print(2); 
}
void loop(){
   // put your setup code here to run repeatedly:
}

Notice that the output is all concatenated onto a single line, this is because we haven't included instructions to specify a space or a new line. We can do this by printing the special character '\n':

void setup(){
   Serial.begin(9600);
   Serial.print("Hello"); 
   Serial.print('\n'); 
   Serial.print('H');
   Serial.print('\n'); 
   Serial.print(2); 
   Serial.print('\n'); 
}
void loop(){
   // put your setup code here to run repeatedly:
}

Or by alternatively using the Serial classes function println opposed to the Serial classes function print:

void setup(){
   Serial.begin(9600);
   Serial.println("Hello"); 
   Serial.println('H');
   Serial.println(2); 
}
void loop(){
   // put your setup code here to run repeatedly:
}

So far we have only used the setup function which runs once. We can also use the loop function which will loop continuously:

void setup(){
   Serial.begin(9600);
   Serial.println("Welcome"); 
}
void loop(){
   Serial.print("Hello"); 
}

However it runs too fast for us to even read the output. Like the blink sketch, we need to add a delay in the loop so we can see the output:

void setup(){
   Serial.begin(9600);
   Serial.println("Welcome"); 
}
void loop(){
   Serial.print("Hello");
   delay(1000); 
}

Getting started with C++

The Arduino IDE uses C++. C++ is an object orientated programming language and it is useful to understand some of the basics before looking at other Arduino sketches.

Let's have a look at declaring and assigning a value to a variable:

// declare a variable
int numZero;
// assign a value to a variable
numZero = 1;

This can be done on a single line:

// declare and assign a variable
int numZero = 1;

We can create two int variables and then sum them together to make a new int variable:

// declare and assign variables
int numZero = 1;
int numOne = 2;

int numAdded = numZero + numOne;

The above can be done in a function. This function will result in an int output which is indicated by the return type int at the start of the functions head. The return statement at the end of the functions body returns an int:

int addNum(int numZero, int numOne){
   int numAdded = numZero + numOne;
   return numAdded;
}

This can be simplified by combining the two lines of code in the functions body:

int addNum(int numZero, int numOne){
   return numZero + numOne;
}

In the above the function is declared but not used. It can be used alongside the correct number of input arguments giving the value 3:

// Define a function
int addNum(int numZero, int numOne){
   return numZero + numOne;
}
// Call a function
addNum(1, 2);

This value of 3 can be assigned to a variable numAdded when the function is called:

// Define a function
int addNum(int numZero, int numOne){
   return numZero + numOne;
}
// Call a function and assign output to a new variable
int numAdded = addNum(1, 2);

It is possible to assign each input argument variable in the functions head to a default value when the function is defined. If these are not supplied when the function is called, the default values are instead taken:

// Define a function
int addNum(int numZero=0, int numOne=0){
   return numZero + numOne;
}
// Call a function and assign output to a new variable
int numAddedZero = addNum(1, 2);
int numAddedOne = addNum(1);
int numAddedTwo = addNum();

In the above numAddedZero = 1+2, numAddedOne = 1+0 and numAddedTwo=0+0.

In an Arduino sketch the function must be directly or indirectly called within either the setup or loop functions.

// Define a function
int addNum(int numZero=0, int numOne=0){
   return numZero + numOne;
}
void setup(){
   Serial.begin(9600);
   int numAddedZero = addNum(1, 2);
   int numAddedOne = addNum(1);
   int numAddedTwo = addNum();
}
void loop(){
}

We can use the Serial classes function println to print the value of these numbers:

// Define a function
int addNum(int numZero=0, int numOne=0){
   return numZero + numOne;
}
void setup(){
   Serial.begin(9600);
   int numAddedZero = addNum(1, 2);
   Serial.println(numAddedZero);
   int numAddedOne = addNum(1);
   Serial.println(numAddedOne);
   int numAddedTwo = addNum();
   Serial.println(numAddedTwo);
}
void loop(){
}

Sometimes when we are working with the Arduino it is useful to define some constants at the beginning of a sketch. You will see this commonly done with Arduino libraries. The library may be setup to use for example pin 7 but when you incorporate the hardware into your setup you may already be using pin 7 and wish to switch to another pin for example pin 8. By using a constant at the top of the Arduino sketch you can readily alter the pin using a single line of code opposed to having to trawl through the entire example sketch to modify the multiple lines of code where the pin is used.

Constants tend to have an uppercase names. We use the #define pre-processor directive to set a constant name in this case MYPIN to a value in this case 2.

#define MYPIN 2

Pre-processor directives and not statements therefore do not terminate with a semi-colon. There is no assignment operator used when using a pre-processor directive.

Sometimes we wish to repeat an instruction for a number of times. We can do this with a for loop. The for loop has a similar structure to a function. Instead of input arguments, the loop head requires two statements and an instruction for iteration. The first statement is the creation of the loop variable and its assignment to an initial value. The second statement is the condition that needs to be valid for the loop to run. It is common to use the iterator ++ for example with the loop variable i, i++ which will increase the value of i by 1 every time the loop is executed. The loop body can contain a number of statements which will be carried out each time the loop is executed.

for(int i=0; i<3; i++){
   Serial.println(i);
}

In the example above the loop variable i is set to an initial value of 0. We then check the loop condition, is i<3, it is, so we carry out the instructions in the loop, that is to print the value of i (0). Now that we have carried out all the instructions within the loop we increment i by 1 using i++.

This means i is now 1. We then check the loop condition, is i<3, it is, so we carry out the instructions in the loop, that is to print the value of i (1). Now that we have carried out all the instructions within the loop we increment i by 1 using i++.

This means i is now 2. We then check the loop condition, is i<3, it is, so we carry out the instructions in the loop, that is to print the value of i (2). Now that we have carried out all the instructions within the loop we increment i by 1 using i++.

This means i is now 3 We then check the loop condition, is i<3, it isn't, so we exit the loop. Note in this case the value 3 is not printed because we do not follow the instructions in the loop when the condition has not been met.

Let's create an Arduino sketch that includes a constant and a loop that prints the loop variable and the constant:

//declare constant
#define MYPIN 2

void setup() {
   //Initialize serial
   Serial.begin(9600);
   for (int i = 0; i < 10; i++) {
      Serial.print("loop index i=");
      Serial.println(i);
      Serial.print("constant MYPIN=");
      Serial.println(MYPIN);
   }
}

void loop() {
}

We can also use an if code block which will be carried out only if a condition has been carried out.

for(int i=0; i<3; i++){
   if(i<1){
      Serial.print("i is less than 1 and has a value ");
      Serial.println(i);
   }
}

In the above we would get only.

i is less than 1 and has a value 0

We can add an associated else code block which will be carried out if the condition presented in the else code is not true.

for(int i=0; i<3; i++){
   if(i<1){
      Serial.print("i is less than 1 and has a value ");
      Serial.println(i);
   }
   else{
      Serial.print("i is greater than or equal to 1 and has a value ");
      Serial.println(i);
   }
}

In the above we would get only.

i is less than 1 and has a value 0

i is greater than or equal to 1 and has a value 1

i is greater than or equal to 1 and has a value 2

//declare constant
#define MYPIN 2

void setup() {
   //Initialize serial
   Serial.begin(9600);
   for (int i = 0; i < 10; i++) {
      if(i<1){
         Serial.print("i is less than 1 and has a value ");
         Serial.println(i);
      }
      else{
         Serial.print("i is greater than or equal to 1 and has a value ");
         Serial.println(i);
      }
   }
}

void loop() {
}

Let's create an Arduino sketch that includes a for loop which uses an if and else code block:

Other conditions can be added using one or multiple else if conditions.

//declare constant
#define MYPIN 2

void setup() {
   //Initialize serial
   Serial.begin(9600);
   for (int i = 0; i < 10; i++) {
      if(i<1){
         Serial.print("i is less than 1 and has a value ");
         Serial.println(i);
      }
      else if(i<1){
         Serial.print("i is less than 2 and has a value ");
         Serial.println(i);
      }
      else{
         Serial.print("i is greater than or equal to 2 and has a value ");
         Serial.println(i);
      }
   }
}

void loop() {
}

Notice that in the case of i is 0. It meets the condition specified in the if code block as well as the else if code block however as the if code block is higher priority, it has followed only the instructions in this code block. An analogy is a car coming to a junction. If the car has turned (left) if, so cannot go (straight) else if:

We can also use the value i as a switch and then specify a code block for a number of cases.

//declare constant
#define MYPIN 2

void setup() {
   //Initialize serial
   Serial.begin(9600);
   for (int i = 0; i < 10; i++) {
      switch(i){
         case 0: {
            Serial.print("i is zero and is ");
            Serial.println(i);
         }
         case 1: {
            Serial.print("i is one and is ");
            Serial.println(i);
         }
         default: {
            Serial.print("i is neither zero or one and is ");
            Serial.println(i);
         }
      }
   }
}

void loop() {
}

switch case does not act like a car at a junction and will by default execute the code block corresponding to the specific case and all subsequent code blocks. In the case of i=0, this executes the code in the code blocks of case 0, case 1 and default. In the case of i=1, this executes the code in the code blocks of case 1 and default.

To stop this behaviour we need to include a break statement at the end of the code block.

//declare constant
#define MYPIN 2

void setup() {
   //Initialize serial
   Serial.begin(9600);
   for (int i = 0; i < 10; i++) {
      switch(i){
         case 0: {
            Serial.print("i is zero and is ");
            Serial.println(i);
            break;
         }
         case 1: {
            Serial.print("i is one and is ");
            Serial.println(i);
            break;
         }
         default: {
            Serial.print("i is neither zero or one and is ");
            Serial.println(i);
            break;
         }
      }
   }
}

void loop() {
}