Raspberry Pi 入門與環境建置
什麼是 Raspberry Pi?
💡 比喻:一台信用卡大小的電腦 想像你把一台桌上型電腦壓縮到跟信用卡一樣大—— 它有 CPU、記憶體、USB、HDMI、WiFi,什麼都有, 但只要一千多塊台幣就能買到。 Raspberry Pi 就是這樣的「迷你電腦」, 可以跑 Linux、裝 .NET、當伺服器,甚至做 POS 收銀機!
Raspberry Pi 的核心概念
Raspberry Pi 就像一台「迷你伺服器」:
傳統伺服器 Raspberry Pi
─────────────────────────────────────────────
大小:一個機櫃 大小:一張信用卡
價格:數萬元 價格:約 1,000~3,000 元
電力:數百瓦 電力:5~15 瓦
用途:企業級服務 用途:IoT、POS、學習、原型開發
雖然效能不如正式伺服器,但用來做 POS 系統綽綽有餘!
型號比較(Pi 4, Pi 5, Pi Zero)
型號 CPU RAM 價格(USD) 適合用途
──────────────────────────────────────────────────────────────────
Pi Zero 2 W 四核 1GHz 512MB $15 簡單感測器、LED 控制
Pi 4 Model B 四核 1.5GHz 2/4/8GB $35~$75 POS 系統、Web 伺服器
Pi 5 四核 2.4GHz 4/8GB $60~$80 高效能應用、多媒體
💡 做 POS 系統建議至少用 Pi 4(4GB RAM)
Pi 5 效能更好,但 Pi 4 已經夠用了
用 C# 來理解型號差異
// 定義 Raspberry Pi 型號的列舉 // 列出所有常用型號
public enum PiModel // Pi 型號列舉
{
PiZero2W, // Pi Zero 2 W:最小最便宜 // 適合簡單 IoT
Pi4B, // Pi 4 Model B:主流選擇 // 適合 POS 系統
Pi5 // Pi 5:最新最強 // 適合高效能需求
}
// 定義 Raspberry Pi 規格的類別 // 描述硬體資訊
public class PiSpec // Pi 規格類別
{
public PiModel Model { get; set; } // 型號 // 哪一款 Pi
public string Cpu { get; set; } = ""; // CPU 規格 // 處理器資訊
public int RamMb { get; set; } // 記憶體(MB)// RAM 大小
public decimal PriceUsd { get; set; } // 價格(美元)// 售價
public bool HasWifi { get; set; } // 是否有 WiFi // 無線網路支援
public bool HasBluetooth { get; set; } // 是否有藍牙 // 藍牙支援
}
// 取得各型號規格的方法 // 回傳規格清單
public static List<PiSpec> GetAllSpecs() // 取得所有 Pi 規格
{
return new List<PiSpec> // 建立規格清單
{
new() // Pi Zero 2 W 的規格
{
Model = PiModel.PiZero2W, // 設定型號為 Zero 2 W
Cpu = "Quad-core 1GHz ARM Cortex-A53", // 四核心 1GHz 處理器
RamMb = 512, // 512MB 記憶體
PriceUsd = 15m, // 售價 15 美元
HasWifi = true, // 有 WiFi
HasBluetooth = true // 有藍牙
},
new() // Pi 4 Model B 的規格
{
Model = PiModel.Pi4B, // 設定型號為 Pi 4B
Cpu = "Quad-core 1.5GHz ARM Cortex-A72", // 四核心 1.5GHz 處理器
RamMb = 4096, // 4GB 記憶體(建議版本)
PriceUsd = 55m, // 售價 55 美元
HasWifi = true, // 有 WiFi
HasBluetooth = true // 有藍牙
},
new() // Pi 5 的規格
{
Model = PiModel.Pi5, // 設定型號為 Pi 5
Cpu = "Quad-core 2.4GHz ARM Cortex-A76", // 四核心 2.4GHz 處理器
RamMb = 8192, // 8GB 記憶體(建議版本)
PriceUsd = 80m, // 售價 80 美元
HasWifi = true, // 有 WiFi
HasBluetooth = true // 有藍牙
}
}; // 回傳完整清單
}
安裝 Raspberry Pi OS
💡 比喻:幫電腦裝 Windows,只不過這次裝的是 Linux Raspberry Pi OS 就是 Pi 專用的作業系統, 基於 Debian Linux,操作方式跟 Ubuntu 很像。 用 Raspberry Pi Imager 燒錄到 SD 卡,插上去就能開機。
安裝步驟
# 步驟 1:下載 Raspberry Pi Imager // 到官網下載燒錄工具
# https://www.raspberrypi.com/software/ // 官方下載頁面
# 步驟 2:選擇作業系統 // 選 Raspberry Pi OS (64-bit)
# Raspberry Pi OS (64-bit) with Desktop // 有桌面環境的版本
# 步驟 3:選擇目標 SD 卡 // 至少 16GB 的 microSD 卡
# 建議使用 32GB 以上的高速 SD 卡 // Class 10 或 U1 以上
# 步驟 4:進階設定(齒輪圖示)// 設定主機名稱和帳號
# 設定主機名稱 // 例如:pos-terminal-01
# 設定使用者帳號和密碼 // 建議不要用預設的 pi / raspberry
# 啟用 SSH // 這樣才能遠端連線
# 設定 WiFi // 輸入你的 WiFi SSID 和密碼
# 步驟 5:燒錄 // 點擊「Write」開始燒錄
# 等待完成後插入 Pi 的 SD 卡槽 // 接上電源就能開機
用 C# 模擬安裝流程
// 定義 Pi 安裝設定的類別 // 描述安裝時需要的參數
public class PiSetupConfig // Pi 安裝設定
{
public string Hostname { get; set; } = "pos-terminal-01"; // 主機名稱 // 設備識別名稱
public string Username { get; set; } = "admin"; // 使用者帳號 // 登入用的帳號
public string Password { get; set; } = ""; // 密碼 // 登入用的密碼
public bool EnableSsh { get; set; } = true; // 啟用 SSH // 遠端連線必須開啟
public string WifiSsid { get; set; } = ""; // WiFi 名稱 // 無線網路 SSID
public string WifiPassword { get; set; } = ""; // WiFi 密碼 // 無線網路密碼
public string OsVersion { get; set; } = "Raspberry Pi OS 64-bit"; // 作業系統版本 // 選擇 64 位元版
public int SdCardSizeGb { get; set; } = 32; // SD 卡大小 // 至少 16GB
}
// 驗證安裝設定是否正確 // 檢查必填欄位
public static List<string> ValidateConfig(PiSetupConfig config) // 驗證設定方法
{
var errors = new List<string>(); // 建立錯誤清單 // 收集所有錯誤訊息
if (string.IsNullOrEmpty(config.Hostname)) // 檢查主機名稱是否為空
errors.Add("主機名稱不可為空"); // 新增錯誤訊息
if (string.IsNullOrEmpty(config.Password)) // 檢查密碼是否為空
errors.Add("密碼不可為空"); // 安全性要求必須設定密碼
if (config.Password == "raspberry") // 檢查是否使用預設密碼
errors.Add("請勿使用預設密碼 raspberry"); // 預設密碼不安全
if (config.SdCardSizeGb < 16) // 檢查 SD 卡大小
errors.Add("SD 卡至少需要 16GB"); // 空間不足會導致安裝失敗
if (!config.EnableSsh) // 檢查 SSH 是否啟用
errors.Add("建議啟用 SSH 以便遠端管理"); // SSH 是遠端管理的關鍵
return errors; // 回傳錯誤清單 // 空清單表示設定正確
}
SSH 遠端連線設定
💡 比喻:遠端遙控你的 Pi SSH 就像是一條「隱形的線」,讓你用自己的電腦 遠端操控 Raspberry Pi,不需要額外接螢幕和鍵盤。 就像用遙控器操作電視一樣方便。
SSH 連線指令
# 用 SSH 連線到 Pi // 輸入你設定的帳號和 IP
ssh admin@192.168.1.100 // 連線到 Pi 的 IP 位址
# 第一次連線會詢問是否信任 // 輸入 yes
# Are you sure you want to continue connecting? // 確認連線
# 輸入 yes 後再輸入密碼 // 就可以登入了
# 查看系統資訊 // 確認 Pi 正常運作
uname -a // 顯示 Linux 核心版本
cat /proc/cpuinfo // 顯示 CPU 資訊
free -h // 顯示記憶體使用情況
df -h // 顯示硬碟(SD 卡)使用情況
# 設定免密碼登入(SSH Key)// 更安全更方便
ssh-keygen -t ed25519 // 產生 SSH 金鑰對
ssh-copy-id admin@192.168.1.100 // 把公鑰複製到 Pi 上
用 C# 模擬 SSH 連線管理
// 定義 SSH 連線資訊的類別 // 儲存連線所需的參數
public class SshConnection // SSH 連線類別
{
public string Host { get; set; } = ""; // Pi 的 IP 位址 // 例如 192.168.1.100
public int Port { get; set; } = 22; // SSH 預設埠號 // 通常不需要改
public string Username { get; set; } = ""; // 登入帳號 // 你設定的使用者名稱
public bool UseKeyAuth { get; set; } = false; // 是否用金鑰認證 // 比密碼更安全
public string KeyPath { get; set; } = ""; // 金鑰檔案路徑 // .ssh/id_ed25519
}
// 定義裝置管理器的類別 // 管理多台 Pi 的連線
public class DeviceManager // 裝置管理器
{
private readonly List<SshConnection> _devices = new(); // 裝置清單 // 儲存所有 Pi 連線
// 新增裝置的方法 // 把新的 Pi 加入管理
public void AddDevice(SshConnection device) // 新增裝置方法
{
if (string.IsNullOrEmpty(device.Host)) // 檢查 IP 是否為空
throw new ArgumentException("IP 位址不可為空"); // 丟出例外
_devices.Add(device); // 加入裝置清單 // 成功新增
Console.WriteLine($"已新增裝置:{device.Host}"); // 顯示成功訊息
}
// 列出所有裝置的方法 // 顯示管理中的所有 Pi
public void ListDevices() // 列出裝置方法
{
Console.WriteLine("=== 管理中的 Raspberry Pi 裝置 ==="); // 顯示標題
foreach (var device in _devices) // 逐一列出裝置
{
var authType = device.UseKeyAuth ? "金鑰" : "密碼"; // 判斷認證方式
Console.WriteLine($" {device.Host}:{device.Port} ({authType}認證)"); // 顯示裝置資訊
}
}
}
安裝 .NET Runtime on ARM
💡 比喻:讓 Pi 學會說 C# 語言 Raspberry Pi 預設只懂 Linux 指令, 安裝 .NET Runtime 後,它就能執行你寫的 C# 程式了。 就像在外國人的電腦上裝翻譯軟體,讓他能讀你寫的文件。
安裝 .NET 8 Runtime
# 方法 1:使用微軟官方安裝腳本 // 最簡單的方式
curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --channel 8.0 --runtime aspnetcore // 安裝 ASP.NET Core Runtime 8.0
# 設定環境變數 // 讓系統找到 dotnet 指令
echo 'export DOTNET_ROOT=$HOME/.dotnet' >> ~/.bashrc // 設定 .NET 安裝路徑
echo 'export PATH=$PATH:$DOTNET_ROOT' >> ~/.bashrc // 把 dotnet 加入 PATH
source ~/.bashrc // 重新載入設定 // 立即生效
# 驗證安裝 // 確認 .NET 已正確安裝
dotnet --info // 顯示 .NET 版本和環境資訊
# 方法 2:使用 apt 套件管理器 // 適合 Debian/Ubuntu 系列
wget https://packages.microsoft.com/config/debian/12/packages-microsoft-prod.deb // 下載微軟套件庫設定
sudo dpkg -i packages-microsoft-prod.deb // 安裝套件庫設定
sudo apt-get update // 更新套件清單
sudo apt-get install -y aspnetcore-runtime-8.0 // 安裝 ASP.NET Core Runtime
用 C# 描述安裝流程
// 定義 .NET 安裝設定的類別 // 描述安裝參數
public class DotNetInstallConfig // .NET 安裝設定
{
public string Channel { get; set; } = "8.0"; // .NET 版本通道 // 目前建議用 8.0 LTS
public string RuntimeType { get; set; } = "aspnetcore"; // Runtime 類型 // Web 應用需要 aspnetcore
public string Architecture { get; set; } = "arm64"; // CPU 架構 // Pi 4/5 用 arm64
public string InstallDir { get; set; } = "~/.dotnet"; // 安裝目錄 // 預設安裝在家目錄
}
// 檢查 .NET 安裝狀態的方法 // 驗證環境是否正確
public static void CheckDotNetStatus() // 檢查安裝狀態
{
var requiredEnvVars = new Dictionary<string, string> // 必要的環境變數 // 需要檢查的設定
{
["DOTNET_ROOT"] = "~/.dotnet", // .NET 安裝路徑 // 必須正確設定
["PATH"] = "包含 ~/.dotnet" // 系統路徑 // 必須包含 .NET 路徑
}; // 環境變數字典結束
foreach (var envVar in requiredEnvVars) // 逐一檢查環境變數
{
Console.WriteLine($"檢查 {envVar.Key}: {envVar.Value}"); // 顯示檢查項目
}
}
安裝 Node.js + Chromium(for Kiosk Mode)
💡 比喻:裝好「舞台」和「演員」 Node.js 是後台的工作人員(Print Agent 會用到), Chromium 是前台的大螢幕(用來顯示 POS 收銀畫面)。 兩個都裝好,你的 Pi 就變成一台完整的 POS 收銀機。
安裝指令
# 安裝 Node.js 20 LTS // 使用 NodeSource 套件庫
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - // 加入 NodeSource 套件庫
sudo apt-get install -y nodejs // 安裝 Node.js 20 LTS
# 驗證 Node.js 安裝 // 確認版本號
node --version // 應該顯示 v20.x.x
npm --version // 應該顯示 10.x.x
# 安裝 Chromium 瀏覽器 // Pi OS 通常已預裝
sudo apt-get install -y chromium-browser // 安裝 Chromium 瀏覽器
# 安裝必要的字型 // 中文字型支援
sudo apt-get install -y fonts-noto-cjk // 安裝 Noto CJK 中文字型
# 測試 Kiosk Mode // 全螢幕開啟 Chromium
chromium-browser --kiosk --noerrdialogs --disable-infobars http://localhost:5000 // 全螢幕開啟指定網址
用 C# 描述 Kiosk 設定
// 定義 Kiosk 模式設定的類別 // 全螢幕顯示設定
public class KioskConfig // Kiosk 設定類別
{
public string Browser { get; set; } = "chromium-browser"; // 瀏覽器路徑 // 使用 Chromium
public string TargetUrl { get; set; } = "http://localhost:5000"; // 目標網址 // POS 系統的首頁
public bool FullScreen { get; set; } = true; // 全螢幕模式 // Kiosk 必須全螢幕
public bool HideCursor { get; set; } = false; // 隱藏游標 // 觸控螢幕可以隱藏
public bool DisableErrorDialogs { get; set; } = true; // 停用錯誤對話框 // 避免干擾操作
}
// 產生 Kiosk 啟動指令的方法 // 組合 Chromium 參數
public static string BuildKioskCommand(KioskConfig config) // 建立 Kiosk 指令
{
var args = new List<string> // 建立參數清單 // 收集所有啟動參數
{
config.Browser // 瀏覽器執行檔 // chromium-browser
}; // 初始化參數清單
if (config.FullScreen) // 如果啟用全螢幕
args.Add("--kiosk"); // 加入 kiosk 參數 // 全螢幕模式
if (config.DisableErrorDialogs) // 如果停用錯誤對話框
{
args.Add("--noerrdialogs"); // 不顯示錯誤對話框 // 避免彈出視窗
args.Add("--disable-infobars"); // 停用資訊列 // 隱藏上方提示
}
args.Add(config.TargetUrl); // 加入目標網址 // 最後一個參數是網址
return string.Join(" ", args); // 組合成完整指令 // 用空格串接
}
GPIO 基礎概念(控制 LED、按鈕)
💡 比喻:Pi 的「觸手」 GPIO(General Purpose Input/Output)就像 Pi 的觸手, 可以伸出去控制 LED 燈、讀取按鈕狀態、驅動馬達。 在 POS 系統中,GPIO 可以用來控制錢箱(Cash Drawer)的開關。
GPIO 腳位說明
Raspberry Pi GPIO 腳位圖(簡化版):
3.3V [1] [2] 5V // 電源腳位
GPIO 2 [3] [4] 5V // I2C SDA / 電源
GPIO 3 [5] [6] GND // I2C SCL / 接地
GPIO 4 [7] [8] GPIO 14 // 通用 / UART TX
GND [9] [10] GPIO 15 // 接地 / UART RX
GPIO 17 [11] [12] GPIO 18 // 通用 / PWM
GPIO 27 [13] [14] GND // 通用 / 接地
GPIO 22 [15] [16] GPIO 23 // 通用 / 通用
3.3V [17] [18] GPIO 24 // 電源 / 通用
GPIO 10 [19] [20] GND // SPI MOSI / 接地
💡 做 POS 系統常用的 GPIO 應用:
- GPIO 控制繼電器 → 打開錢箱
- GPIO 讀取按鈕 → 緊急關閉鍵
- GPIO 控制 LED → 狀態指示燈
用 C# 控制 GPIO
// 引用 GPIO 套件 // 需要安裝 System.Device.Gpio NuGet 套件
// dotnet add package System.Device.Gpio // 安裝 GPIO 控制套件
// 定義 GPIO 控制器的類別 // 封裝 GPIO 操作
public class PiGpioController // GPIO 控制器類別
{
private const int LedPin = 17; // LED 連接的 GPIO 腳位 // 使用 GPIO 17
private const int ButtonPin = 27; // 按鈕連接的 GPIO 腳位 // 使用 GPIO 27
private const int DrawerPin = 22; // 錢箱連接的 GPIO 腳位 // 使用 GPIO 22
// 初始化 GPIO 腳位的方法 // 設定腳位模式
public static void InitializeGpio() // 初始化方法
{
Console.WriteLine("初始化 GPIO 腳位..."); // 顯示初始化訊息
Console.WriteLine($" LED 腳位:GPIO {LedPin}(輸出)"); // 設定 LED 為輸出
Console.WriteLine($" 按鈕腳位:GPIO {ButtonPin}(輸入)"); // 設定按鈕為輸入
Console.WriteLine($" 錢箱腳位:GPIO {DrawerPin}(輸出)"); // 設定錢箱為輸出
}
// 控制 LED 的方法 // 開啟或關閉 LED
public static void SetLed(bool on) // 設定 LED 狀態
{
var state = on ? "HIGH(亮)" : "LOW(暗)"; // 判斷 LED 狀態 // HIGH=亮, LOW=暗
Console.WriteLine($"設定 GPIO {LedPin} = {state}"); // 顯示設定結果
}
// 開啟錢箱的方法 // 送出脈衝信號打開錢箱
public static void OpenCashDrawer() // 開啟錢箱方法
{
Console.WriteLine($"送出脈衝到 GPIO {DrawerPin}..."); // 顯示脈衝訊息
Console.WriteLine("錢箱已開啟!"); // 顯示開啟成功
// 實際上是送出一個短暫的 HIGH 信號 // 大約 200ms 的脈衝
}
}
比喻總結:Raspberry Pi 是你的迷你伺服器
你的 POS 系統架構:
┌─────────────────────────────────────────────┐
│ Raspberry Pi(迷你伺服器) │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ .NET │ │ Node.js │ │ Chromium │ │
│ │ Runtime │ │ Print │ │ Kiosk │ │
│ │ (後端) │ │ Agent │ │ (前端) │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │ │
│ ┌─────┴──────────────┴─────────────┴──┐ │
│ │ Linux (Raspberry Pi OS) │ │
│ └─────────────────────────────────────┘ │
│ │ │ │ │
│ GPIO USB HDMI │
│ │ │ │ │
└─────────┼──────────────┼─────────────┼──────┘
│ │ │
┌────┴────┐ ┌────┴────┐ ┌───┴────┐
│ 錢箱 │ │ 印表機 │ │ 觸控 │
│ LED │ │ 掃描器 │ │ 螢幕 │
└────────┘ └────────┘ └────────┘
🤔 我這樣寫為什麼會錯?
❌ 錯誤 1:在 Pi 上安裝 x64 版本的 .NET
// ❌ 錯誤:下載 x64 版本的 .NET // Pi 的 CPU 是 ARM 架構
// 很多人直接從官網下載 x64 的 .NET SDK // 但 Pi 用的是 ARM 處理器
var config = new DotNetInstallConfig // 錯誤的安裝設定
{
Architecture = "x64", // ❌ 錯!Pi 不是 x86/x64 架構 // 這是桌機用的
Channel = "8.0" // .NET 版本沒問題 // 但架構錯了
}; // 這樣安裝會無法執行
// ✅ 正確:使用 ARM64 架構 // Pi 4/5 使用 64 位元 ARM 處理器
var correctConfig = new DotNetInstallConfig // 正確的安裝設定
{
Architecture = "arm64", // ✅ 正確!Pi 4/5 用 arm64 // ARM 64 位元架構
Channel = "8.0" // .NET 8.0 LTS // 長期支援版本
}; // 這樣才能正確安裝
❌ 錯誤 2:直接用 root 帳號操作所有事情
# ❌ 錯誤:全程使用 root // 這是非常不安全的做法
sudo su // 切換成 root 帳號
# 然後用 root 做所有事情 // 任何錯誤都可能毀掉整個系統
# ✅ 正確:只在需要時使用 sudo // 最小權限原則
sudo apt-get install nodejs // 只在安裝軟體時用 sudo
dotnet run // 執行程式不需要 sudo // 用一般使用者即可
❌ 錯誤 3:忘記設定環境變數就關掉終端機
# ❌ 錯誤:只在終端機裡設定環境變數 // 關掉終端機就消失了
export DOTNET_ROOT=$HOME/.dotnet // 這只是暫時的 // 關掉就沒了
# ✅ 正確:寫入 .bashrc 永久保存 // 每次開機都會自動載入
echo 'export DOTNET_ROOT=$HOME/.dotnet' >> ~/.bashrc // 寫入設定檔 // 永久生效
echo 'export PATH=$PATH:$DOTNET_ROOT' >> ~/.bashrc // PATH 也要設定 // 才能找到 dotnet 指令
source ~/.bashrc // 立即套用設定 // 不需要重新開機