Taillieu.Info

More Than a Hobby..

Raspbian Lite with RPD/LXDE/XFCE/MATE/i3/Openbox/X11 GUI

 

Table of Contents
1. Introduction
2. Memory Usage
3. Part 1 - Build the Foundation
4. Part 2 - Bring in the Furniture
5. Sample Screenshots
6. What Do I Use?
7. Virtual Machine Playground
8. Advanced - X11 Forwarding (Remote Applications)
9. Advanced - Remote Desktop Protocol (RDP)
10. Advanced - Custom Desktop Environment using i3 WM
11. Advanced - Custom Desktop Environment using Openbox WM
12. Extras

Requirements:
1. Any Raspberry Pi microcomputer
2. Raspbian Lite image
3. SD / microSD card (At least 4GB or higher, but it is possible to use smaller storage space depending on your configuration)
4. Keyboard and Mouse (For using the GUI, but can vary depending on how the Raspberry Pi will be used)
5. TV / Monitor (For seeing the GUI) (NOTE:For those wanting to use a touchscreen, I do not cover this in this guide. You need to research this.)
6. A normal computer with Linux, macOS, or Windows (For burning Rasbian Lite image to SD / microSD)
7. Internet connection

Introduction

There are two official Linux distributions for the Raspberry Pi which are Raspbian and Raspbian Lite. Rasbian is a full Linux distribution for the Raspberry Pi which uses Raspberry Pi Desktop (RPD) desktop environment. The desktop environment is the GUI (Graphical User Interface) of the operating system. Raspbian includes preinstalled applications for word processing, games, programming, and so on. This is great for beginners and people who just want to start using their Raspberry Pi immediately.

But, some of us don't like that. We want the ability to work with a GUI, but with our own preferences. In other words, we want to start with a clean install, and then install whatever packages we need on top. Packages can consist of desktop environments, drivers, compilers, applications, utilities, and so on.

As a reward, there would be more storage space, less usage on memory, and GUI customization! This is where Raspbian Lite comes into play.

Raspbian Lite is similar to that of a core. A core basically contains all the essential packages needed to make the hardware on the Raspberry Pi work correctly. Raspbian Lite was made so that the Pi can run as a headless system where the Pi is controlled by commands sent from an external source. Raspbian Lite does not contain a GUI but has a command line interface (CLI) which is shown automatically if it is connected to an external display. Configuration of Raspbian Lite can also be done via SSH (Secure Shell) from a computer connected to the same network as the Raspberry Pi. More information on SSH in the official Raspberry Pi documentation.

If you have ever heard of Arch Linux, Raspbian Lite is similar to that. Since Raspbian Lite is supported by the Raspberry Pi Foundation, it is the preferred operating system for most Raspberry Pi microcomputers.

To summarize, this guide talks about how to run Raspbian Lite with a GUI, in this case you choose your desktop environment, RPD, LXDE, XFCE, or MATE. There is an advanced section in this guide that talks about how to create your own desktop environment if you are interested. The official Rasbian distribution uses RPD as its default desktop environment, but reality, it is actually a fork (or a branch) of LXDE. Other distributions such as Xubuntu uses XFCE as its default desktop environment, and Ubuntu MATE uses MATE as its default desktop environment. If you are not familiar with Linux desktop environments, be sure to watch videos or research on the types of GUIs available. That way, you will have and idea of what GUI to install, if any.

For those that are really consciousness about memory usage, a desktop environment based on LXDE would be a recommended choice. For those that prefer a prettier or modern look, then XFCE or MATE would be a recommended choice. However, both do the exact same job which is to make your Raspberry Pi a simple desktop computer that is easy to use. This is assuming that you want to use a prebuilt desktop environment. Otherwise you are free to create your own desktop environment.

So why do this? Well, you decide how your desktop looks like, you decide what applications to install, and finally, you decide what do to next!

Let's begin!

Memory Usage

Before beginning to install Raspbian Lite with a GUI, let's explore memory usage. In a nutshell, the less memory your Raspberry Pi consumes, the more applications it can run. Raspbian Lite itself consumes very little memory since it is a core. As discussed earlier, a core only has the essential packages that make the hardware on the Raspberry Pi work.

NOTE:The memory used shown in the screenshots may be different than what your installation may actually use. Use this information as a reference to determine what desktop environment is right for you.

So how much memory does Raspbian Lite itself use? 

Image
*Right Click > Open Image in New Tab to see full size image.

If we take a look at the screenshot, the memory is displayed in megabytes. This Raspberry Pi has 925MB of total memory. Some of the memory is internally allocated to the GPU by default. This means that the operating system and applications can use up to 925MB of memory. 

Currently, Raspbian Lite is using 30MB of memory. Very impressive. This means that the available memory to use is now 895MB.

How does this compare to Raspbian with RPD? 

Image
*Right Click > Open Image in New Tab to see full size image.

On a clean installation, Raspbian with RPD is using about 90MB of memory. That's pretty good. Now, let's see what the memory usage is with Raspbian Lite running various GUIs.

If Raspbian Lite is running RPD Desktop Environment:

Image
*Right Click > Open Image in New Tab to see full size image.

Here we see that Raspbian Lite with RPD is using about 76MB of Memory.

If Raspbian Lite is running LXDE Desktop Environment:

Image
*Right Click > Open Image in New Tab to see full size image.

Here we see that Raspbian Lite with LXDE is using about 97MB of Memory.

If Raspbian Lite is running the XFCE Desktop Environment:

Image
*Right Click > Open Image in New Tab to see full size image.

Here we see that Raspbian Lite with XFCE is using about 107MB of Memory.

If Raspbian Lite is running the MATE Desktop Environment:

Image
*Right Click > Open Image in New Tab to see full size image.

Here we see that Raspbian Lite with MATE is using about 101MB of Memory.

Running a desktop environment with Raspbian Lite can consume quite a bit of memory. Now, we have to remember that Linux operating systems are flexible. Not every package required for a desktop environment is needed to be installed. This means that memory usage (as well as storage space) can be lowered even further, but you would have to be very familiar with how a package as well as its dependencies work. Not installing a required package or dependency may bring unwanted behavior. However, the good news is that it won't break your Raspberry Pi so long it is software related!

Part 1 - Build the Foundation

In this part, we will focus on preparing Raspbian Lite.

1. Download the latest Raspbian Lite image.
2. Format the SD / microSD card with Raspbian Lite (Plenty of guides out there on how to do this. For macOS, Linux, and Windows users, Etcher is an easy to use application that can help you do this.)
3. Insert the SD / microSD card into the Pi. 
4. Connect the Pi to the Internet using an Ethernet cable. If you want to use Wi-Fi instead, you will have to read on how to configure your wireless receiver using the command line after your Pi has finished booting.
5. Connect your TV / Monitor and keyboard. (Mouse is optional at this time.) Turn on the Pi. The Pi should boot up successfully and a prompt to log in will appear.
6. Log into Raspbian. The username is pi and the password is raspberry.

7. We need to expand the file system so that Raspbian takes full use of the SD / microSD space. To do this, we need to use raspi-config. Type in:

Code: Select all

sudo raspi-config

and press Enter. 

8. The Raspberry Pi Software Configuration Tool (raspi-config) main menu will appear. The option we are interested is option #7 (Advanced Options). Select that option using the arrow keys on your keyboard and press Enter. Then select option #A1 (Expand Filesystem) and press Enter. A message will appear saying that the boot partition has been resized. Select OK using arrow keys on your keyboard and press Enter. The main menu will reappear. Select Finish at the bottom of the menu and press Enter. A popup message will ask you to reboot your Raspberry Pi. Reboot the Pi.

9. Log into Raspbian again. We want to make sure we currently have the latest files and packages so type in:

Code: Select all

sudo apt-get update

and press Enter. If there are updates available, install them. To install the updates, you would type in the letter "y" when asked "Do you want to continue?" and then press Enter. When finished, the message "pi@raspberrypi:~ $" will appear signifying that the Pi is ready to receive a command. Now, type in:

Code: Select all

sudo apt-get upgrade

and press Enter. If there are updates available, install them. Now, type in:

Code: Select all

sudo apt-get dist-upgrade

and press Enter. If there are any updates available, install them.

If packages were updated and installed, then these packages were stored somewhere in the SD / microSD card. We need to delete them so that they don't take up valuable space. To clean up leftover packages, type in:

Code: Select all

sudo apt-get clean

and press Enter. 

10. At this time, you may want to configure your localization settings which include language, keyboard layout, and regional settings. To change this, we need to go back to raspi-config. Type in:

Code: Select all

sudo raspi-config

and press Enter.

The option we are interested is option #4 (Localization Options). Select that option and press Enter. You will be presented with 4 different options. 

Begin by selecting option #I1 (Change Locale) and press Enter. Find your locale by scrolling through the list using the up and down arrow keys on your keyboard. By default, en_GB.UTF-8 UTF8 will contain an asterisk, meaning that Raspbian Lite is using this locale. However, this may be incorrect if you live in another country, like the US. You can deselect this locale by highlighting it and pressing the Space bar on your keyboard. For example, if you live in the US, then the locale used should be en.US.UTF-8 UTF8. You would find this locale on the list and then press the Spacebar to select it. An asterisk will appear meaning that this locale will be used. Once you are ready, press Enter. A popup will appear asking you to select the default locale used for the entire system. Select the same locale you selected previously by highlighting it using the up and down arrow keys and then press Enter. Raspbian Lite will configure your system automatically and return to the main menu.

NOTE:You may notice that after you have changed your locale, if you change other internationalization settings, you may get some text randomly popping up at the bottom of the screen saying that setting the locale has failed and that LC_CTYPE, LC_Message, LC_ALL complain that there is no such file or directory. No problem. Exit out of raspi-config and type in:

Code: Select all

sudo reboot

and press Enter. This will reboot your Pi. Now you can reopen raspi-config and you will no longer see that weird message. Don't ask me why that hasn't been fixed yet.

Return to the Localization Options menu by selecting option #4 and press Enter. Now configure your timezone by selecting option #I2 (Change Timezone) and press Enter. Select your geological area using the arrow keys and press Enter. Select your region or city and press Enter. Raspbian Lite will configure your system automatically and return to the main menu.

Return to the Localization Options menu by selecting option #4 and press Enter. Now configure your keyboard layout by selecting option #I3 (Change Keyboard Layout) and press Enter. Select your keyboard model using the arrow keys and press Enter (In a case where you don't know what keyboard model to select, the Generic 105-key (Intl) PC keyboard model would be good choice). Now, you will select the keyboard layout. Select the appropriate keyboard layout and press Enter (If you don't see your keyboard layout, select Other and press Enter. Select the keyboard language and press Enter. Now you will be presented with various keyboard layouts corresponding to your language. Select the appropriate layout and press Enter). The next few prompts may ask you about configuring the AltGr and Compose key. This is up for you to decide. Select the appropriate options and press Enter. You will then return to the main menu.

If you are using a Raspberry Pi 3, this microcomputer come equipped with a built in Wi-Fi/Bluetooth wireless receiver. You may want to change the Wi-Fi country settings. Return to the Internationalization Options menu by selecting option #4 and press Enter. Now configure your Wi-Fi country settings by selecting option #I4 (Change Wi-Fi Country) and press Enter. Select your country using the arrow keys and press Enter. A confirmation message will appear confirming your selection. Select OK. You will return to the main menu.

12. Select Finish and press Enter. If you are asked to reboot, then reboot the Pi by selecting Yes and pressing Enter. If you are not asked to reboot, reboot anyways by typing in:

Code: Select all

sudo reboot

13. That's it! The foundation has been built! The Pi is ready to be used now, well obviously without the GUI. We have built the house but there's no furniture inside. 

Part 2 - Bring in the Furniture

This next part focuses on installing a GUI on top of Raspbian Lite. In order to have a GUI, we need these 4 things:

1. Display Server
2. Desktop Environment
3. Window Manager
4. Login Manager

Since we need 4 things, to make life easier, these 4 things are:

1. Xorg Display Server
2. Raspberry Pi Desktop (RPD) or Lightweight X11 Desktop Environment (LXDE) or XFCE Desktop Environment (XFCE) or MATE Desktop Environment (MATE)
3. Openbox Window Manager (RPD/LXDE) or XFWM Window Manager (XFCE) or Marco Window Manager (MATE)
4. LightDM Login Manager

For those that know about Linux, you may be wondering why the login manager chosen here is LightDM. For the most part, it is lightweight and it looks nice. But one feature that I believe stands out from other login managers is the ability to run Synergy client without errors. Synergy is a utility that allows you to use a computer's mouse and keyboard (Windows, Mac, or Linux) and share it with another computer, in this case, a Raspberry Pi. Of course you can install another login manager if you don't want LightDM.

Some users may not want a login manager. This is perfectly fine depending on how you will use your Raspberry Pi. For example, we may want the Pi to boot into the command line always and if there is a need to launch a desktop environment, a simple command will let you launch it. Continue to read on for more information.

Since we are focusing on Raspbian Lite, then the GUI installed will also be "lite". I understand that "lite" can have different meanings, but beginners are the main focus here. The important thing here is for users to personalize their Pi, without relying on prebuilt Raspbian. I believe these are the best GUI options. As always, you are free to use whatever you want. Moving forward, we will be installing the core of RPD, LXDE, XFCE, or MATE. This will give us only the GUI. There won't be any applications installed other than the required PIXEL, LXDE, XFCE, or MATE components such as a file manager, terminal, and settings. 

1. Turn on your Pi and log in. We will install Xorg. To do this type in:

Code: Select all

sudo apt-get install --no-install-recommends xserver-xorg

and press Enter. There will be a lot of dependent packages to install but these must be installed for the GUI to work. Install the packages. 

If you only install xserver-xorg, you will not have the ability to launch the Xorg Display Server from the command line. This would be a problem if you are not planning on installing a login manager. Otherwise, you do not need to do this. If this is the case, you may want to also install xinit by typing in:

Code: Select all

sudo apt-get install --no-install-recommends xinit

and press Enter. There will be some more dependent packages to install but these must be installed so that you can have the ability to start the Xorg Display Server from the command line if no login manager is installed. Install the packages.

-----

2. Now, choose your path:

Raspberry Pi Desktop (RPD) GUI

1 (RPD). You're reading this part because you want to install RPD right? Let's continue. RPD is a desktop environment designed by the Raspberry Pi Foundation. It is designed to be easy to use, which is why it looks simple. The backend of RPD is LXDE, which is a great choice as it is known for its low memory usage. For this desktop environment, you have two choices. You can either install the basic RPD desktop environment or a stripped version of it. The basic RPD desktop environment is the same as the one included in the regular Raspbian distribution, but without preinstalled applications. Essentials such as settings, task manager, terminal and file manager are included. To install the basic RPD desktop environment, type in:

Code: Select all

sudo apt-get install raspberrypi-ui-mods

and press Enter. There will be a lot of dependent packages to install but these must be installed for the GUI to work. Install the packages.

The stripped version of the RPD desktop environment only contains the file manager and settings for appearance, audio, network, and bluetooth. There is no trash support, no mounting of drives, or terminal included since the required components are not installed by default. No other applications are included either. However, you can add these components later if you wish. If you want to install the stripped version of the RPD desktop environment, type in:

Code: Select all

sudo apt-get install --no-install-recommends raspberrypi-ui-mods lxsession

and press Enter. There will be a lot of dependent packages to install but these must be installed for the GUI to work. Install the packages.

Now, here are some list of packages you may want to install if you are installing the stripped version of RPD:

Code: Select all

pi-greeter : The Raspberry Pi LightDM login theme
rpd-icons : The Raspberry Pi Desktop icon theme
gtk2-engines-clearlookspix : GTK Theme Engine (used to render Raspberry Pi LightDM login/desktop theme properly)

2 (RPD). Openbox Window Manager is installed by default when you install RPD. You do not need to do anything here.

LXDE GUI

1 (LXDE). You're reading this part because you want to install LXDE right? Let's continue. We will be installing the LXDE core. When you install LXDE, some essentials such as settings, terminal and file manager are included. LXAppearance is used to change the look of applications such as panels, icons, progress bars, cursors, and so on. This is optional to install but I recommend installing it in order to give yourself more customization abilities. To install LXDE with LXAppearance type in:

Code: Select all

sudo apt-get install lxde-core lxappearance

and press Enter. There will be a lot of dependent packages to install but these must be installed for the GUI to work. Install the packages.

2 (LXDE). Openbox Window Manager is actually installed by default when you install lxde-core. You do not need to do anything here. You can customize the look of the titlebar using the Openbox settings which is also installed by default. By using LXAppearance and Openbox settings together, you chose what LXDE looks like!

Now, go to STEP 3.

XFCE GUI

1 (XFCE). You're reading this part because you want to install XFCE right? Let's continue. We will be installing the XFCE core. When you install XFCE, some essentials such as settings and file manager are included. By default, XFCE uses XFCE4 Terminal. This is optional to install, however if you choose not to install it, then XTerm will be the default Terminal app.. To install XFCE with XFCE4 Terminal, type in:

Code: Select all

sudo apt-get install xfce4 xfce4-terminal

and press Enter. There will be a lot of dependent packages to install but these must be installed for the GUI to work. Install the packages.

2 (XFCE). XFWM Window Manager is actually installed by default when you install xfce4. You do not need to do anything here!

Now, go to STEP 3.

MATE GUI

1 (MATE). You're reading this part because you want to install MATE right? Let's continue. We will be installing the MATE core. When you install MATE, some essentials such as settings, terminal, and file manager are included. To install MATE, type in:

Code: Select all

sudo apt-get install mate-desktop-environment-core

and press Enter. There will be a lot of dependent packages to install but these must be installed for the GUI to work. Install the packages.

2 (MATE). Marco Window Manager is actually installed by default when you install MATE. You do not need to do anything here!

Now, go to STEP 3.

-------------

3 (STEP 3). Finally, we need to install LightDM login manager. If you have installed the basic or stripped version of the RPD desktop environment, then LightDM package is installed automatically so you can skip this step. As of the release of Raspbian Stretch, if you installed the XFCE desktop environment, LightDM is also installed automatically so you do not need to do this step. Otherwise, to install LightDM, type in:

Code: Select all

sudo apt-get install lightdm

and press Enter. Install the packages.

If you choose not to install a login manager but you did install xinit earlier, then this means that everytime your Pi boots, you will always boot into the command line. However, the desktop environment is already set up for you and is ready to be launched at any time. 

4. Everything we need to have Raspbian Lite with a GUI is ready! Fortunately, we don't have to do anything else but reboot! Reboot your Pi. When it finishes booting, you will see the LightDM login screen. From here, you will need use both a keyboard and a mouse. Log in and you should now see either RPD, LXDE, XFCE, or MATE desktop!

Otherwise, if no login manager was installed, then just login via the command line! At anytime, you can launch the Xorg Display Server by typing in:

Code: Select all

startx

and press Enter. You should now see either RPD, LXDE, XFCE, or MATE desktop! From here, you will need use both a keyboard and a mouse.

5. So what now? This is where you decide what you want to do with your custom Rasbian Lite installation with a GUI. You can change the look, install applications, start programming, do what is necessary to make it work the way you want it to!

Sample Screenshots

NOTE:The screenshots shown below do not represent the desktop that you will see after installation. For more information, see the GUI Customization section. Be aware that using composition effects (transparency, shadows, etc.) may impact performance and memory usage depending on your configuration.

Raspberry Pi Desktop (RPD)

Right Click > Open Image in New Tab to see full size image. Screenshot shown is a customized RPD desktop.

Image
A clean desktop showing HTop System Monitor.

Image
A desktop showing various windows opened.

LXDE

Right Click > Open Image in New Tab to see full size images. Screenshots shown are of a customized LXDE desktop. The memory used will vary depending on how you configure LXDE.

Image
A clean desktop showing Terminal.

Image
A desktop showing various windows opened.

XFCE

Right Click > Open Image in New Tab to see full size images. Screenshots shown are of a customized XFCE desktop. The memory used will vary depending on how you configure XFCE.

Image
A clean desktop showing Terminal. No composition effects enabled.

Image
A desktop showing various windows opened. No composition effects enabled.

Image
A clean desktop showing Terminal. Composition effects enabled.

Image
A desktop showing various windows opened. Composition effects enabled.

MATE

Right Click > Open Image in New Tab to see full size images. Screenshots shown are of a customized MATE desktop. The memory used will vary depending on how you configure MATE.

Image
A clean desktop showing Terminal. No composition effects enabled.

Image
A desktop showing various windows opened. No composition effects enabled.

Image
A clean desktop showing Terminal. Composition effects enabled.

Image
A desktop showing various windows opened. Composition effects enabled.

What Do I Use?

So the question is, what desktop environment does the author of this thread use? I actually use my own custom desktop environment. Let's take a look at my Raspbian Lite desktop:

Image

This a custom desktop environment using Openbox as the foundation. First impression; it looks clean, simple, and beautiful (to me of course!). The main reason I don't use a prebuilt desktop environment is because I want control over how the desktop environment looks. However, I will say that XFCE would be my preferred choice if I were to use a prebuilt desktop environment. This is how my desktop environment is laid out:

Image

The top and bottom panels are Tint2 panels. I customized the Tint2 panels to my liking to achieve this look. The notifications displayed on the desktop are from xfce4-notifyd. I want to be notified of things such as disconnection from the Internet, or Raspberry Pi is getting hot, or other notifications thrown by Raspbian Lite. Let's see the memory usage of my custom desktop environment:

Image

The desktop environment itself is using around ~146 MB which is very good. There is plenty of memory left for applications. Finally, here is a look of how the desktop looks when there is a lot of activities going on:

Image

And that's my brief tour of the desktop environment I use on Raspbian Lite! That's the reason why I wrote this guide. For you to learn how to become independent from regular Raspbian and personalize Raspbian Lite to your own liking. Personalization is of the greatest things about Linux in general.

Virtual Machine Playground

Installing a GUI on Raspbian Lite can either be easy or hard. If you want a particular desktop environment, you just follow the steps to install that environment. For the majority of Raspberry Pi users, that's more than enough. 

But what if we wanted to get our hands dirty? In other words, what if we want the desktop environment to be focused solely on a particular application. For example, the desktop environment should just be focused on a web browser, or it should just be focused on a music player. Is it really necessary for a file manager to be in an operating system that its primary focus is to display web pages? Is it really necessary for an operating system to be running blown desktop environment just to play music? This is where you explore ideas for what kind of GUI Raspian Lite should have.

Can you explore GUI ideas directly on Raspbian Lite? Yes, but the idea of a virtual desktop is for you to explore those GUI ideas in the comfort of your own computer. It is basically a playground. You don't need to worry about reformatting SD / microSD cards, and you can go back in time using a feature called "snapshots" included in most virtual machine virtualizers in case if you made a mistake or you broke your installation. There is no risk. Not only that, but you also learn more about the inner workings of Linux.

Once you build your desktop environment to your liking in the virtual machine, you simply follow the steps you did on the virtual machine and apply them to your Raspbian Lite installation. If you are interested in reading more on this topic, simply click on the link below to see the full tutorial:

viewtopic.php?p=1109518#p1109518

Advanced - X11 Forwarding (Remote Applications)

X11 Forwarding is an SSH remote tunneling system where you can run applications installed on a Linux system remotely from another system running Windows, macOS, or Linux. 

For example, let's say that you have a clean Raspbian Lite installation on your Raspberry Pi. Now, if you physically want use your Raspberry Pi like a normal computer (with monitor, keyboard, mouse), then most likely you want to install a GUI on Raspbian Lite. However, if you only care about running specific applications on Rasbian Lite and don't have a need to use it as a normal computer (no monitor/keyboard/mouse/GUI), then X11 Forwarding may be something you'd like to use.

Here's how it works. You would connect to your Raspberry Pi via SSH with X11 Forwarding option enabled from another system. When it is connected, if you type in an application name, lets say "leafpad" and press Enter, the application will open on your desktop. That's it! So in other words, your system will show you the application's GUI while the Raspberry Pi handles the workload for that application. Pretty neat right?

If you want to use X11 Forwarding, it's very simple. Follow the instructions below:

1. Follow the steps on Part 1 - Build the Foundation to have a clean installation of Raspbian Lite. If you already installed a desktop environment and still want to enable X11 Forwarding, continue to step 2.

2. You need to enable SSH on Raspbian Lite. Using the command line (or Terminal window), type in:

Code: Select all

sudo raspi-config

and press Enter. Select option #5 (Interfacing Options) and press Enter. Then select option #P2 (SSH) and press Enter. You will be asked if you want to enable the SSH server. Select "Yes" and press enter. A popup will open saying the SSH server has been enabled. Select "Ok" and you will be returned to the main menu. Select Finish and press Enter to exit raspi-config. 

3. Obtain the IP address of your Raspberry Pi. Using the command line (or Terminal window), type in:

Code: Select all

hostname -I

and press Enter. Take note of that IP address since you need it to connect to the Raspberry Pi via SSH.

4. Reboot the Raspberry Pi by typing in:

Code: Select all

sudo reboot

and press Enter.

5. Once the Raspberry Pi has been rebooted, you no longer need to physically use the Raspberry Pi since you can now remotely log onto the Raspberry Pi via SSH. 

6 (Windows). You will need to install an SSH client with X11 Forwarding capabilities on the computer you wish to run the Raspberry Pi applications on. In order for the applications to appear on the computer, you also need to install Xorg Server on the computer as well. For Windows, there is an application called MobaXterm which is free and it is an SSH client that integrates Xorg Server. No need to install Xorg Server separately.

Image

Create a session by clicking on the "Session" icon on the toolbar.

Image

Enter the IP address of the Raspberry Pi as well as the Raspberry Pi username. Make sure that X11 Forwarding is enabled by click on the Advanced SSH Settings tab. When ready, click OK. You will be asked to enter the password.

Image

Once you are logged in, you are ready to launch Raspberry Pi applications remotely! To launch applications remotely, type in:

Code: Select all

nameOfApp &

and press Enter. The "&" symbol allows you to continue to use the MobaXterm window and open multiple Raspberry Pi applications without freezing it.

Image

6 (macOS). You will need to install an SSH client with X11 Forwarding capabilities on the computer you wish to run the Raspberry Pi applications on. In order for the applications to appear on the computer, you also need to install Xorg Server on the computer as well. On macOS, you will need to install XQuartz since no application comes with Xorg Server integrated. Once XQuartz has been installed, you can use Terminal to connect to your Raspberry Pi. To start an SSH session with X11 forwarding, type in:

where "username" is your Raspberry Pi username and "raspberrypiadrress" is your Raspberry Pi's IP address. Then press Enter. You may be asked if you are sure if you want to connect to the host. Type in "yes". Enter the Raspberry Pi password when asked.

Image

Once you are logged in, you are ready to launch Raspberry Pi applications remotely! To launch applications remotely, type in:

Code: Select all

nameOfApp &

and press Enter. The "&" symbol allows you to continue to use the MobaXterm window and open multiple Raspberry Pi applications without freezing it.

Image

For those wondering about memory usage, the memory used on Raspbian Lite is only the application as well as essential processes. The usage is very small. No Xorg, no desktop environment, no login manager memory consumption. More memory, more storage space!
Image
Advanced - Remote Desktop Protocol (RDP)

If you are a Windows user, you may be interested in accessing your Raspberry Pi desktop remotely without having to connect your Raspberry Pi to a TV or monitor to use it. This is where the Remote Desktop Protocol (RDP) comes into play. With this protocol, you will be able to use the built-in Remote Desktop Connection application on Windows to access your Raspberry Pi desktop remotely.

Assuming that your Raspberry Pi is running Raspbian Lite with a desktop environment and has no installation of VNC Server or TightVNC Server, the installation and configuration should be very easy.

To use the Remote Desktop Protocol, you must install XRDP on Raspbian Lite. Simply run the command below:

Code: Select all

sudo apt-get install xrdp

Once XRDP has been installed, it will run automatically in the background and will transmit the Raspberry Pi desktop whenever Remote Desktop Connection on Windows connects to your Raspberry Pi.

Now, run Remote Desktop Connection on Windows.

Image

On the Computer textfield, enter the Raspberry Pi IP address and then press Connect.

Image

You may get a warning saying that the computer you are connecting to cannot be verified. Just click on Yes.

Image

Now you will be presented with the XRDP login window.

Image

Enter your Raspberry Pi's username and password and press OK.

Image

And that's it! You can now remotely use the Raspberry Pi desktop on Windows!

Advanced - Custom Desktop Environment using i3 WM

Let's get serious now. The real reason to use Raspbian Lite is to make the Raspberry Pi microcomputer work for a specific application purpose. The operating system should be customized to that specific application. What kind of applications?

Anything really. Some people use the Raspberry Pi just for:

Clock and Weather
Internet Radio
Web Browser
Music Player
Surveillance
Retro Game Console

and the list goes on and on. What will you be building? To understand the idea of a custom desktop environment, I will go over some examples and maybe it can give you an idea of how to approach and implement your idea. If you are interested in reading more on this topic, simply click on the link below to see the full tutorial:

viewtopic.php?p=1109520#p1109520

Advanced - Custom Desktop Environment using Openbox WM

Openbox is a window manager that can run as a standalone desktop environment, or with another desktop environment. Window managers normally handle application windows as well as their window decorations and effects. If you run Openbox as a standale desktop environment, you would have control over how your desktop environment looks. Openbox does not have any panels, desktop icons, wallpapers, or other UI elements since that is not the job of Openbox. You would have to provide that yourself.

There are some benefits of going this route. The main benefit is resource usage. Since you would only have Openbox running, most of the memory used will be used for applications that you run. The second benefit is simplicity. There are many users who only want to run a single application and don't need a full desktop environment. Third benefit is customization. You can build your own desktop environment and use Openbox as its window manager.

If you think Openbox window manager sounds like something you want to use on Raspbian Lite, let's continue!

1) In order to use Openbox, you need to have Xorg Display Server installed. To install Xorg, type in:

Code: Select all

sudo apt-get install --no-install-recommends xserver-xorg

and press Enter. 

If you are planning on not using a login manager, then you will also need to install Xinit. This will allow you to start Openbox manually. To install Xinit, type in:

Code: Select all

sudo apt-get install --no-install-recommends xinit

and press Enter.

2) Now you need to install Openbox. Remember that Openbox does not include any applications other than Openbox Configuration Manager. If you need to use Terminal in Openbox, you have to install one yourself. In the command below, I included LXTerminal. Otherwise, install your own Terminal if needed. To install Openbox with LXTerminal, type in:

Code: Select all

sudo apt-get install openbox lxterminal

and press Enter.

3) If you are planning on installing a login manager, to install LightDM login manager, type in:

Code: Select all

sudo apt-get install lightdm

and press Enter. 

However, if you plan on starting Openbox manually, then you need to do some more work. First, we need to generate an .xinitrc file. This file will have all the commands to start your custom desktop environment. For this case, we only need to implement the Openbox command to the file.

First, copy a sample xinitrc file and paste it to your home directory. To do this type in:

Code: Select all

cp /etc/X11/xinit/xinitrc ~/.xinitrc

and press Enter. Now, edit the xinitrc file by typing in:

Code: Select all

nano ~/.xinitrc

and press Enter.

Image

Delete everything inside this file. After that, copy the command below onto your xinitrc file:

Code: Select all

exec openbox-session

Image

Save the xinitrc file.

4) Now, restart your Raspberry Pi. For those that installed LightDM login manager, you should see LightDM appear. Login with your username and password and you should now see the Openbox desktop! Well actually, you would see nothing. If you right-click, you will see the Openbox menu.

For those that did not install a login manager, simply log onto the Raspberry Pi. To start Xorg with Openbox, type in:

Code: Select all

startx

and press Enter. Similarly, you should see nothing but a blank screen. If you right-click, you will see the Openbox menu. 

That's it! After this, you decide what to do next with Openbox! 

For those wondering about memory usage, Openbox uses very little memory.

Image

As you can see, it's very lightweight!

Extras

1. Raspberry Pi Configuration Tool

If you have used the regular Rasbian distribution, you probably noticed that there was a tool for configuring the Raspberry Pi. No problem, you can bring it back in Raspbian Lite.

In Terminal, type in:

Code: Select all

sudo apt-get install rc-gui

and press Enter. Install the necessary packages. You may have to reboot your Raspberry Pi to see the configuration tool in your Applications menu or Preferences menu.

2. GUI Package Dependency List

Sometimes you may want to know what dependency packages are required for a primary package to work. Here I created PDF documents listing all dependency packages for the following primary packages. Packages listed under "The following additional packages will be installed" and "The following NEW packages will be installed" are installed. Packages listed under "Suggested packages" are not installed but are shown in case you want to install them manually later on. Packages listed under "Recommended packages" are installed only if you do not use the --no-install-recommends flag with apt-get. The current package lists are updated as of 3/11/2018:

xserver-xorg
https://onedrive.live.com/download?cid= ... yx57I&em=2

xserver-xorg (No Install Recommends)
https://onedrive.live.com/download?cid= ... z-BvU&em=2

raspberrypi-ui-mods
https://onedrive.live.com/download?cid= ... dII7I&em=2

raspberrypi-ui-mods (No Install Recommends)
https://onedrive.live.com/download?cid= ... cgmYk&em=2

-----------------------------------------------------------------

Hope you found this guide useful! If there are any questions, comments, suggestions, or concerns, you are free to say down below. :)

How to Backup your Raspberry Pi SD Card

In this guide, we will be showing you various ways on how to backup your Raspberry Pi and also how to restore it. Backing up is a crucial task that you should be doing often, especially if you make many changes or are storing data on it.

One thing to note is that some backup methods are going to be way more thorough the others, for instance backing up your Raspberry Pi SD Card image is going to be more reliable than just backing up all the files to a USB device since the image is a replication of all partitions on the SD Card.

We will be exploring two different methods of backing up your Raspberry Pi in this guide, the two different methods that we will be showing you how to do is the following:

 Backing up your Raspberry Pi to a computer using a SD Card Reader
 Backup the Raspberry Pi to a USB device

Personally, we recommend backup to a computer as it is the most robust method. Mainly since the Raspberry Pi doesn’t have the best USB speeds or network speeds so creating backups can take considerable time and put a fair bit of stress on the Raspberry Pi’s limited resources. As an added bonus the backup we make using a tool like win32diskimager is a 1 to 1 copy of the SD Card meaning every byte should be the same.

Backing up the Raspberry Pi is an important step in making sure you don’t lose any data when you go to make big changes to your system. This is important if you have stuff that you would prefer not to lose if you’re looking at doing a complicated Pi project, upgrade or something else to the operating system.

 Backing up your Raspberry Pi SD Card

To start off we are first going to show you how to backup your Raspberry Pi SD Card as an image. To do this tutorial you will need to have a SD Card reader handy.

To begin this tutorial, please first turn off your Raspberry Pi by running the following command on your Pi’s terminal:

sudo shutdown now

Once it has shut down, disconnect the power and remove your SD Card. Place the SD Card into your SD Card reader and proceed onwards with this section of the guide.

This section of the guide will be split into 3 parts, one for Windows, one for Mac OS X and one for Linux based systems.

 Backing up your Raspberry Pi SD Card on Windows

1. To backup our Raspberry Pi’s SD Card on Windows we will be utilizing the imaging tool that is called win32diskimager. Win32diskimager is an incredibly useful tool that can read and write images to USB Sticks or SD/CF Cards. It is a tool many will be familiar with since it is used often to write the initial Raspbian image to your Raspberry Pi.

We will start off this section of the guide by downloading and installing this tool by going to win32diskimager’s homepage.

2. With win32diskimager now installed, open it up. You should be greeted with a screen like we have shown below.

For now we need to make sure the right drive has been selected by clicking the dropdown box under “Device:” (1.) and ensuring the correct drive letter of our SD Card is selected.

Afterwards, click the folder icon (2.) that is directly to the left of the device dropdown box.

Selecting drive to backuph

 

3. You will now be shown a file selection screen, however we won’t be selecting any file. Instead navigate to the folder you want to keep your backup file. Once within this folder, type in the name you want to give your backup file in the textfield (1.) at the bottom as shown in the screenshot below.

Make sure you have .img at the end of the name you choose to use. For example, we named our backup file RaspberryPiMyLifeUp.img

Once you have typed in your file name you want to utilize, click the Open button.

Backing up Raspberry Pi Selecting a disk image

 

4. Finally with our device set and our new filename set we can begin the backup process. To do this we simply just need to click the “Read” button. Please note that this can take some time as it is a complete backup of your SD Card, meaning every single byte is replicated.

Raspberry Pi Backup SD Card

 Restoring your Raspberry Pi Backup on Windows

1. Now when it comes time that you need to make use of your full SD Card backup we will need to once again make use of win32diskimager. Before opening the software, make sure you have inserted your SD Card into a SD Card Reader that is plugged into your computer.

With the win32diskimager software now opened, lets click the dropdown box that is located under the “Device” (1.) header and ensuring that the correct drive letter of our SD Card is selected.

 

After you have set the device we can now, click the folder icon (2.) that is located to the left of the dropdown box.

Selecting drive to backup

2. Now that we have the file browser loaded up, let’s find the backup file that we created earlier. Once you have found it either double click the file, or single click it and click the “Open” button.

3. With our backup image now selected, we can now proceed with writing the backup file to the SD Card. Please note this will wipe everything currently on the SD Card so make sure that you have the correct device selected. When you are happy you have everything correct, click the “Write” button.

Raspberry Pi write backup image

 

4. Once the writing process has completed you should now have a SD Card that is in the exact state of when you originally made the backup. Thanks to the full image backup it means all partitions on the card are restored.

 Backup up your Raspberry Pi SD Card on OS X

1. With your SD Card inserted into a card reader on your Mac we can begin the process of making a full image backup of your Raspberry Pi. Unlike Windows, we can easily just use the terminal to do this.

To proceed with this tutorial, start off by opening the Terminal application.

2. With the Terminal application now open on your Mac device, we need to utilize the following command. This command will display all available disks on your device.

diskutil list

Within this list, look for your SD Card by looking for a disk that is about the size of your SD Card. For instance, with a 16gbSD Card you should be looking at a "_partition_scheme" of about 16gb. You will also notice that there is likely a partition called "boot".

Once you have found your SD Card in this list, take notice of the mount location. For instance, my own SD Card was under /dev/disk1.

3. Now still within the terminal on your Mac, we need to utilize the following command. This command will basically create a copy of your SD Cards image, and save it to your home directory as PiSDBackup.dmg (The file format being a disc image)

Make sure you swap out /dev/disk1 with whatever you found when using the diskutil list command.

sudo dd if=/dev/disk1 of=~/PiSDBackup.dmg

This command can take some time to complete as it requires reading the entire SD Card to the disk. The command also provides no feedback on how far along it is, so please be patient and wait for the prompt to enter another command to reappear before removing your SD Card from your Mac.

 Restoring your Raspberry Pi Backup on OS X

1. Now that you need to restore your Raspberry Pi to its backup we need to again use the diskutil list command to find our SD Card. Remember to as before, take note of partition sizes to find your SD Card.

diskutil list

2. Now before we can write to the SD Card we will need to unmount it. The reason for this is that OSX will attempt to write to it at the same time, unmounting the SD Card prevents this from happening.

Run the following command on your Mac device to unmount the card, again making sure that you replace /dev/disk1 with the one you found using the diskutil list command.

diskutil unmountDisk /dev/disk1

3. Finally we can now write the image back to the SD Card, please be prepared for this to take some time as it involves rewriting the entire SD Card. Remember to change out /dev/disk1 with the mount location you grabbed using the diskutil list command.

sudo dd if=~/PiSDBackup.dmg of=/dev/disk1

Like reading the SD Card to a disk image file, the process of writing the image also takes a long time. As an added note, the dd tool doesn't show any write progress so please be patient and wait till the enter command prompt reappears.

4. Once the write process has completed we can now eject the SD Card from the Mac so we can continue using our Raspberry Pi Backup. To eject the SD Card, we will need to utilize the command below.

Your Raspberry Pi's SD Card should now be in the exact same state as when you made the original backup.

sudo diskutil eject /dev/rdisk3

 Backing up your Raspberry Pi SD Card on Linux

1. Before starting to backup up your Raspberry Pi's SD Card on Linux we will first run a command with the reader not plugged in. The reason for this is makes it much easier to see which device is which.

df -h

This command will return something like what is shown below.

Filesystem      Size  Used Avail Use% Mounted on
/dev/root        15G  4.0G  9.6G  29% /
devtmpfs        458M     0  458M   0% /dev
/dev/mmcblk0p1   41M   21M   21M  52% /boot

2. Now insert your SD Card reader back into your Linux computer and again run the following command again, but this time take note of the additional entries.

df -h

This command will return something like what you got above, but with an additional entry, in our case /dev/sda1 is that additional entry, with your entry, remove the partition number. For instance, /dev/sda1 will become /dev/sda. We need to do this as we want to write to the entire drive and not just a singular partition.

Filesystem      Size  Used Avail Use% Mounted on
/dev/root        15G  4.0G  9.6G  29% /
devtmpfs        458M     0  458M   0% /dev
/dev/mmcblk0p1   41M   21M   21M  52% /boot
/dev/sda1       3.7G   75M  3.6G   3% /media/boot

3. We can now utilize dd, the same tool we make use of on Mac OS X since it is also built on Linux. We can utilize the following command to begin dumping the SD Cards image to our home directory.

Make sure you replace /dev/sda with the filesystem that you grabbed using the df -h command.

sudo dd if=/dev/sda of=~/PiSDBackup.img

The process of backing up your Raspberry Pi can take some serious time, so be patient and wait. The dd tool provides no feedback, so you will have to wait until the input command returns to your terminal.

Once it reappears you will have successfully backed up your Raspberry Pi.

 Restoring your Raspberry Pi Backup on Linux

1. Now that you have made a backup of your Raspberry Pi you will want to at some stage make use of this. To do this we will need to again go through the process of finding out the location of our filesystems.

Use the df -h command like we did in the first segment of this guide, though this time you might have more than one partition pop up for your SD Card such as /dev/sda1 and /dev/sda2. Take note of all new entries as you will need to unmount all of them.

2. Now that we have all our partition locations ready, we can unmount each of them by running the following command for each one. Switching out /dev/sda1 for the locations that you got in the previous step.

sudo unmount /dev/sda1

3. With all the partitions now unmounted let's write our backup image to the SD Card. We can do that by running the following command. Remember swap out /dev/sda with your devices mount location.

sudo dd bs=4M if=~/PiSDBackup.img of=/dev/sda

 Backing up your Raspberry Pi to a USB Drive

1. Before plugging in your USB device that you want to keep the backups on let's first run the following command to find out the current filesystems that are available to us.

df -h

This command will return something like what is shown below.

Filesystem      Size  Used Avail Use% Mounted on
/dev/root        15G  4.0G  9.6G  29% /
devtmpfs        458M     0  458M   0% /dev
/dev/mmcblk0p1   41M   21M   21M  52% /boot

2. Now insert your USB Device into your Raspberry Pi and run the following command, take note of any new entries that pop up.

df -h

This command will return something like what is shown below.

Filesystem      Size  Used Avail Use% Mounted on
/dev/root        15G  4.0G  9.6G  29% /
devtmpfs        458M     0  458M   0% /dev
/dev/mmcblk0p1   41M   21M   21M  52% /boot
/dev/sda1       3.7G   75M  3.6G   3% /media/pi/MYBACKUPDRIVE

3. With our USB device now showing on the list, we need to look at the "Mounted on" location. In our case this is /media/pi/MYBACKUPDRIVE. This will be the location that we will write our backup images to. So, make note of it for later in the tutorial.

Now with our backup location now handy we can download the backup script that we are going to use, this script was written by a user on the Raspberry Pi forums called Jinx.

Let's clone the script to our Raspberry Pi by running the following two commands.

cd ~
git clone https://github.com/lzkelley/bkup_rpimage.git

4. With the script now saved to the Raspberry Pi we can start to make use of it. We can do an initial backup by running the command below on our Raspberry Pi. Make sure you replace /media/pi/MYBACKUPDRIVE with your own mount location that you grabbed in the previous step.

sudo sh bkup_rpimage.sh start -c /media/pi/MYBACKUPDRIVE/rpi_backup.img

Basically this script will create a dummy image then launch an rsync process to copy all the files from the system to the dumby image. Please note that the initial backup can take up to an hour to complete.

5. Now that we have created our initial backup file and know that the script is working as intended we can move onto automating the backup. To do this we will be making use of cronjobs.

One thing to decide on how is whether you want an incremental backup or multiple backups. An incremental backup just updates the original backup and doesn't generate a new file.

Run the following command on your Raspberry Pi to begin editing the crontab.

sudo crontab -e

6. In the crontab editor, add one of the following lines to the bottom of the file. This will make a backup every day. If you want to edit the cron timings you can use the Crontab guru website to easily work them out.

Incremental Backup

0 0 * * * sudo sh ./home/pi/bkup_rpimage/bkup_rpimage.sh start -c /media/pi/MYBACKUPDRIVE/rpi_backup.img

Multiple Backup

0 0 * * * sudo sh ./home/pi/bkup_rpimage/bkup_rpimage.sh start -c /media/pi/MYBACKUPDRIVE/rpi_$(date +%Y-%m-%d).img

Now save the file by pressing Ctrl + X then pressing Y and then hitting Enter.

7. You should now have an automated backup system up and running that will continually backup your Raspberry Pi to your USB device. To restore these images follow our Restoring guides located in the SD Card section of this guide.

I hope that you now know how to backup your Raspberry Pi SD card on both your main system or backing up directly to a USB device. You can now continue on with working on some Raspberry Pi projects or just using your Pi as you would normally. If you run into any issues or have any feedback feel free to drop a comment below.

Stopping SD Card Corruption on Raspberry Pi’s Raspbian

The following are instructions for minimizing SD card writes for Raspberry Pi’s “Raspbian” Distribution.

If you’re like me, you’ve run into a corrupted SD card too many times to not become hell-bent on making it never happen again. I have the following setup, and it seems to be working well for me.

The biggest offender for Filesystem writes on any linux system is logging. If you are like me, you don’t really look at /var/log after a recycle anyways. This area, and /var/run, a location where lock files, pid files and other “stuff” shows up, are the most common areas for mess-ups. Take a look at your blinking FS light on the board. Our goal is to make that light stay off as long as possible.

Set up tmpfs mounts for worst offenders. Do other tweaks.

Linux has with it the concept of an in-memory filesystem. If you write files to an in-memory filesystem, they will only exist in memory, and never be written to disk. There are two common mount types you can use here: ramfs, which will continue to eat memory until your system locks up (bad), and tmpfs, which sets a hard upper limit on mount size, but will swap things out if memory gets low (bad for raspberry pi, you will probably be hard stopping your device if it is low on memory).

We will first solve the usual corruption culprit and then move on to making sure we are covered when our programs decide to blow up.

The following two lines should be added to /etc/fstab:

none        /var/run        tmpfs   size=1M,noatime         00
none        /var/log        tmpfs   size=1M,noatime         00

UPDATE (unverified): I have been told that /var/run is now a symlink to a tmpfs filesystem, anyways, so you may not need to add /var/run anymore, and adding it may cause issues.

There’s more, however. By default, linux also records when a file was last accessed. That means that every time you read a file, the SD card is written to. That is no good! Luckily, you can specify the “noatime” option to disable this filesystem feature. I use this flag generously.

Also, for good measure, i set /boot to read-only. There’s really no need to regularly update this, and you can come back here and change it to “defaults” and reboot when you need to do something.

After this, /etc/fstab should look as follows:

proc            /proc               proc    defaults                    0   0
/dev/mmcblk0p1  /boot               vfat    ro,noatime                  0   2
/dev/mmcblk0p2  /                   ext4    defaults,noatime            0   1
none            /var/run            tmpfs   size=1M,noatime             0   0
none            /var/log            tmpfs   size=1M,noatime             0   0

UPDATE (unverified): I have been told that /var/run is now a symlink to a tmpfs filesystem, anyways, so you may not need to add /var/run anymore, and adding it may cause issues.

Go ahead and reboot now to see things come up. Check the Filesystem light on your raspberry pi after it’s fully booted. You should see no blinking at all.

Disable swapping

As a note, since i have done the changes above, i have not corrupted an SD card. I’m not saying I’ve tried very hard, but it is much better, even with power plug pulls, which i tried a few of after doing these changes.

One protection against SD card corruption is an optional, but potentially “I’m glad i did that” change to disable swapping.

The raspberry pi uses dphys-swapfile to control swapping. It dynamically creates a swap partition based on the available RAM. This tool needs to be used to turn off swap, and then needs to be removed from startup.

Run the following commands to disable swapping forever on your system:

sudo dphys-swapfile swapoff
sudo dphys-swapfile uninstall
sudo update-rc.d dphys-swapfile remove

After doing this, call free -m in order to see your memory usage:

pi@raspberrypi ~ $ free -m
             total       used       free     shared    buffers     cached
Mem:           438         59        378          0          9         27
-/+ buffers/cache:         22        416
Swap:            0          0          0

If you reboot, and run a free -m again, you should still see swap at 0. Now we don’t have to worry about tmpfs filesystems swapping out to hard disk!

Housekeeping!

As you go on and install other tools and frameworks on your raspberry pi (like ROS), you need to be aware of where caches and logfiles are written to. If, for example, you use ROS, the nodes will, by default, log to ~/.ros/log/. For these sorts of things, and for ROS in particular, point these logs to a folder on /dev/shm. This mount is created by default on linux boxes, and is a tmpfs filesystem that is globally writable by default. Mine has 88 MB.
For example, pointing ROS logs to this file could be done by adding the following to your .bashrc:

export ROS_LOG_DIR=/dev/shm/rosLogs

If you feel like creating more mounts, feel free, but I have run into ownership issues that required having another script on startup that had to be run as root to chown directories to their proper owners.

Getting to 100%

The only way to fully protect against SD card corruption is to mount your root filesystem as readonly. For me, this was too much of a usability issue. I am editing files and installing new packages too often for this to be feasible. The steps listed above should, however, cover you 98% of the time. Try not to pull power while you’re editing files or installing new packages on your device, and you should be fine. Still make backup images of your SD card every once in a while! This is a best practice no matter what!

Happy Hacking!

Use the Adafruit PCA9685 with a Raspberry PI

Use the Adafruit PCA9685 with a Raspberry PI, in Java Raspberry PI
to drive up to 16 servos

The Servo Driver we are talking about here is the Adafruit 16-Channel 12-bit PWM/Servo Driver - I2C interface - PCA9685.

The original tutorial from Adafruit is available here. The language it uses is Python. 

This board has an I2C (pronounce I "square" C) interface, that needs to be enabled on the Raspberry PI. 
I2C stands for Inter-Integrated-Circuit. 
Arduino & Adafruit provide python libraries that go along with their components. The code we present here is in big part an adaptation of this code.

Enable I2C on the Raspberry PI

We will show how to enable I2C on a Model B Raspberry PI. There is a lot of documentation on the web on how to do it on whatever version on the RasPI you have. We are not going to duplicate the web in this document... 
We will need to edit several configuration files. Use the editor you prefer (nanovigedit, ...), as root (sudo).

  1. Edit /etc/modules 
    Make sure its content eventually looks like this:
      i2c-bcm2708
      i2c-dev
              
    Save your modifications, if you have done any.
  2. Install some I2C Utilities (in python) 
     Prompt> sudo apt-get install python-smbus
     Prompt> sudo apt-get install i2c-tools
              
  3. Edit /etc/modprobe.d/raspi-blacklist.conf, comment the two lines it contents: 
    Before:
     blacklist spi-bcm2708
     blacklist i2c-bcm2708
              

    After:
     # blacklist spi-bcm2708
     # blacklist i2c-bcm2708
              
    Save your modifications, if you have done any.
  4. By now (the PCA9685 needs to be wired for that), you should be able to run the i2cdetect utility, which will will use to know the address of the servo driver:
     Prompt> sudo i2cdetect -y 1
          0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
     00:          -- -- -- -- -- -- -- -- -- -- -- -- --
     10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
     20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
     30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
     40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
     50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
     60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
     70: 70 -- -- -- -- -- -- --
              
    As seen above, the I2C addresses range from 0x03 to 0x77 (binary 0000011 to 1110111). This way, several boards can be used simultaneously from the RasPI, as long as their I2C addresses are different, even if the GPIO interface pins are connected to several different boards. 
    For example, if you have connected
    • A PCA9685 (servo driver)
    • A BMP180 (Pressure, Altitude, Temperature)
    • A LSM303 (Magnetometer & Accelerometer)
    you would have
     Prompt> sudo i2cdetect -y 1
          0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
     00:          -- -- -- -- -- -- -- -- -- -- -- -- --
     10: -- -- -- -- -- -- -- -- -- 19 -- -- -- -- 1e --
     20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
     30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
     40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
     50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
     60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
     70: 70 -- -- -- -- -- -- 77
              
    where, in addition to the above,
    • 0x19 would be the magnetometer address (LSM303)
    • 0x1e would be the accelerometer address (LSM303)
    • 0x77 would be the BMP180 address

Wiring

The connection setting is quite simple.

PCA9685Raspberry PI
VCC 1. 3.3 VDC Power
GND 6. 0V (Ground)
SDA 3. SDA0 (I2C)
SCL 5. SCL0 (I2C)
Raspberry PI P1 Connector map Click to enlarge Click to enlarge 
The Raspberry PI, connected to a PCA9685, with 2 servos.

This diagram shows the name of the pins you want to use on the GPIO Connector of the Raspberry PI. As we said before, we need to use the pins 1, 3, 5, and 6.

Programming

You will need to know what address to talk to to reach the PCA9685. Run the i2cdetect utility.

 Prompt> sudo i2cdetect -y 1
      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
 00:          -- -- -- -- -- -- -- -- -- -- -- -- --
 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
 40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
 70: 70 -- -- -- -- -- -- --
      

We will use the 0x40 address to reach the PCA9685. 
The Java code we are interested in is in the class named adafruiti2c.AdafruitPCA9685. Check it out in the repository. We are going to comment only on the main method of this class, which is a basic example. It assumes that 2 servos are connected to the PCA9685, on the 15 and 14 slots.
The PCA9685 has 16 such slots, numbered - on the board - from 0 to 15. See them on the picture at the top of this document. The slots we are talking about are the 16 columns of 3 holes drilled at the bottom of the board. Their number is printed on top of each column of 3 holes.

  ...
  public static void main(String[] args)
  {
    AdafruitPCA9685 servoBoard = new AdafruitPCA9685();   // 0x40 is the default address
    servoBoard.setPWMFreq(60); // Set frequency to 60 Hz
    int servoMin = 150;   // Min pulse length out of 4096
    int servoMax = 600;   // Max pulse length out of 4096
    
    final int CONTINUOUS_SERVO_CHANNEL = 14;
    final int STANDARD_SERVO_CHANNEL   = 15;
    
    for (int i=0; i<10; i++)
    {
      System.out.println("i=" + i);
      servoBoard.setPWM(STANDARD_SERVO_CHANNEL,   0, servoMin);
      servoBoard.setPWM(CONTINUOUS_SERVO_CHANNEL, 0, servoMin);
      waitfor(1000);
      servoBoard.setPWM(STANDARD_SERVO_CHANNEL,   0, servoMax);
      servoBoard.setPWM(CONTINUOUS_SERVO_CHANNEL, 0, servoMax);
      waitfor(1000);
    } 
    servoBoard.setPWM(CONTINUOUS_SERVO_CHANNEL, 0, 0); // Stop the continuous one
    System.out.println("Done with the demo.");
  }
  ...
      

This code loops 10 times and makes the servos go from a value of 150 to a value of 600, and vice versa. It waits for 1000 milliseconds between each message to the servos. 
Notice the two int variables, CONTINUOUS_SERVO_CHANNEL and STANDARD_SERVO_CHANNEL
For this demo, the standard servo we use is the Standard servo - TowerPro SG-5010 - 5010
As seen in its documentation, the servo rotates on 180°, 90° on each side. Position "0" (1.5ms pulse) is middle, "90" (~2ms pulse) is all the way to the right, "-90" (~1ms pulse) is all the way to the left. 
We see we use a 60 Hz frequency. This means we will have 60 cycles per second. Each cycle contains 4096 ticks. 
The value minServo is 150. 
The value maxServo is 600. 
A full cycle (of 4096 ticks) at 60 Hz will take 1 / 60 ~ 16 ms. 
150 ticks would take 150 / (60 * 4096) seconds, which is ~ 0.61 ms. 
600 ticks would take 600 / (60 * 4096) seconds, which is ~ 2.44 ms. 

More generically

  • TickTime = 1 / (freq * 4096).
  • PulseTime = TickTime * nbTicks.

It is quite easy - and convenient - to put those formulas in a spreadsheet. 
Based on those formulas, we should have:

Pulse Width
in ms
Nb Ticks
1 246
1.5 369
2 492

The values given in the Adafruit tutorial (150 & 600) happens to be a bit different of what the documentation of the servo says..., but they actually work fine, and this is the ones we use in the code:

Pulse Width
in ms
Nb Ticks
1 150
1.5 375
2 600

Running

We run the code from a script named servo:

 #!/bin/bash
 PI4J_HOME=/home/pi/pi4j/pi4j-distribution/target/distro-contents
 CP=./classes
 CP=$CP:$PI4J_HOME/lib/pi4j-core.jar
 sudo java -cp $CP adafruiti2c.AdafruitPCA9685
      
 Prompt> ./servo
      

And here is the result

 Prompt> ./servo
 Connected to bus. OK.
 Connected to device. OK.
 Setting PWM frequency to 60 Hz
 Estimated pre-scale: 100.72526
 Final pre-scale: 101.0
 i=0
 i=1
 i=2
 i=3
 i=4
 i=5
 i=6
 i=7
 i=8
 i=9
 Done with the demo
 Prompt>
              
The console output

And what next?

Drive the Raspberry PI, on its own cart... 
Fuel the Raspberry PI with a solar panel, oriented by servos to face the sun for greater efficiency.

Something to be aware of...

I followed the PWM instructions, came up with several spreadsheets for the calculations, and... it just did not work correctly. 
Both standard and continuous servos are supposed to be triggered with pulses having width ranging from 1 to 2 ms. As seen above, at 60 Hz, that makes 246 to 492 ticks. 
In reality, after many manual trials, for a frequence of 60 Hz, I used:

For the Standard Servo Between 122 & 615 ticks
For the Continuous Servo Between 340 & 410 ticks, stop at 375

Those values are suprisingly different from the theorical ones..., but they work. 
See in the code the classes named adafruiti2c.samples.DemoContinuous and adafruiti2c.samples.DemoStandard
Those are the ones I will use as bases for robotic projects.

Serial Port Sample

Serial Port Sample

This sample has been verified to work with the following configuration:

Windows 10 IoT Core: version 10.0.10586.0Visual Studio: Visual Studio 2015 update 1Windows SDK: version 10586 (Included with Visual Studio Update 1. Check Visual Studio install options)

We’ll create a simple app that allows communication between a desktop and an IoT device over a serial interface.

This is a headed sample. To better understand what headed mode is and how to configure your device to be headed, follow the instructions here.

Load the project in Visual Studio

You can find the C# and C++ versions of this sample here. Make a copy of the folder on your disk and open the project from Visual Studio.

This app is a Universal Windows app and will run on both the PC and your IoT device.

Wiring the serial connection

You have two options for wiring up your board:

  1. using the On-board UART controller
  2. using a USB-to-TTL adapter cable such as this one

On-board UART (MinnowBoard Max)

The MinnowBoard Max has two on-board UARTs. See the MBM pin mapping page for more details on the MBM GPIO pins.

  • UART1 uses GPIO pins 6, 8, 10, and 12.
  • UART2 uses GPIO pins 17 and 19.

In this sample we will use UART2.

Make the following connections:

  • Insert the USB end of the USB-to-TTL cable into a USB port on the PC
  • Connect the GND wire of the USB-to-TTL cable to Pin 1 (GND) on the MBM board
  • Connect the RX wire (white) of the USB-to-TTL cable to Pin 17 (TX) on the MBM board
  • Connect the TX wire (green) of the USB-to-TTL cable to Pin 19 (RX) on the MBM board

Note: Leave the power wire of the USB-to-TTL cable unconnected.

On-board UART (Rasperry Pi2)

The Rasperry Pi2 has one on-board UART. See the Raspberry Pi 2 Pin Mappings page for more details on the MBM GPIO pins.

  • UART0 uses GPIO pins 6 (GND), 8 (TX) and 10 (RX).

Make the following connections:

  • Insert the USB end of the USB-to-TTL cable into a USB port on the PC
  • Connect the GND wire of the USB-to-TTL cable to Pin 6 (GND) on the RPi2 board
  • Connect the RX wire (white) of the USB-to-TTL cable to Pin 8 (TX) on the RPi2 board
  • Connect the TX wire (green) of the USB-to-TTL cable to Pin 10 (RX) on the RPi2 board

Note: Leave the power wire of the USB-to-TTL cable unconnected.

On-Board UART (DragonBoard 410c)

The DragonBoard has two on-board UARTs.

  • UART0 uses GPIO pins 3, 5, 7, and 9.
  • UART1 uses GPIO pins 11 and 13.

In this sample, UART1 will be used. Make the following connections:

  • Insert the USB end of the USB-to-TTL cable into a USB port on the PC
  • Connect the GND wire of the USB-to-TTL cable to pin 1 (GND)
  • Connect the RX wire (white) of the USB-to-TTL cable to pin 11 (UART1 TX)
  • Connect the TX wire (green) of the USB-to-TTL cable to pin 13 (UART1 RX)

NOTE: Leave the power wire of the USB-to-TTL cable unconnected.

Using USB-to-TTL Adapter

Note: Only USB-to-TTL cables and modules with Silicon Labs chipsets are natively supported on MinnowBoard Max and Raspberry Pi2.

You will need:

Make the following connections:

  • Insert the USB end of the USB-to-TTL cable into a USB port on the PC

  • Insert the USB end of the USB-to-TTL module into a USB port on the RPI2 or MBM device

  • Connect the GND pin of the USB-to-TTL module to the GND wire of the USB-to-TTL cable

  • Connect the RX pin of the USB-to-TTL module to the TX wire (green) of the USB-to-TTL cable

  • Connect the TX pin of the USB-to-TTL module to the RX wire (white) of the USB-to-TTL cable

Leave the power pin of the USB-to-TTL cable unconnected. It is not needed.

Below is an image of our USB-to-TTL module connected to a USB port in our RPi2. The GND, TX, and RX pins of the module are connected to the GND, RX, TX wires of the USB-to-TTL cable that is connected to our PC.

Deploy and Launch the SerialSample App

Now that our PC and RPi2 or MBM are connected, let’s setup and deploy the app. If you are not familiar with how to set the target device and target architecture in Visual Studio see this section for details.

  1. Download the Visual Studio 2015 SerialSample source project.

  2. Make two separate copies of the app. We’ll refer to them as the ‘Device copy’ and ‘PC copy’.

  3. Open two instances of Visual Studio 2015 on your PC. We’ll refer to these as ‘Instance A’ and ‘Instance B’.

  4. Open the Device copy of the SerialSample app in VS Instance A.

  5. Open the PC copy of the SerialSample app in VS Instance B.

  6. In VS Instance A, configure the app for deployment to your RPi2 or MBM device)

    *For RPi2, set the target device to ‘Remote Machine’ and target architecture to ‘ARM’

    *For MBM, set the target device to ‘Remote Machine’ and target architecture to ‘x86’

  7. In VS Instance B, set the target architecture to ‘x86’. This will be the instance of the sample we run on the PC.

  8. In VS Instance A, press F5 to deploy and launch the app on your RPi2 or MBM.

  9. In VS Instance B, press F5 to deploy and launch the app on your PC.

Using the SerialSample App

When the SerialSample app is launched on the PC, a window will open with the user interface similar to the screenshot shown below. When launched on the RPi2 and MBM, the SerialSample will display the user interface shown below on the entire screen.

Selecting a Serial Device

When the SerialSample app launches, it looks for all the serial devices that are connected to the device. The device ids of all the serial devices found connected to the device will be listed in the top ListBox of the SerialSample app window.

Select and connect to a serial device on the PC and RPi2 or MBM by doing the following:

  1. Select the desired serial device by clicking on the device ID string in the top ListBox next to “Select Device:”.

    • On the PC, the device ID for the USB-to-TTL cable connected in this example begins with ‘\?\USB#VID_067B’.

    • On the MBM, if using the GPIO for serial communication, select the device ID with UART2 in it. UART1 may require using CTS/RTS signals.

    • On the DragonBoard, select the device with QCOM24D4 and UART1 in it. This will likely be the last device in the listbox (you may need to scroll down).

    • On the MBM and RPi2, if using the USB-to-TTL adapter module, select the device ID that begins with \?\USB#. For the USB-to-TTL module used in this example, the device ID should begin with ‘\?\USB#VID_10C4’.

  2. Click ‘Connect’.

The app will attempt to connect and configure the selected serial device. When the app has successfully connected to the attached serial device it will display the configuration of the serial device. By default, the app configures the serial device for 9600 Baud, eight data bits, no parity bits and one stop bit (no handshaking).

Sending and Receiving Data

After connecting the desired serial device in the SerialSample apps running on both the PC and the RPi2 or MBM we can begin sending and receiving data over the serial connection between the two devices.

To send data from one device to the other connected device do the following:

  1. Choose a device to transmit from. On the transmit device, type the message to be sent in the “Write Data” text box. For our example, we typed “Hello World!” in the “Write Data” text box of the SerialSample app running on our PC.

  2. Click the ‘Write’ button.

The app on the transmitting device will display the sent message and “bytes written successfully!” in the status text box in the bottom of the app display.

The device that is receiving the message will automatically display the text in the ‘Read Data:’ window.

KNOWN ISSUES:

  • When connecting to the USB-to-TTL device for the first time from the IoT Device, you may see the error “Object was not instantiated” when you click on Connect. If you see this, un-plug the device, plug it back in and refresh the connection or redeploy the app.
  • If you have more than one Silicon Labs USB-to-TTL devices connected to your IoT device, only the device that was first connected will be recognized. In order to run this sample, connect only one device
  • When connecting USB-to-TTL device to MinnowBoard Max, use a powered USB hub or the bottom USB port

Let’s look at the code

The code for this sample uses the Windows.Devices.SerialCommunication namespace.

The SerialDevice class will be used to enumerate, connect, read, and write to the serial devices connected to the device.

NOTE: The SerialDevice class can be used only for supported USB-to-TTL devices (on PC, Raspberry Pi 2, and MinnowBoard Max) and the on-board UART (on MinnowBoard Max).

For accessing the serial port, you must add the DeviceCapability to the Package.appxmanifest file in your project.

You can add this by opening the Package.appxmanifest file in an XML editor (Right Click on the file -> Open with -> XML (Text) Editor) and adding the capabilities as shown below:

Visual Studio 2015 has a known bug in the Manifest Designer (the visual editor for appxmanifest files) that affects the serialcommunication capability.  If 
your appxmanifest adds the serialcommunication capability, modifying your appxmanifest with the designer will corrupt your appxmanifest (the Device xml child 
will be lost).  You can workaround this problem by hand editting the appxmanifest by right-clicking your appxmanifest and selecting View Code from the 
context menu.
  <Capabilities>
    <DeviceCapability Name="serialcommunication">
      <Device Id="any">
        <Function Type="name:serialPort" />
      </Device>
    </DeviceCapability>
  </Capabilities>

Connect to selected serial device

This sample app enumerates all serial devices connected to the device and displays the list in the ListBox ConnectDevices. The following code connects and configure the selected device ID and creates a SerialDevice object.

private async void comPortInput_Click(object sender, RoutedEventArgs e)
{
    var selection = ConnectDevices.SelectedItems; // Get selected items from ListBox

    // ...

    DeviceInformation entry = (DeviceInformation)selection[0];         

    try
    {                
        serialPort = await SerialDevice.FromIdAsync(entry.Id);

        // ...

        // Configure serial settings
        serialPort.WriteTimeout = TimeSpan.FromMilliseconds(1000);
        serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000);                
        serialPort.BaudRate = 9600;
        serialPort.Parity = SerialParity.None;
        serialPort.StopBits = SerialStopBitCount.One;
        serialPort.DataBits = 8;

        // ...
    }
    catch (Exception ex)
    {
        // ...
    }
}

Perform a read on the serial port

Reading input from serial port is done by Listen() invoked right after initialization of the serial port. We do this in the sample code by creating an async read task using the DataReader object that waits on the InputStream of the SerialDevice object.

Due to differences in handling concurrent tasks, the implementations of Listen() in C# and C++ differ:

  • C# allows awaiting ReadAsync(). All we do is keep reading the serial port in an infinite loop interrupted only when an exception is thrown (triggered by the cancellation token).
private async void Listen()
{
    try
    {
        if (serialPort != null)
        {
            dataReaderObject = new DataReader(serialPort.InputStream);

            // keep reading the serial input
            while (true)
            {
                await ReadAsync(ReadCancellationTokenSource.Token);
            }
        }
    }
    catch (Exception ex)
    {
        ...
    }
    finally
    {
        ...
    }
}

private async Task ReadAsync(CancellationToken cancellationToken)
{
    Task<UInt32> loadAsyncTask;

    uint ReadBufferLength = 1024;

    // If task cancellation was requested, comply
    cancellationToken.ThrowIfCancellationRequested();

    // Set InputStreamOptions to complete the asynchronous read operation when one or more bytes is available
    dataReaderObject.InputStreamOptions = InputStreamOptions.Partial;

    // Create a task object to wait for data on the serialPort.InputStream
    loadAsyncTask = dataReaderObject.LoadAsync(ReadBufferLength).AsTask(cancellationToken);

    // Launch the task and wait
    UInt32 bytesRead = await loadAsyncTask;
    if (bytesRead > 0)
    {
        rcvdText.Text = dataReaderObject.ReadString(bytesRead);
        status.Text = "bytes read successfully!";
    }            
}
  • C++ does not allow awaiting ReadAsync() in Windows Runtime STA (Single Threaded Apartment) threads due to blocking the UI. In order to chain continuation reads from the serial port, we dynamically generate repeating tasks via “recursive” task creation - “recursively” call Listen() at the end of the continuation chain. The “recursive” call is not a true recursion. It will not accumulate stack since every recursive is made in a new task.
void MainPage::Listen()
{
    try
    {
        if (_serialPort != nullptr)
        {
            // calling task.wait() is not allowed in Windows Runtime STA (Single Threaded Apartment) threads due to blocking the UI.
            concurrency::create_task(ReadAsync(cancellationTokenSource->get_token()));
        }
    }
    catch (Platform::Exception ^ex)
    {
        ...
    }
}

Concurrency::task<void> MainPage::ReadAsync(Concurrency::cancellation_token cancellationToken)
{
    unsigned int _readBufferLength = 1024;
    
    return concurrency::create_task(_dataReaderObject->LoadAsync(_readBufferLength), cancellationToken).then([this](unsigned int bytesRead)
    {
        if (bytesRead > 0)
        {
            rcvdText->Text = _dataReaderObject->ReadString(bytesRead);
            status->Text = "bytes read successfully!";

            /*
            Dynamically generate repeating tasks via "recursive" task creation - "recursively" call Listen() at the end of the continuation chain.
            The "recursive" call is not true recursion. It will not accumulate stack since every recursive is made in a new task.
            */

            // start listening again after done with this chunk of incoming data
            Listen();
        }
    });
}

Perform a write to the serial port

When the bytes are ready to be sent, we write asynchronously to the OutputStream of the SerialDevice object using the DataWriter object.

private async void sendTextButton_Click(object sender, RoutedEventArgs e)
{	
    // ...
	
    // Create the DataWriter object and attach to OutputStream   
    dataWriteObject = new DataWriter(serialPort.OutputStream);

    //Launch the WriteAsync task to perform the write
    await WriteAsync();   
	
    // ..

    dataWriteObject.DetachStream();
    dataWriteObject = null;	
}

private async Task WriteAsync()
{
    Task<UInt32> storeAsyncTask;

    // ...
	
    // Load the text from the sendText input text box to the dataWriter object
    dataWriteObject.WriteString(sendText.Text);                

    // Launch an async task to complete the write operation
    storeAsyncTask = dataWriteObject.StoreAsync().AsTask();

    // ...    
}

Cancelling Read

You can cancel the read operation by using CancellationToken on the Task. Initialize the CancellationToken object and pass that as an argument to the read task.

private async void comPortInput_Click(object sender, RoutedEventArgs e)
{
    // ...

    // Create cancellation token object to close I/O operations when closing the device
    ReadCancellationTokenSource = new CancellationTokenSource();
	
    // ...	
}

private async void rcvdText_TextChanged(object sender, TextChangedEventArgs e)
{
    // ...

    await ReadAsync(ReadCancellationTokenSource.Token);

    // ...	
}

private async Task ReadAsync(CancellationToken cancellationToken)
{
    Task<UInt32> loadAsyncTask;

    uint ReadBufferLength = 1024;

    cancellationToken.ThrowIfCancellationRequested();
    
    // ...
	
}
 
private void CancelReadTask()
{         
    if (ReadCancellationTokenSource != null)
    {
        if (!ReadCancellationTokenSource.IsCancellationRequested)
        {
            ReadCancellationTokenSource.Cancel();
        }
    }         
}

Closing the device

When closing the connection with the device, we cancel all pending I/O operations and safely dispose of all the objects.

In this sample, we proceed to also refresh the list of devices connected.

private void closeDevice_Click(object sender, RoutedEventArgs e)
{
    try
    {
        CancelReadTask();
        CloseDevice();
        ListAvailablePorts(); //Refresh the list of available devices
    }
    catch (Exception ex)
    {
       // ...
    }          
}    

private void CloseDevice()
{            
    if (serialPort != null)
    {
        serialPort.Dispose();
    }    

    // ...
}    

To summarize:

  • First, we enumerate all the serial devices connected and allow the user to connect to the desired one using device ID

  • We create an asynchronous task for reading the InputStream of the SerialDevice object.

  • When the user provides input, we write the bytes to the OutputStream of the SerialDevice object.

  • We add the ability to cancel the read task using the CancellationToken.

  • Finally, we close the device connection and clean up when done.