How to Develop and Control of Arduino Systems on Linux

Today we are going to learn how to install Arduino IDE on Linux, some of basic features to help you get started, build and upload you programs to the Arduino board, create a basic unix-like command interface based on Arduino's Serial library, use system utilities to control it and how to create a simple web-based interface using Apache and Perl CGI.

Table of Contents

  • Intro
    • What is Arduino?
    • What can it do?
    • Requirements
  • Install Arduino
  • Running Arduino IDE
    • Connect the board
    • Select port
    • Load Example
    • Upload to Arduino
      • Troubleshooting AVRDUDE
  • Talking to the Board
    • Linux Shell
    • Minicom
    • Perl


What is Arduino?

Arduino is an open source electronics prototyping platform, it provides application programming libraries, development environment  and hardware modules, which are based on Atmel's 8 and 32-bit AVR microcontrollers. It has a simple programming language based on C, full of libraries, examples and a large community, which make it fairly easy to get started and make cool things.

What can I do with it?

  • Engineers uses it to make prototypes much faster and cheaper to their projects
  • Sysadmins can monitor systems health, automate tasks on the data center, such as physical backups.
  • Hackers can create awesome gadgets such as, augmented reality goggles, 3D printers and all others kinds amazing stuff
  • Musicians creates entire new instruments, that can literary tune and play itself when needed.
  • Kids have fun while learning computer programming and electronics engineering to make their own toys.

The limits of what you can do with Arduino is up to you, from systems  to help people with special needs to clouds of shooting drones, so remember that great powers comes with great responsibility.


  • Arduino board - This tutorial uses UNO board, but should be OK for others too
  • cdc-acm.ko or ftdi_sio.ko - Linux kernel with CDC ACM or FTDI module to interface with the USB port
  • Arduino IDE - The Arduino development environment
    • Contained - The following requirements are now distributed within the IDE package
      • JRE - Java Runtime Environment
      • AVRDUDE -AVRDownloaderUploaDEr
  • System dependent - shared libraries are needed and missing  or in different version on some systems, install will be covered
  • - Terminfo shared library
  • - readline shared library
  • Optional - For the web interface
    • ApacheHTTPD - Web server
      • Perl - Server-side language
        • Device::SerialPort and CGI modules

Install Arduino

We are going to use the new packaged version of Arduino, which comes with java runtime environment and avr tools, and thus make things much easier and in older versions.

Download the package with wget


Extract the contents from the xz tarball:

tar Jxvf arduino-1.6.5-linux64.tar.xz

Move the extracted package to /opt and link its arduino shell script on /usr/local/bin:

mv arduino-1.6.5 /opt/ && cd /opt/ && ln -s arduino-1.6.5 arduino && ln -s /opt/arduino/arduino /usr/local/bin/arduino

Now you should be able to start the IDE by simply calling arduino:

Arduino splash screen
Arduino splash screen

Running Arduino

Now that we have Arduino ready on our system, let's focus out attention on how to upload our programs to it.

Connect your board

Once you connect the board on the Linux system, it should be registered by the kernel as /dev/ttyACMx, where x is numeral and may change. To be sure on how your board was recognized, connect your board and run the following command:

dmesg | tail -n 7


Detect arduino lsmod and dmesg
lsmod tells that cdc-acm module were loaded and dmesg shows where

Select port

By default, the IDE will detect your board, however, it may fail when you disconnect and reconnect your board or you have a deadlock on computer side for instance,so you may need to click on Tools->Port, from the menu, as in the image below:

Select serial port
Select serial port

Load example

Let's say hello to Arduino, for this select the example sketch from the menu File->Examples->Basics->Blink, as follows:

Load blink example sketch
Load blink example sketch

Upload you program

Once you have a program ready on the IDE, click on the Arrow on the top-left area of the IDE or press [Ctrl+u] to sent it to the board. You will see the status of the upload on the output console on the bottom of the IDE.

Upload succeeded
Upload succeeded

Alright, your board should be blinking now, if so you can go to the Talking to Arduino section, otherwise, continue on the next section.

Troubleshooting Avrdude

On some distros (at least on  Slackware 14.1), the packaged avrdude throws error messages regarding missing and  The following lines describes how to build and install these shared libraries from source

libtinfo-terminfo.9 error during upload
libtinfo-terminfo.9 error during upload


wget &&  tar zxvf ncurses-5.9.tar.gz

Enter on sources directory

cd ncurses-5.9

Configure the ncurses build with Terminfo and shared library options enabled

./configure --with-termlib --with-shared

Then, make and install ncurses

make && make install



wget && tar xzvf readline*

Enter sources directory

cd readline*

No special flag needed


Then make and install

make && make install

Update your shared libraries database:


Now try to upload your code again and look at your board to see if it is blinking now, if not, the following command may help you to find out what is going wrong:

From within the Arduino directory try:

ldd hardware/tools/avr/bin/avrdude_bin

On the following example with libreadline, you see two outputs, highlighted in the red when  some library can't be found and on green is the output when things are good.

ldd showing missing or found readline library.
ldd showing missing or found readline library.

Talking to the Arduino board

You can communicate with the program on your board in many ways, I am going to show you how to use the serial port to do this.

Arduino serial terminal

The following program is based on the SerialEvent example that comes with Arduino, it will process the data coming from the serial port, perform actions based on it, such as blink, read sensor, report uptime or reboot.


String inputString = "";

String lastcmd = "";

boolean stringComplete = false;

int sensor = A0;

int ledstate = LOW;

//use some wiring from this pin to reset pin to disable auto-reset

int resetPin = 8;

//Check if inputString match the given cmd string

bool cmd(String cmd){

if (inputString.startsWith(cmd)){ return true;} else { return false; }

} //Simply blink the led for some time void blink(int led, int mil){

digitalWrite(led,HIGH);  delay(mil); digitalWrite(led,LOW);  delay(mil);

} //This function will restart your board void(* reboot) (void) = 0; void setup() {

//Set the serial port speed


Serial.begin(9600); inputString.reserve(255); pinMode(13,OUTPUT);


//with some wiring from the resetPin (pin 8) to the reset pin, this will disable auto-restart




//blink 3 times to show that system is starting


blink(13,200); blink(13,200); blink(13,200);


//print a cool penguin and initial prompt


Serial.println("  .^."); Serial.println("  /\V\\"); Serial.println(" / - \\"); Serial.println("/(   )\\"); Serial.println(" ^`~'^"); Serial.print("Arduino:");

} //Perform actions based on the input void check_input(String input){

//if the input is an exclamation, repeat last command


if(cmd("!")){ inputString = lastcmd;}


//Turn led on


if (cmd("led_on")){


ledstate = HIGH; Serial.println("LED was turned on");


//Turn led off


} else if (cmd("led_off")) {


ledstate = LOW; Serial.println("LED was turned off");


//Read sensor pin


} else if (cmd("read_sensor")) {


Serial.println("Sensor value was:"+String(analogRead(sensor)));


//Call blink function


} else if (cmd("blink")) {








//Call reboot


} else if (cmd("reboot")) {


Serial.println("Rebooting..."); delay(200); reboot();


//Show time since last boot in milliseconds


} else if (cmd("uptime")) {


unsigned long time = millis(); Serial.println("Uptime: "+String(time));


//Input string does not have any registered command


}else {


Serial.println(" command not found->"+inputString);




//Add the command to "history" lastcmd = inputString;


//prepare for next command inputString = ""; stringComplete = false; Serial.print("Arduino:");

} //The main loop function void loop() {

serialEvent(); if (stringComplete) {


//Call our input handler function




} digitalWrite(13,ledstate);

} //This function works when we have data comming from the serial port void serialEvent() {

while (Serial.available()) {


char inChar = (char); // [ Backspace ]


if ( inChar == '\b') {


inputString.remove(inputString.length() - 1, inputString.length()); Serial.print(' '); Serial.print('\b');


} // [ Enter ] else if ( int(inChar) == 13 ) {


inChar = '\n';


} else {


//add current character to input command


inputString += inChar;


//Serial.print(int(inChar)); //debug control characters




if (inChar == '\n') {


stringComplete = true;






Serial Monitor

The most simple way to talk to your board is the Serial Monitor available from the IDE, for that, click on Tools->Serial Monitor or press [Ctrl+Shift+m]

Controlling Arduino with Serial Monitor
Controlling Arduino with Serial Monitor

This approach is particularly useful for debugging, use it when creating your program.

Linux Shell

You can also interact to it using bash, to do this, open 2 terminal sessions, one for read and other write, run following commands.

Session 1:

tail -f /dev/ttyACM0

Session 2:

echo "my message" >> /dev/ttyACM0

Here is an example:

Interacting with Arduino using tail and echo
Interacting with Arduino using tail and echo


Minicom is an terminal emulator that comes with many Linux distros, to use it with Arduino try:

minicom -D /dev/ttyACM0

Then type the following key sequence to configure port settings

[Ctrl+a], z, p, c, q, [Enter]

Arduino session on Minicom
Arduino session on Minicom

Web Interface

blink(13,200);We are now going to use our browser to interface with Arduino, for that you will need a web server and a server-side language, and we are going to use Perl.

Apache CGI feature

Before we can continue on the Perl script, we need to set Apache to enable CGI feature, for that you must remove comment on the line referring to the cgi_module, that looks like the following:

LoadModule cgi_module lib64/httpd/modules/

Disable auto-reset

Also have in mind that most boards will restart after you close the serial port, to disable this, put wiring from pin 8 to reset on your board. If there current on reset pin Arduino will not reset, and we set this pin HIGH during setup function on our code.

Access to serial port

Assuming that the owner of Apache process is apache, add it to the dialout group, which is owners of the /dev/ttyACMx device

usermod -a -G dialout apache || usermod -a -G uucp apache

Perl Modules

In fact we could be using IO::File to the device much  and simple print to generate our page, but things start to become complex for the reading from serial and user submitted data, so let's use CGI and Device::SerialPort modules to make our lives easier.

CGI module to process the  HTTP requests and print out some html using perl syntax, so install with cpan:

cpan -i CGI

Device::SerialPort as the name suggests, if for the serial communication:

cpan -i Device::SerialPort

Once you have Apache set and the modules installed, create the Perl script under the cgi-bin directory of your web server with the following content:

#!/usr/bin/perl -wT

use CGI qw(:standard);
use Device::SerialPort;

#initialize CGI object
my $cgi = new CGI;

#get command from user request
my $cmd = $cgi->param('cmd');

my  $read_timeout = 1, #time limit to wait for input from Arduino
$start_time = 2, #time to wait before connection is ready
$char_count = 0, #total characters read from Arduino
$arduino_output = ""; #response received from Arduino
$port = '/dev/ttyACM1';

#open connection to Arduino on the specified port
my $arduino = Device::SerialPort->new($port) or print header,a "Cannot open $port" and die "Cannot open $port";

#configure serial parameters

#wait connection to be ready
sleep $start_time;

#send http headers, start html, head, body and headings
print header,

start_html({-title=>'Arduino serial connection'}),


h2('Arduino serial web'), br,


#create a form for the command




a('Command:'), input({-type=>'text',-name=>'cmd',-value=>"$cmd",-tabindex=>'1'}),




#if we have any command if(defined $cmd){


#send to arduino $arduino->write($cmd."\n");


#untill time is over


while ($read_timeout>0) {


#read up to 255 characters


my ($count,$char)=$arduino->read(255);


#if we have atleat 1 character


if ($count > 0) {


$char_count+=$count; #sum to total character count


$arduino_output.=$char; #append to output string


} else {


$read_timeout--; #decrease remaining wait time






$arduino_output =~ s' '&nbsp;'g; # parse blank space $arduino_output =~ s'\n'<br />'g; # parse line break


#print the final output


print hr, b("$arduino_output");

} print end_html; #close html #finish connection $arduino->close; undef $arduino;

Take a look:

Arduino web interface
Arduino web interface


If you really want to give a try on Arduino, go on its official site, to learn more, there is many things to learn yet, and there you will find everything you need, as the API reference.

Have in mind that these codes where not intended for production, but for learning, and to make things there is not security, performance on any kind of reliability check. It could also be simpler, and thus cleaner, however that is what we got, I hope it is enough to get you started, maybe we do more in the future. :)

That is all for now! With this concept in mind, you can start to create your commands and read or write to Arduino. I hope you like it, have some fun and create cool stuff using Linux and Arduino power.

Thanks for reading!

Leave a Comment