###### tags: `自駕車` # 自駕車 Orange Pi 建置工作 以下都請先登入成 root 再執行, OrangePi 若登入成一般使用者再使用 sudo 就是有些地方怪怪的, 執行登入成 root 比較簡單。 :::info 預設密碼都是 orangepi。 ::: ## 建置 OpenCV 環境 1. 將檔案系統延伸, 擴大可用空間: :::info 本步驟主要參考 [OrangePi 論壇討論](http://www.orangepi.org/orangepibbsen/forum.php?mod=viewthread&tid=844)。 ::: 首先調整分割區: ``` # fdisk /dev/mmcblk0 Command (m for help): p Disk /dev/mmcblk0: 15.8 GB, 15804137472 bytes 4 heads, 16 sectors/track, 482304 cylinders, total 30867456 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x34605ba5 Device Boot Start End Blocks Id System /dev/mmcblk0p1 40960 124927 41984 83 Linux /dev/mmcblk0p2 124928 7170047 3522560 83 Linux Command (m for help): d Partition number (1-4): 2 Command (m for help): n Partition type: p primary (1 primary, 0 extended, 3 free) e extended Select (default p): p Partition number (1-4, default 2): 2 First sector (2048-30867455, default 2048): 124928 Last sector, +sectors or +size{K,M,G} (124928-30867455, default 30867455): Using default value 30867455 Command (m for help): w ``` 要注意重建分割區時起始磁區要跟原本一樣。完成後重新開機: ``` # reboot ``` 開機後重新登入, 延伸調整後的分割區: ``` # resize2fs /dev/mmcblk0p2 ``` :::info 如果要更極致的節省空間, 也可以將不需要的程式刪除, 例如根本跑不起來的 Firefox、還有幾乎用不到的 LibreOffice: ``` # apt remove firefox thunderbird # apt remove "libreoffice*" # apt autoremove ``` ::: 2. 設置並啟用置換檔, 避免記憶體空間不足: ``` # touch /swapfile # dd if=/dev/zero of=/swapfile bs=1M count=1024 # mkswap /swapfile # swapon /swapfile ``` 這個步驟非常重要, 沒有置換檔, 系統會卡到不行, 很容易在建置過程中死當, 瀏覽器也幾乎處於無法使用的超頓狀態。也請將 `swapon /swapfile` 這一行放入 /etc/local.rc 檔中, 讓系統開機時自動啟用置換檔。 4. 安裝必要的套件: ``` # apt-get update # apt-get upgrade ``` :::info 使用 Orangepilite2_2.1.0_ubuntu_focal_desktop_linux5.4.65.7z 這個映像檔會在 `apt update` 時發生以下錯誤: ``` Traceback (most recent call last): File "/usr/lib/cnf-update-db", line 26, in <module> col.create(db) File "/usr/lib/python3/dist-packages/CommandNotFound/db/creator.py", line 94, in create self._fill_commands(con) File "/usr/lib/python3/dist-packages/CommandNotFound/db/creator.py", line 138, in _fill_commands self._parse_single_commands_file(con, fp) File "/usr/lib/python3/dist-packages/CommandNotFound/db/creator.py", line 176, in _parse_single_commands_file suite=tagf.section["suite"] KeyError: 'suite' Error in sys.excepthook: Traceback (most recent call last): File "/usr/lib/python3/dist-packages/apport_python_hook.py", line 153, in apport_excepthook with os.fdopen(os.open(pr_filename, FileNotFoundError: [Errno 2] No such file or directory: '/var/crash/_usr_lib_cnf-update-db.0.crash ``` 根據[這篇文章](https://bugs.launchpad.net/ubuntu/+source/command-not-found/+bug/1876034/comments/2)的說法, 可如下繞過問題暫時解決: 1. 在 /etc/apt/ 下建立 apt 的設定檔 apt.conf, 並在其中加入這行取消 gzip 格式索引的設定: ``` Acquire::GzipIndexes "false"; ``` 3. 確認沒有 gzip 格式的索引檔: ``` grep -r GzipIndexes /etc/apt ``` 1. 刪除清單快取檔: ``` rm -rf /var/lib/apt/lists ``` 1. 重新執行 update 指令: ``` apr update ``` ::: ``` # apt-get install unzip build-essential cmake libgtk2.0-dev libgtk-3-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev libjpeg8-dev libtiff5-dev libjasper-dev libpng12-dev libv4l-dev libxvidcore-dev libx264-dev python3-numpy # apt-get install python3-pip # python3 -m pip install --upgrade pip # apt-get install python3.5-dev ``` :::info 使用 Orangepilite2_2.1.0_ubuntu_focal_desktop_linux5.4.65.7z 這個映像檔會找不到 libjasper-dev 與 libpng12-dev, 不過系統已經有 libpng-dev, 而 libjasper-dev 可以自行到[這裡](https://ubuntu.pkgs.org/16.04/ubuntu-main-arm64/libjasper-dev_1.900.1-debian1-2.4ubuntu1_arm64.deb.html)下載 \.deb 檔案裝, 它需要先安裝 [libjasper1](https://ubuntu.pkgs.org/16.04/ubuntu-main-arm64/libjasper1_1.900.1-debian1-2.4ubuntu1_arm64.deb.html)。 ::: 3. 檢查 Python 開發工具的嵌入檔路徑: ``` # python3.5-config --includes #列出 .h 檔所在的路徑 ``` 4. 複製 OpenCV 遠端倉庫: ``` # mkdir OpenCV-tmp # cd OpenCV-tmp # wget https://github.com/opencv/opencv/archive/3.4.5.zip # unzip 3.4.5.zip ``` 5. 建置 OpenCV 所需的前置作業: ``` # cd opencv-3.4.5/ # mkdir build # cd build # cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local PYTHON3_EXECUTABLE=/usr/bin/python3 PYTHON_INCLUDE_DIR=/usr/include/python3.5m PYTHON_LIBRARY=/usr/lib/aarch64-linux-gnu/libpython3.5m.so PYTHON3_NUMPY_INCLUDE_DIRS=/usr/local/lib/python3.5/dist-packaes/numpy/core/include/ .. ``` :::info 請仔細觀察輸出結果, 如果你看到的 Python 開發工具嵌入檔路徑和輸出結果不同, 就需要自行在指令中指定路徑: ``` # cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local PYTHON3_EXECUTABLE=/usr/bin/python3 PYTHON_INCLUDE_DIR=/usr/include/python3.5m PYTHON_LIBRARY=/usr/lib/aarch64-linux-gnu/libpython3.5m.so PYTHON3_NUMPY_INCLUDE_DIRS=/usr/local/lib/python3.5/dist-packaes/numpy/core/include/ .. ``` ::: 1. 使用 j4 選項以多核心平行編譯: ``` # make -j4 ``` 6. 編譯完成後將 OpenCV 安裝至系統: ``` # make install ``` ## 安裝 TightVNCServer :::info 本節內容參考 [OrangePi 官網](http://www.orangepi.org/Docs/LogintotheOrangePi.html#Using_VNC)。 ::: OrangePi 的作業系統預設會安裝並啟用 ssh server, 但是並不會安裝 VNC server, 請依照以下程序安裝: 1. 安裝 TightVNCServer 套件: ``` $ apt-get install tightvncserver ``` 2. 初次執行設定登入密碼: ``` # vncserver You will require a password to access your desktops. Password: Verify: Would you like to enter a view-only password (y/n)? n New 'X' desktop is orangepilite2:1 Creating default startup script /root/.vnc/xstartup Starting applications specified in /root/.vnc/xstartup Log file is /root/.vnc/orangepilite2:1.log ``` 3. 修改 VNC 啟動檔, 設定登入後要執行的桌面環境: ```bash vim /root/.vnc/xstartup ``` 由於預設的桌面環境是 xfce, 所以我們設定遠端登入時也使用相同的桌面環境, 這樣就不需要再安裝額外的套件了: ```bash #!/bin/sh xrdb $HOME/.Xresources xsetroot -solid grey x-terminal-emulator -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" & xfce4-session & #x-window-manager & # Fix to make GNOME work export XKL_XMODMAP_DISABLE=1 /etc/X11/Xsession ``` 修改完後請記得存檔。 4. 重新啟動 VNC server: 先把目前執行的 VNC server 停掉: ```bash vncserver -kill :1 ``` 再重新執行 VNC server: ```bash vncserver :1 ``` 5. 遠端即可連上 5901 埠號啟用遠端桌面了。 :::info 在 Ubuntu 20.04 下的 tightvncserver 有 bug, 會讓遠端登入時視窗都沒有標題列, 也就無法用滑鼠直接移動視窗、關閉視窗等, 這是因為系統上 xfwm 4.14.1 的 bug, 這個問題已經在 4.14.2 修正, 不過系統的軟體倉庫內並沒有更新, 必須自行下載新版的[套件檔案](https://launchpad.net/ubuntu/groovy/arm64/xfwm4/4.14.2-1), 然後手動更新: ``` dpkg -i xfwm4_4.14.2-1_arm64.deb ``` 重新開機後, 再從 VNC 登入就正常了。 ::: ## 開機時自動執行 tightvncserver :::info 本節內容參考[這篇文章](https://leesiropi.blogspot.com/2019/12/installsetup-xfce-and-tightvnc-to.html)。 ::: 使用 systemctl 方式讓 tightvncserver 可以再開機時自動執行。 1. 編輯 /usr/local/bin/tightvncserver 檔案為以下內容: ```bash #!/bin/bash PATH="$PATH:/usr/bin/" DISPLAY="1" DEPTH="16" GEOMETRY="1024x768" OPTIONS="-depth ${DEPTH} -geometry ${GEOMETRY} :${DISPLAY}" case "$1" in start) /usr/bin/vncserver ${OPTIONS} ;; stop) /usr/bin/vncserver -kill :${DISPLAY} ;; restart) $0 stop $0 start ;; esac exit 0 ``` 1. 將剛剛建立的檔案設定為可執行: ```bash sudo chmod +x /usr/local/bin/tightvncserver ``` 1. 建立 systemctl 腳本檔案 /lib/systemd/system/tightvncserver.service 如下: ```ini [Unit] Description=Manage tightVNC Server [Service] Type=forking ExecStart=/usr/local/bin/tightvncserver start ExecStop=/usr/local/bin/tightvncserver stop ExecReload=/usr/local/bin/tightvncserver restart User=root [Install] WantedBy=multi-user.target ``` 1. 重新載入 systemd 服務並啟用 tightvncserver 服務: ```bash sudo systemctl daemon-reload sudo systemctl enable tightvncserver.service ``` 如此一來, 就可以使用以下幾種指令控制 tightvncserver 了: ```bash sudo systemctl start tightvncserver.service sudo systemctl stop tightvncserver.service sudo systemctl restart tightvncserver.service sudo systemctl status tightvncserver.service ``` 1. 重新啟動 Orange Pi, 開機後就會自動執行 tightvncserver 了。 1. 由於上述自動執行時會以 cron 的身份採用預設的 sh 當成 shell, 如果要改用不同的 shell, 請在 ~/.vnc/xstartup 中加入以下這行: ```bash export SHELL=/bin/bash ``` ## 開機自動登入帳號 OrangePi 使用 lightdm 管理登入事宜, 請依照以下步驟設定要自動登入的帳號, 請編輯 /etc/lightdm/lightdm.conf 檔案如下: ```ini [SeatDefaults] autologin-user=root autologin-user-timeout=0 ``` 重新開機後就會自動以 root 帳號登入, 不會顯示 (其實是顯示 0 秒) 登入畫面。 ## 建立 Wi-Fi AP ```bash iw dev wlan0 interface add uap0 type __ap nmcli con add type wifi ifname uap0 con-name Hotspot autoconnect yes ssid "FlagCar" nmcli con modify Hotspot 802-11-wireless.mode ap 802-11-wireless.band bg ipv4.method shared nmcli con modify Hotspot wifi-sec.key-mgmt wpa-psk nmcli con modify Hotspot wifi-sec.psk "12345678" nmcli con modify Hotspot connection.autoconnect yes nmcli con up Hotspot ``` 之後在 /etc/rc.local 中加入以下指令讓開機後自動啟用 AP: ``` iw dev wlan0 interface add uap0 type __ap ``` ## 設定 ttyS3 Orangepilite2_2.1.0_ubuntu_focal_desktop_linux5.4.65.7z 這個映像檔不知道為什麼預設 uart3 是停用的, 用 `dmesg | grep tty` 查詢就會發現 ttyS3 沒有作用。請修改設定檔 /boot/orangepiEnv.txt 檔, 加入以下這行: ``` overlays=uart3 ``` 存檔後重新開機即可啟用 uart3, 也就是 ttyS3。 ## 製作 img 檔 ### 利用圖形化工具 最簡單的方法可用 Mac 上的 [Apple Pi Baker](https://www.tweaking4all.com/software/macosx-software/applepi-baker-v2/), 它有自動縮放的選項, 可以在製作 img 檔時有自動根據使用空間縮小 img 檔的功能, 或是從 img 檔寫回 SD 卡時根據 SD 卡大小自動調整分割區空間。唯一的缺點是好像不大穩定。 ### 使用命令列工具 如果不使用上述工具, 可以根據[這一篇的說明](https://www.instructables.com/How-to-BackUp-and-Shrink-Your-Raspberry-Pi-Image/)製作並調整 img 檔的大小。 #### 製作與 SD 卡一樣大小的映像檔 1. 先使用讀卡機將 RPi 的 SD 卡插入。 2. 確認 SD 卡的裝置名稱: ``` # df -h Filesystem Size Used Avail Use% Mounted on /dev/mmcblk0p2 57G 3.7G 51G 7% / devtmpfs 478M 0 478M 0% /dev tmpfs 487M 24K 487M 1% /dev/shm tmpfs 487M 7.4M 480M 2% /run tmpfs 5.0M 4.0K 5.0M 1% /run/lock tmpfs 487M 0 487M 0% /sys/fs/cgroup /dev/mmcblk0p1 50M 19M 32M 38% /boot /dev/sda1 50M 19M 32M 38% /media/usb0 /dev/sda2 29G 3.7G 24G 14% /media/usb1 tmpfs 98M 36K 98M 1% /run/user/0 ``` 上例中可以看到 USB 對應的裝置名稱是 /dev/sda1 和 /dev/sda2。 1. 先將剛剛看到的 SD 卡從檔案系統上卸載: ``` # umount /dev/sda1 /dev/sda2 ``` 1. 安裝 dcfldd 工具: ``` # apt install dcfldd ``` 1. 製作目前 SD 卡的映像檔: ``` # dcfldd if=/dev/sda of=orangepi.img 955392 blocks (29856Mb) written. 955584+0 records in 955584+0 records out ``` 1. 原本是使用 32G 的 SD 卡, 所以製作出的映像檔是 32G 大小: ``` # ls -l -rw-r--r-- 1 root root 31312576512 Jan 26 17:41 orangepi.img ``` #### 使用 PiShrink 工具縮減映像檔大小 1. 安裝 [PiShrink](https://github.com/Drewsif/PiShrink) 工具: ``` # wget https://raw.githubusercontent.com/Drewsif/PiShrink/master/pishrink.sh --2021-01-26 17:42:49-- https://raw.githubusercontent.com/Drewsif/PiShrink/master/pishrink.sh Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.0.133, 151.101.64.133, 151.101.128.133, ... Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.0.133|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 10729 (10K) [text/plain] Saving to: ‘pishrink.sh’ pishrink.sh 100%[========>] 10.48K --.-KB/s in 0.003s 2021-01-26 17:42:50 (3.94 MB/s) - ‘pishrink.sh’ saved [10729/10729] # chmod +x pishrink.sh # sudo mv pishrink.sh /usr/local/bin/ ``` 1. 使用 PiShrink 工具縮減映像檔大小: ``` # pishrink.sh orangepi.img pishrink.sh v0.1.2 pishrink.sh: Gathering data ... Kernel not configured for semaphores (System V IPC). Not using udev synchronisation code. Kernel not configured for semaphores (System V IPC). Not using udev synchronisation code. Kernel not configured for semaphores (System V IPC). Not using udev synchronisation code. Creating new /etc/rc.local pishrink.sh: Checking filesystem ... rootfs: 151026/1856544 files (0.1% non-contiguous), 1095340/7626752 blocks resize2fs 1.42.13 (17-May-2015) pishrink.sh: Shrinking filesystem ... resize2fs 1.42.13 (17-May-2015) Resizing the filesystem on /dev/loop0 to 1365241 (4k) blocks. Begin pass 2 (max = 105962) Relocating blocks ------------------------------------XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Begin pass 3 (max = 233) Scanning inode table ------------------------------------XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Begin pass 4 (max = 9759) Updating inode references ------------------------------------XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX The filesystem on /dev/loop0 is now 1365241 (4k) blocks long. Kernel not configured for semaphores (System V IPC). Not using udev synchronisation code. Kernel not configured for semaphores (System V IPC). Not using udev synchronisation code. pishrink.sh: Shrinking image ... Kernel not configured for semaphores (System V IPC). Not using udev synchronisation code. pishrink.sh: Shrunk orangepi.img from 30G to 5.3G ... ``` 1. 調整後的映像檔縮小到 5.3G 了: ``` # ls -l orangepi.img -rw-r--r-- 1 root root 5665427968 Jan 26 18:00 orangepi.img ``` #### 將新的映像檔寫到空白的 SD 卡上 1. 接著請插上有空白 SD 卡片的讀卡機, 一樣先卸載 SD 卡: ``` # umount /dev/sda1 /dev/sda2 ``` 1. 將剛剛縮減大小的映像檔寫到 SD 卡上: ``` # dcfldd of=/dev/sda if=orangepi.img 172800 blocks (5400Mb) written. 172895+1 records in 172895+1 records out ``` 1. PiShrink 有個貼心的功能, 預設縮減過的映像檔寫入 SD 卡後, 會在 SD 卡第一次啟動 OrangePi 時自動擴展檔案系統到 SD 卡的大小, 例如若將映像檔寫到 8G 的卡上, 啟動後看到的檔案系統就是這樣: ``` # df -h Filesystem Size Used Avail Use% Mounted on /dev/mmcblk0p2 7.0G 3.7G 3.0G 56% / devtmpfs 478M 0 478M 0% /dev tmpfs 487M 24K 487M 1% /dev/shm tmpfs 487M 14M 474M 3% /run tmpfs 5.0M 4.0K 5.0M 1% /run/lock tmpfs 487M 0 487M 0% /sys/fs/cgroup /dev/mmcblk0p1 50M 19M 32M 38% /boot tmpfs 98M 36K 98M 1% /run/user/0 ```