Semorphe

光感應

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

你會學到三件事

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

開始之前

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

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

一、0 到 1023

int raw = analogRead(A0);
範圍
digitalRead 兩種:HIGH / LOW
analogRead 1024 種:0 到 1023

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

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

⚠️ analogRead 的腳不用 pinMode

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

它什麼意思都沒有。

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

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

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

Serial.println(raw);

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

三、map:把範圍換掉

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

int level = map(raw, 0, 1023, 0, 255);

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

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

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

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

四、接起來

int raw = analogRead(A0);
int level = map(raw, 0, 1023, 0, 255);
Serial.println(level);
analogWrite(9, level);

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

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

完成的樣子

void setup() {
    Serial.begin(9600);
    pinMode(9, OUTPUT);
}

void loop() {
    int raw = analogRead(A0);
    int level = map(raw, 0, 1023, 0, 255);
    Serial.println(level);
    analogWrite(9, level);
    delay(200);
}

換你了

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

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

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

這一課你做了什麼

如果卡住了

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