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
Introduction
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.
Requirements
- 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
- Contained - The following requirements are now distributed within the IDE package
- System dependent - shared libraries are needed and missing or in different version on some systems, install will be covered
- libtinfo.so.5 - Terminfo shared library
- libreadline.so.6 - readline shared library
- Optional - For the web interface
- ApacheHTTPD - Web server
- Perl - Server-side language
- Device::SerialPort and CGI modules
- Perl - Server-side language
- ApacheHTTPD - Web server
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
wget http://downloads.arduino.cc/arduino-1.6.5-linux64.tar.xz
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
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
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:
Load example
Let's say hello to Arduino, for this select the example sketch from the menu File->Examples->Basics->Blink, as follows:
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.
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 libtinfo.so.5 and libreadline.so.6. The following lines describes how to build and install these shared libraries from source
libtinfo.so.5
Download
wget http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.9.tar.gz && 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
libreadline.so.6
Download
wget ftp://ftp.cwru.edu/pub/bash/readline-6.3.tar.gz && tar xzvf readline*
Enter sources directory
cd readline*
No special flag needed
./configure
Then make and install
make && make install
Update your shared libraries database:
ldconfig
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.
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.
my_serial_interface.ino
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
digitalWrite(resetPin,HIGH);
//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")) {
blink(13,200);
blink(13,200);
blink(13,200);
//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
check_input(inputString);
} digitalWrite(13,ledstate);
} //This function works when we have data comming from the serial port void serialEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read(); // [ 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]
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:
Minicom
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]
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/mod_cgi.so
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 $arduino->baudrate(9600); $arduino->databits(8); $arduino->parity("none"); $arduino->stopbits(1); $arduino->read_char_time(0); $arduino->read_const_time(1000); #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
start_form,
a('Command:'), input({-type=>'text',-name=>'cmd',-value=>"$cmd",-tabindex=>'1'}),
end_form;
#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' ' '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:
Conclusion
If you really want to give a try on Arduino, go on its official site, arduino.cc 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!