Introduction
The Arduino IDE is a great bit of software to get you up and running quickly, but as projects get larger, or if you already have preferred code editor etc., it might not be the best way to go. In this post, we will discuss a simple approach to building projects for Arduino with-out using the IDE. The Arduino IDE still needs to be installed, we need some of the libraries it provides, but we won’t actually need to run it to develop code for the Arduino platform.
Prerequisites
You have a working installation of the GNU AVR toolchain. See this previous blog entry on how to build this from source.
You have the Arduino IDE installed. This can be downloaded from here.
You have an Arduino platform of some sort connected to you Linux box, here I will be using the uno. Other platforms should be very similar.
Let’s go
Right with the prerequisites out of the way, we are ready to start.
First of all, we need to define an Environment Variable called ARDUINO_IDE
that contains the base directory of where you installed your Arduino IDE. In my case, I installed version 1.6.7 in my home directory. Therefore ARDUINO_IDE
is defined as $HOME\arduino-1.6.7
, adjust this based on whichever version you’ve got.
For future use, I added the following to the end of my .profile:
export ARDUINO_IDE=$HOME/arduino-1.6.7
To get it, just run the following:
git clone git@github.com:thingsforhackers/Arduino-Make.git
tfh@hex64:/tmp$ ls -l Arduino-Make/
total 80
-rw-rw-r-- 1 tfh tfh 16959 Mar 5 15:20 Arduino.mk
-rw-rw-r-- 1 tfh tfh 494 Mar 5 15:20 blink.cpp
-rw-rw-r-- 1 tfh tfh 35141 Mar 5 15:20 LICENSE
-rw-rw-r-- 1 tfh tfh 242 Mar 5 15:20 Makefile
-rwxrwxr-x 1 tfh tfh 589 Mar 5 15:20 newProject
-rwxrwxr-x 1 tfh tfh 4210 Mar 5 15:20 parseBoardsFile
-rw-rw-r-- 1 tfh tfh 233 Mar 5 15:20 README.md
tfh@hex64:/tmp$ Arduino-Make
Building
As a quick test, you can build the this project by simply running make
.
If everything is working OK, you should see a lot of compiler output, with the last line being something similar to this:
/home/tfh/opt/avr/bin/avr-objcopy -O ihex -R .eeprom build-cli/Arduino-Make.elf build-cli/Arduino-Make.hex
ARDUINO_IDE
is not defined. Check this by runningecho $ARDUINO_IDE
.The GNU AVR toolchain is not installed correctly. Check this by running
avr-gcc --version
. If you got an error, go back through these instructions.
The output of your build will be in the build-cli sub directory.
As shown above, the default make target is to build the project, other make targets are:
- show_boards: this will produce a list of the supported boards, and their tag.
- clean: this will remove all of the generate files left over from a build.
- upload: this will upload the program to a connected Arduino (more on this later).
As far as the contents of the project is concerned, the main files of interest here are Makefile & blink.cpp. We will now discuss each one in turn.
Makefile
This defines a few things about your project, the initial contents are as follows:
ARDUINO_DIR = $(ARDUINO_IDE)
BOARD_TAG = uno
ARDUINO_PORT = /dev/ttyACM0
ARDUINO_LIBS =
AVR_TOOLS_PATH = $(HOME)/opt/avr/bin
ARDUINO_ETC_PATH = $(ARDUINO_DIR)/hardware/tools/avr/etc/
ARDUINO_OPT_LIB_PATH=
include Arduino.mk
BOARD_TAG: this specifies your target platform, see the output of
make show_boards
for a complete list.ARDUINO_PORT: this is the Linux device file that’s connected to your Arduino platform (again, more on this later).
ARDUINO_LIBS: For anything more that the most basic project, you will usual use some external library, SPI & Wire being two such examples. Simple add them to this to ensure that they get included in your project.
ARDUINO_OPT_LIB_PATH: Sometimes, you will need use a library that doesn’t come with the IDE, this define allows you to specify a directory on where to look for these.
blink.cpp
This is your source code file, in this example, it’s contents are as follows:
#include <Arduino.h>
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin 13 as an output.
pinMode(13, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level)
delay(100); // wait for a second
digitalWrite(13, LOW); // turn the LED off by making the voltage LOW
delay(100); // wait for a second
}
The file has a .cpp extension, this is telling the compiler, and anyone looking at it, that this is a C++ file.
There’s an additional include at the top of the file,
#include <Arduino.h>
.
In general you can import an Arduino .ino program by renaming it to *.cpp, and adding #include <Arduino.h>
to the top.
You are not limited to a single source file, for larger projects you can, and should, split you code over multiple *.cpp & .h files.
Uploading
Once you’ve got a built project, it’s time to upload to your target platform. As previously stated, this post is assumes you’ve got an Arduino Uno. When connected to your PC, the Uno presents itself as a USB serial port. Linux will assigned a device file to this when it’s connected. An easy way to find this file, is to connect your Uno and run dmesg
, you should see something similar to this:
tfh@hex64:~$ dmesg
[25453.093972] usb 3-1.4: USB disconnect, device number 3
[25455.457977] usb 3-1.4: new full-speed USB device number 4 using ehci-pci
[25455.553957] usb 3-1.4: New USB device found, idVendor=2341, idProduct=0043
[25455.553962] usb 3-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=220
[25455.553965] usb 3-1.4: Manufacturer: Arduino (www.arduino.cc)
[25455.553967] usb 3-1.4: SerialNumber: 55330343731351A02282
[25455.554404] cdc_acm 3-1.4:1.0: ttyACM0: USB ACM device
tfh@hex64:~$
The line of interest here, is
[25455.554404] cdc_acm 3-1.4:1.0: ttyACM0: USB ACM device
This means that the Uno has been allocated a device named ttyACM0, or to give it its absolute path /dev/ttyACM0
. To check this, run ls -l /dev/ttyACM0
, you should see something like this:
tfh@hex64:~/code/projects/fishy/inside$ ls -l /dev/ttyACM0
crw-rw---- 1 root dialout 166, 0 Mar 5 15:53 /dev/ttyACM0
tfh@hex64:~/code/projects/fishy/inside$
This shows you that the file exists, and only root or members of the dialout group can write/read to/from it. Because of this, you need to ensure that your user is a member of dialout. If this is not the case, just perform the following:
sudo adduser $USER dialout
Note, you may need to log-out and back in again for this change to take affect
Now, you need to ensure that ARDUINO_PORT is defined as /dev/ttyACM0 in your Makefile.
To upload, simple run make upload
, you should see something similar to this:
tfh@hex64:/tmp/nj6$ make
cat build-cli/blink.d > build-cli/depends.mk
make: Nothing to be done for `all'.
tfh@hex64:/tmp/nj6$ make upload
for STTYF in 'stty -F' 'stty --file' 'stty -f' 'stty <' ; \
do $STTYF /dev/tty >/dev/null 2>&1 && break ; \
done ; \
$STTYF /dev/ttyACM0 hupcl ; \
(sleep 0.1 2>/dev/null || sleep 1) ; \
$STTYF /dev/ttyACM0 -hupcl
avrdude -q -V -p atmega328p -C /home/tfh/arduino-1.6.7/hardware/tools/avr/etc//avrdude.conf -c arduino -b 115200 -P /dev/ttyACM0 \
-U flash:w:build-cli/nj6.hex:i
avrdude: AVR device initialized and ready to accept instructions
avrdude: Device signature = 0x1e950f
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "build-cli/nj6.hex"
avrdude: writing flash (1050 bytes):
avrdude: 1050 bytes of flash written
avrdude: safemode: Fuses OK (H:00, E:00, L:00)
avrdude done. Thank you.
tfh@hex64:/tmp/nj6$
If you get a failure, some things to check are:
Avr-dude is installed. Run
avrdude --version
, if this fails, install withsudo apt-get install avrdude
.You are not a member of dialout. Run
id
, if you don’t see dialout listed, add yourself as shown above.
Summary
You should now have a working build environment.
comments powered by Disqus