☀️ سنسور نور LDR (فتوسل) با آردوینو: مقسم ولتاژ، کد کامل و چراغ خواب خودکار
چراغ کوچه چطور میفهمد شب شده؟ چراغ خوابهایی که خودشان روشن میشوند چه؟ بیشترشان یک قطعهی چند صدتومنی دارند به اسم LDR یا فتوسل. در این آموزش سنسور نور LDR را به آردوینو اونو وصل میکنیم، میفهمیم چرا یک مقاومت ۱۰ کیلواهم کنارش لازم است، عدد نور را روی نمودار میبینیم و یک چراغ خواب میسازیم که در تاریکی روشن شود بدون اینکه در غروب چشمک بزند. در آخر هم لامپی داریم که هرچه اتاق تاریکتر شود، پرنورتر میشود. همهی اینها را میتوانی رایگان در شبیهساز فارسی امتحان کنی، مثل کاری که کاربران ووکوی (Wokwi) آنلاین انجام میدهند.
LDR چطور کار میکند؟
LDR مخفف Light Dependent Resistor است: «مقاومتی که به نور وابسته است». روی سطحش یک نوار زیگزاگ از مادهای نیمهرسانا (معمولاً سولفید کادمیوم) هست. وقتی نور به آن میخورد، الکترونهای بیشتری آزاد میشوند و جریان راحتتر عبور میکند؛ یعنی هرچه نور بیشتر، مقاومت کمتر. یک فتوسل معمولی مثل GL5528 در نور اتاق حدود ده تا بیست کیلواهم و در تاریکی کامل نزدیک یک مگااهم مقاومت دارد. LDR قطب ندارد و جهت پایههایش مهم نیست.
چرا مقسم ولتاژ؟
پین آنالوگ آردوینو ولتاژ را بین صفر تا ۵ ولت میخواند و به عددی بین ۰ تا ۱۰۲۳ تبدیل میکند. ولی LDR ولتاژ تولید نمیکند؛ فقط مقاومتش عوض میشود. راهحل، مقسم ولتاژ است: LDR و یک مقاومت ثابت ۱۰ کیلواهم را پشت هم بین 5V و GND میگذاریم و نقطهی وسطشان را به A0 میدهیم. وقتی LDR در نور کممقاومت میشود، سهم بیشتری از ۵ ولت به نقطهی وسط میرسد و عدد بالا میرود. اگر میخواهی با عدد ببینی چه ولتاژی به A0 میرسد، ماشینحساب مقسم ولتاژ را با مقاومتهای مختلف امتحان کن.
قطعهها و سیمکشی
- یک آردوینو Uno
- یک مقاومت نوری LDR
- یک مقاومت ۱۰ کیلواهم
- یک LED با مقاومت ۲۲۰ اهم (پین 13 در کد اول، پین 9 در پروژهی دوم)
| از | به | توضیح |
|---|---|---|
| 5V آردوینو | یک پایهی LDR | بالای مقسم |
| پایهی دیگر LDR | A0 و یک سر مقاومت ۱۰k | نقطهی وسط، همان که اندازه میگیریم |
| سر دیگر مقاومت ۱۰k | GND | پایین مقسم |
| LED (از راه ۲۲۰ اهم) | پین 13 و GND | چراغ خواب |
کد کامل
// LDR (photoresistor) light sensor on an Arduino Uno.
// Wiring: 5V -> LDR -> A0 -> 10k -> GND (more light = bigger number)
const int LDR_PIN = A0;
const int LED_PIN = 13;
const int DARK_ON = 300; // night light ON below this
const int DARK_OFF = 380; // and OFF again only above this
bool nightMode = false;
void setup() {
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
}
void loop() {
int raw = analogRead(LDR_PIN); // 0..1023
int percent = map(raw, 0, 1023, 0, 100); // 0..100 %
if (!nightMode && raw < DARK_ON) nightMode = true;
if (nightMode && raw > DARK_OFF) nightMode = false;
digitalWrite(LED_PIN, nightMode ? HIGH : LOW);
Serial.print("light:");
Serial.print(raw);
Serial.print(" percent:");
Serial.println(percent);
delay(200);
}
توضیح کد
analogRead(LDR_PIN)ولتاژ نقطهی وسط مقسم را به عددی بین ۰ (صفر ولت) و ۱۰۲۳ (پنج ولت) تبدیل میکند. اگر با این تابع راحت نیستی، آموزش analogRead را ببین.map(raw, 0, 1023, 0, 100)عدد خام را به درصد تبدیل میکند تا خواناتر باشد. برای امتحان سریع map با عددهای دلخواه، ماشینحساب map هست.- دو آستانه بهجای یکی: هنگام غروب نور آرامآرام کم میشود و عدد حول آستانه بالا و پایین میرود. با یک آستانهی تنها، LED چند ثانیه مدام چشمک میزند. با دو آستانه (زیر ۳۰۰ روشن، بالای ۳۸۰ خاموش) یک «منطقهی بیتصمیمی» ساختهایم که همان هیسترزیس است.
nightModeحافظهی مدار است: وقتی عدد بین ۳۰۰ و ۳۸۰ است، هیچ شرطی درست نیست و وضعیت قبلی حفظ میشود.- قالب
light:… percent:…را نمودار سریال مستقیم به دو خط تبدیل میکند؛ دستت را روی سنسور بگیر و افت منحنی را تماشا کن.
اجرا در شبیهساز، رایگان
LDR در تینکرکد فارسی رایگان است. وقتی آن را انتخاب کنی، اسلایدر «☀️ میزان نور» را در پنل ویژگیها میبینی؛ آن را آرام بکش و ببین LED دقیقاً کجا روشن و کجا خاموش میشود. سادهترین مثال آماده «خواندن LDR» است و نسخهی چراغدارش «چراغ شب». اگر درسمحور جلو میروی، درس ۲۲: نورسنج با LDR و پروژهی پایانی چراغ خواب هوشمند را ببین. تعریف کوتاه قطعه هم در واژهنامه: مقاومت نوری است.
پروژهی کوچک: لامپی که با تاریکی پرنورتر میشود
بهجای روشن و خاموش، این بار نور LED را با PWM کم و زیاد میکنیم. LED را از راه مقاومت ۲۲۰ اهم به پین 9 ببر، چون فقط پینهای علامتدار با ~ PWM دارند. برای اینکه لرزش عددها نور را نلرزاند، از هشت اندازهگیری میانگین میگیریم.
// Mini project: a lamp that gets brighter as the room gets darker.
const int LDR_PIN = A0;
const int LAMP_PIN = 9; // a PWM pin (~)
const int BRIGHT_ROOM = 800; // reading in a well-lit room
const int DARK_ROOM = 150; // reading in the dark
int readSmooth() {
long sum = 0;
for (int i = 0; i < 8; i++) { // average 8 readings
sum += analogRead(LDR_PIN);
delay(5);
}
return sum / 8;
}
void setup() {
Serial.begin(9600);
pinMode(LAMP_PIN, OUTPUT);
}
void loop() {
int light = readSmooth();
int level = map(light, DARK_ROOM, BRIGHT_ROOM, 255, 0); // dark = 255
level = constrain(level, 0, 255);
analogWrite(LAMP_PIN, level);
Serial.print("light:");
Serial.print(light);
Serial.print(" lamp:");
Serial.println(level);
delay(100);
}
در map بازهی دوم را برعکس نوشتهایم (۲۵۵ تا ۰) تا نور کم، روشنایی زیاد بدهد. constrain هم نمیگذارد عدد از ۰ تا ۲۵۵ بیرون بزند، چون نور واقعی ممکن است از عددهایی که اندازه گرفتهای کمتر یا بیشتر شود. دو عدد BRIGHT_ROOM و DARK_ROOM را با سریال مانیتور در اتاق خودت اندازه بگیر و جایگزین کن؛ این همان «کالیبره کردن» است.
اشکالهای رایج
- عدد همیشه ۱۰۲۳ یا نزدیک صفر است: مقاومت ثابت را نگذاشتهای یا به جای اشتباه وصل است. بدون مقسم، A0 یا مستقیم به 5V وصل میشود یا شناور میماند.
- عدد بیدلیل بالا و پایین میرود: پایهی A0 شناور است (سیم شل)، یا نور لامپهای اتاق با فرکانس برق میلرزد. چند خواندن را میانگین بگیر.
- چراغ خواب در غروب چشمک میزند: فقط یک آستانه داری. دو آستانه با فاصله بگذار.
- چراغ روشن میشود و فوراً خاموش: نور خود LED به LDR میتابد و سنسور فکر میکند صبح شده. LED را دورتر یا پشت سنسور بگذار.
- analogWrite روی پین 13 فقط روشن و خاموش میکند: پین 13 در اونو PWM ندارد. از 3، 5، 6، 9، 10 یا 11 استفاده کن.
عددهای LDR را روی نمودار زنده ببین: سریال مانیتور و پلاتر آردوینو. با PIR ترکیبش کن تا چراغ راهرو بسازی: سنسور حرکت PIR با آردوینو. همین خواندن آنالوگ روی ESP32 دوازده بیتی است: analogRead در ESP32.
چراغ شب با LDR را رایگان اجرا کن ☀️سؤالهای رایج
چرا LDR را مستقیم به A0 وصل نمیکنیم؟
LDR فقط مقاومتش عوض میشود و آردوینو مقاومت نمیفهمد، ولتاژ میفهمد. با یک مقاومت ثابت یک مقسم ولتاژ میسازیم تا تغییر مقاومت به تغییر ولتاژ روی A0 تبدیل شود.
برای LDR چه مقاومتی بگذارم؟
برای بیشتر فتوسلهای رایج مثل GL5528 مقاومت ۱۰ کیلواهم انتخاب خوبی است. اگر بیشتر در نور کم کار داری، مقاومت بزرگتر مثل ۴۷ یا ۱۰۰ کیلواهم حساسیت در تاریکی را بیشتر میکند.
آیا با LDR میشود شدت نور را به لوکس اندازه گرفت؟
بهطور دقیق نه. LDR برای «تاریک یا روشن» و مقایسه عالی است، ولی هر قطعه کمی با دیگری فرق دارد و پاسخش خطی نیست. برای لوکس دقیق از سنسورهایی مثل BH1750 استفاده میشود.