Fundamentals

The following information applies to all programming languages. These are the basic things you need to know to create and run programs on ev3dev.

File Permissions

Linux (and other Unix-like operating systems) have a special file permission setting to make a file executable. If this permission is not set, then you cannot run a file directly. Instead, you will get a “Permission denied” error when you try to run the file.

In the Brickman file browser, executable files have a * after the file name. If this * is missing, you will not be able to run the file from Brickman.

Tip

The ev3dev Visual Studio Code extension automatically takes care of setting permissions for you, so you don’t need to do anything special in that case and you can skip reading this section.

If you are transferring files a different way, then you need to need to know how to set the executable bit.

Command Line

One way to set file permissions is to use a remote terminal to get command prompt on your device, then run:

chmod +x my.file

Of course, replace my.file with the actual name of your file. This tells the OS to change the mode of the file by setting the executable bit globally for the file. This can be verified by running:

ls -l my.file

This tells the OS to list some basic information about this file. You should see something like this:

-rwxr-xr-x 1 robot robot 0 Oct 28 19:39 my.file

As you can see, x is actually listed three times in the file permissions (-rwxr-xr-x). This is because each file has three sets of permissions, one for the user (i.e. robot), one for the group (also robot) and one for others (everyone).

In terms of ev3dev, the really important one is the first one, the user.

WinSCP

Todo

Add screenshots that show how to set file permissions using WinSCP.

Filezilla

Todo

Add screenshots that show how to set file permissions using Filezilla.

Scripts

A script is a text file that can be run as a program. There are many scripting languages available on ev3dev, such as Bash, Lua, Python and Perl. There are a few things you need to watch out for when writing scripts.

Although it is possible to run scripts by invoking the interpreter directly, such as:

python3 my_script.py

…we don’t usually do this in ev3dev. Instead, we do a few things to make the file work as a stand-alone executable file.

The Shebang

In Linux (and other Unix-like operating systems), there is a special syntax used in the first line of a file to tell the operating system which interpreter to use to run the file. It looks like this:

#!/usr/bin/env python3

When you run the script, the operating system runs /usr/bin/env python3, which finds python3 and then runs python3 $0 where $0 is the filename of your script.

You can also just write the path to the interpreter directly instead of using /usr/bin/env, like this:

#!/bin/bash

Without a shebang, Linux will fall back to trying to run file as a shell script. So, if you forget this in your Python program, you will see strange errors about commands not found and whatnot.

Tip

Using /usr/bin/env is considered best practice for Python, since it is more flexible (e.g. when using virtualenv, the Python interpreter in your virtual environment may not be the same as the one at /usr/bin/python).

Furthermore, according to PEP 394, if your script is Python 3.x only, you should use python3 in your shebang. If your script is Python 2.x only, you should use python2. Using python with no number after it should only be used if your script was designed to run with both 2.x and 3.x.

Note

The name shebang comes from the characters #!. In computer-speak, # is sometimes refered to as a sharp or a shell prompt and ! is often called bang.

Line Endings

Line endings are the hidden characters at the end of each line in a text file. Windows and Linux use different line endings, which can cause problems. Windows uses two character, a carriage return and a line feed (also written CRLF or \r\n). Linux only uses a single character, a line feed (also written LF or \n).

Most interpreters for scripts don’t care about line endings. But, Windows line endings will break the magic shebang line we talked about above. For example, Linux will try to run python3\r instead of just python3 and you will get a “File not found” error.

If your program runs when you type python3 my_file.py but not when you type ./my_file.py, this is probably why it is not working.

So, if you are using Windows, be sure to change the line endings in your text editor to Unix or CRLF when writing a script for ev3dev. On Linux and macOS, Unix line endings are the default, so you generally don’t have to worry about this.

Executable Bit

Linux will not let you run just any file directly. The last step needed to make the magic shebang work is to set the executable bit of the file. See the File Permissions section above for details.

Running Programs

Although you can just run a program from a terminal directly, like this:

./my_script.py

…you generally don’t want to do this. Why? Well, if your program crashes, for example, the motors won’t stop and your robot might try to destroy itself.

Instead, start your programs using the brickrun command. This takes care of some tricky things in ev3dev/Linux, like console switching, and will clean up after your program when it exits (or crashes). Just add brickrun before your program like this:

brickrun ./my_script.py

Note

Brickman and the Visual Studio Code extension both use brickrun behind the scenes too, so using brickrun from the command line will ensure that your program runs the same no matter how your start it.

Todo

Add links to Brickman docs and Visual Studio Code extension docs about running programs.

Standard I/O

All computer programs have standard input and output streams commonly called stdin, stdout and stderr. Normally, these read from/write to the terminal that started the program, but they can also be redirected from/to files or other programs. When you run programs using ev3dev tools these streams are handled in a special way.

stdin

If you run a program in a remote terminal, the usual behavior is for stdin to read whatever is typed into the remote terminal while the program is running. However, when programs are run with brickrun, stdin comes from the active console on the remote device itself. This means you need to press the built-in buttons on the device or use a keyboard attached to the device instead of typing into the remote terminal where the program was launched.

The behavior is the same when the program is started without a remote terminal, e.g. when the program is started from the Brickman user interface, stdin will still come from the device itself.

stdout

If you run a program in a remote terminal, the usual behavior is for stdout to print to the remote terminal while the program is running. However, when programs are run with brickrun, stdout prints to the active console on the remote device itself. In other words, it prints to the screen on the remote device.

The behavior is the same when the program is started without a remote terminal, e.g. when the program is started from the Brickman user interface, stdin will still print to the screen on the device itself.

stderr

If you run a program in a remote terminal, the usual behavior is for stderr to print to the remote terminal while the program is running (just like stdout). Likewise, when programs are run from a remote terminal with brickrun, stderr will still print to the remote terminal instead of on the remote device (unlike stdout).

When running programs from the Brickman user interface, there is no remote terminal, so stderr is saved to a file with the same name as your program plus the file extension .err.log added to the end. You can read this file to see any errors from your program. If nothing was printed to stderr, this file will not be created.

When using the Visual Studio Code extension, stderr is printed in the OUTPUT pane of Visual Studio Code.

Note

stderr is a second output stream, like stdout that is used for error messages (at least in well-behaved programs). Most of the time, you don’t notice the difference between the two because they both print to the same place. But, they are designed so that you can redirect one but not the other if needed.

Tip

You can print debug messages to stderr to help troubleshoot your program.