[基礎] 以 VNC 和 Raspberry Pi 連線

VNC 是一種使用 RFB 協定的螢幕畫面分享及遠端操作軟體。由於 VNC 與作業系統無關,因此可跨平台使用。如果我們需要和 Pi 做有圖形介面的連線,VNC 是首選。

這裡簡介如何在 Pi 上安裝設定 VNC 伺服器,並透過個人電腦以 VNC 用戶端連線到 Pi。

1. 在 Pi 上安裝 VNC 伺服器。

pi@raspberrypi:~$ sudo apt-get install tightvncserver

2. 在個人電腦安裝 VNC 用戶端。

sosorry@ubuntu:~$ sudo apt-get install vncviewer gtkvncviewer

3. 在 Pi 上啟動 vncserver。

pi@raspberrypi:~$ vncserver

如果是第一次執行 vncserver 時會問幾個問題,包括登入的密碼和可供其他人流覽的 read-only 密碼,而 read-only 密碼可以不設定。登入的密碼會加密後存在 ~/.vnc/passwd 檔案裡。

You will require a password to access your desktops.

Password: 
Verify:   
Would you like to enter a view-only password (y/n)? n

之後我們就可以透過 vncviewer 或是 gtkvncviewer 之類的軟體和 Pi 連線了。假設 Pi 的 IP 為 192.168.1.2。

sosorry@ubuntu:~$ vncviewer 192.168.1.2:5901

tightvnc

如果要對 VNC 伺服器做更多設定,常用的參數有:
- 連線埠 (:$NUM):例如設定 :1 開啟的 port 為5901,:2 開啟的 port 為5902,依此類推,預設為 :1。
- 解析度(geometry):例如 640×480, 800×600, 1024×768 等,預設為 1024×768。
- 像素深度(depth):例如 8, 16, 24 等,這是指每個像素可顯示的位元數,預設為 16。

例如我們想設定 VNC 伺服器監聽 5902 這個埠號,當有用戶連線到 5902 後可開啟一個 640×480 BGR233的畫面。

pi@raspberrypi:~$ vncserver :2 -geometry 640x480 -depth 8

如果使用 gtkvncviewer 連線,需要輸入 IP、port 和密碼,使用者名稱可任意輸入。

sosorry@ubuntu:~$ gtkvncviewer

gtkvncviewer_setup

連線成功的畫面。
gtkvncviewer

 

常見問與答:

1. 如何修改 VNC 伺服器的連線密碼?
我們可以用 vncpasswd 這個指令改 VNC 的連線密碼。

Using password file /home/pi/.vnc/passwd
Password: 
Verify:   
Would you like to enter a view-only password (y/n)? n

 

2. 我忘了設定 VNC 伺服器聽哪一個 port 了?
我們可以用 netstat 這個指令來查看目前系統開啟的 port。

pi@raspberrypi:~$ netstat -nutlp

-n :列出數字形式的連線地址
-u :列出 UDP 的連線
-t :列出 TCP 的連線
-l :正在進行 Listen (監聽)的服務之網路狀態
-p :列出 PID 與 Program 的檔名

pi@raspberrypi:~$ netstat -nutlp
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:6002            0.0.0.0:*               LISTEN      2124/Xtightvnc  
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -               
tcp        0      0 0.0.0.0:5902            0.0.0.0:*               LISTEN      2124/Xtightvnc  
udp        0      0 0.0.0.0:22316           0.0.0.0:*                           -               
udp        0      0 0.0.0.0:68              0.0.0.0:*                           -               
udp        0      0 192.168.1.2:123         0.0.0.0:*                           -               
udp        0      0 127.0.0.1:123           0.0.0.0:*                           -               
udp        0      0 0.0.0.0:123             0.0.0.0:*                           -

我們也可以用 ps 這個指令查看目前系統執行的程序中。

pi@raspberrypi:~$ ps aux | grep vnc

- a :不和終端機 (terminal) 有關的所有程序
- u :所有有效使用者 (effective user) 的程序
- x :與 a 這個參數一起使用可列出完整資訊
- | grep vnc 表示只列出有包含 vnc 關鍵字的程序

pi@raspberrypi:~$ ps aux | grep vnc
pi        2124  0.0  0.9   6532  3460 ?        S    14:36   0:03 Xtightvnc :2 -desktop X -auth /home/pi/.Xauthority -geometry 640x480 -depth 8 -rfbwait 120000 -rfbauth /home/pi/.vnc/passwd -rfbport 5902 -fp /usr/share/fonts/X11/misc/,/usr/share/fonts/X11/Type1/,/usr/share/fonts/X11/75dpi/,/usr/share/fonts/X11/100dpi/ -co /etc/X11/rgb
pi        2128  0.0  0.1   1760   508 ?        S    14:36   0:00 /bin/sh /home/pi/.vnc/xstartup
pi        2426  0.0  0.2   3548   800 pts/0    S+   15:44   0:00 grep --color=auto vnc

 

3. 如何在開機時就啟動 VNC 伺服器?
在 /etc/init.d/ 下建立一個控制的腳本 (script),例如取名為 tightvncserver

pi@raspberrypi:~$ sudo vim /etc/init.d/tightvncserver

內容如下,重要的是在 start) 部份設定啟動的參數。

#!/bin/bash
### BEGIN INIT INFO
# Provides:          tightvncserver
# Required-Start:    $syslog
# Required-Stop:     $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: vnc server
# Description:
### END INIT INFO

export USER='pi'

eval cd ~$USER

# Check the state of the command - this'll either be start or stop 
case "$1" in
  start)
    # if it's start, then start vncserver using the details below
    su $USER -c '/usr/bin/vncserver :1 -geometry 800x600 -depth 16 -pixelformat rgb565'
    echo "Starting vncserver for $USER "
    ;;
  stop)
    # if it's stop, then just kill the process
    pkill Xtightvnc
    echo "vncserver stopped"
    ;;
  *)
    echo "Usage: /etc/init.d/tightvncserver {start|stop}"
    exit 1
    ;;
esac
exit 0

修改腳本權限。

pi@raspberrypi ~ $ sudo chmod 755 /etc/init.d/tightvncserver

將該腳本加入預設的啟動程序。

pi@raspberrypi ~ $ sudo update-rc.d tightvncserver defaults

執行結果如下。

update-rc.d: using dependency based boot sequencing
insserv: warning: script 'mathkernel' missing LSB tags and overrides

如果不喜歡這 warning,就順便修改一下 mathkernel 的腳本吧。

pi@raspberrypi ~ $ sudo vim /etc/init.d/mathkernel

根據 LSB 的規則將啟動資訊加到最前面。

### BEGIN INIT INFO
# Provides:          mathkernel
# Required-Start:    $local_fs 
# Required-Stop:     $local_fs
# Default-Start:     2 3 4 5 
# Default-Stop:      0 1 6 
# Short-Description: mathkernel
### END INIT INFO

重新啟動 Pi,再執行 netstat -nutlp 或是 ps aux | grep vnc,可以看到 VNC 伺服器已經跑起來了。

[常見問題] sudo: effective uid is not 0, is sudo installed setuid root?

在某些情況下,sudo 會突然失靈,回傳錯誤訊息如: sudo: effective uid is not 0, is sudo installed setuid root?

解決方法如下:

1. 將 SD 卡接到其他電腦,在 /boot/cmdline.txt 最後面加上 single

2. 將 SD 卡插回 Raspberry Pi,重新啟動後將會進入 single user mode。

3. 將 /usr 的擁有者和群組改成 root,並修改全部權限為 rX 。

chown -R root:root /usr
chmod -R a+rX /usr

4. 更改 sudo 相關檔案的使用者和權限。

chown root:root /usr/lib/sudo/sudoers.so
chown -R root:root /etc/sudoers*
chmod 4755 /usr/bin/sudo

5. 測試。

su - pi
sudo
usage: sudo [-D level] -h | -K | -k | -V
usage: sudo -v [-AknS] [-D level] [-g groupname|#gid] [-p prompt] [-u user name|#uid]
usage: sudo -l[l] [-AknS] [-D level] [-g groupname|#gid] [-p prompt] [-U user name] [-u user name|#uid] [-g groupname|#gid] [command]
usage: sudo [-AbEHknPS] [-r role] [-t type] [-C fd] [-D level] [-g groupname|#gid] [-p prompt] [-u user name|#uid] [-g groupname|#gid] [VAR=value] [-i|-s] []
usage: sudo -e [-AknS] [-r role] [-t type] [-C fd] [-D level] [-g groupname|#gid] [-p prompt] [-u user name|#uid] file ...

6. 將 single user mode 取消後重開機就大功告成了。

[進階] 編譯 Raspberry Pi 的核心

本文前言來自鳥哥的私房菜中的第二十六章、Linux 核心編譯與管理

核心是什麼?

其實核心就是系統上面的一個檔案而已,這個檔案包含了驅動主機各項硬體的偵測程式與驅動模組。

為什麼要編譯核心?

新功能的需求、原本核心太過臃腫、與硬體搭配的穩定性、其他需求(如嵌入式系統)。

 

這裡簡介編譯安裝 Raspberry Pi 的流程,未來我們還會常常回來看這篇。

1. 在個人電腦建構交叉編譯的環境,步驟可參考這裡

2. 查詢目前 Pi 的核心版本(以安裝2014-01-07-wheezy-raspbian.img 的映像檔為例,使用的核心版本為 3.10.25)。

pi@raspberrypi:~$ uname -a
Linux raspberrypi 3.10.25+ #622 PREEMPT Fri Jan 3 18:41:00 GMT 2014 armv6l GNU/Linux

3. 取得 Pi 的核心設定。

pi@raspberrypi:~$ zcat /proc/config.gz > .config

4. 在個人電腦下載核心原始碼。

sosorry@ubuntu:~$ cd rpi
sosorry@ubuntu:~/rpi$ git clone https://github.com/raspberrypi/linux.git
Initialized empty Git repository in /home/sosorry/linux/.git/
remote: Counting objects: 3512060, done.
remote: Compressing objects: 100% (586452/586452), done.
Receiving objects: 100% (3512060/3512060), 957.40 MiB | 3.18 MiB/s, done.
remote: Total 3512060 (delta 2897634), reused 3510306 (delta 2896207)
Resolving deltas: 100% (2897634/2897634), done.
Checking out files: 100% (43371/43371), done.

5. 切到目標分支。

sosorry@ubuntu:~/rpi$ cd linux
sosorry@ubuntu:~/rpi/linux$ git checkout rpi-3.10.y

6. 讀取目前 Pi 的核心設定,假設 Pi 的 IP 為 192.168.1.2。

sosorry@ubuntu:~/rpi/linux$ make mrproper
  CLEAN   scripts/basic
  CLEAN   scripts/kconfig
  CLEAN   include/config include/generated

sosorry@ubuntu:~/rpi/linux$ scp pi@192.168.1.2:/home/pi/.config .

sosorry@ubuntu:~/rpi/linux$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- oldconfig
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/kconfig/conf.o
  SHIPPED scripts/kconfig/zconf.tab.c
  SHIPPED scripts/kconfig/zconf.lex.c
  SHIPPED scripts/kconfig/zconf.hash.c
  HOSTCC  scripts/kconfig/zconf.tab.o
  HOSTLD  scripts/kconfig/conf
scripts/kconfig/conf --oldconfig Kconfig
*
* Restart config...
*
*
* ALSA for SoC audio support
*
ALSA for SoC audio support (SND_SOC) [M/n/?] m
  SoC Audio for the Atmel System-on-Chip (SND_ATMEL_SOC) [N/m/?] n
  SoC Audio support for the Broadcom BCM2708 I2S module (SND_BCM2708_SOC_I2S) [M/n/?] m
    Support for HifiBerry DAC (SND_BCM2708_SOC_HIFIBERRY_DAC) [M/n/?] m
    Support for HifiBerry Digi (SND_BCM2708_SOC_HIFIBERRY_DIGI) [N/m/?] (NEW) 
    Support for RPi-DAC (SND_BCM2708_SOC_RPI_DAC) [M/n/?] m
    Support for IQaudIO-DAC (SND_BCM2708_SOC_IQAUDIO_DAC) [N/m/?] (NEW) 
  Synopsys I2S Device Driver (SND_DESIGNWARE_I2S) [N/m/?] n
  Build all ASoC CODEC drivers (SND_SOC_ALL_CODECS) [N/m/?] n
  ASoC Simple sound card support (SND_SIMPLE_CARD) [N/m/?] n
#
# configuration written to .config
#

7. 以選單方式選取所需要的功能。

sosorry@ubuntu:~/rpi/linux$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig

raspberry_pi_kernel_configuration

8. 編譯核心(k, –keep-going)。

sosorry@ubuntu:~/rpi/linux$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -k V=1

9. 安裝核心模組。

sosorry@ubuntu:~/rpi/linux$ mkdir ../modules
sosorry@ubuntu:~/rpi/linux$ make modules_install ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- INSTALL_MOD_PATH=../modules/

10. 使用內建的工具產生出 Raspberry Pi 的核心(kernel.img)。

sosorry@ubuntu:~/rip/linux$ cd ~/tools/mkimage
sosorry@ubuntu:~/rpi/tools/mkimage$ ./imagetool-uncompressed.py ~/rpi/linux/arch/arm/boot/zImage"

11. 將 kernel、firmware、lib 安裝到 Pi 上(假設 SD 卡已經 mount 在 ~/sdb1 和 ~/sdb2)。

sosorry@ubuntu:~/rpi/tools/mkimage$ sudo cp -Rf ~/rpi/modules/lib/firmware/ ~/sdb2/lib/
sosorry@ubuntu:~/rpi/tools/mkimage$ sudo cp -Rf ~/rpi/modules/lib/modules/ ~/sdb2/lib/

12. 移除 SD 卡,重新啟動 Pi,查詢核心版本,可以看到我們從 3.10.25 升級到 3.10.37。

pi@raspberrypi:~$ uname -a
Linux raspberrypi 3.10.37+ #1 PREEMPT Wed Apr 16 03:12:08 CST 2014 armv6l GNU/Linux

[進階] 安裝 Raspberry Pi 的 Toolchain

Toolchain 是一套能讓你編譯、鍊結、除錯程式的軟體,例如 GCCLDGDBAS glibc 等。

假設我們寫了一個 hello.c 的程式要在個人電腦上執行,我們只要打 gcc hello.c 就可以將 hello.c 編譯成 x86 架構的可執行檔。

由於 Raspberry Pi 上的處理器是 ARM 架構的,因此要將同樣的 hello.c 在 Raspberry Pi 執行,必須將程式編譯成 ARM 架構的可執行檔。

我們有兩個選擇,第一是直接在 Raspberry Pi 上編譯。第二是先在我們的個人電腦用 Raspberry Pi 的 toolchain 編譯完成後,再上傳到 Pi。

這裡簡介如何在個人電腦安裝 Raspberry Pi 的 toolchain,以在 ubuntu 上安裝 gcc-linaro-arm-linux-gnueabihf-raspbian 為例。

1. 在個人電腦安裝必要的套件。

sosorry@ubuntu:~$ sudo apt-get install make git-core ncurses-dev

2. 下載最新版的 toolchain。

sosorry@ubuntu:~$ mkdir rpi
sosorry$ubuntu:~$ cd rpi
sosorry@ubuntu:~/rpi$ git clone https://github.com/raspberrypi/tools.git
remote: Reusing existing pack: 17273, done.
remote: Total 17273 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (17273/17273), 311.52 MiB | 343 KiB/s, done.
Resolving deltas: 100% (11698/11698), done.
Checking out files: 100% (15860/15860), done.

3. 安裝 toolchain。安裝方法是將 gcc-linaro-arm-linux-gnueabihf-raspbian 加到環境變數里。

sosorry@ubuntu:~/rpi$ vi ~/.bashrc
export PATH=$PATH:/home/sosorry/rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin   # add this line at the end of file

4. 測試。先開啟一個新的終端機,輸入 arm 後連續按兩次 tab 鍵,如果跑出來一堆像下面的提示表示安裝成功。

arm-linux-gnueabihf-addr2line        arm-linux-gnueabihf-gcc              arm-linux-gnueabihf-gfortran         arm-linux-gnueabihf-objdump
arm-linux-gnueabihf-ar               arm-linux-gnueabihf-gcc-4.7.2        arm-linux-gnueabihf-gprof            arm-linux-gnueabihf-pkg-config
arm-linux-gnueabihf-as               arm-linux-gnueabihf-gcc-ar           arm-linux-gnueabihf-ld               arm-linux-gnueabihf-pkg-config-real
arm-linux-gnueabihf-c++              arm-linux-gnueabihf-gcc-nm           arm-linux-gnueabihf-ld.bfd           arm-linux-gnueabihf-ranlib
arm-linux-gnueabihf-c++filt          arm-linux-gnueabihf-gcc-ranlib       arm-linux-gnueabihf-ldd              arm-linux-gnueabihf-readelf
arm-linux-gnueabihf-cpp              arm-linux-gnueabihf-gcov             arm-linux-gnueabihf-ld.gold          arm-linux-gnueabihf-size
arm-linux-gnueabihf-elfedit          arm-linux-gnueabihf-gdb              arm-linux-gnueabihf-nm               arm-linux-gnueabihf-strings
arm-linux-gnueabihf-g++              arm-linux-gnueabihf-gdbtui           arm-linux-gnueabihf-objcopy          arm-linux-gnueabihf-strip

讓我們實際寫一個 hello.c 並編譯它吧。

sosorry@ubuntu:~/rpi$ vi hello.c
#include <stdio.h>
int main()
{
	printf("hello, world\n");
        return 0;
}

用 Raspberry Pi 的 toolchain 編譯 hello.c。這一步驟稱為交叉編譯(cross-compiling)。

sosorry@ubuntu:~/rpi$ arm-linux-gnueabihf-gcc hello.c -o hello-arm

讓我們看看檔案的資訊,可以看到該檔案是 ARM 的格式。

sosorry@ubuntu:~/rpi$ file hello-arm
hello-arm: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, not stripped

如果我們在 x86 環境下試著執行會發現無法成功。

sosorry@ubuntu:~/rpi$ ./hello-arm 
bash: ./hello-arm: cannot execute binary file

我們把 hello-arm 上傳到我們的 Pi,假設 IP 為 192.168.1.2。

sosorry@ubuntu:~/rpi$ scp hello-arm pi@192.168.1.2:/home/pi
pi@192.168.1.2's password: 
hello-arm                                                                                                                             100% 5447     5.3KB/s   00:00

在我們的 Pi 上執行,看看結果吧。

pi@raspberrypi:~$ ./hello-arm
hello, world

 

常見問與答:

1. 為什麼要在個人電腦上安裝 toolchain?
因為個人電腦的處理速度通常高於 Raspberry Pi ,因此如果要開發比較大的專案(例如編譯核心),建議在個人電腦上處理,才不會等等等等。實務上在嵌入式系統的開發過程中,目標機器通常不會有 toolchain,因此常常會需要先在開發環境上將專案交叉編譯後再燒到目標機器。

2. 為什麼要安裝 gcc-linaro-arm-linux-gnueabihf-raspbian?
因為在 userland README.md 告訴我們的。

This repository contains the source code for the ARM side libraries used on Raspberry Pi. These typically are installed in /opt/vc/lib and includes source for the ARM side code to interface to: EGL, mmal, GLESv2, vcos, openmaxil, vchiq_arm, bcm_host, WFC, OpenVG.

Use buildme to build. It requires cmake to be installed and an arm cross compiler. It is set up to use this one: https://github.com/raspberrypi/tools/tree/master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian

[活動] Raspberry Pi社群聚會 #4 @ 2014/04/21

台灣第四次Raspberry Pi社群聚會,希望能透過社群活動的分享和交流,找到更多Rasperry Pi的可能。本次主題是自走車 / 機器人。

分享者1:邱展逢(學習樹莓派作者)
Topic:scratch和自走車

分享者2:葉難(Raspberry Pi從入門到應用作者)
Topic:用Raspberry做紅外線遙控車

活動資訊

  • 活動時間: 2014/04/21 19:30 ~ 2014/04/21 21:30 (7:00pm 開始入場)
  • 語言: Chinese/中文
  • 活動人數上限: 100
  • 活動地點:CLBC台北市大安區復興南路一段293號4樓
  • 交通資訊:(地圖:http://clbc.tw/location/)至捷運大安站下車,出口後直走60秒內可抵達 CLBC 大安館


顯示詳細地圖

費用

  • 每人150元場地費用
  • 帶作品展示的參加者免收場地費用

備註

  • 活動場地有提供無線網路
  • 場地有飲料,另外請大家可先在附近用餐再入場

[產品] PiTFT Mini Kit – 320×240 2.8″ TFT+Touchscreen for Pi

PiTFT_Mini_Kit

《規格》
- 2.8″ TFT, 可達320×240解析度@16-bit per pixel
- 本套件只含一塊觸控螢幕(已和電路板相連)與兩個26pin的連接器,不包含其他組件
- 耗電量約100mA
* 注意:需自行焊接

《教學》
- Adafruit PiTFT – 2.8″ Touchscreen Display for Raspberry Pi
- DIY WiFi Raspberry Pi Touchscreen Camera

$ 1,350

[產品] UK製Raspberry Pi rev 2 Model B 512MB

SONY DSC

《規格》
- SoC:Broadcom BCM2835
- CPU:700 MHz,ARM1176JZF-S core
- GPU:Broadcom VideoCore IV, OpenGL ES 2.0, MPEG-2 and VC-1, 1080p30 h.264/MPEG-4 AVC
- 記憶體:512MB (SDRAM)
- 視訊輸出:Composite RCA, HDMI
- 音訊輸出:3.5 mm jack, HDMI
- 儲存:SD / MMC / SDIO card slot
- 其他周邊:USB 2.0 x 2, Ethernet RJ45

$ 1,680