第13章 Raspberry Pi SPI 通訊入門:MCP3008 ADC 讀取類比訊號

發布日期: |更新日期:
文章主圖:第13章 Raspberry Pi SPI 通訊入門:MCP3008 ADC 讀取類比訊號

上一章我們學會:

Raspberry Pi
      │
      ├── SDA
      └── SCL
           │
           ▼
          I²C
           │
           ▼
        LCD1602

並且理解:

I²C
=
2 條主要訊號線
+
Device Address

這一章要進入另一個非常重要的 Serial Bus:

SPI

SPI 通常使用:

SCLK
MOSI
MISO
Chip Select

和 I²C 最大的差異之一,是 SPI 通常不是利用 Device Address 選擇裝置,而是使用:

Chip Select

選擇目前要通訊的 Peripheral。

Raspberry Pi 官方目前的標準 SPI0 Header 對應為 GPIO10=MOSI、GPIO9=MISO、GPIO11=SCLK、GPIO8=CE0、GPIO7=CE1。

本章更重要的目的,是解決 Raspberry Pi 與 Arduino 之間一個非常明顯的差異:

Arduino UNO
有 A0~A5 Analog Input

Raspberry Pi 5
40-pin Header
沒有 Arduino 式一般 Analog Input

Raspberry Pi 官方將一般 GPIO Input 描述為讀取 HIGH 3.3V 或 LOW 0V,也就是數位輸入。

因此如果要讀取:

Potentiometer
光敏電阻
Analog Sensor
Joystick Analog Axis

就需要:

ADC

Analog-to-Digital Converter。

本章使用:

MCP3008

將類比電壓轉換成 Raspberry Pi 可以處理的數位資料。

1. SPI 是什麼?

SPI:

Serial Peripheral Interface

是一種同步式 Serial Communication Bus。

典型架構:

Raspberry Pi
SPI Controller
      │
      ├── SCLK
      ├── MOSI
      ├── MISO
      └── CE / CS
             │
             ▼
        SPI Peripheral

Linux Kernel 的 SPI Framework 目前就是以 Linux 作為 Controller、和外部 SPI Peripheral 通訊的架構設計。

2. SPI 有哪些主要 Signal?

標準 SPI 最常見:

SCLK
MOSI
MISO
CS / CE

Raspberry Pi 官方也將 Standard SPI 描述為 SCLK、MOSI、MISO 三條 Serial Signal,再搭配 Chip Select 選擇裝置。

3. SCLK 是什麼?

SCLK:

Serial Clock

由 SPI Controller 產生 Clock。

例如:

Raspberry Pi
    │
    └── SCLK
          │
          ▼
       MCP3008

Clock 用來決定:

何時送資料
何時讀資料

因此 SPI 屬於:

Synchronous Serial Communication

4. MOSI 是什麼?

MOSI 傳統名稱:

Master Out, Slave In

現代也常理解為:

Controller Out, Peripheral In

資料方向:

Raspberry Pi
    │
   MOSI
    │
    ▼
 MCP3008

Raspberry Pi SPI0:

MOSI
=
GPIO10
=
Physical Pin 19

5. MISO 是什麼?

MISO:

Master In, Slave Out

也可以理解:

Controller In, Peripheral Out

方向:

Raspberry Pi
    ▲
   MISO
    │
 MCP3008

Raspberry Pi SPI0:

MISO
=
GPIO9
=
Physical Pin 21

6. SCLK 使用哪一支 GPIO?

Raspberry Pi SPI0:

SCLK
=
GPIO11
=
Physical Pin 23

7. CE / CS 是什麼?

CE:

Chip Enable

CS:

Chip Select

概念幾乎是在說:

現在要和哪一顆 SPI Peripheral 通訊?

例如:

┌── ADC
CE0 ─────────┤
             └── MCP3008

CE1 ─────────── Other SPI Device

Raspberry Pi 官方 SPI 文件也將 CE 定義為 Chip Enable,常稱 Chip Select。

8. Raspberry Pi SPI0 有兩個常見 Chip Select

標準 40-pin Header:

Raspberry Pi SPI0 Pin 對照表
SPI Function BCM GPIO Physical Pin
MOSI GPIO10 Pin 19
MISO GPIO9 Pin 21
SCLK GPIO11 Pin 23
CE0 GPIO8 Pin 24
CE1 GPIO7 Pin 26

這就是本章 MCP3008 使用的主要 SPI0 Pin。

9. 本章 MCP3008 使用 CE0

我們設定:

MCP3008 CS
     │
     ▼
GPIO8
CE0
Physical Pin 24

如果未來第二顆 SPI Device 使用:

CE1

則可使用:

GPIO7
Physical Pin 26

10. SPI 不像 I²C 使用 Address

上一章 I²C:

Device A
0x27

Device B
0x68

靠 Address 選擇。

SPI:

Device A
← CE0

Device B
← CE1

主要由 Chip Select 決定目前 Peripheral。

因此 SPI 通常需要更多 Wire,但控制方式非常直接。

11. SPI 可以同時傳送與接收資料

標準 SPI 有:

MOSI
+
MISO

兩條獨立 Data Line。

所以在 Clock 進行時,可以:

Controller
→ Peripheral

同時

Peripheral
→ Controller

形成 Full-duplex Transfer。

Linux SPI Framework 支援這種同時 TX/RX 的 Transfer Model。

12. SPI 和 I²C 比較

I²C 與 SPI 通訊比較
項目 I²C SPI
Clock SCL SCLK
Controller → Device SDA 共用 MOSI
Device → Controller SDA 共用 MISO
Device Selection Address Chip Select
主要 Signal 數 2 通常 4
Full-duplex 通常不是 標準 SPI 可
多 Device Address 區分 多 CS
Pull-up 需要 一般不依賴 I²C 式 Pull-up

兩者不是誰全面比較好,而是適合不同 Peripheral 與資料傳輸需求。

13. SPI 要先在 Raspberry Pi OS 啟用

目前 Raspberry Pi OS 可以從:

Preferences
→ Control Centre
→ Interfaces
→ SPI

啟用。

也可以:

sudo raspi-config

目前官方選單:

3 Interface Options
→ I4 SPI
→ Yes

啟用後會開啟 SPI Interface,並在開機時載入相關 Kernel 支援。

14. 使用 raspi-config 啟用 SPI

執行:

sudo raspi-config

選:

3 Interface Options

再選:

I4 SPI

回答:

Yes

完成後:

OK
Finish

這是目前 Raspberry Pi 官方提供的標準方式。

15. SPI0 預設是關閉的

Raspberry Pi 官方硬體文件目前指出:

SPI0
=
disabled by default

可透過 raspi-config 開啟,或讓 /boot/firmware/config.txt 中:

dtparam=spi=on

生效。

初學者仍建議:

raspi-config

或:

Control Centre

不要一開始就手動修改 Boot Configuration。

16. 啟用後如何確認?

可以:

ls -l /dev/spidev*

正常的 SPI0 + CE0 / CE1 環境通常可以看到類似:

/dev/spidev0.0
/dev/spidev0.1

Raspberry Pi 官方將 spidev 定義為 Linux User-space 對單一 SPI Chip Select 的介面。

17. spidev0.0 是什麼?

可以拆成:

spidev 0 . 0
       │   │
       │   └── Device / Chip Select 0
       │
       └────── SPI Port 0

所以:

/dev/spidev0.0

通常就是:

SPI0
+
CE0

18. spidev0.1 是什麼?

同樣:

/dev/spidev0.1

代表:

SPI0
+
Device 1
+
CE1

GPIO Zero 對 Hardware SPI 也使用 port=0,而 device=0 對應 GPIO8、device=1 對應 GPIO7。

19. Raspberry Pi 為什麼需要 ADC?

Raspberry Pi 一般 GPIO Input 讀取:

LOW
=
0V

HIGH
=
約 3.3V

但如果電位器現在是:

1.37V

Digital GPIO 並不會告訴你:

1.37V

只會根據 Logic Threshold 判斷 HIGH / LOW。

因此需要:

Analog Voltage
      │
      ▼
     ADC
      │
      ▼
Digital Number

20. ADC 是什麼?

ADC:

Analog-to-Digital Converter

中文:

類比數位轉換器

功能:

Analog Voltage
       ↓
     Sample
       ↓
  Quantization
       ↓
Digital Code

例如:

0V
→ 0

1.65V
→ 約中間值

3.3V
→ 接近 Full Scale

21. 本章使用 MCP3008

Microchip MCP3008 是:

10-bit、8-channel、SPI ADC

Microchip 目前仍將 MCP3008 列為量產產品,主要規格為 10-bit、最多 200kSPS、8-channel ADC,使用 SPI Serial Interface。

22. MCP3008 是 SAR ADC

MCP3008 使用:

Successive Approximation Register

也就是 SAR ADC 架構。

Microchip Datasheet 將 MCP3008 描述為具有 Sample-and-Hold 的 10-bit Successive Approximation ADC。

本章不需要深入 SAR Comparator 細節。

先理解:

Analog Voltage
↓
MCP3008
↓
10-bit Number

即可。

23. MCP3008 有幾個 Channel?

MCP3008 提供:

CH0
CH1
CH2
CH3
CH4
CH5
CH6
CH7

總共:

8 Channels

可設定成 8 個 Single-ended Input,或者形成 Pseudo-differential Pair。

本章全部使用:

Single-ended Mode

24. 什麼是 10-bit ADC?

10-bit 表示:

2^10
=
1024

個量化 Code。

Code 範圍:

0
~
1023

Microchip Datasheet 明確指定 MCP3008 Resolution 為 10-bit。

25. 為什麼最大是 1023,不是 1024?

因為從:

0

開始計數。

1024 個不同 Code:

0
1
2
...
1022
1023

總共就是:

1024

個狀態。

26. Arduino 使用者會很熟悉 0~1023

Arduino UNO 的 10-bit ADC 教學中也常看到:

0~1023

MCP3008 也是 10-bit。

因此概念非常接近:

Arduino
analogRead()

對應概念

Raspberry Pi
+
MCP3008

差異在於:

Arduino
ADC 在 MCU 裡

Raspberry Pi
ADC 在外部 MCP3008

27. MCP3008 VREF 是什麼?

MCP3008 有:

VREF

Reference Voltage。

它決定 ADC 的 Full-scale Analog Range。

Microchip Datasheet 指定 Single-ended Input Range 由 VSS 到 VREF。

如果本章:

VREF = 3.3V

那麼類比輸入範圍就設定為約:

0V
~
3.3V

28. 本章 VDD 與 VREF 都使用 3.3V

MCP3008 的正常 Supply Range 為:

2.7V ~ 5.5V

所以使用 Raspberry Pi 3.3V 可以正常落在 MCP3008 工作電壓範圍內。

本章統一:

VDD
=
3.3V

VREF
=
3.3V

這樣有一個非常重要的好處:

MCP3008 SPI Digital Logic 和 Raspberry Pi 同樣位於 3.3V Domain。

29. 為什麼不把 MCP3008 VDD 接 5V?

MCP3008 本身可以 5V 工作。

但是 Datasheet 的 Digital Input HIGH Threshold 與 VDD 有關,規格為:

VIH ≥ 0.7 × VDD

如果:

VDD = 5V

則最低 HIGH Threshold 約為:

3.5V

Raspberry Pi GPIO HIGH 約為:

3.3V

因此 5V VDD 不應被當成 Raspberry Pi SPI Logic 的理想教學接法。

本章直接使用:

3.3V VDD

最簡單。

30. 類比輸入也不能超過 VREF

本章:

VREF = 3.3V

所以 CH0~CH7 的 Single-ended Analog Input 應保持:

0V ~ 3.3V

Microchip Datasheet 將 Single-ended Analog Input Range 定義為 VSS 到 VREF。

因此:

不要把 5V Analog Signal 直接接到 CH0。

31. ADC 不會因為是 Analog 就自動耐 5V

這是一個重要觀念。

Raspberry Pi GPIO
3.3V

MCP3008 VREF
3.3V

並不代表:

MCP3008 CH0
可以隨便輸入 5V

ADC Input 必須遵守:

Input Voltage Range

32. MCP3008 有 16 支 Pin

以常見 16-pin PDIP MCP3008,從上方看 IC 缺口:

┌───────┐
CH0    1  │       │ 16 VDD
CH1    2  │       │ 15 VREF
CH2    3  │       │ 14 AGND
CH3    4  │       │ 13 CLK
CH4    5  │       │ 12 DOUT
CH5    6  │       │ 11 DIN
CH6    7  │       │ 10 CS/SHDN
CH7    8  │       │  9 DGND
          └───────┘

這個 Pinout 來自 Microchip 官方 MCP3008 Datasheet。

33. 一定要先找 IC 缺口

PDIP IC 通常有:

Notch

或:

Pin 1 Mark

用來判斷 Pin Number。

不要看到兩排 8 Pin 就直接猜:

左上
右上

方向。

如果 MCP3008 旋轉 180°,VDD、GND 和 SPI Signal 就會全部錯位。

34. MCP3008 Pin 功能表

MCP3008 16-pin 功能表
MCP3008 Pin 名稱 用途
1 CH0 Analog Input 0
2 CH1 Analog Input 1
3 CH2 Analog Input 2
4 CH3 Analog Input 3
5 CH4 Analog Input 4
6 CH5 Analog Input 5
7 CH6 Analog Input 6
8 CH7 Analog Input 7
9 DGND Digital Ground
10 CS/SHDN Chip Select
11 DIN SPI Data In
12 DOUT SPI Data Out
13 CLK SPI Clock
14 AGND Analog Ground
15 VREF Reference Voltage
16 VDD Supply Voltage

35. DIN 對應 Raspberry Pi 哪一支?

MCP3008:

DIN

是:

Data Into MCP3008

因此要接 Raspberry Pi:

MOSI

也就是:

MCP3008 Pin 11 DIN
          │
          ▼
GPIO10 MOSI
Physical Pin 19

36. DOUT 對應哪一支?

MCP3008:

DOUT

資料從 ADC 輸出。

所以接:

Raspberry Pi MISO

也就是:

MCP3008 Pin 12 DOUT
          │
          ▼
GPIO9 MISO
Physical Pin 21

37. CLK 對應 SCLK

MCP3008 Pin 13 CLK
          │
          ▼
GPIO11 SCLK
Physical Pin 23

38. CS/SHDN 對應 CE0

本章:

MCP3008 Pin 10
CS/SHDN
     │
     ▼
GPIO8
CE0
Physical Pin 24

因此在 Linux:

SPI0
Device 0

對應這顆 MCP3008。

39. VDD

MCP3008 Pin 16
VDD
     │
     ▼
Raspberry Pi 3.3V
Physical Pin 1

MCP3008 支援 2.7~5.5V Supply,本章採 3.3V。

40. VREF

MCP3008 Pin 15
VREF
     │
     ▼
Raspberry Pi 3.3V

因此:

ADC Full Scale
≈ 3.3V

41. AGND 和 DGND 都要接 Ground

本章:

MCP3008 Pin 14
AGND
     │
     ▼
GND

以及:

MCP3008 Pin 9
DGND
     │
     ▼
GND

Microchip Datasheet 明確區分 Analog Ground 與 Digital Ground,並建議良好 PCB 設計中妥善連接兩者以降低數位 Noise 耦合。

Breadboard 教學中兩者都接 Raspberry Pi GND。

42. MCP3008 完整 SPI 接線表

MCP3008 與 Raspberry Pi SPI0 完整接線表
MCP3008 Raspberry Pi BCM Physical
VDD Pin 16 3.3V — Pin 1
VREF Pin 15 3.3V — Pin 1
AGND Pin 14 GND — Pin 6
CLK Pin 13 SCLK GPIO11 Pin 23
DOUT Pin 12 MISO GPIO9 Pin 21
DIN Pin 11 MOSI GPIO10 Pin 19
CS Pin 10 CE0 GPIO8 Pin 24
DGND Pin 9 GND — Pin 6

Raspberry Pi SPI0 Mapping 與 MCP3008 Pinout 分別由 Raspberry Pi 官方文件與 Microchip Datasheet 確認。

43. 建議增加 Bypass Capacitor

Microchip Datasheet 建議 MCP3008 應使用 Bypass Capacitor,並儘量靠近 Device Pin;Datasheet 建議值為:

1 µF

所以更完整的實驗電路,可以在:

VDD
│
1 µF
│
GND

附近加入去耦。

初學 Breadboard 雖然常省略,但正式設計最好養成:

Power Decoupling

習慣。

44. 本章 Analog Source 使用可變電阻

使用:

10kΩ Potentiometer

它有三支腳:

Left
Center
Right

其中中心腳通常是:

Wiper

旋轉時 Wiper Voltage 會在兩端電壓之間變化。

45. Potentiometer 接線

將一端:

3.3V

另一端:

GND

中間 Wiper:

MCP3008 CH0

完整:

3.3V
 │
 │
 ┌────────────┐
 │ 10kΩ POT   │
 └────────────┘
      │
      └── Wiper
            │
            ▼
        MCP3008 CH0

另一端
 │
 ▼
GND

旋轉後:

CH0
≈
0~3.3V

46. 為什麼 Pot 不可以接 5V?

因為本章:

VREF = 3.3V

CH0 Single-ended Input Range 為 VSS~VREF。

如果電位器兩端使用:

5V

Wiper 就可能輸出:

0~5V

超過本章 ADC Full-scale Range。

所以一定:

Potentiometer 使用 3.3V。

47. 完整硬體架構

Raspberry Pi 5             MCP3008

3.3V Pin 1 ─────────────── VDD Pin 16
     │
     └──────────────────── VREF Pin 15

GND Pin 6 ──────────────── AGND Pin 14
     │
     └──────────────────── DGND Pin 9

GPIO11 / Pin 23 ────────── CLK Pin 13
GPIO9  / Pin 21 ◀───────── DOUT Pin 12
GPIO10 / Pin 19 ─────────▶ DIN Pin 11
GPIO8  / Pin 24 ────────── CS Pin 10


3.3V
 │
10k Pot
 │── Wiper ─────────────── CH0 Pin 1
 │
GND

48. 接線前先關機

和前面所有 GPIO 實驗相同:

sudo poweroff

接著:

關機
↓
拔除 USB-C
↓
確認 MCP3008 缺口
↓
接 VDD / VREF
↓
接 AGND / DGND
↓
接 SPI
↓
接 Pot
↓
檢查
↓
再開機

不要在 Raspberry Pi 通電時拿 MCP3008 在 Breadboard 上移位。

49. 最危險的 MCP3008 錯接

要特別避免:

5V
→ CH0

以及:

5V
→ MCP3008 Digital Interface

或:

VDD / GND 接反

所以在第一次 Power On 之前,至少重新確認:

Pin 16 = VDD
Pin 15 = VREF
Pin 14 = AGND
Pin 9  = DGND

50. 先確認 SPI Device Node

開機後:

ls -l /dev/spidev*

如果 SPI0 正常,通常會看到:

/dev/spidev0.0
/dev/spidev0.1

如果:

No such file or directory

先檢查 SPI 是否真的啟用,不要先改 Python。

51. 本章優先使用 GPIO Zero MCP3008

GPIO Zero 目前內建:

MCP3008

支援 MCP3008 的:

8 Channels
10-bit ADC
SPI

官方範例就是:

from gpiozero import MCP3008

pot = MCP3008(0)

print(pot.value)

這是本章最適合初學者的方式。

52. GPIO Zero SPI Mapping

GPIO Zero 對預設 Hardware SPI:

port=0

使用:

SCLK GPIO11
MOSI GPIO10
MISO GPIO9

而:

device=0
→ GPIO8

device=1
→ GPIO7

所以:

MCP3008(channel=0)

預設正好對應本章:

SPI0
+
CE0

53. 建立 Chapter 13 目錄

cd ~

建立:

mkdir -p raspberrypi-course/chapter13

進入:

cd raspberrypi-course/chapter13

54. GPIO Zero 通常已存在 Raspberry Pi OS

前面 GPIO 章節已經使用:

gpiozero

所以先確認:

python3 -c \
"from gpiozero import MCP3008; print('MCP3008 OK')"

如果顯示:

MCP3008 OK

就可以開始。

55. 第一支 MCP3008 Python 程式

建立:

nano mcp3008_value.py

內容:

from gpiozero import MCP3008
from time import sleep


adc = MCP3008(
    channel=0
)


try:
    while True:
        print(
            f"Value: "
            f"{adc.value:.3f}"
        )

        sleep(0.2)

except KeyboardInterrupt:
    print(
        "\nProgram stopped."
    )

finally:
    adc.close()

56. 執行

python3 mcp3008_value.py

旋轉 Potentiometer。

可能看到:

Value: 0.001
Value: 0.172
Value: 0.406
Value: 0.701
Value: 0.998

GPIO Zero 將 MCP3008 value Normalized 到:

0.0 ~ 1.0

57. value=0 是什麼?

大約代表:

Analog Input
接近 GND

也就是:

CH0 ≈ 0V

58. value=0.5 是什麼?

若:

max_voltage = 3.3V

則:

value ≈ 0.5

大約代表:

1.65V

59. value=1.0 是什麼?

大約代表:

CH0
接近 Full Scale

本章:

Full Scale ≈ 3.3V

GPIO Zero MCP3008 的 voltage 會依 max_voltage 輸出 0~max_voltage,而預設 max_voltage 為 3.3V。

60. 直接讀 Voltage

建立:

nano mcp3008_voltage.py

內容:

from gpiozero import MCP3008
from time import sleep


adc = MCP3008(
    channel=0,
    max_voltage=3.3
)


try:
    while True:
        print(
            f"Voltage: "
            f"{adc.voltage:.3f} V"
        )

        sleep(0.2)

except KeyboardInterrupt:
    print(
        "\nProgram stopped."
    )

finally:
    adc.close()

GPIO Zero 官方 API 的 voltage Property 會將目前 Reading 轉成 0~max_voltage。

61. 讀取 Raw ADC Value

GPIO Zero 還提供:

adc.raw_value

代表 ADC 直接讀出的 Raw Code。

MCP3008 是 10-bit ADC,因此 Single-ended Raw Code 為:

0~1023

62. Raw Value 程式

from gpiozero import MCP3008
from time import sleep


adc = MCP3008(
    channel=0
)


try:
    while True:
        print(
            f"Raw: "
            f"{adc.raw_value}"
        )

        sleep(0.2)

except KeyboardInterrupt:
    print(
        "\nProgram stopped."
    )

finally:
    adc.close()

旋轉可變電阻:

Raw: 12
Raw: 268
Raw: 507
Raw: 812
Raw: 1020

63. 一次顯示 Raw、Value、Voltage

最適合 Debug:

from gpiozero import MCP3008
from time import sleep


adc = MCP3008(
    channel=0,
    max_voltage=3.3
)


try:
    while True:
        print(
            f"Raw={adc.raw_value:4d}  "
            f"Value={adc.value:.3f}  "
            f"Voltage={adc.voltage:.3f} V"
        )

        sleep(0.2)

except KeyboardInterrupt:
    print(
        "\nProgram stopped."
    )

finally:
    adc.close()

可能:

Raw= 510  Value=0.499  Voltage=1.646 V

64. 10-bit 每一個 LSB 大約是多少?

如果:

VREF = 3.3V

理想 10-bit ADC 有:

1024

個量化 Step。

因此每個 LSB 約:

3.3V / 1024
≈
0.00322V

也就是:

約 3.22mV / LSB

這只是理想量化解析度,不代表實際整個系統一定具有 3.22mV 的絕對量測精度;Reference、Noise、ADC Error、Source Impedance 與 Wiring 都會影響實際結果。Microchip 對 MCP3008 規格另外定義 INL、DNL 與 Gain/Offset Error。

65. Resolution 不等於 Accuracy

這是 ADC 非常重要的觀念。

10-bit

代表:

Quantization Resolution

不代表:

實際電壓一定準到 1/1024。

實際 Accuracy 會受到:

VREF
Noise
INL
DNL
Offset
Gain Error
Wiring
Power Supply

影響。

MCP3008 Datasheet 對 INL / DNL 提供 ±1 LSB 等級的規格。

66. 為什麼 Value 可能不會剛好到 0 或 1?

實際 Potentiometer、Reference、Contact Resistance、Noise 與 ADC 誤差都可能讓結果是:

0.002

到:

0.997

而不是理想:

0.000
1.000

這很正常。

67. 類比值為什麼一直跳?

例如:

512
513
510
514
511

這種小幅變化通常與:

Analog Noise
ADC Quantization
Power Noise
Breadboard
Pot Contact

有關。

不要把每 1 LSB 的變化都當成故障。

68. 可以使用 Moving Average

假設最近五次:

510
513
511
515
512

取平均:

512.2

可以讓顯示值更平滑。

69. 第一個 Moving Average 程式

from collections import deque
from statistics import mean
from time import sleep

from gpiozero import MCP3008


adc = MCP3008(
    channel=0
)

samples = deque(
    maxlen=10
)


try:
    while True:
        samples.append(
            adc.raw_value
        )

        average = mean(
            samples
        )

        print(
            f"Raw={adc.raw_value:4d} "
            f"Average={average:7.2f}"
        )

        sleep(0.05)

except KeyboardInterrupt:
    print(
        "\nProgram stopped."
    )

finally:
    adc.close()

70. Average Window 越大越好嗎?

不是。

例如:

10 Samples

比:

2 Samples

平滑。

但如果使用:

1000 Samples

系統反應就可能變慢。

因此:

Smoothness
和
Response Time

需要取得平衡。

71. GPIO Zero 本身也有 Filtering Tool

GPIO Zero 提供:

gpiozero.tools.smoothed

可對 ADC Value 做移動平均,官方文件也直接用 MCP3008 作為平滑 Analog Data 的 Example。

所以較大型 GPIO Zero Project 可以使用 Library 現成的 Data Pipeline。

72. 讀取第二個 Channel

假設另一顆 Sensor 接:

CH1

建立:

adc0 = MCP3008(
    channel=0
)

adc1 = MCP3008(
    channel=1
)

MCP3008 GPIO Zero API 支援 Channel:

0~7

73. 一次讀 8 Channels

例如:

from gpiozero import MCP3008
from time import sleep


channels = [
    MCP3008(channel=i)
    for i in range(8)
]


try:
    while True:
        values = [
            adc.raw_value
            for adc in channels
        ]

        print(
            values
        )

        sleep(0.5)

except KeyboardInterrupt:
    print(
        "\nProgram stopped."
    )

finally:
    for adc in channels:
        adc.close()

輸出可能:

[512, 0, 1023, 217, 681, 0, 0, 0]

74. 8 Channel 可以拿來做什麼?

例如:

CH0
→ Potentiometer

CH1
→ Light Sensor

CH2
→ Joystick X

CH3
→ Joystick Y

CH4
→ Analog Temperature Sensor

MCP3008 的 8 個 Single-ended Channel 很適合 Raspberry Pi 小型 Data Acquisition Project。Microchip 將其應用包含 Sensor Interface 與 Data Acquisition。

75. MCP3008 的 Reference 可以不是 3.3V 嗎?

技術上 VREF 可以依 Datasheet 條件設計;Reference Input 最大不能超過 VDD,而 Datasheet 列出的正常 Reference Range與性能需依實際條件評估。

但是本系列初學統一:

VDD = 3.3V
VREF = 3.3V

避免增加:

  • External Reference
  • Level Compatibility
  • Full-scale Calculation

等額外變數。

76. 不要把 VREF 當 Power Output

VREF 是:

Reference Input

不是:

給 Sensor 大電流供電的 Power Supply。

如果 Sensor 需要供電,應從合適的:

3.3V Rail

取得。

77. GPIO Zero 直接控制 PWMLED

第 10 章學過:

PWMLED

現在可以把:

Potentiometer
↓
MCP3008
↓
Normalized Value

直接控制:

LED Brightness

這是一個非常漂亮的:

Analog Input → PWM Output

範例。

78. LED 接線

LED 使用:

GPIO17
=
Physical Pin 11

接:

GPIO17
   │
 330Ω
   │
  LED
   │
  GND

MCP3008 則仍使用 SPI0。

79. 手動控制 LED Brightness

from gpiozero import MCP3008
from gpiozero import PWMLED
from time import sleep


adc = MCP3008(
    channel=0
)

led = PWMLED(
    17
)


try:
    while True:
        led.value = adc.value

        print(
            f"ADC={adc.value:.3f} "
            f"LED={led.value:.3f}"
        )

        sleep(0.02)

except KeyboardInterrupt:
    print(
        "\nProgram stopped."
    )

finally:
    led.off()

    adc.close()
    led.close()

旋轉 Pot:

低電壓
↓
LED 暗

高電壓
↓
LED 亮

80. GPIO Zero 還可以更簡單

GPIO Zero 官方 MCP3008 文件直接示範:

from gpiozero import MCP3008
from gpiozero import PWMLED


pot = MCP3008(
    channel=0
)

led = PWMLED(
    17
)

led.source = pot

這會把:

MCP3008 Value

直接 Feed 給:

PWMLED

81. 這叫 Declarative Device Connection

傳統寫法:

Read ADC
↓
Save Variable
↓
Write PWMLED

GPIO Zero source:

ADC
────────▶ LED

直接描述:

LED 的輸出來源就是 Potentiometer。

這種資料流設計在 GPIO Zero 中非常方便。

82. Analog Input + PWM Output 架構

現在我們已經做到:

Human
  │
  ▼
Potentiometer
  │
  ▼
Analog Voltage
  │
  ▼
MCP3008
  │
  ▼
SPI
  │
  ▼
Raspberry Pi
  │
  ▼
Python
  │
  ▼
PWMLED
  │
  ▼
Brightness

這就是完整的:

Analog Control Interface

83. 也可以直接使用 Python spidev

GPIO Zero 很方便,但學習 SPI 時,也值得知道較底層的:

spidev

Linux Kernel 提供 spidev User-space SPI Interface,而 Raspberry Pi 官方文件也列出 Python spidev 作為 SPI User-space 使用方式。

84. 安裝 Python spidev

Debian Trixie 提供:

python3-spidev

Package,作為 Linux spidev 的 Python Binding。

可以:

sudo apt update
sudo apt install -y \
  python3-spidev

85. 如果在 venv 使用 apt spidev

可以建立:

python3 -m venv \
  .venv \
  --system-site-packages

再:

source .venv/bin/activate

即可讓 venv 使用部分系統安裝 Package。

86. spidev 第一個 MCP3008 Reader

建立:

nano mcp3008_spidev.py

內容:

import time

import spidev


SPI_BUS = 0
SPI_DEVICE = 0


spi = spidev.SpiDev()

spi.open(
    SPI_BUS,
    SPI_DEVICE
)

spi.max_speed_hz = 1_000_000

spi.mode = 0


def read_adc(channel):
    if not 0 <= channel <= 7:
        raise ValueError(
            "channel must be 0-7"
        )

    command = [
        1,
        (8 + channel) << 4,
        0
    ]

    response = spi.xfer2(
        command
    )

    raw = (
        ((response[1] & 0x03) << 8)
        | response[2]
    )

    return raw


try:
    while True:
        raw = read_adc(0)

        voltage = (
            raw
            * 3.3
            / 1023
        )

        print(
            f"Raw={raw:4d} "
            f"Voltage≈{voltage:.3f} V"
        )

        time.sleep(0.2)

except KeyboardInterrupt:
    print(
        "\nProgram stopped."
    )

finally:
    spi.close()

Microchip MCP3008 的 SPI Protocol 會傳送 Start Bit、Single/Differential 選擇與 Channel Bits,再讀回 10-bit Conversion Result;GPIO Zero 現行 Source 也依這個 3-byte MCP3008 Transaction 結構實作。

87. spi.open(0, 0)

spi.open(
    0,
    0
)

代表:

SPI Bus 0
+
Device 0

也就是本章:

CE0
GPIO8

對應:

/dev/spidev0.0

88. 如果 MCP3008 接 CE1

硬體 CS 改接:

GPIO7
Physical Pin 26

程式:

spi.open(
    0,
    1
)

GPIO Zero 則可以:

adc = MCP3008(
    channel=0,
    device=1
)

GPIO Zero 官方 SPI API 明確對應 device 0→GPIO8、device 1→GPIO7。

89. SPI Mode

MCP3008 Datasheet 支援:

SPI Mode 0,0
和
Mode 1,1

本章使用:

spi.mode = 0

也就是常見:

CPOL = 0
CPHA = 0

模式。

90. 為什麼設定 1 MHz?

本章使用:

spi.max_speed_hz = 1_000_000

目的不是追求最大速度,而是為 Breadboard 教學提供保守、容易工作的 Clock。

MCP3008 最大可用 Clock / Sample Rate 會隨 VDD 與條件變化,Datasheet 在不同 Supply 下提供不同 Throughput 與 SCLK 規格。

所以不要看到:

SPI 很快

就直接:

50 MHz

硬跑 MCP3008。

91. GPIO Zero 和 spidev 哪個比較好?

對本系列:

GPIO Zero

適合:

快速實作
初學
MCP3008
PWMLED Integration

spidev

適合:

理解 SPI Transaction
自己處理 Protocol
特殊 SPI Device
Register-level Driver

因此:

先會 GPIO Zero,再理解 spidev。

92. GPIO Zero 不是把 SPI 原理藏掉就沒有 SPI

例如:

MCP3008(0)

背後仍然需要:

CS
SCLK
MOSI
MISO

GPIO Zero 只是替我們封裝:

Start Bit
Channel Selection
SPI Transfer
10-bit Result Extraction

而已。

GPIO Zero Source 目前就可以看到 MCP3008 3-byte Transfer 的實作。

93. ADC Raw Value 如何估算 Voltage?

若:

VREF ≈ 3.3V

並希望用 Raw Endpoint 做簡單顯示,可以寫:

voltage = (
    raw
    * 3.3
    / 1023
)

這會把:

0
→ 0V

1023
→ 3.3V

做端點式估算。

如果使用 GPIO Zero,更簡單:

adc.voltage

因為 GPIO Zero 已提供 0~max_voltage 的 Voltage Property。

94. 量測電壓還是應該用 Multimeter 驗證

例如 Pot Wiper:

1.65V

先用 Multimeter 量:

Wiper ↔ GND

再比較:

MCP3008

結果。

如果:

Multimeter = 1.65V
ADC = 0.1V

就明顯有:

Wiring
VREF
Ground
SPI
Channel

問題。

95. ADC 永遠顯示 0

優先檢查:

Pot Wiper
→ CH0?

Pot 兩端
→ 3.3V / GND?

VREF
→ 3.3V?

VDD
→ 3.3V?

AGND / DGND
→ GND?

如果 SPI 完全沒有工作,也可能讀到不合理或固定結果。

96. ADC 永遠顯示 1023

可能:

CH0 一直接近 VREF

或:

Pot 接錯

也可能 Analog Input Floating 且被其他路徑拉高。

先使用 Multimeter 量 CH0。

97. ADC 值只有一半範圍

例如 Pot 完整旋轉卻只能:

0~500

先檢查:

Pot Supply Voltage
VREF
Wiper Voltage

假設:

VREF = 3.3V

但 Pot 最大只到:

1.65V

那 10-bit ADC 讀到約 Full Scale 一半是合理的。

98. ADC 值劇烈亂跳

檢查:

AGND
DGND
VREF
VDD
Pot Wiper
Breadboard Connection
Power Noise
Wire Length

Microchip 也建議使用靠近 Device 的 Bypass Capacitor,並減少 Digital Clock 等高頻 Signal 對 Analog Circuit 的 Noise Coupling。

99. Analog Ground 和 Digital Ground 為什麼分開?

ADC 一邊處理:

Analog Signal

另一邊處理:

Fast Digital Clock

Digital Signal 容易帶來 Noise。

因此 MCP3008 提供:

AGND
DGND

協助 PCB Layout 分離 Analog 與 Digital Return Current。

在本章 Breadboard 中:

兩個都接共同 GND。

正式 PCB 則依 Datasheet 的 Ground Layout Guidance 設計。

100. SPI Device Not Found 怎麼辦?

SPI 不像 I²C:

i2cdetect

那樣有常用 Address Scanner。

SPI Device 通常不會自動回答:

我是誰。

所以 Debug 更依賴:

Device Node
Wiring
CS
Protocol
Known Register / Known Response

101. Raspberry Pi 官方提供 SPI Loopback 測試

官方 SPI Troubleshooting 建議可將:

MOSI

和:

MISO

暫時相接做 Loopback Test,確認送出的資料是否能讀回。這個方法不測試 CE0 / CE1,但可以協助確認 SPI Data/Clock Path。

這屬於進階 Debug,測試時不要同時接 MCP3008。

102. 不要同時讓兩個程式搶 spidev0.0

例如:

Program A
使用 MCP3008

Program B
也直接操作 /dev/spidev0.0

就可能造成:

Resource Conflict

所以一個實際 SPI Peripheral 應由明確的 Application / Driver 管理。

103. 不要用 sudo 當第一個解法

如果 Python:

Permission denied

不要立刻:

sudo python3 program.py

當永久方案。

先檢查:

ls -l /dev/spidev0.0

以及:

groups

找出真正 Device Permission 問題。

104. SPI 可以接很多 Device 嗎?

可以共用:

SCLK
MOSI
MISO

然後每顆 Device 使用不同:

CS

例如:

┌─ MCP3008
CE0 ──────────┘

              ┌─ Display
CE1 ──────────┘

如果需要更多 Device,可以透過額外 GPIO 作 Software Chip Select;Raspberry Pi 官方 Linux SPI 文件也支援使用 GPIO 作為 CS。

105. 多 Device 的 MISO 要注意

未被選中的 Peripheral 應該正確 Release MISO。

如果某個設計在未選中時仍強制驅動 MISO,就可能與其他 Device 發生 Bus Contention。

所以多 Device SPI Project 必須:

查 Datasheet

不能只把所有 MISO 任意並在一起。

106. SPI Wire 可以拉很長嗎?

和 I²C 一樣,不應把 Breadboard SPI 當成:

長距離 Field Bus。

高 Clock Speed 對:

Signal Integrity
Rise/Fall Time
Crosstalk
Ground
Wire Length

更敏感。

SPI 越高速,Breadboard 與長 Dupont Wire 越容易出問題。

107. 高速 SPI Debug 第一招是降速

如果:

低速正常
高速錯誤

通常應優先懷疑:

Signal Integrity
Wiring
Device Timing

而不是 Python Random Bug。

所以 spidev 測試時可以先從:

500kHz
1MHz

這種保守值開始。

108. MCP3008 最高 200kSPS 不等於 Python 一定可以穩定讀 200kSPS

Microchip 說的是 ADC Device 在指定電氣與 Clock 條件下的最大 Conversion Rate,例如 5V 條件最高可到 200kSPS。

但完整 Raspberry Pi Python Application 還包含:

Linux
Python
SPI Driver
Function Call
Scheduling
Printing
Data Processing

所以:

Datasheet 200kSPS

不等於:

print() while loop
可以得到 200000 lines/s。

109. 如果需要高速 Data Acquisition

應該重新評估:

Sampling Rate
Timing Determinism
Buffering
DMA
C / C++
Kernel Driver
Dedicated ADC Hardware
Microcontroller

而不是只把 Python sleep() 刪掉。

110. 本章的目標不是高速示波器

MCP3008 本章的定位是:

理解 ADC
理解 SPI
讀 Potentiometer
讀慢速 Analog Sensor
建立 Data Acquisition 基礎

不是製作:

高速 Oscilloscope。

這樣學習路徑比較正確。

111. MCP3008 Differential Mode

MCP3008 除了:

8 個 Single-ended

也可使用:

4 組 Pseudo-differential Pair

Microchip Datasheet 有完整 Channel Selection Table。

GPIO Zero 也提供:

MCP3008(
    channel=0,
    differential=True
)

相關能力。

不過本章基礎全部維持:

differential=False

112. 為什麼初學先用 Single-ended?

因為比較直觀:

CH0 Voltage
相對
GND

也就是:

0~3.3V

而 Pseudo-differential 要理解:

IN+
IN-
Common Mode
Differential Range

屬於更進階 Analog Measurement。

113. MCP3008 Data Logging

現在每次已經可以取得:

Timestamp
Raw
Value
Voltage

例如:

2026-08-17 23:20:01
Raw=512
Voltage=1.652V

後面第 19 章就可以直接:

ADC
↓
SQLite
↓
Historical Data

114. Analog Sensor 也能加入 MQTT

後面:

MCP3008
↓
Python
↓
MQTT
↓
Network
↓
Remote Dashboard

因此本章其實已經為 IoT Analog Sensor 做好基礎。

115. 本章 SPI Pin 快速對照

SPI0 與 MCP3008 快速對照
SPI0 BCM Physical MCP3008
MOSI GPIO10 Pin 19 DIN Pin 11
MISO GPIO9 Pin 21 DOUT Pin 12
SCLK GPIO11 Pin 23 CLK Pin 13
CE0 GPIO8 Pin 24 CS Pin 10
CE1 GPIO7 Pin 26 第二裝置可用

116. MCP3008 Power 快速對照

MCP3008 Power 與 Reference 配置
MCP3008 Raspberry Pi
VDD Pin 16 3.3V
VREF Pin 15 3.3V
AGND Pin 14 GND
DGND Pin 9 GND

本章把 VDD 與 VREF 都設為 3.3V,既符合 MCP3008 2.7~5.5V 工作範圍,也讓 SPI Digital Interface 和 Pi 3.3V Logic 保持一致。

117. GPIO Zero MCP3008 API 速查

GPIO Zero MCP3008 API 速查表
API 功能
MCP3008(channel=0) 建立 CH0 ADC
channel 目前 Channel
value Normalized 0~1
raw_value Raw ADC Code
voltage 估算 Voltage
max_voltage Full-scale Voltage 設定
bits ADC Resolution
close() 釋放 SPI Resource

目前 GPIO Zero MCP3008 為 10-bit、8-channel Device,並提供 value、raw_value 與 voltage Property。

118. SPI Linux 指令速查

sudo raspi-config

用途:

啟用 SPI

目前選單:

3 Interface Options
→ I4 SPI

查看 Device:

ls -l /dev/spidev*

安裝 Python spidev:

sudo apt install \
  python3-spidev

Debian Trixie 目前提供 python3-spidev。

119. GPIO Zero 和 spidev 快速比較

GPIO Zero MCP3008 與 spidev 比較
項目 GPIO Zero MCP3008 spidev
難度 低 中
Channel 自動處理 自己組 Command
Raw ADC raw_value 自己解析
Voltage voltage 自己計算
SPI Protocol Library 封裝 自己處理
適合 初學、應用 Driver、Protocol 學習

120. 本章故障排除總流程

遇到 MCP3008 無法正常讀值時,建議依序檢查:

SPI Enabled?
     ↓
/dev/spidev0.0 ?
     ↓
MCP3008 Direction?
     ↓
VDD = 3.3V?
     ↓
VREF = 3.3V?
     ↓
AGND / DGND?
     ↓
CLK = GPIO11?
     ↓
DIN = GPIO10?
     ↓
DOUT = GPIO9?
     ↓
CS = GPIO8?
     ↓
Pot Wiper = CH0?
     ↓
CH0 Voltage 0~3.3V?
     ↓
Python Library?

這個順序比直接一直修改 Python 有效得多。

121. 本章重點整理

完成本章後,應掌握以下核心觀念:

  1. SPI 是同步式 Serial Communication Bus。
  2. Raspberry Pi 標準 SPI0 使用 MOSI、MISO、SCLK 與 CE。
  3. SPI0 MOSI 是 GPIO10 / Pin 19。
  4. SPI0 MISO 是 GPIO9 / Pin 21。
  5. SPI0 SCLK 是 GPIO11 / Pin 23。
  6. SPI0 CE0 是 GPIO8 / Pin 24。
  7. SPI0 CE1 是 GPIO7 / Pin 26。
  8. SPI 通常透過 Chip Select 選擇 Peripheral。
  9. MOSI 代表 Controller → Peripheral Data。
  10. MISO 代表 Peripheral → Controller Data。
  11. 標準 SPI 可以同時 TX / RX。
  12. Raspberry Pi OS 目前由 3 Interface Options > I4 SPI 啟用 SPI。
  13. SPI0 預設關閉。
  14. dtparam=spi=on 可以啟用 SPI0。
  15. /dev/spidev0.0 對應 SPI0 Device 0。
  16. /dev/spidev0.1 對應 SPI0 Device 1。
  17. Raspberry Pi 一般 GPIO 沒有 Arduino 式類比讀值功能,GPIO Input 基本上讀 HIGH / LOW。
  18. ADC 用來將 Analog Voltage 轉成 Digital Code。
  19. MCP3008 是 10-bit ADC。
  20. MCP3008 有 8 個 Analog Channel。
  21. MCP3008 使用 SPI Interface。
  22. MCP3008 Supply Range 為 2.7~5.5V。
  23. 本章 MCP3008 VDD 使用 3.3V。
  24. 本章 VREF 使用 3.3V。
  25. CH0~CH7 Single-ended Input 應維持 VSS~VREF。
  26. 本章 Analog Input 因此限制為約 0~3.3V。
  27. 不可把 5V Analog Signal 直接接 CH0。
  28. MCP3008 10-bit 有 1024 個 Code。
  29. Raw Range 為 0~1023。
  30. VREF=3.3V 時理想 LSB 約 3.22mV。
  31. Resolution 不等於實際 Accuracy。
  32. MCP3008 有 INL、DNL、Offset 與 Gain Error 等實際誤差。
  33. MCP3008 Pin 1~8 是 CH0~CH7。
  34. Pin 9 是 DGND。
  35. Pin 10 是 CS/SHDN。
  36. Pin 11 是 DIN。
  37. Pin 12 是 DOUT。
  38. Pin 13 是 CLK。
  39. Pin 14 是 AGND。
  40. Pin 15 是 VREF。
  41. Pin 16 是 VDD。
  42. DIN 接 Raspberry Pi MOSI。
  43. DOUT 接 Raspberry Pi MISO。
  44. CLK 接 SCLK。
  45. CS 接 CE0。
  46. AGND / DGND 都需正確 Ground。
  47. Microchip 建議 MCP3008 加入靠近 IC 的 Bypass Capacitor。
  48. 本章使用 10kΩ Potentiometer。
  49. Pot 兩端接 3.3V / GND。
  50. Wiper 接 MCP3008 CH0。
  51. GPIO Zero 目前直接支援 MCP3008。
  52. MCP3008(channel=0) 讀 CH0。
  53. value 約為 0~1。
  54. raw_value 可讀取 Raw ADC Result。
  55. voltage 可回傳 0~max_voltage 的電壓估算。
  56. GPIO Zero 預設 MCP3008 max_voltage=3.3。
  57. Channel 可選 0~7。
  58. GPIO Zero device=0 對應 CE0。
  59. GPIO Zero device=1 對應 CE1。
  60. Moving Average 可以降低顯示抖動。
  61. Filter Window 越大不代表越好。
  62. GPIO Zero 也提供 Analog Value Smoothing Tool。
  63. MCP3008 可以同時建立多個 Channel Object。
  64. Potentiometer 可以控制 PWMLED Brightness。
  65. GPIO Zero 可直接 led.source = pot。
  66. Linux spidev 提供 SPI User-space Interface。
  67. Raspberry Pi 官方支援從 Python 使用 spidev。
  68. Debian Trixie 提供 python3-spidev。
  69. MCP3008 支援 SPI Mode 0,0 與 1,1。
  70. 本章 spidev 使用 Mode 0。
  71. SPI Clock 不應盲目追求最大值。
  72. 高速 SPI 對 Wire、Ground 與 Signal Integrity 更敏感。
  73. MCP3008 Datasheet 最高 Conversion Rate 可達 200kSPS,但依 VDD 等條件而定。
  74. Python Application Rate 不等於 ADC Datasheet Maximum Rate。
  75. SPI 不像 I²C 一樣有普遍可用的 Address Scanner。
  76. SPI Debug 依靠 Wiring、Chip Select 與已知 Protocol Response。
  77. Raspberry Pi 官方提供 MOSI/MISO Loopback 的 SPI Troubleshooting 方法。
  78. Analog Noise 不代表一定硬體故障。
  79. Multimeter 是 ADC Debug 非常重要的工具。
  80. 本章已讓 Raspberry Pi 第一次具備真正一般用途的 Analog Input 能力。

FAQ:Raspberry Pi SPI / MCP3008 常見問題

Q1:Raspberry Pi 5 有 Analog Input 嗎?

標準 Raspberry Pi 40-pin Header 沒有 Arduino UNO A0~A5 這種一般類比讀取介面;官方 GPIO Input 的基本模式是讀 HIGH 3.3V 或 LOW 0V。

因此讀 Analog Sensor 通常需要外部:

ADC

例如 MCP3008。

Q2:MCP3008 是什麼?

MCP3008 是 Microchip 生產的:

10-bit
8-channel
SPI ADC

目前仍為量產產品。

Q3:MCP3008 的 ADC 範圍是多少?

本章設定:

VREF = 3.3V

因此 Single-ended Input 使用約:

0~3.3V

MCP3008 Datasheet 規定 Single-ended Input Range 為 VSS 到 VREF。

Q4:MCP3008 可以輸入 5V 嗎?

如果本章 VREF 為 3.3V:

不可以直接輸入 5V。

Analog Input 不應超出 VREF 定義的範圍。

Q5:MCP3008 為什麼讀值是 0~1023?

因為 MCP3008 是:

10-bit ADC

10-bit 有:

2^10 = 1024

種 Code,因此從:

0~1023。

Q6:SPI MOSI 是哪一支 Raspberry Pi Pin?

GPIO10
=
Physical Pin 19

Q7:SPI MISO 是哪一支?

GPIO9
=
Physical Pin 21

Q8:SPI SCLK 是哪一支?

GPIO11
=
Physical Pin 23

Q9:CE0 是哪一支?

GPIO8
=
Physical Pin 24

Q10:如何開啟 Raspberry Pi SPI?

sudo raspi-config

目前選:

3 Interface Options
→ I4 SPI
→ Yes

Q11:如何確認 SPI 已啟用?

執行:

ls -l /dev/spidev*

通常 SPI0 會有:

/dev/spidev0.0
/dev/spidev0.1

spidev 是 Linux 提供給 User-space SPI Application 的介面。

Q12:GPIO Zero 如何讀 MCP3008?

最簡單:

from gpiozero import MCP3008

adc = MCP3008(
    channel=0
)

print(
    adc.value
)

這就是 GPIO Zero 官方 MCP3008 基本用法。

Q13:如何取得 0~1023?

使用:

adc.raw_value

raw_value 會回傳 ADC 的原始讀值。

Q14:如何直接取得 Voltage?

adc.voltage

GPIO Zero 會依 max_voltage 提供電壓值,本章使用:

max_voltage=3.3

Q15:MCP3008 可以讀幾個 Sensor?

MCP3008 有:

8 Channels

也就是 CH0~CH7。

Q16:為什麼 MCP3008 數值一直跳?

小幅跳動可能來自:

Analog Noise
Power Noise
ADC Quantization
Pot Contact
Breadboard

可以採用:

Moving Average

改善顯示穩定度。

Q17:可以用 MCP3008 控制 LED 亮度嗎?

可以。

例如:

from gpiozero import MCP3008
from gpiozero import PWMLED

pot = MCP3008(0)
led = PWMLED(17)

led.source = pot

這是 GPIO Zero 官方直接示範的 Analog Input → PWMLED 用法。

Q18:GPIO Zero 還是 spidev 比較適合?

初學 MCP3008:

GPIO Zero

比較簡單。

如果要理解:

SPI Command
Register
Bit Protocol

則應學:

spidev

兩者都值得掌握。

Q19:SPI 和 I²C 哪個比較快?

SPI 一般能提供較高的資料吞吐能力,但實際速度取決於 Controller、Peripheral、Clock、Wiring 與 Driver。

選擇不應只看:

誰比較快。

還要看:

Device 數量
Pin 數
Address
Chip Select
Power
Protocol

Q20:下一步 MCP3008 可以接什麼?

可以逐步接:

Potentiometer
Photoresistor Circuit
Joystick
Analog Temperature Sensor
Force Sensor
Gas Sensor Analog Output

但每一種 Sensor 都必須先確認:

輸出電壓不超過 MCP3008 VREF。

結語

完成第 13 章後,我們的 Raspberry Pi 硬體能力已經從:

Digital Input
+
Digital Output
+
PWM
+
Digital Sensor
+
I²C

進一步增加:

Analog Input

雖然 Raspberry Pi 本身沒有 Arduino UNO 式的 A0~A5,

但透過:

Analog Signal
      ↓
   MCP3008
      ↓
      SPI
      ↓
Raspberry Pi
      ↓
    Python

現在已經可以讀取:

0~3.3V

的類比訊號,轉成:

0~1023

的 10-bit Digital Code。

而且我們不是只讀數字。

最後還完成:

Potentiometer
      ↓
Analog Voltage
      ↓
MCP3008
      ↓
SPI
      ↓
Python
      ↓
PWMLED
      ↓
LED Brightness

這代表 Raspberry Pi 已經第一次具備真正的:

類比人機控制能力。

現在我們已學會兩種非常重要的 Peripheral Bus:

I²C
+
SPI

下一章則要進入第三種極重要通訊介面:

UART Serial

不同於 I²C 與 SPI,

UART 不需要:

Clock Line

而是透過:

TX
RX
Baud Rate

進行非同步 Serial Communication。

更重要的是,下一章我們會真正讓兩個不同平台互相合作:

Raspberry Pi 5 ↔ Arduino UNO R3

Raspberry Pi 負責:

Linux
Network
Python
Database
Web
MQTT

Arduino 負責:

Real-time GPIO
Sensor Timing
Motor
Low-level Control

正式建立多處理器控制架構。

下一章

第 14 章 Raspberry Pi UART Serial 通訊:與 Arduino 進行序列資料交換

下一章將完整介紹:

UART
TX
RX
Baud Rate
Start Bit
Data Bit
Stop Bit
Parity
Asynchronous Serial
GPIO14
GPIO15
Physical Pin 8
Physical Pin 10
Raspberry Pi 5 UART 架構
Dedicated Debug UART
Primary UART
/dev/serial0
/dev/ttyAMA*
raspi-config
Serial Port
Serial Console
3.3V Logic
Arduino UNO 5V Logic
Level Shifter
TX → RX
RX ← TX
Common Ground
Python pyserial
serial.Serial()
Arduino Serial.begin()
Raspberry Pi → Arduino
Arduino → Raspberry Pi
文字命令
LED ON / OFF
Sensor Data
CSV Protocol
JSON Protocol
Timeout
Buffer
Newline
Serial Debug

完成第 14 章後,就可以建立:

Raspberry Pi
Linux / Python
       │
       │ UART
       ▼
Arduino UNO
Real-time Control
       │
       ▼
Sensor / Motor / Relay

也就是把 Raspberry Pi 與 Arduino 從兩個獨立平台,真正整合成一套完整控制系統。

下一步學習

不要停在這一篇,接著把內容做成自己的實作

目前主題:Raspberry Pi。從完整學習路線、免費資源、會員下載,再接到實作所需材料。

同系列:Raspberry-Pi |  已是會員?直接前往 Getfile
相關資源與會員文章下載
文章可免費閱讀;下載完整 DOCX 或 PDF 需登入免費基本會員。
查看相關資源 會員免費下載 DOCX 會員免費 PDF/列印

← 回文章列表