This repository utilizes the Yocto Project's Poky reference distribution to a create the core-image-base
image for the Raspberry Pi 4 with a custom layer (meta-machine-control) that contains the necessary recipes to include the unleashing_grpc Flutter backend and frontend applications as services. The OS itself is very simple and is responsible for three things:
- Connecting to the network (via wifi or ethernet)
- Spinning up the
unleashing-grpc-backend.service
, which spins up a gRPC server and controls the state of the connected LED - Spinning up the
unleashing-grpc-frontend.service
, which spins up a Flutter application that connects to the gRPC server and allows the user to control the state of the connected LED
Note: if you are interested in learning more about embedded Flutter, checkout the meta-flutter repository and the "Getting Started with Flutter for Embedded Linux" blog!
This repository is referenced in the "Unleashing gRPC" blog series. Check out the blogs for more information on what is being built!
Part 1: Getting Started with Machine Control Using Flutter and gRPC
Part 2: Diving Deeper into Machine Control Using Flutter with gRPC
⚠️ Yocto Project tooling is required to run in a Linux environment. If you are on Windows or an Intel-based Mac, you will need to setup a Linux environment. Please note that, although this is tooling in this repository to facilitate developing on Windows/MacOS, full support is not guaranteed.
See the Dockerfile for the full list of dependencies if you are on a Linux host.
If you are on a Windows 11 (or 10) host, see windows_11_setup_steps.md for instructions on setting up your environment.
Clone this repository:
git clone --recursive [email protected]:lapumb-spindance/machine-control-os.git
Note: if you do not add the
--recursive
flag, run./tools/update_submodules.sh
once the repository has successfully been cloned.
This repository utilizes Yocto Project tooling that is required to be run in a Linux environment. Since not everyone has access to a Linux machine, this repository has been containerized using Visual Studio Code Remote Containers. This allows you to develop in a Linux environment without having to install Linux on your machine.
If you choose to use a containerized environment for development, the following dependencies must be installed:
MacOS:
brew install node
npm install -g @devcontainers/cli
Linux / WSL2:
Note: along with the following dependencies, if you are working in WSL(2) and have not already done so, it is probably a good idea to hike up your resources. For example, on a machine with 16GB RAM and 20 (logical) cores, you may want a configuration like the following in your
${env:USERPROFILE}\.wslconfig
:[wsl2] memory=14GB swap=4GB processors=18
See the Microsoft documentation for more information about the
.wslconfig
.
sudo apt install nodejs npm -y
sudo npm cache clean -f
sudo npm install -g n
sudo n stable
sudo npm install -g @devcontainers/cli
Docker Desktop must also be installed and running. Make sure you are signed into a docker account (free is fine) and docker is running.
Note: before proceeding, make sure you have the Dev Containers Extension installed and enabled in Visual Studio Code.
To utilize the container defined in this repository, open this repository in Visual Studio Code. You will likely be greeted with a prompt to "Reopen in Container". If so, click the "Reopen in Container" button, which will create a Docker container (if necessary) and mount you at the location of this repository in the container filesystem. If not, open the command palette (Mac: Cmd+Shift+P
, Windows: Ctrl+Shift+P
) and search for "Remote-Containers: Reopen in Container". A new VSCode window will open with the container running, where you can execute all your git
commands and run the Yocto Project tooling.
If you do not want to use VSCode, you can still use the containerized environment. From the root of this repository, run the following command, which will create a Docker container (if necessary) and mount you at the location of this repository in the container filesystem:
./.devcontainer/enter_container.sh
To exit the container, enter the
exit
command.
It has been observed that errors occur when attempting to enter the container in VS Code after having already entered the container from the command line (and / or vice-versa). If you run into this issue, delete the image / container that was spun up by the other method and try again. That said, it is probably best to stick to one method of entering the container until we figure out a more graceful solution.
Don't want to use a Docker container to build? No problem! See the Yocto Project Quick Start for setting up either your native Linux host.
Once you have your Linux environment setup, it is time to setup the project environment by sourcing the .envrc
file:
source .envrc
This can be done manually, or you can use direnv (sudo apt install direnv
) to automatically source this file when you enter the project directory.
Note: if using
direnv
, ensure the tool is properly hooked into your shell.
The .envrc
file also sources a .userenv
file if one is available. This file is ignored by git, so you can add any custom environment variables or overwrite any existing environment variables you see fit. For an example .userenv
file, see the example file.
Two particularly useful environment variables suggested to export
in the .userenv
file are NETWORK_SSID
and NETWORK_PASSWORD
. These variables are used to configure wpa_supplicant
on the image so the Raspberry Pi automatically connects to your network upon boot.
This repository is setup in a way that makes it simple for multiple developers to contribute to the same project. In order to achieve this, several custom environment variables have to be sent to bitbake
to map dynamic paths correctly. Because of this, using the raw bitbake
command will not work. Instead, utilize the execute_bitbake.sh
script to properly source the environment variables and execute bitbake
:
./execute_bitbake <additional_args_here>
Note: this script is used within the build.sh. Do not use this script directly unless you are experienced with the Yocto Project tooling.
Once you have your environment setup and your hardware connected, it is time to build and flash the image to a uSD card. Building has been simplified to a build.sh
script, which will build the core-image-base
image by default. To build the image, simply run ./build.sh
.
Once the build completes successfully, you can flash the image to a uSD card by running ./flash.sh
if you are working on a native Linux machine. This script will automatically detect the newest image, but you also have the option to supply a specific image. Run ./flash.sh -h
for more information.
If you are not on a native Linux machine, use the following for flashing:
- Windows: rufus
Keep the default options, but when "SELECT"ing a file, make sure to change the filter to
All files (*.*)
. When you plug in your uSD card, Windows will complain. Only focus on therufus
application and do not do anything with any explorer windows that pop up. - MacOS: balenaEtcher
Since this repository builds an image that is intended to run on the Raspberry Pi 4b, you could also use the Raspberry Pi Imager to flash the image.
- Raspberry Pi 4b
This repository sets the
MACHINE
variable toraspberrypi4
by default. Theoretically, any Raspberry Pi Single Board Computer (SBC) should work. If you opt to go with a different Raspberry Pi SBC,export MACHINE=<your_machine_here>
in your.userenv
file after finding your machine name here. - uSD card
The generated
.wic
image is < 600MB, so a 2GB uSD card should be sufficient, but it's always nice having a larger card laying around for future projects. - USB-C power supply
- Micro HDMI to HDMI cable (or adapter if you have an extra HDMI already laying around)
- Waveshare 7" Capacitive Touch Display
Having a touchscreen display is not a necessity, but it is nice to actually interact with the device. If you opt to use a different HDMI display, you may want a USB mouse to interact with the UI.
- Breadboard kit
- (Optional for debugging) USB to TTL Serial Cable
I like the ESP-Prog, but any USB to TTL Serial Cable should work. This is used to monitor the serial output of the Raspberry Pi.
- (Optional) Ethernet cable
If you do not have a wireless network or do not have an TTL cable to setup your credentials, you can use an ethernet cable to connect the Raspberry Pi to your network.
To hook up your LED to the Raspberry Pi, plug a 5mm LED into the breadboard and connect the longer leg (anode) to GPIO 6 (pin 31) and the shorter leg (cathode) to a 10KΩ resistor, which is then connected to a ground pin (pin 39). See the Raspberry Pi Pinout for exact pin locations.
If you opt to use a different GPIO pin, be sure to set the correct
LED_GPIO=<your_gpio_here>
in thelocal.conf
file.
On the ESP-Prog, we will use the 6-pin breakout section. Below is the pin layout for this section (x
's denote pins we don't care about):
+--------------+
| x GND x |
| x TX RX |
+----- -----+
NOTE: Notice the orientation of the break in the bottom of the wall around these pins; please make sure when you are wiring this, that break is facing down/south.
Once you have wires connected to those pins, please connect them to their respective pins on the Raspberry Pi breakout header:
+-----------+
| x x |
| x x |
| x GND |
| x TX |
| x RX |
| x x |
| .. .. |
+-----------+
NOTE: When looking at the Raspberry Pi, the above diagram assumes an orientation where the pins on the right side of the board.
Once the connections are made, you can monitor serial output from your Raspberry Pi by executing picocom
(sudo apt install picocom
), minicom
(sudo apt install minicom
), or any other serial monitoring tool of your choice after finding your device (ls /dev/ttyUSB*
) and setting the baud rate to 115200
:
# To exit picocom, press Ctrl+A followed by Ctrl+X.
picocom -b 115200 /dev/ttyUSB1
-
The first build will take a long time. Subsequent builds will be faster due to the caching mechanism of the Yocto Project.
-
If the image was built without wifi credentials, use the following command after creating an TTL connection to the Raspberry Pi:
# Setup wifi credentials in the wpa_supplicant.conf file wpa_passphrase "NETWORK_SSID" NETWORK_PASSWORD >> /etc/wpa_supplicant.conf # Reconfigure the wpa_supplicant service wpa_cli reconfigure
Take note of the lack of quotes around
NETWORK_PASSWORD
in the command above. This is intentional as thewpa_passphrase
command will include the quotes in the generated PSK. -
The
unleashing-grpc-backend.service
will not start until an IP is obtained onwlan0
which could take a minute or so. This is because the gRPC server needs a connection in order to serve.
- Yocto Project Documentation
- OpenEmbedded Layers Index
- DigiKey Yocto Project Introduction
The first video in the series is focused on buildroot, but the rest of the videos are focused on the Yocto Project.
Want to contribute to this repository? Feel free to open a pull request, file an issue, or make a suggestion!