Create a directory named after your project. For our example, we'll call our project “blink”.
~$ mkdir blink
~$ cd blink
That's it: it's no harder than that. But to make this section
more interesting, let's run dno in this
directory:
blink$ dno
make: Nothing to be done for 'unknown'.
blink$
Here dno can't figure out what the right thing to do is, so does nothing. Which is the right thing to do.
Let's create a copy of the much-used
blink.ino sketch. You can use your favourite
editor, or get it from github, or whatever. You could even copy
and paste it from below:
/*
Blink
Turns an LED on for one second, then off for one second, repeatedly.
Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO
it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to
the correct LED pin independent of which board is used.
If you want to know what pin the on-board LED is connected to on your Arduino
model, check the Technical Specs of your board at:
https://www.arduino.cc/en/Main/Products
modified 8 May 2014
by Scott Fitzgerald
modified 2 Sep 2016
by Arturo Guadalupi
modified 8 Sep 2016
by Colby Newman
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/Blink
*/
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
Now our directory looks like this:
blink$ ls
blink.ino
blink$
Let's run dno again:
blink$ dno
Nothing to be done here (in /home/user/proj/blink).
Try dno ./BOARD_TYPE or dno tests
blink$
This tells us that dno does not know what sort of Arduino board
to build for. You can get more information about this using
dno info or dno help.
We can tell dno what sort of board to build for by creating a
BOARD_TYPE file. The simplest way to do this
is using dno's BOARD_TYPE target.
To see what boards are available use dno
show_boards.
Let's assume that we want to compile for a 3.3V Arduino pro
mini. Using show_boards, we find that that
the board name for this is “pro”, and that there
are 4 cpu options:
blink$ dno show_boards BOARD=pro OPTIONS=y
Supported Arduino Board Types
============================================================
arduino.avr.pro: Arduino Pro or Pro Mini
cpu=16MHzatmega328 ATmega328P (5V, 16 MHz)
cpu=8MHzatmega328 ATmega328P (3.3V, 8 MHz)
cpu=16MHzatmega168 ATmega168 (5V, 16 MHz)
cpu=8MHzatmega168 ATmega168 (3.3V, 8 MHz)
Supported ArduinoBoard and CPU Types
blink$
We create our BOARD_TYPE file as follows:
blink$ dno BOARD_TYPE BOARD=pro.8MHzatmega328
Creating BOARD_TYPE...
blink$ ls
blink.ino BOARD_TYPE
blink$
We can see that dno has created a BOARD_TYPE file, which identifies the type of board that we are to compile for. Looking at it:
blink$ cat BOARD_TYPE
arduino.avr.pro.cpu=8MHzatmega328
blink$
We see that it contains the full board-specifier and cpu identification for our pro mini board.
Let's now run dno again and see what happens:
blink$ dno
C++ ./blink.ino
AS [core] wiring_pulse.S
C [core] wiring_shift.c
C [core] wiring_pulse.c
C [core] wiring_digital.c
C [core] wiring.c
C [core] wiring_analog.c
C [core] WInterrupts.c
C [core] hooks.c
C++ [core] WString.cpp
C++ [core] WMath.cpp
C++ [core] USBCore.cpp
C++ [core] Tone.cpp
C++ [core] Stream.cpp
C++ [core] Print.cpp
C++ [core] PluggableUSB.cpp
C++ [core] new.cpp
C++ [core] main.cpp
C++ [core] IPAddress.cpp
C++ [core] HardwareSerial.cpp
C++ [core] HardwareSerial3.cpp
C++ [core] HardwareSerial2.cpp
C++ [core] HardwareSerial1.cpp
C++ [core] HardwareSerial0.cpp
C++ [core] CDC.cpp
C++ [core] abi.cpp
AR [libcore] abi.o...
LD blink.ino.o
OBJCOPY (hex) blink.elf
Program size: 924 out of 30720 (3%: 29796 remaining)
Data size: 9 out of 2048 (0%: 2039 remaining)
marc:blink$
blink$ ls
blink.ino BOARD_INFO BOARD_TYPE build pro.8MHzatmega328
blink$ rm -rf pro.8MHzatmega328/
blink$ ls -l
total 24
-rw-r--r-- 1 user user 1192 May 9 17:02 blink.ino
-rw-r--r-- 1 user user 11086 May 9 17:03 BOARD_INFO
-rw-r--r-- 1 user user 34 May 9 17:03 BOARD_TYPE
drwxr-xr-x 3 user user 4096 May 9 17:03 build
blink$
From dno's output we can see that BOARD_INFO
was created, and then a bunch of compilation and other commands
were executed. In addition to compiling the sketch
blink.ino, the components of the
core library were built, an archive file was
built from those components (AR), the whole
thing was linked together to create an executable
(LD), and then, finally, a downloadable
version of the executable was created
(OBJCOPY).
Note that the dno output shows a sanitised version of what is
actually being done. This is mainly for aesthetic reasons:
showing the full commands that are executed is pretty ugly. But
if that's what you want, you can (as shown here) set VERBOSE on
the command line:
blink$ dno VERBOSE=y
From our directory listing we can also see that a
build directory was created. This is where
all of our object, lib and executable files are created:
blink$ ls -l build/
total 372
-rwxr-xr-x 1 user user 14104 May 10 12:47 blink.elf
-rw-r--r-- 1 user user 2615 May 10 12:47 blink.hex
-rw-r--r-- 1 user user 1113 May 10 12:47 blink.ino.d
-rw-r--r-- 1 user user 3840 May 10 12:47 blink.ino.o
drwxr-xr-x 2 user user 4096 May 10 12:47 libcore
-rw-r--r-- 1 user user 345462 May 10 12:47 libcore.a
blink$ ls build/libcore
abi.d HardwareSerial.o Stream.d wiring.o
abi.o hooks.d Stream.o wiring_pulse.d
CDC.d hooks.o Tone.d wiring_pulse.o
CDC.o IPAddress.d Tone.o wiring_pulse.S.d
HardwareSerial0.d IPAddress.o USBCore.d wiring_pulse.S.o
HardwareSerial0.o main.d USBCore.o wiring_shift.d
HardwareSerial1.d main.o WInterrupts.d wiring_shift.o
HardwareSerial1.o new.d WInterrupts.o WMath.d
HardwareSerial2.d new.o wiring_analog.d WMath.o
HardwareSerial2.o PluggableUSB.d wiring_analog.o WString.d
HardwareSerial3.d PluggableUSB.o wiring.d WString.o
HardwareSerial3.o Print.d wiring_digital.d
HardwareSerial.d Print.o wiring_digital.o
blink$
Note that once everything is built, dno will not rebuild it unless something changes:
blink$ dno
make: Nothing to be done for 'build'.
blink$
Note that the message says make:.... This is
because dno is implemented using
GNU make.
Now we need to connect our Arduino device to our computer.
Typically, this is through a USB connection. Once done, we can
verify that the device can be seen using dno
devices:
blink$ dno devices
DEVICES: /dev/ttyUSB0
blink$
This shows that a serial device is connected to
/dev/ttyUSB0. This is a good sign.
Now, as long as there is a single device connected, we should be able to upload our sketch:
blink$ dno upload
Resetting device attached to (/dev/ttyUSB0)...
/usr/local/bin/dno do_upload
make[1]: Entering directory '.../proj/blink'
Uploading blink.hex to /dev/ttyUSB0
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.01s
avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: reading input file "build/blink.hex"
avrdude: writing flash (924 bytes):
Writing | ################################################## | 100% 0.51s
avrdude: 924 bytes of flash written
avrdude: verifying flash memory against build/blink.hex:
avrdude: load data flash data from input file build/blink.hex:
avrdude: input file build/blink.hex contains 924 bytes
avrdude: reading on-chip flash data:
Reading | ################################################## | 100% 0.43s
avrdude: verifying ...
avrdude: 924 bytes of flash verified
avrdude: safemode: Fuses OK (E:00, H:00, L:00)
avrdude done. Thank you.
make[1]: Leaving directory '.../blink'
blink$
If you dislike the ridiculous verbosity of this, you can set
QUIET=y on the command line.
If you have an appropriate programmer, you can also
upload your compiled sketch using dno
uploadp.
In summary, to create a brand new project, blink, from scratch, and upload it to an Arduino board takes only the following steps (dno output not shown):
~$ mkdir blink
~$ cd blink
blink$ [create blink.cpp using your favourite editor]
blink$ dno BOARD_TYPE BOARD=pro.8MHzatmega328
[ . . . ]
blink$ dno
[ . . . ]
blink$ dno upload
[ . . . ]
It could hardly be more simple.
Note that if you were confident that
blink.cpp would build without errors, you
could even omit the build step: ie the step before the upload,
as dno upload will automatically realise that
compilation and linking is needed and will make it happen.