Semorphe

光感應

讀一個「有很多種可能」的值。 · ⏱ 約 30 分鐘

你會學到三件事

  1. analogRead 讀到的不是兩種值,是 0 到 1023
  2. map 把一個範圍換算成另一個範圍
  3. 感測器讀到的數字沒有單位,單位是你給的

開始之前

上一課的按鈕只有兩種答案,而光線是連續的:它可以是任何亮度。

接線:光敏電阻一腳接 A0、一腳接 5V,A0 再用一顆 10kΩ 電阻接 GND。 這叫分壓電路,它把「電阻變化」變成「電壓變化」,因為板子只讀得懂電壓。

🟢 先把編輯器打開,跟著下面一起做:跟著做

一、0 到 1023

類比腳讀進來的是一個 0 到 1023 的數字:

1int raw = analogRead(A0);
變數A0讀取類比腳位宣告int(整數)變數raw=1
範圍
digitalRead 兩種:HIGH / LOW
analogRead 1024 種:0 到 1023

為什麼是 1023?和上一課同一個理由:10 個位元,2¹⁰ = 1024 種值。

⚠️ 只有 A0 到 A5 這幾支腳可以。 一般數位腳沒有這個能力。

📋 而 A0 到 A5 各是幾號、你這塊板子有沒有 A6/A7 ——板子規格 查得到。⚠️ 不同板子不一樣。

積木盤上它寫著「讀取類比腳位 …」——與上一課那顆「讀取腳位」是一對。

⚠️ analogRead 的腳不用 pinMode。

二、那個數字是什麼意思?

它什麼意思都沒有。

analogRead 回報的是「這支腳上的電壓,佔滿格的幾分之幾」。 它不是「幾勒克斯」、不是「幾度」,它只是一個比例。

感測器給你的是原始讀數,意義是你賦予的。 要變成「亮度」或「溫度」,你得自己換算——而換算要靠實測。

所以第一步永遠是:印出來看看。

先把它印出來,遮住感應器再看一次:

🔎 這一段是試一下——打了看結果就好,不要留在程式裡。

1Serial.println(raw);
變數raw序列埠輸出小數位數並換行1

用手遮住感測器、拿燈照它,看那個數字怎麼變。先觀察,再寫邏輯。

三、map:把範圍換掉

讀到的是 0~1023,而 analogWrite 要的是 0~255。差 4 倍。

map 把一個範圍換成另一個範圍:

1int level = map(raw, 0, 1023, 0, 255);
變數raw010230255把從~換算到~宣告int(整數)變數level=1

讀法:「把 raw 從 0~1023 這個範圍,換算到 0~255」。

raw     0 ────────────────── 1023
level   0 ──────────────────  255

⚠️ map 用的是整數除法(C++ 入門第 5 課那件事),所以會有一點誤差。 map(500, 0, 1023, 0, 255) 得到 124 而不是 124.6。

⚠️ 而 map 不會幫你把值夾在範圍內。輸入超出去的話輸出也會超出去, 要夾住得用 constrain。

四、接起來

照著打上這一段,光越暗,燈越亮:

1int raw = analogRead(A0);2int level = map(raw, 0, 1023, 0, 255);3Serial.println(level);4analogWrite(9, level);
變數A0讀取類比腳位變數raw010230255把從~換算到~變數level9變數level把類比腳位輸出成序列埠輸出小數位數並換行宣告int(整數)變數level=宣告int(整數)變數raw=1234

越暗,燈越亮,一個會自己調整的夜燈。

⚠️ 而方向對不對取決於你怎麼接線。反了的話,把 map 的後兩個數字對調: map(raw, 0, 1023, 255, 0)。

完成的樣子

這一課的參考做法——程式碼每一行的號碼,就印在對應的那塊積木上。

1void setup() {2    Serial.begin(9600);3    pinMode(9, OUTPUT);4}5 6void loop() {7    int raw = analogRead(A0);8    int level = map(raw, 0, 1023, 0, 255);9    Serial.println(level);10    analogWrite(9, level);11    delay(200);12}
96009OUTPUT設定腳位為開啟序列埠 傳輸速率變數A0讀取類比腳位變數raw010230255把從~換算到~變數level9變數level200等待毫秒把類比腳位輸出成序列埠輸出小數位數並換行宣告int(整數)變數level=宣告int(整數)變數raw=定義函式 回傳型別void(無回傳)loop定義函式 回傳型別void(無回傳)setup12637891011

換你了

先只印 raw,用手遮住感測器,記下最暗和最亮的實際數字 (多半不是 0 和 1023,可能是 200 和 800)。

然後把 map 的前兩個數字換成你量到的,畫面會靈敏很多。

這就是「校正」。規格書寫的範圍,和你桌上這一顆的範圍,不一樣。

到編輯器做這一題:練習:量出你這一顆的實際範圍,拿去校正 map

做一個

暗了就開燈、亮了就關燈。

🔴 先做最直覺的版本(一個門檻值),然後把手慢慢移過感測器。 燈會在臨界點瘋狂閃爍,那不是壞掉,是門檻只有一個的必然結果。 ⚠️ 修法是兩個門檻:暗到 300 才開,亮到 500 才關。那個中間地帶叫遲滯。

到編輯器做這一題:做一個:不會抖的自動夜燈

這一課你做了什麼

如果卡住了

你看到 多半是因為
一直是 0 或一直是 1023 接線問題——分壓電阻沒接,或接到 5V/GND 短路了
數字跳來跳去 正常。類比讀數本來就會抖,可以多讀幾次取平均
analogRead(9) 得到 0 9 號腳不是類比輸入。要用 A0~A5
越亮燈越亮(想要相反) 把 map 的後兩個數字對調
在編輯器打開這一課 →