Ubuntu now supports a flavor that runs in the Raspberry Pi platform, unfortunately as of the time of writing there is still a fair bit of configuration needed by the user to use the Pi beyond a generic use case. This series of posts is a culmination of the lessons learned of many dead ends that I have experienced. I attempt to be both minimalistic in configurations but explanatory so, if you are so inclined, you can better understand the why and how of what configurations have been made.
That said, if there any surprises or if the code doesn’t work off the shelf, then please leave a comment.
Download Ubuntu Image
Ubuntu have done an excellent job to provide a flavor in support of Raspberry Pi, ranging from Pi 2 through to Pi 400 as well as supporting 32bit and 64bit architectures as of the time of writing this. Images are available for download here.
I have a Raspberry Pi 4B with 8GB of RAM and though the recommendation is to use the 64bit architecture I have chosen Ubuntu Server 20.04 LTS 32bit for the Raspberry 4 as my OS.
- Why Ubuntu Server? I intend to use the Pi headerless (i.e. without a screen) so all the bells and whistles that come with Ubuntu Desktop are superfluous to my needs.
- Why the LTS version? Because I want to avoid doing a Linux distribution upgrade as far as I can and possibly brake elements of my prior work.
- Why the 32bit? Some libraries don’t fully support 64bit (e.g. userland) and hence to save a lot of wasted effort I chose the 32bit.
Run UBUNTU on RASPBERRY PI
I’m assuming you have chosen Ubuntu Server. In which case just follow the excellent instructions by Ubuntu here. However, I’d add that it is recommended that you use a SD micro card that has a speed class of 10 (looks like a 10 within a C) or better. C10 indicates that the card is possible to write at 10MB/s. For a great overview of SD cards I refer to a explanation provided by Dignited.com.
If you can’t find the Raspberry Pi’s IP address even after a few minutes then it is either that you made a typo when modifying /system-boot/network-config, or that the Pi has the right network information but for some reason doesn’t make the connection. Obviously in the first instance you need to double check but removing the SD card from the Pi and connecting it back to your main computer. In the second instance, especially if the Pi’s activity green LED is not showing any signs of life, then simply unplug the Pi and re-plug it (on my second attempts the Pi connects to the network).
If you follow the Ubuntu set up guide you will be familiar with how to use
ssh . The rest of the guide assumes you are already logged in with secure shell protocol.
Keeping OS up to date
Keeping your OS in order is important. As soon as you logged in via ssh do the following:
$ sudo apt update $ sudo apt upgrade -y
aptis a tool to manage the many different packages you have. To use it you need to have sudo priveledges
updateupdates the lists of packages with new versions, new packages whilst
upgradeupgrades the versions you already have to new versions
-yargument gives an automatic confirmation that all upgraded revisions are to be accepted. If you want to review the upgrades before they are executed then remove
-yfrom the above snippet
|(vertical bar) in
command1 | command2seralizes commands on the same line.
Customising user configurations
~/.bashrc holds user configurations which you don’t want to change manually. Cleverly it makes a reference to another configuration file that you are able to modify, which is ~/.bash_aliases. Open ~/.bashrc and find the following block which does the referencing
if [ -f ~/.bash_aliases ]; then . ~/.bash_aliases fi
- Essentially the above snippets asks “If ~/.bash_aliases does exist then includes its contents”. By default ~/.bash_aliases does not exist. To create the file then do
$ touch ~/.bash_aliases
touchcommand either creates a file if it does not exist or updates the access and modification times of the file if it does exist.
Now we want to populate it with custom configurations. The below are just some ideas
$ echo "alias ls='ls -la --color=auto'" >> ~/.bash_aliases
- The command goes like this
echo [STRING] >> [FILE]and is typically used to append a string to the end of a file. Be careful, if you swapped
>then the string will overwrite the file with the new string.
Now we want to replace the current shell with a new bash shell so that we can use the new alias.
$ exec bash
Purely optional but I prefer to have a lean Home folder. To this end I create a folder called repositories by typing
$ mkdir ~/repositories . Similar line to create a folder to hold all the virtual environments
$ mkdir ~/environments
ENABLE RASPISTILL & RASPIVID
Frustratingly Ubuntu Server 20.04 does not bundle the tools to use the camera off the shelf. This is the plan of attack:
- Configure boot to enable the camera port
- Install tools that we will need to build from source.
- Download and build userland repository from source. This will give use tools such as raspistill and raspivid. If you’ve skipped the beginning of this post to get here then note that I’m running 32bit architecture. If you are running 64bit architecture and are coming across other errors not shown below the bad news is that it may be because userland doesn’t 100% support 64bit architecture yet.
- Enable configuration to be able to use raspistill without an absolute path
- Give rights to the user to be able to use raspistill without needing sudo
- Reboot and test
Ok, let’s get to work.
Step 1. Configure boot
In /boot/firmware/config.txt type the following text (note that for some reason if you followed the recommended practice of appending the below to /boot/firmware/usercfg.txt then the config.txt file doesn’t include it, hence the need to modify config.txt directly):
#enable camera port start_x=1 gpu_mem=128
Step 2. Install library dependencies
Now install cmake and build-essential:
$ sudo apt install cmake build-essential
Step 3. Clone userland
Now clone the userland repository and modify the build instructions slightly.
$ cd ~/repositories $ git clone https://github.com/raspberrypi/userland.git $ cd userland $ nano CMakeLists.txt
In CMakeLists.txt add the line
SET(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-as-needed") this will allow us to use the picamera library that will later be installed. Now build from source. Note that there is no space after the comma in
Step 4. Update your shell configuration
Update the configuration so that you can use the raspistill command
$ echo -e 'PATH=$PATH:/opt/vc/bin\nexport PATH' >> ~/.bash_aliases $ echo -e 'LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/vc/lib\nexport LD_LIBRARY_PATH' >> ~/.bash_aliases $ exec bash $ sudo ldconfig
Step 5. Modify Permissions
Double check that the user is a member of the
video group by typing
$ groups ubuntu . If you see ‘video’ in the list you are good. If not then fix that by typing
$ sudo usermod -aG video ubuntu. Note if we tried to run
$ raspistill it will return a
failed to open vchiq instance error. That’s why we need to change the read/write rights to the vchiq device.
$ sudo nano /etc/udev/rules.d/10-vchiq-permissions.rules
By default /dev/vchiq is owned by
root the user and
root the group but is read/write to the the root user only. We want it to be accessible to the group
video and change its rights so that the group can read/write. Check this page by cyberciti.biz for a good introduction to
chmod. Note that if you didn’t create the above file but ran a line like
$ sudo chown :video /dev/vchiq | sudo chmod 660 /dev/vchiq then it effectively assigns the same rights as those in the file but with the disadvantage of /dev/vchiq returning to the default setting after you reboot.
Step 6. Reboot and then test
$ sudo shutdown -r now
$ raspistill -o output.jpg
There should be no errors and a output.jpg file created in the folder you were in when you ran the above command
ENABLE PICAMERA PYTHON CLASS
With Raspistill operational now we want to use the camera from inside a Python program. This is the plan of attack:
- Install tool to create a virtual environment (optional)
- Modify configuration
- Enable virtual environment and check dependencies
- Install PiCamera with pip
Step 1. Install Virtual Environments
I advocate the use of virtual environments for your different projects because you will find that different projects need different dependencies. If you tried to run all your projects from the globally available dependencies that you installed over time then you may find that there are conflicts and you will spend some time trying to untangle them. Using virtual environments allows you to compartmentalize these dependencies according to the specific needs of the project. The install then run
$ sudo apt-get install python3-virtualenv
Step 2. Modifying configuration
When I try to install picamera with pip here it returns the following error:
ValueError: This system does not appear to be a Raspberry Pi. To solve this error you need to add
export READTHEDOCS=True to ~/.bash_aliases. Type:
$ echo 'export READTHEDOCS=True' >> ~/.bash_aliases
Step 3. Enable virtual environment and check dependencies
To create a virtual environment type the following:
$ cd ~/environments $ python3 -m virtualenv testenv
testenv with whatever name you want to call your new environment. The line to activate the new environment is
$ source ~/environments/testenv/bin/activate which you would need to type each time. I think this is a bit unwieldy so you can make an alias in ~/.bash_aliases by typing:
$ echo "alias src_testenv='source ~/environments/testenv/bin/activate'" >> ~/.bash_aliases $ exec bash $ src_testenv
Check that you have
(testenv) $ pip3 install wheel
Step 4. Install picamera
(testenv) $ pip3 install picamera
Step 5. Test picamera
In a folder of your choosing create a python file.
(testenv) $ touch cameratest.py
Populate the file with the following (taken from picamera.readthedocs.io)
from time import sleep from picamera import PiCamera camera = PiCamera() camera.resolution = (1024, 768) camera.start_preview() # Camera warm-up time sleep(2) camera.capture('foo.jpg')
Test it with
(testenv) $ python3 cameratest.py
If everything went well you will see that there is a file foo.jpg in the folder you ran the script. To deactivate the virtual environment then just type
(testenv) $ deactivate