Skip to content

Software Setup and the Developer Environment on the Raspberry Pi 5

Summary

This chapter sets up the software development environment used across the Pi 5 AI projects in later chapters. It covers Python virtual environments and package dependency management, installing libraries, and version control with Git and GitHub. It also covers code editors (including VS Code running on the Pi), file transfer, and headless setup for running a Pi 5 without a monitor attached. Students finishing this chapter will be able to set up an isolated Python environment, manage a project with Git, and configure a Pi 5 for headless operation.

Concepts Covered

This chapter covers the following 14 concepts from the learning graph:

  1. Operating System Image
  2. Cross Compilation
  3. Python Virtual Environment
  4. Package Dependency
  5. Library Installation
  6. Version Control
  7. Git Basics
  8. GitHub Repository
  9. Code Editor
  10. VS Code On Pi
  11. File Transfer Protocol
  12. Headless Setup
  13. Case And Ventilation
  14. Storage Benchmark

Prerequisites

This chapter builds on concepts from:


Setting Up Shop

Berry waving welcome You picked out the hardware last chapter — storage, camera, cooling, all sorted. Now it's time to make that hardware actually usable for real projects: an operating system on the storage, a way to reach the Pi without a monitor plugged in, and a clean, organized way to write and track your code. Let's build something!

A powerful board is only as useful as the software workflow built on top of it. This chapter walks through that workflow from the very first step — putting an operating system onto storage — through the habits you'll lean on in every AI project later in this book: working without a monitor attached, editing code remotely, keeping Python projects isolated from each other, and tracking your work with version control. None of this is exclusive to the Pi 5; the same workflow works on the Pi 500+ too. But it matters most here, because the AI vision and audio projects coming up need a development setup that's fast, reliable, and reproducible.

Flashing an Operating System Image

Before a Pi 5 can do anything, it needs an operating system on its storage. An operating system image is a single file containing a complete, ready-to-boot copy of an operating system — every system file, default setting, and startup program — that gets copied byte-for-byte onto microSD or NVMe storage rather than installed step by step the way you might install software on a regular computer. Raspberry Pi Imager, the official tool for this job, writes that image directly onto the storage device you plug into your everyday laptop, and lets you pre-configure details like the Wi-Fi network, username, and password before the Pi ever boots for the first time.

Here's a question worth asking: who builds that operating system image in the first place, and on what computer? Raspberry Pi OS is based on Linux, and it's compiled — translated from human-readable source code into the machine instructions a processor actually runs — on powerful desktop and server computers, not on the Pi itself. That's possible because of cross compilation: the process of compiling software on one type of computer (the "host," typically a fast desktop with an x86 processor) to produce a program that runs on a different type of computer (the "target," in this case the Pi's ARM processor). Cross compilation is why a fresh operating system image is available to download and flash the same day new Pi hardware ships — the heavy lifting of building it happened elsewhere, on hardware built for the job.

Berry's Tip

Berry sharing a tip Raspberry Pi Imager offers a "Lite" operating system image alongside the full desktop version — no desktop, no browser, just the terminal. For a Pi 5 you plan to run headless as a dedicated vision or audio project, Lite boots faster and leaves more memory free for your actual program.

Booting Without a Monitor: Headless Setup

Plenty of Pi 5 projects in this book don't need a monitor at all — a camera pointed at a birdfeeder, or a sound-recognition box tucked in a corner, works better without a screen and keyboard permanently attached. Headless setup is the practice of configuring and operating a computer entirely without a directly connected monitor, keyboard, or mouse, controlling it instead from another computer over a network connection. Raspberry Pi Imager supports this directly: before flashing, you can pre-set the Wi-Fi credentials and enable remote access, so the Pi joins your network and becomes reachable the moment it finishes its first boot.

The standard way to reach a headless Pi is SSH — Secure Shell — a protocol that gives you a full command-line session on the remote machine, exactly as if you had a keyboard plugged directly into it. Once you know the Pi's network address, connecting looks like this from your everyday laptop's own terminal:

ssh pi@raspberrypi.local

That command's two parts matter: pi is the username to log in as, and raspberrypi.local is the Pi's network address, using its hostname rather than a numeric IP address that might change. After entering the password you set during imaging, you land in a terminal running directly on the Pi 5 — every command from here behaves exactly as if you were sitting in front of it with its own keyboard.

Working headless still means moving files back and forth between your everyday computer and the Pi — a Python script you wrote locally, or a captured image you want to pull off the Pi to inspect. A file transfer protocol is a defined set of rules for copying files between two computers over a network connection, and scp — secure copy, built on the same secure connection SSH uses — is the one you'll reach for most often in this book:

scp my_script.py pi@raspberrypi.local:/home/pi/projects/

This copies my_script.py from your local machine to the /home/pi/projects/ folder on the Pi. Reversing the two arguments copies a file from the Pi back to your local machine instead.

Berry's Gentle Warning

Berry warning The very first thing to do after logging into a fresh headless Pi is change the default password. A Pi reachable over the network with a default or guessed password is a real security risk, not a hypothetical one — treat this step as mandatory, not optional, before you do anything else.

Before the diagram, it helps to see the full headless path as one sequence rather than three separate facts: flash the image with credentials pre-configured, boot without a monitor, then reach the Pi and move files over the network.

Diagram: Headless Pi 5 Setup Workflow

Run the Headless Pi 5 Setup Workflow MicroSim fullscreen

Headless Pi 5 Setup Workflow (interactive workflow diagram)

Type: workflow sim-id: headless-pi5-setup-workflow
Library: p5.js
Status: Specified

Learning objective: Students will sequence (Bloom L3: Apply) the steps required to set up and connect to a Raspberry Pi 5 without a directly attached monitor.

Canvas: 700x420px, responsive — recompute step-box spacing as a fraction of width inside windowResized(), switching from a horizontal row to a vertical stack below 560px wide.

Layout: four connected step boxes in sequence: "1. Flash OS Image" (with Wi-Fi and SSH pre-configured) → "2. First Boot" (no monitor attached) → "3. Connect via SSH" → "4. Transfer Files via scp." Each box uses a distinct accent color from the book palette (indigo #3F51B5, raspberry #C2185B, circuit green #2E7D32, copper gold #D4AF37) and a small icon drawn with basic p5.js shapes.

Controls: a createButton() labeled "Walk Through Steps" that advances a highlighted marker from box 1 to box 4 one click at a time, and a createButton() labeled "Reset" that returns the marker to before box 1.

Interaction: clicking any step box directly (independent of the walkthrough button) opens an infobox beneath the diagram showing the exact terminal command associated with that step (for steps 3 and 4, the ssh and scp commands from the surrounding chapter text) and one sentence explaining what could go wrong at that step (for example, step 3's infobox notes "Fails here if Wi-Fi credentials were mistyped during imaging"). Only one infobox is open at a time.

Implementation: p5.js. Step data stored as an array of four objects {title, color, command, commonFailure}. Hit-testing via rectangular bounding boxes. Track the walkthrough marker's current index in a variable and redraw its position each frame based on that index, interpolating smoothly between box centers using lerp().

A Case for Airflow: Enclosures and Ventilation

The previous chapter covered active cooling and heat sinks directly on the board, but the enclosure around that board matters just as much and is easy to overlook. Case and ventilation refers to the physical enclosure around a Pi 5 and the airflow paths designed into it — vents, gaps, or an internal fan mount — that let heat actually leave the case instead of building up inside it. A heat sink or an active cooling fan can only move heat as far as the inside surface of a sealed case; if that case has no way for warm air to escape and cooler air to enter, heat simply accumulates inside the enclosure until the processor throttles anyway, defeating the cooling hardware entirely.

This matters most for exactly the headless setups this section just covered: a birdfeeder camera or an audio-recognition box often ends up in an enclosure chosen for looks or weather protection rather than airflow, and that choice can quietly undo a well-cooled board. When you're selecting or designing a case for a Pi 5 project, check that it doesn't fully enclose the active cooling fan's intake and exhaust, and prefer a case with vents over one that's fully sealed unless it's specifically rated for passive cooling at your board's expected workload.

Writing Code: Editors and Remote Development

With the Pi reachable over SSH, the next question is how you actually want to write code against it. A code editor is software built for writing and editing source code, offering features like syntax highlighting, error checking, and file management that a plain text editor lacks. You already have options from earlier chapters — Thonny, used throughout the Pico chapters, is a code editor built specifically to be simple and beginner-friendly.

For Pi 5 projects, many makers switch to a more full-featured editor: VS Code on Pi refers to running Microsoft's Visual Studio Code editor either directly on the Pi 5's desktop, or — more commonly for a headless setup — on your everyday laptop while it connects to the Pi over SSH through a "Remote-SSH" extension. In that remote mode, the editor's interface runs locally on your laptop, but every file you open, every terminal you run, and every Python interpreter you use is the Pi's own, not your laptop's. That distinction matters: you get your laptop's comfortable screen and keyboard, while your code actually executes on the Pi hardware it's meant for, with direct access to the camera, GPIO header, and AI HAT+ covered in later chapters.

Berry's Key Insight

Berry thinking Remote development is really just the headless workflow you already learned, wearing a nicer outfit. Under the hood, VS Code's Remote-SSH extension is opening the same kind of SSH connection you'd type by hand — it just wraps that connection in file browsing, syntax highlighting, and a built-in terminal so you don't have to juggle separate ssh and scp commands for every single edit.

Diagram: VS Code Remote Development Architecture

Run the VS Code Remote Development Architecture MicroSim fullscreen

VS Code Remote Development Architecture (interactive diagram)

Type: interactive-diagram sim-id: vscode-remote-dev-architecture
Library: p5.js
Status: Specified

Learning objective: Students will explain (Bloom L2: Understand) which parts of a remote-development workflow run on the local laptop and which parts run on the Raspberry Pi 5.

Canvas: 700x420px, responsive — two labeled zones ("Your Laptop" and "Raspberry Pi 5") recomputed as fractions of width, stacked vertically below 560px wide instead of side by side.

Layout: left zone "Your Laptop" contains a box labeled "VS Code Window (editor UI, keyboard, screen)"; right zone "Raspberry Pi 5" contains three boxes labeled "Your Python Files," "Python Interpreter," and "GPIO / Camera / AI HAT+ Hardware." A dashed line labeled "SSH Connection" links the laptop zone to the Pi zone.

Interaction: clicking any box highlights it and opens an infobox stating in one sentence whether that component runs locally or remotely and why (for example, clicking "Python Interpreter" shows "Runs on the Pi — so your code can directly reach hardware like the camera and GPIO header without any extra network step"). A toggle createButton() labeled "Where does typing happen?" animates a small dot traveling from the laptop's VS Code box, across the dashed SSH line, into the Pi's file box, to visualize that every keystroke is relayed over the network connection rather than staying local.

Implementation: p5.js. Store the six components (one laptop box, three Pi boxes, the SSH line, the animated dot) with fixed relative positions computed from zone bounding boxes each windowResized() call. Hit-testing via rectangular bounds. Animate the dot along a simple linear or bezier path using an accumulating progress variable advanced each frame, resetting after reaching the destination.

Keeping Python Projects Clean: Virtual Environments and Dependencies

Every Python project in the AI chapters ahead needs specific external code libraries — for camera access, for talking to the AI HAT+, for image processing. A library installation is the act of adding a piece of pre-written, reusable code to your Python environment so your own program can import and use it instead of writing that functionality from scratch. Most libraries aren't standalone; they depend on specific versions of other libraries to function correctly. A package dependency is a relationship where one piece of installed software requires another specific package — often a specific version of it — to be present in order to run.

Dependencies create a real problem the moment you work on more than one project: if Project A needs version 1 of a library and Project B needs version 2 of that same library, installing both directly onto the Pi's system-wide Python installation creates a conflict where satisfying one project breaks the other. A Python virtual environment solves this by creating an isolated, self-contained copy of the Python interpreter and its installed libraries for a single project, completely separate from the system-wide Python installation and from any other project's virtual environment. Each project gets its own sandbox; installing or upgrading a library inside one virtual environment has zero effect on any other.

Creating and using one takes three short commands, worth walking through before you see them: the first creates a new virtual environment folder named env; the second activates it, so that any Python command you run afterward uses this isolated environment instead of the system-wide one; the third installs a library — in this example, the popular NumPy numerical computing library — into that isolated environment specifically.

python3 -m venv env
source env/bin/activate
pip install numpy

Once activated, your terminal prompt usually changes to show the environment's name, a visual reminder of which sandbox you're currently working inside.

Berry's Key Insight

Berry thinking A virtual environment is the software equivalent of giving every project its own toolbox instead of one shared toolbox for the whole workshop. Nobody accidentally walks off with the screwdriver another project needed.

Diagram: Python Virtual Environment Sandbox Explorer

Run the Python Virtual Environment Sandbox Explorer MicroSim fullscreen

Python Virtual Environment Sandbox Explorer (interactive infographic)

Type: interactive-infographic sim-id: python-venv-sandbox-explorer
Library: p5.js
Status: Specified

Learning objective: Students will explain (Bloom L2: Understand) how a Python virtual environment isolates one project's package dependencies from another project's.

Canvas: 700x460px, responsive — recompute box positions as fractions of width/height inside windowResized(), stacking the two project boxes vertically below 560px wide instead of side by side.

Layout: a "System Python" box at the top, with two separate boxed "sandboxes" below it labeled "Project A: venv (numpy 1.x)" and "Project B: venv (numpy 2.x)," each drawn with a distinct border color (indigo #3F51B5 and raspberry #C2185B). Small package icons (simple labeled circles) sit inside each sandbox, showing that each has its own copy of shared library names, possibly at different version numbers.

Interaction: clicking "Install numpy 1.x" or "Install numpy 2.x" buttons (createButton(), one per sandbox) animates a package icon dropping into that sandbox only, while the other sandbox and the System Python box visibly remain unchanged — demonstrating that the install has no effect outside its own sandbox. A createButton() labeled "Reset Sandboxes" empties both sandboxes back to their starting state. Hovering any package icon shows a tooltip with its exact version number.

Implementation: p5.js. Each sandbox tracked as an array of installed package objects {name, version}. Button clicks push a new object into the clicked sandbox's array only. Redraw all packages inside their sandbox's bounding box each frame from that sandbox's array, arranging them in a simple grid that grows as packages are added.

Tracking Changes: Version Control with Git and GitHub

Every project in this book benefits from one more habit: never losing work, and always being able to see what changed and when. Version control is a system for recording changes to a set of files over time, so you can review the history of those changes, compare versions, and recover an earlier version if something breaks. Git basics covers the core commands of Git, the version control tool used throughout this book: git init creates a new repository in the current folder, git add stages specific changed files to be included in the next snapshot, and git commit permanently records that snapshot, along with a short message describing what changed, into the project's history.

git init
git add my_script.py
git commit -m "Add first draft of camera capture script"

Git tracks history on your own machine, but a GitHub repository extends that history to a remote server, giving your project a backup that survives even if your Pi's storage fails, and a shareable link a teacher or teammate can view or contribute to. Pushing your local Git history to a GitHub repository — after creating an empty one on GitHub's website and linking it as a "remote" — is how your local commits actually reach that shared copy.

Now that both the local and remote sides are defined, it helps to see them as one continuous path rather than two separate systems.

Diagram: Git and GitHub Workflow

Run the Git Workflow MicroSim fullscreen

Git Workflow (reused MicroSim)

Type: workflow sim-id: git-workflow-diagram
Library: Mermaid
Status: Reused
Source: https://dmccreary.github.io/moving-rainbow/sims/git-workflow-diagram/
Source Repo: https://github.com/dmccreary/moving-rainbow/tree/main/docs/sims/git-workflow-diagram

Reused from the MicroSim catalog (WHAT match score 0.75). Learning objective: Students will describe (Bloom L2: Understand) the three locations where Git stores data — working directory, local repository, and GitHub — and which command moves data between each.

You've Got This!

Berry encouraging you Git's vocabulary — stage, commit, push, remote — can feel like a wall of new words the first time through. You don't need to memorize every command today. Run git add, git commit, and git push a few times on real projects in this book, and the pattern clicks faster than you'd expect.

Berry's Tip

Berry sharing a tip Write commit messages for your future self, not for right now. "Fixed bug" tells you nothing three weeks later; "Fix camera capture crashing when no card is inserted" tells you exactly what changed and why, even after you've forgotten the details.

Measuring What You Built: Storage Benchmarks

Back in the hardware chapter, the storage comparison table described microSD, USB 3.0, and NVMe storage in general terms. Now that you have a working terminal and a headless Pi 5 to run commands on, you can measure the real difference yourself rather than taking the table's word for it. A storage benchmark is a controlled test that measures a specific storage device's read or write speed under a repeatable, defined workload, producing a number you can compare directly against another device tested the same way.

A simple benchmark uses the dd command to time how long it takes to write a fixed amount of data to a storage device:

dd if=/dev/zero of=testfile bs=1M count=512 conv=fsync

This command writes 512 one-megabyte blocks of zero-bytes to a file named testfile, forcing the write all the way to physical storage (conv=fsync) rather than letting it sit in a memory cache, and reports the total time taken and the effective write speed once it finishes. Running this same command against a microSD card and then against an NVMe drive, and comparing the reported speeds, turns the earlier chapter's storage table from an abstract comparison into a number you measured yourself on your own hardware.

Diagram: Storage Benchmark Results Chart

Run the Storage Benchmark Results Chart MicroSim fullscreen

Storage Benchmark Results Chart (interactive chart)

Type: chart sim-id: storage-benchmark-results-chart
Library: Chart.js
Status: Specified

Learning objective: Students will interpret (Bloom L3: Apply) a dd-style storage benchmark result to decide which storage option best fits a given Pi 5 project.

Chart type: bar chart, responsive Chart.js canvas.

Purpose: show sample write-speed results (in megabytes per second) from running the chapter's dd benchmark command against three real storage devices, letting students connect the earlier abstract storage comparison to concrete measured numbers.

X-axis: three device categories — "MicroSD Card," "USB 3.0 External Drive," "NVMe via PCIe."

Y-axis: measured write speed in megabytes per second (MB/s).

Data series: a single bar per device using representative sample values (microSD lowest, USB 3.0 in the middle, NVMe clearly highest), colored gray, indigo #3F51B5, and circuit green #2E7D32 respectively, matching the color convention from the Chapter 14 storage chart.

Interaction (required): a <select> control lets students pick a hypothetical project ("Text-based script," "Photo capture project," "Real-time video project") which redraws a horizontal threshold line on the chart marking the minimum write speed that project needs, so students can see which bars clear the bar for their chosen use case. Hovering any bar shows its exact MB/s value in a tooltip.

Implementation: Chart.js bar chart with responsive: true and maintainAspectRatio: false. Store the three threshold values keyed by project type and redraw the annotation line (via a Chart.js annotation plugin or a manually drawn overlay line) on the <select>'s change event, then call chart.update().

Here's how the concepts from this section line up against the ones from the storage comparison two chapters back.

Term What It Measures Where You Use It
Storage Benchmark Actual read/write speed on your own hardware Confirming a storage choice before committing a real project to it
Operating System Image The complete bootable system written to that storage The very first thing placed on a fresh card or drive
Case and Ventilation Whether heat generated during heavy storage/CPU use can escape Selecting or designing an enclosure for a benchmark-passing setup

Bringing It Together

You now have a complete Pi 5 software workflow: an operating system flashed and configured for headless use, a way to reach the board and move files over the network, a remote-capable code editor, isolated Python environments for each project, and Git tracking every change with a GitHub repository backing it up. That workflow is what makes the rest of this book's Pi 5 projects manageable instead of chaotic. The next chapter puts this environment to work on something genuinely new: the AI HAT+ accelerator and the neural network vocabulary you'll need to understand what it actually speeds up.

You Unlocked a Superpower!

Berry celebrating That's berry organized work! You've now got a development setup a professional maker would recognize — headless access, isolated environments, and version control watching your back. STEM is our superpower, and this one's now yours. Let's build something — see you in Chapter 16!

See Annotated References