Arduino on Ubuntu 14.04 without the Arduino IDE
Dec 8, 2015
warning
This post is more than 5 years old. While math doesn't age, code and operating systems do. Please use the code/ideas with caution and expect some issues due to the age of the content. I am keeping these posts up for archival purposes because I still find them useful for reference, even when they are out of date!
In this post I will document my setup for working with an Arduino Uno on Ubuntu 14.04. You can learn more about the Arduino at Arduino.cc if you are unfamiliar with the microcontroller. However, be warned, I am not going to use the official Arudino IDE, if you'd like the official setup checkout the official Arduino installation instructions . Instead I'm going to setup the basic requirements for writing and pushing code, including libraries and make files, and use vim as my editor. So, if you're interested in this approach, follow along.
First, I'll make a few comments on why I want to use this setup instead of the standard Arduino IDE (if these don't make sense to you, you should probably not use this guide:)
- 
      This setup will use standard c++ coding instead of the Arduino 
      *.ino variant used with Arduino IDE.
      As a result, code will have to be slightly modified from examples you'll find
      at the Arduino website or elsewhere on the web. Header files will have to be
      included, loops made explicit, etc. Also, instead of clicking buttons
      on the Arduino IDE to compile code and push to the Arduino you'll have to use
      make files, as in 
      $ makeand$ make upload. So, this becomes standard c++ coding with an upload step-- this can be good, or bad, depending on your experience.
- The Arduino IDE requires Java 6, an old version of Java, be installed for use-- I really don't want to deal with this requirement and I'm very happy coding with vim and using make at the terminal.
Credits
I'll be using this nice (but old--2011!) post on jayway-- jaway post on Ubuntu and Arduino -- as my starting point. Additional comments by Havard, at the end of the post, provide some nice updates, thanks!
Install
So, let's get started with the repository installs that provide libraries and make files for Ubuntu (14.04):
$ sudo apt-get install arduino-mk
  This will install arduino-mk and arduino-core 
  along with a bunch of needed libraries-- say Y 
  to all the dependencies. All of Arduino-specific libraries and documentation 
  is located in the following set of directories once the install is complete::
/usr/share/arduino
/usr/share/doc/arduino-core
/usr/share/doc/arduino-mkCheck these directories out to see what's included and be sure to try out the examples (however, as noted above, we'll have to modify the code a bit to work with our setup-- I'll do an example later):
$ ls -l /usr/share/doc/arduino-core/examples/
total 44
drwxr-xr-x  8 root root 4096 Dec  8 12:21 01.Basics
drwxr-xr-x 11 root root 4096 Dec  8 12:21 02.Digital
drwxr-xr-x  8 root root 4096 Dec  8 12:21 03.Analog
drwxr-xr-x 13 root root 4096 Dec  8 12:21 04.Communication
drwxr-xr-x  8 root root 4096 Dec  8 12:21 05.Control
drwxr-xr-x  6 root root 4096 Dec  8 12:21 06.Sensors
drwxr-xr-x  4 root root 4096 Dec  8 12:21 07.Display
drwxr-xr-x 17 root root 4096 Dec  8 12:21 08.Strings
drwxr-xr-x  5 root root 4096 Dec  8 12:21 09.USB
drwxr-xr-x 16 root root 4096 Dec  8 12:21 10.StarterKit
drwxr-xr-x  2 root root 4096 Dec  8 12:21 ArduinoISPThere are a bunch of things to try out! Note that each of the above is a directory of examples that can help getting started.
USB access
Finding your port
  Connect the Arduino to your computer via usb and can see
  that the board is recognized using lsusb. 
  An example looks like:
$ lsusb
Bus 001 Device 002: ID 8087:8000 Intel Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 002 Device 003: ID 174f:14a1 Syntek
Bus 002 Device 002: ID 8087:07dc Intel Corp.
Bus 002 Device 004: ID 2341:0043 Arduino SA Uno R3 (CDC ACM)
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
  Notice the Arduino Uno on the second-to-last line.  Okay, what port is it on?
  We need to know the port for uploading code to the Arduino. Often the port is
  /dev/ttyACM0 or something similar-- how do 
  we find this?  The best method I've found is using a combination of 
  dmesg and 
  grep--when the Arduino is connected, try:
$ dmesg | grep Arduino -C 3
[ 6433.058276] usb 2-2: new full-speed USB device number 4 using xhci_hcd
[ 6433.077095] usb 2-2: New USB device found, idVendor=2341, idProduct=0043
[ 6433.077104] usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=220
[ 6433.077110] usb 2-2: Manufacturer: Arduino (www.arduino.cc)
[ 6433.077114] usb 2-2: SerialNumber: 75439333335351105031
[ 6433.077340] usb 2-2: ep 0x82 - rounding interval to 1024 microframes, ep desc says 2040 microframes
[ 6433.106521] cdc_acm 2-2:1.0: ttyACM0: USB ACM device
  Notice the last line in the output, giving 
  ttyACM0 as the port in my
  case-- yours might be different. If you just run 
  dmesg there is a ton
  of output. This is why I pipe it to grep, 
  searching for Arduino. The argument 
  -C 3 provides three lines of 
  context-- you can increase, or decrease this number to get more/less 
  info if the port is not immediately obvious. Okay, that's my approach -- 
  do you know a better way to do this?--
  please leave a comment below!
dialout group and permissions
One of the issues many users seem to have using Arduino with Ubuntu is getting the usb permissions to work. When the Arduino is connected, we can inspect the properties of the usb port (hopefully found above):
$ ls -l /dev/ttyACM0
crw-rw---- 1 root dialout 166, 0 Dec  9 11:39 /dev/ttyACM0Notice that the group is dialout-- we will use that in a second. However, when the Arduino is not connected, the same command will give an error:
$ ls -l /dev/ttyACM0
ls: cannot access /dev/ttyACM0: No such file or directoryNow, to allow access to the usb port we add our (your) username to the dialout group-- be sure to change username below:
$ sudo adduser username dialout
  The above command accomplishes the same thing as adding the username to the
  file /etc/group, as discussed by Havard 
  in their comments.  Also, you'll have to logoff and logon 
  for the group changes to take effect.
Okay, take a deep breath, everything is setup-- let's try implementing the blinking light example, as detailed in my motivational post.
An example -- blinking light
  As an example, let's do the standard blinking led example. We can use pin 13 to
  blink an led on the board, so no circuit to build.  In this way we can focus
  on the difference between the Arduino *.ino files and the 
  *.cc files we'll be using.  The examples directory, 
  mentioned above, has this example in
  /usr/share/arduino/examples/01.Basics/Blink/Blink.ino-- 
  replicated here (with minor formatting):
//  Blink.ino
//
//  Turns on an LED on for one second,
//  then off for one second, repeatedly.
//
//  This example code is in the public domain.
// Pin 13 has an LED connected on most
// Arduino boards.
int led = 13;
// the setup routine runs once when you press reset
void setup() {
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
}
// the loop routine runs over and over
void loop() {
  // turn the LED on (HIGH is the voltage level)
  digitalWrite(led, HIGH);
  // wait for a second
  delay(1000);
  // turn the LED off by making the voltage LOW
  digitalWrite(led, LOW);
  // wait for a second
  delay(1000);     
}
  The above code can be compiled and uploaded to the Arduino as-is if you are
    using the Arduino IDE.  However, we are not. So, we modify the above 
  to make it standard c++ and call the file 
  main.cc:
//  main.cc -- from Blink.ino
//
//  Turns on an LED on for one second,
//  then off for one second, repeatedly.
//
//  This example code is in the public domain.
// include Arduino.h header file
#include <Arduino.h>
// Pin 13 has an LED connected on most
// Arduino boards.
int led = 13;
// the setup routine runs once when you press reset
void setup() {
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
}
// the loop routine runs over and over
void loop() {
  // turn the LED on (HIGH is the voltage level)
  digitalWrite(led, HIGH);
  // wait for a second
  delay(1000);
  // turn the LED off by making the voltage LOW
  digitalWrite(led, LOW);
  // wait for a second
  delay(1000);     
}
// main function
int main(void) {
  // call init()
  init();
  // make explicit call to setup()
  setup();
  // use a for-loop -- to make loop
  for (;;) {
    loop();
  }
}If we compare the two versions there are only a few differences:
- 
      main.cc adds the 
      #include <Arduino.h>statement
- 
      main.cc adds a main()function that initializes with a call toinit(), explicitly calls thesetup()function and then uses a never-endingforloop to repeatedly call theloop()function.
  All of these changes make a lot of sense to c++ coder. Finaly, a fairly
  minimal makefile (literally name the file 
  makefile) looks like
  this:
ARDMK_DIR = /usr/share/arduino
ARDUINO_PORT = /dev/ttyACM0
BOARD_TAG = uno
include $(ARDMK_DIR)/Arduino.mk
  Most of the heavy-lifting is done by Arduino.mk, 
  as seen by the inclusion of this file.  The 
  BOARD_TAG = uno is not required because
  the default is uno-- if you're using 
  another board you'll have to change this.  The 
  ARDUINO_PORT 
  is important-- this must be correct
  and permissions need to be assigned (as discussed above) for the upload to work.
  So, getting ready to compile and upload, we put these two files in a directory,
  say:
blink_pin13/
├── main.cc
└── makefileTo compile open the terminal and navigate to the directory and use make:
$ makeAssuming that everything went well the code can be uploaded to the Arduino using:
$ make uploadThat's it we're Arduino-ing! Try changing the amount of time that the led is off/on followed by:
$ make clean
$ make
$ make uploadto see the changes.
Finally, all of the code for this example is available at my github account--- blinking lights at github .
Wrapping Up
As always-- if you find typos, mistakes, or have suggestions or questions please leave a comment below. I'd also be interested to find out about different approaches to setup-- if you have one, leave a comment and/or link to your ideas.