Ночник на Arduino: фоторезистор и плавное включение света
Ночник — это первый проект, где Arduino становится не «мигающим светодиодом», а полезной вещью на столе: стемнело — свет мягко разгорелось, рассвело — погасло. Вся электроника — фоторезистор с резистором 10 кОм и светодиод на ШИМ-пине, вся логика — один analogRead и два порога. Хитрость, отличающая рабочий ночник от «примера из интернета», — гистерезис: два порога вместо одного, иначе светильник мигает ровно в сумерках, когда освещённость дрейфует у порога.
В нашем симуляторе ночник оживает без лампы: карточка «Фоторезистор» из палитры «Макетка» задаёт освещённость ползунком, её значение течёт в analogRead, а светодиодная карточка показывает яркость ШИМ в каждый момент. Рантайм исполняет весь скетч — пороги, гистерезис, плавный разгон — и печатает переходы в Serial. Ниже — проверенный код, разбор гистерезиса и таблица честной границы.
Делитель и пороги: как фоторезистор превращается в цифру
Фоторезистор меняет сопротивление от ~1 кОм под лампой до ~1 МОм в темноте, но analogRead измеряет не сопротивление, а напряжение — нужен делитель: LDR с 5V на A0, резистор 10 кОм с A0 на GND. В темноте сопротивление фоторезистора растёт, напряжение на A0 падает, analogRead показывает сотню-другую; под лампой — 800-900. Конкретные числа у каждого экземпляра свои, поэтому скетч печатает значение в Serial, а пороги подбирают по этим печатям.
Второй ключ — гистерезис: включаем при значении ниже 300, выключаем выше 450, а в коридоре 300–450 ничего не меняем. Сумерки — это именно коридор: облако, тень от руки, фары за окном плавают вокруг одного порога, и однопороговый ночник щёлкает туда-сюда каждые несколько секунд. Зазор в 150 единиц означает, что освещённость должна вырасти на половину диапазона, прежде чем свет погаснет — на глаз это «выключился и не мигает».
const int POROG_TEMNO = 300; // ниже — стемнело, включаемconst int POROG_SVETLO = 450; // выше — рассвело, гасим (гистерезис 150)const int PIN_LED = 9; // ШИМ-пин: плавный разгон яркостиint svetit = 0; void setup() { pinMode(PIN_LED, OUTPUT); Serial.begin(9600); Serial.println("nochnik start");} void loop() { int svet = analogRead(A0); if (svet < POROG_TEMNO && svetit == 0) { svetit = 1; Serial.print("temno: "); Serial.println(svet); for (int y = 0; y <= 255; y = y + 5) { // разгорается ~0,8 секунды analogWrite(PIN_LED, y); delay(15); } } if (svet > POROG_SVETLO && svetit == 1) { svetit = 0; Serial.print("svetlo: "); Serial.println(svet); for (int y = 255; y >= 0; y = y - 5) { // плавно гаснет analogWrite(PIN_LED, y); delay(15); } } delay(150);}Прогон в симуляторе: двигаете ползунок карточки фоторезистора — при значении ниже 300 светодиодная карточка за ~0,8 секунды разгоняется до полной яркости (pwm 255), Serial печатает «temno: 200»; ползунок выше 450 — та же волна гаснет, «svetlo: 700». Значение 350 — в гистерезисной зоне — ничего не меняет: свет остаётся в прежнем состоянии, как и у живого ночника в сумерках.
Честная граница: что исполняет симулятор
| Проверка | Симулятор | Только железо |
|---|---|---|
| analogRead(A0) из карточки LDR | исполняется, ползунок 0–100 % = 0–1023 | то же самое, но фонариком |
| analogWrite ШИМ 0–255 | исполняется, яркость видна на карточке | то же самое |
| Гистерезис и переходы состояния | исполняются, печатает temno/svetlo | то же самое |
| Реальная освещённость комнаты | нет: свет задаёте ползунком | да |
| Разброс экземпляров LDR (кОм в темноте) | не моделируется | да — пороги под каждый |
| Мигание лампы дневного света на A0 | не моделируется | да — усреднение выборок |
Грабли: пороги, полярность и место установки
- Один порог вместо двух — главный брак: ночник строчит включениями в сумерках. Если светильник «моргает» — увеличьте зазор: 250/500 вместо 300/450.
- Поменяли местами резистор и фоторезистор — логика инвертировалась: в темноте analogRead растёт. Ничего страшного: поменяйте пороги местами или переставьте делитель обратно.
- Не ставьте датчик так, чтобы на него светил сам ночник: свет разгорелся — датчик увидел яркое — погас — увидел темноту — снова разгорелся. Датчик смотрит в окно или вверх, светильник отгорожен от него.
- Плавный разгон по 5 единиц с паузой 15 мс занимает меньше секунды — глазу приятно. Но весь цикл держит скетч в delay: в это время он слеп. Для ночника это неважно, для задач с реакцией — читайте про millis.
- Светодиод — только через резистор 220–330 Ом: в палитре «Макетка» он встроен в карточку, у живого LED без резистора выгорает сегмент за вечер.