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 Supported ArduinoBoard and CPU Types ============================================================ pro Arduino Pro or Pro Mini 16MHzatmega168 ATmega168 (5V, 16 MHz) 8MHzatmega168 ATmega168 (3.3V, 8 MHz) 16MHzatmega328 ATmega328P (5V, 16 MHz) 8MHzatmega328 ATmega328P (3.3V, 8 MHz) blink$
We create our BOARD_TYPE
file as follows:
blink$ dno BOARD_TYPE BOARD=pro CPU=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 pro.8MHzatmega328 blink$
We see that it simply contains the board and cpu identification for our pro mini board.
Let's now run dno
again and see what happens:
blink$ dno Creating BOARD_INFO... 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 blink$ ls -l total 28 -rw-r--r-- 1 user user 1233 Jan 6 11:04 blink.ino -rw-r--r-- 1 user user 12701 Jan 6 12:15 BOARD_INFO -rw-r--r-- 1 user user 18 Jan 6 12:04 BOARD_TYPE drwxr-xr-x 3 user user 4096 Jan 6 12:15 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 thet 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 14108 Jan 6 12:15 blink.elf -rw-r--r-- 1 user user 2615 Jan 6 12:15 blink.hex -rw-r--r-- 1 user user 1104 Jan 6 12:15 blink.ino.d -rw-r--r-- 1 user user 3860 Jan 6 12:15 blink.ino.o drwxr-xr-x 2 user user 4096 Jan 6 12:15 libcore -rw-r--r-- 1 user user 345554 Jan 6 12:15 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
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$
Please note that the ridiculous verbosity of this is outside of dno's control.
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 CPU=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.