Skip to main content

💡 Датчик освещенности

🎯 Цели и планируемые результаты урока

Предметные результаты:

  • Понимание принципов работы фоторезисторов и фотодиодов
  • Освоение методов измерения освещенности аналоговыми датчиками
  • Навыки калибровки световых датчиков
  • Умение создавать системы автоматического управления освещением
  • Практические навыки работы с делителями напряжения в датчиках
  • Создание умных устройств, реагирующих на освещение

Метапредметные результаты:

  • Развитие понимания взаимосвязи между физическими явлениями и электроникой
  • Формирование навыков калибровки и настройки измерительных систем
  • Умение анализировать изменения окружающей среды
  • Развитие навыков создания адаптивных систем

Личностные результаты:

  • Понимание роли освещения в жизни человека
  • Развитие экологического сознания (энергосбережение)
  • Формирование интереса к автоматизации бытовых процессов

🚀 Мотивационное начало (8 минут)

“Глаза для роботов - учим ESP32 видеть свет”

Учитель демонстрирует ESP32 с фоторезистором, который автоматически включает светодиод в темноте

🌟 Магическая демонстрация:

🔦 Направляем фонарик на датчик → Светодиод гаснет
🖐️ Закрываем датчик рукой → Светодиод загорается  
🌤️ Открываем окно → Яркость светодиода меняется
💡 Включаем/выключаем свет в классе → Система реагирует мгновенно!

🎭 Интерактивная аналогия “Умные глаза”:

👁️ ГЛАЗА ЧЕЛОВЕКА           ↔    💡 ДАТЧИК ОСВЕЩЕННОСТИ
Зрачок сужается на свету    ↔    Сопротивление уменьшается
Зрачок расширяется в темноте ↔    Сопротивление увеличивается
Мозг анализирует сигналы    ↔    ESP32 обрабатывает данные
Реакция: щуриться/открывать ↔    Реакция: включить/выключить свет

🏠 Демонстрация “Умный дом в действии”:

🌅 УТРО: Датчик видит рассвет → Постепенно выключает ночник
☀️ ДЕНЬ: Яркое солнце → Все искусственное освещение выключено
🌆 ВЕЧЕР: Солнце садится → Постепенно включает освещение
🌙 НОЧЬ: Темно → Включает ночное освещение

🌟 Интрига урока: “Сегодня мы научим ESP32 видеть и создадим систему, которая будет экономить электричество лучше любого человека!”

🎯 Вызов дня: “К концу урока ваше устройство будет автоматически управлять освещением, как в настоящем умном доме!”

📖 Основная часть урока

Блок 1: “Принципы работы световых датчиков” (12 минут)

🔬 “Фоторезистор - переменное сопротивление от света”

Физические основы работы:

⚡ ПРИНЦИП РАБОТЫ ФОТОРЕЗИСТОРА (LDR):

🌟 ПРИ ЯРКОМ СВЕТЕ:
- Фотоны попадают на полупроводник
- Электроны получают энергию
- Проводимость увеличивается
- Сопротивление УМЕНЬШАЕТСЯ (100-1000 Ом)

🌚 ПРИ СЛАБОМ СВЕТЕ:
- Мало фотонов попадает на датчик
- Электроны не активны
- Проводимость падает
- Сопротивление УВЕЛИЧИВАЕТСЯ (10кОм-1МОм)

📊 ТИПИЧНЫЕ ЗНАЧЕНИЯ:
Яркий солнечный день: 50-100 Ом
Комнатное освещение: 1-10 кОм
Сумерки: 10-100 кОм
Полная темнота: 100кОм-1МОм

🔌 “Делитель напряжения - преобразуем сопротивление в напряжение”

Схема и принцип работы:

⚡ ДЕЛИТЕЛЬ НАПРЯЖЕНИЯ С ФОТОРЕЗИСТОРОМ:

        +3.3V
          ├─── Постоянный резистор 10кОм
          ├─── Сигнал на ESP32 (GPIO 34)
          ├─── Фоторезистор (переменный)
         GND

🧮 ФОРМУЛА:
U_выход = 3.3V × (R_фото / (R_пост + R_фото))

📊 ПРИМЕРЫ РАСЧЕТОВ:
Яркий свет (R_фото = 100 Ом):
U = 3.3V × (100 / (10000 + 100)) = 0.03V

Сумерки (R_фото = 10кОм):
U = 3.3V × (10000 / (10000 + 10000)) = 1.65V

Темнота (R_фото = 100кОм):
U = 3.3V × (100000 / (10000 + 100000)) = 3.0V

📐 “Альтернативные световые датчики”

Сравнение типов датчиков:

📊 СРАВНЕНИЕ СВЕТОВЫХ ДАТЧИКОВ:

🔍 ФОТОРЕЗИСТОР (LDR):
✅ Простой и дешевый
✅ Широкий диапазон сопротивлений
❌ Медленный отклик (~100мс)
❌ Зависит от температуры
🎯 Применение: Уличное освещение, ночники

📱 ФОТОДИОД:
✅ Быстрый отклик (~1мкс)
✅ Точность измерений
❌ Дороже
❌ Нужна сложная схема
🎯 Применение: Камеры, оптические мыши

🌈 ФОТОТРАНЗИСТОР:
✅ Усиление сигнала
✅ Хорошая чувствительность
❌ Может насыщаться
❌ Температурная зависимость
🎯 Применение: Охранные системы

💎 BH1750 (цифровой):
✅ Точные измерения в люксах
✅ I2C интерфейс
✅ Не требует калибровки
❌ Дороже аналоговых
🎯 Применение: Профессиональные устройства

🧪 Практическое исследование “Поведение фоторезистора”

Эксперименты с освещением:

🔬 ЛАБОРАТОРИЯ СВЕТОВЫХ ИЗМЕРЕНИЙ:

Эксперимент 1: Измерение сопротивления
Оборудование: Мультиметр, фоторезистор, различные источники света

📊 ТАБЛИЦА ИЗМЕРЕНИЙ:
┌─────────────────────┬──────────────┬────────────┐
│ Условия освещения   │ Сопротивление│ Напряжение │
├─────────────────────┼──────────────┼────────────┤
│ Фонарик вплотную    │ _____ Ом     │ _____ В    │
│ Комнатный свет      │ _____ Ом     │ _____ В    │
│ Свет из окна        │ _____ Ом     │ _____ В    │
│ Тень от руки        │ _____ Ом     │ _____ В    │
│ Закрыт полностью    │ _____ Ом     │ _____ В    │
└─────────────────────┴──────────────┴────────────┘

Эксперимент 2: Скорость отклика
- Резко закрываем/открываем фоторезистор
- Засекаем время изменения показаний: _____ мс

Эксперимент 3: Угол чувствительности  
- Поворачиваем фоторезистор к источнику света
- Максимальная чувствительность под углом: _____°

Блок 2: “Подключение и калибровка датчика освещенности” (15 минут)

🔧 “Схема подключения фоторезистора”

Пошаговая сборка:

🛠️ СБОРКА ДАТЧИКА ОСВЕЩЕННОСТИ:

Компоненты:
□ ESP32 DevKit
□ Фоторезистор (LDR) 
□ Резистор 10кОм (постоянный)
□ Макетная плата
□ Провода (красный, черный, желтый)

🔗 СХЕМА ПОДКЛЮЧЕНИЯ:
        ESP32                   Датчик освещенности
     ┌─────────┐              ┌─────────────────┐
     │  3.3V   │──────────────│ +3.3V           │
     │         │              │        │        │
     │ GPIO 34 │──────────────│ Средняя точка   │
     │         │              │        │        │
     │   GND   │──────────────│ GND    │        │
     └─────────┘              │     10кОм       │
                              │        │        │
                              │   Фоторезистор  │
                              └─────────────────┘

🎯 ПОСЛЕДОВАТЕЛЬНОСТЬ СБОРКИ:
1. Установить резистор 10кОм между +3.3V и средней точкой
2. Подключить фоторезистор между средней точкой и GND
3. Подключить среднюю точку к GPIO 34 (аналоговый вход)
4. Проверить все соединения мультиметром

💻 “Базовая программа чтения освещенности”

Код с подробными комментариями:

// 💡 ПРОГРАММА ДАТЧИКА ОСВЕЩЕННОСТИ
// Урок 13: Измерение уровня освещенности

// 🔧 Настройки
const int LIGHT_SENSOR_PIN = 34;    // Аналоговый пин датчика
const int LED_PIN = 2;              // Встроенный светодиод
const int READINGS_COUNT = 10;      // Количество измерений для усреднения

// 📊 Переменные для калибровки
int minLightValue = 4095;           // Минимальное значение (яркий свет)
int maxLightValue = 0;              // Максимальное значение (темнота)
bool calibrationMode = true;       // Режим калибровки
unsigned long calibrationTime = 10000; // 10 секунд на калибровку

void setup() {
  Serial.begin(9600);
  Serial.println("💡 Инициализация датчика освещенности");
  
  pinMode(LED_PIN, OUTPUT);
  
  Serial.println("🔧 Режим калибровки запущен!");
  Serial.println("📖 В течение 10 секунд:");
  Serial.println("   🔦 Посветите фонариком на датчик");
  Serial.println("   🖐️ Закройте датчик рукой");
  Serial.println("─────────────────────────────────────");
  
  // 🎯 Калибровка датчика
  calibrateSensor();
  
  Serial.println("✅ Калибровка завершена!");
  Serial.printf("📊 Диапазон: %d (свет) - %d (темнота)\n", 
                minLightValue, maxLightValue);
  Serial.println("─────────────────────────────────────");
}

void loop() {
  // 📖 Читаем значение освещенности
  int lightLevel = readLightLevel();
  
  // 📊 Преобразуем в проценты (0% = темно, 100% = светло)
  int lightPercent = map(lightLevel, maxLightValue, minLightValue, 0, 100);
  lightPercent = constrain(lightPercent, 0, 100);
  
  // 🌟 Анализируем уровень освещенности
  String lightCondition = analyzeLightLevel(lightPercent);
  
  // 💡 Управляем светодиодом (включается в темноте)
  bool ledState = (lightPercent < 30);  // Включаем при освещенности < 30%
  digitalWrite(LED_PIN, ledState);
  
  // 📊 Выводим результаты
  Serial.printf("💡 Сырое значение: %d | Освещенность: %d%% | %s | LED: %s\n",
                lightLevel, lightPercent, lightCondition.c_str(),
                ledState ? "ВКЛ" : "ВЫКЛ");
  
  delay(500);  // Обновляем каждые 0.5 секунды
}

// 🎯 Функция калибровки датчика
void calibrateSensor() {
  unsigned long startTime = millis();
  
  while (millis() - startTime < calibrationTime) {
    int currentValue = analogRead(LIGHT_SENSOR_PIN);
    
    // 📊 Находим минимум и максимум
    if (currentValue < minLightValue) {
      minLightValue = currentValue;
    }
    if (currentValue > maxLightValue) {
      maxLightValue = currentValue;
    }
    
    // 📈 Показываем прогресс
    unsigned long elapsed = millis() - startTime;
    int progress = (elapsed * 100) / calibrationTime;
    
    if (elapsed % 1000 == 0) {  // Каждую секунду
      Serial.printf("🔧 Калибровка: %d%% | Текущее: %d | Мин: %d | Макс: %d\n",
                    progress, currentValue, minLightValue, maxLightValue);
    }
    
    delay(50);
  }
}

// 📖 Функция чтения уровня освещенности с усреднением
int readLightLevel() {
  long sum = 0;
  
  // 📊 Берем несколько измерений для точности
  for (int i = 0; i < READINGS_COUNT; i++) {
    sum += analogRead(LIGHT_SENSOR_PIN);
    delay(10);
  }
  
  return sum / READINGS_COUNT;
}

// 🔍 Функция анализа уровня освещенности
String analyzeLightLevel(int percent) {
  if (percent >= 80) {
    return "☀️ Очень ярко";
  } else if (percent >= 60) {
    return "🌤️ Ярко";
  } else if (percent >= 40) {
    return "🌥️ Умеренно";
  } else if (percent >= 20) {
    return "🌫️ Тускло";
  } else {
    return "🌚 Темно";
  }
}

🎛️ “Продвинутая калибровка и настройка”

Автоматическая адаптация к условиям:

// 🎯 ПРОДВИНУТЫЕ ФУНКЦИИ КАЛИБРОВКИ

// 📊 Переменные для адаптивной калибровки
struct LightCalibration {
  int minValue;
  int maxValue;
  unsigned long lastUpdate;
  bool isValid;
};

LightCalibration calibration = {4095, 0, 0, false};

// 🔄 Функция непрерывной калибровки
void continuousCalibration() {
  int currentReading = analogRead(LIGHT_SENSOR_PIN);
  unsigned long currentTime = millis();
  
  // 📈 Обновляем границы, если прошло достаточно времени
  if (currentTime - calibration.lastUpdate > 60000) {  // Каждую минуту
    
    // 🔍 Плавно адаптируем границы
    if (currentReading < calibration.minValue) {
      calibration.minValue = (calibration.minValue + currentReading) / 2;
    }
    if (currentReading > calibration.maxValue) {
      calibration.maxValue = (calibration.maxValue + currentReading) / 2;
    }
    
    calibration.lastUpdate = currentTime;
    
    Serial.printf("🔄 Адаптация калибровки: %d - %d\n", 
                  calibration.minValue, calibration.maxValue);
  }
}

// 💾 Функция сохранения калибровки в EEPROM
void saveCalibration() {
  // Сохраняем калибровку для следующего запуска
  EEPROM.write(0, calibration.minValue & 0xFF);
  EEPROM.write(1, (calibration.minValue >> 8) & 0xFF);
  EEPROM.write(2, calibration.maxValue & 0xFF);
  EEPROM.write(3, (calibration.maxValue >> 8) & 0xFF);
  EEPROM.commit();
  
  Serial.println("💾 Калибровка сохранена в память");
}

// 📖 Функция загрузки калибровки из EEPROM
void loadCalibration() {
  calibration.minValue = EEPROM.read(0) | (EEPROM.read(1) << 8);
  calibration.maxValue = EEPROM.read(2) | (EEPROM.read(3) << 8);
  
  // 🔍 Проверяем разумность загруженных значений
  if (calibration.minValue < calibration.maxValue && 
      calibration.minValue >= 0 && calibration.maxValue <= 4095) {
    calibration.isValid = true;
    Serial.printf("📖 Загружена калибровка: %d - %d\n", 
                  calibration.minValue, calibration.maxValue);
  } else {
    calibration.isValid = false;
    Serial.println("⚠️ Сохраненная калибровка повреждена, требуется новая");
  }
}

🔬 “Диагностика и отладка датчика”

Инструменты для проверки работы:

🚨 ДИАГНОСТИКА ПРОБЛЕМ ДАТЧИКА ОСВЕЩЕННОСТИ:

❌ ПРОБЛЕМА: Значения не изменяются
🔍 ПРОВЕРКИ:
1. Правильность подключения фоторезистора
2. Качество соединений на макетной плате
3. Не закрыт ли датчик корпусом/проводами
4. Работоспособность фоторезистора (мультиметром)

❌ ПРОБЛЕМА: Слишком малый диапазон значений
🔍 ПРОВЕРКИ:
1. Номинал постоянного резистора (должен быть ~10кОм)
2. Не перепутаны ли местами резисторы
3. Калибровка в достаточно разных условиях
4. Чувствительность фоторезистора

❌ ПРОБЛЕМА: Шумные/нестабильные значения
🔍 ПРОВЕРКИ:
1. Добавить конденсатор 100нФ для сглаживания
2. Увеличить количество усредняемых измерений
3. Проверить качество питания ESP32
4. Убрать источники электромагнитных помех

🛠️ ИНСТРУМЕНТЫ ДИАГНОСТИКИ:
- Мультиметр для проверки сопротивлений
- Осциллограф для анализа шумов
- Serial Plotter для визуализации изменений
- Контрольный фоторезистор для сравнения

Блок 3: “Создание автоматической системы освещения” (18 минут)

🏠 “Умный ночник - базовая автоматика”

Простая система автоматического освещения:

// 🌙 ПРОГРАММА "УМНЫЙ НОЧНИК"
// Автоматическое управление освещением

// 🔧 Настройки системы
const int LIGHT_SENSOR_PIN = 34;
const int LED_PIN = 2;
const int EXTERNAL_LED_PIN = 5;     // Внешний светодиод (более яркий)

// 🎛️ Пороговые значения (в процентах освещенности)
const int TURN_ON_THRESHOLD = 25;   // Включать при освещенности < 25%
const int TURN_OFF_THRESHOLD = 35;  // Выключать при освещенности > 35%
                                    // Гистерезис предотвращает мигание

// ⏱️ Временные настройки
const unsigned long RESPONSE_DELAY = 2000;  // 2 сек задержка перед реакцией
const unsigned long FADE_DURATION = 3000;   // 3 сек на плавное изменение яркости

// 📊 Переменные состояния
bool lightSystemOn = false;
unsigned long lastChangeTime = 0;
int currentBrightness = 0;
int targetBrightness = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("🌙 Умный ночник v2.0 запущен");
  
  pinMode(LED_PIN, OUTPUT);
  pinMode(EXTERNAL_LED_PIN, OUTPUT);
  
  // 🎯 Быстрая калибровка (или загрузка из памяти)
  quickCalibration();
  
  Serial.println("✅ Система готова к работе");
  Serial.println("🌟 Автоматическое управление освещением активно");
  Serial.println("─────────────────────────────────────────────────");
}

void loop() {
  // 📖 Читаем текущий уровень освещенности
  int lightPercent = readLightPercent();
  
  // 🎯 Определяем нужное состояние освещения
  bool shouldLightBeOn = decideLightState(lightPercent);
  
  // 💡 Обновляем систему освещения
  updateLightSystem(shouldLightBeOn);
  
  // 📊 Выводим статус системы
  printSystemStatus(lightPercent);
  
  delay(100);  // Быстрый цикл для плавной работы
}

// 🎯 Функция принятия решения о включении/выключении
bool decideLightState(int lightPercent) {
  static unsigned long conditionStartTime = 0;
  static bool conditionMet = false;
  
  // 🔍 Проверяем условия включения/выключения
  bool currentCondition;
  if (lightSystemOn) {
    // Система включена - проверяем условие выключения
    currentCondition = (lightPercent > TURN_OFF_THRESHOLD);
  } else {
    // Система выключена - проверяем условие включения
    currentCondition = (lightPercent < TURN_ON_THRESHOLD);
  }
  
  // ⏱️ Отслеживаем время выполнения условия
  if (currentCondition) {
    if (!conditionMet) {
      conditionMet = true;
      conditionStartTime = millis();
    }
    
    // 🎯 Условие выполняется достаточно долго?
    if (millis() - conditionStartTime >= RESPONSE_DELAY) {
      return !lightSystemOn;  // Меняем состояние
    }
  } else {
    conditionMet = false;
  }
  
  return lightSystemOn;  // Состояние не меняется
}

// 💡 Функция обновления системы освещения
void updateLightSystem(bool shouldBeOn) {
  if (shouldBeOn != lightSystemOn) {
    // 🔄 Меняем состояние системы
    lightSystemOn = shouldBeOn;
    targetBrightness = shouldBeOn ? 255 : 0;
    lastChangeTime = millis();
    
    Serial.printf("🔄 Система освещения: %s\n", 
                  shouldBeOn ? "ВКЛЮЧЕНА" : "ВЫКЛЮЧЕНА");
  }
  
  // 🌈 Плавное изменение яркости
  updateBrightness();
}

// 🌈 Функция плавного изменения яркости
void updateBrightness() {
  if (currentBrightness != targetBrightness) {
    unsigned long elapsed = millis() - lastChangeTime;
    
    if (elapsed < FADE_DURATION) {
      // 📈 Интерполяция яркости
      int startBrightness = lightSystemOn ? 0 : 255;
      float progress = (float)elapsed / FADE_DURATION;
      currentBrightness = startBrightness + 
                         (targetBrightness - startBrightness) * progress;
    } else {
      currentBrightness = targetBrightness;
    }
    
    // 💡 Применяем яркость к светодиодам
    analogWrite(EXTERNAL_LED_PIN, currentBrightness);
    digitalWrite(LED_PIN, currentBrightness > 128);
  }
}

// 📊 Функция вывода статуса системы
void printSystemStatus(int lightPercent) {
  static unsigned long lastPrint = 0;
  
  if (millis() - lastPrint >= 1000) {  // Каждую секунду
    Serial.printf("💡 Освещенность: %d%% | Система: %s | Яркость: %d/255\n",
                  lightPercent,
                  lightSystemOn ? "ВКЛ" : "ВЫКЛ",
                  currentBrightness);
    lastPrint = millis();
  }
}

🌅 “Режимы работы умного освещения”

Различные алгоритмы автоматики:

// 🎭 РАЗЛИЧНЫЕ РЕЖИМЫ РАБОТЫ ОСВЕЩЕНИЯ

enum LightMode {
  MODE_AUTO,        // Автоматический режим
  MODE_SCHEDULE,    // По расписанию
  MODE_MOTION,      // По движению + освещенность
  MODE_MANUAL,      // Ручное управление
  MODE_ENERGY_SAVE  // Энергосберегающий
};

LightMode currentMode = MODE_AUTO;

// 🌅 Режим "Имитация рассвета/заката"
void sunriseMode() {
  static unsigned long sunriseStart = 0;
  const unsigned long SUNRISE_DURATION = 30 * 60 * 1000; // 30 минут
  
  if (sunriseStart == 0) {
    sunriseStart = millis();
    Serial.println("🌅 Режим рассвета активирован");
  }
  
  unsigned long elapsed = millis() - sunriseStart;
  
  if (elapsed < SUNRISE_DURATION) {
    // 📈 Плавное увеличение яркости
    int brightness = map(elapsed, 0, SUNRISE_DURATION, 0, 255);
    analogWrite(EXTERNAL_LED_PIN, brightness);
    
    // 🌈 Изменение "цветовой температуры" (имитация RGB)
    int warmth = map(elapsed, 0, SUNRISE_DURATION, 255, 100);
    // Здесь можно добавить управление RGB светодиодом
  } else {
    sunriseStart = 0;  // Рассвет завершен
  }
}

// ⚡ Энергосберегающий режим
void energySaveMode(int lightPercent) {
  static unsigned long lastMotion = 0;
  const unsigned long MOTION_TIMEOUT = 5 * 60 * 1000; // 5 минут без движения
  
  // 🚶 Имитация датчика движения (можно заменить на реальный)
  bool motionDetected = (lightPercent < 20); // Условная логика
  
  if (motionDetected) {
    lastMotion = millis();
  }
  
  unsigned long timeSinceMotion = millis() - lastMotion;
  
  if (timeSinceMotion < MOTION_TIMEOUT && lightPercent < 30) {
    // 💡 Включаем освещение только при движении в темноте
    analogWrite(EXTERNAL_LED_PIN, 128); // 50% яркости для экономии
  } else {
    // 💤 Переходим в спящий режим
    analogWrite(EXTERNAL_LED_PIN, 0);
  }
  
  Serial.printf("⚡ Энергосбережение: движение %lu сек назад\n", 
                timeSinceMotion / 1000);
}

// 📅 Режим по расписанию
void scheduleMode() {
  // 🕐 Получаем текущее время (в реальном проекте используем RTC)
  unsigned long uptime = millis() / 1000;
  int hours = (uptime / 3600) % 24;
  int minutes = (uptime / 60) % 60;
  
  // 🌙 Ночное время: 22:00 - 06:00
  bool isNightTime = (hours >= 22 || hours < 6);
  
  // 🌆 Вечернее время: 18:00 - 22:00
  bool isEveningTime = (hours >= 18 && hours < 22);
  
  if (isNightTime) {
    analogWrite(EXTERNAL_LED_PIN, 50);   // Ночник
  } else if (isEveningTime) {
    analogWrite(EXTERNAL_LED_PIN, 200);  // Вечернее освещение
  } else {
    analogWrite(EXTERNAL_LED_PIN, 0);    // Дневное время - выключено
  }
  
  Serial.printf("📅 Расписание: %02d:%02d | Режим: %s\n", 
                hours, minutes,
                isNightTime ? "Ночник" : 
                isEveningTime ? "Вечер" : "День");
}

🎛️ “Интерфейс управления и настройки”

Система команд через Serial Monitor:

// 🎮 ИНТЕРФЕЙС УПРАВЛЕНИЯ ЧЕРЕЗ SERIAL

void handleSerialCommands() {
  if (Serial.available()) {
    String command = Serial.readStringUntil('\n');
    command.trim();
    command.toLowerCase();
    
    // 📋 Обработка команд
    if (command == "help") {
      printHelp();
    } else if (command == "status") {
      printDetailedStatus();
    } else if (command == "calibrate") {
      recalibrateSensor();
    } else if (command.startsWith("mode ")) {
      changeMode(command.substring(5));
    } else if (command.startsWith("threshold ")) {
      setThreshold(command.substring(10));
    } else if (command.startsWith("brightness ")) {
      setManualBrightness(command.substring(11).toInt());
    } else {
      Serial.println("❌ Неизвестная команда. Введите 'help' для справки");
    }
  }
}

// 📖 Справка по командам
void printHelp() {
  Serial.println("🎮 ДОСТУПНЫЕ КОМАНДЫ:");
  Serial.println("├ help - эта справка");
  Serial.println("├ status - подробный статус системы");
  Serial.println("├ calibrate - перекалибровка датчика");
  Serial.println("├ mode [auto|manual|schedule|energy] - смена режима");
  Serial.println("├ threshold [число] - установка порога включения");
  Serial.println("└ brightness [0-255] - ручная установка яркости");
}

// 📊 Подробный статус системы
void printDetailedStatus() {
  Serial.println("📊 СТАТУС СИСТЕМЫ ОСВЕЩЕНИЯ:");
  Serial.printf("├ Режим: %s\n", getModeString(currentMode));
  Serial.printf("├ Освещенность: %d%%\n", readLightPercent());
  Serial.printf("├ Порог включения: %d%%\n", TURN_ON_THRESHOLD);
  Serial.printf("├ Порог выключения: %d%%\n", TURN_OFF_THRESHOLD);
  Serial.printf("├ Текущая яркость: %d/255\n", currentBrightness);
  Serial.printf("├ Система освещения: %s\n", lightSystemOn ? "ВКЛ" : "ВЫКЛ");
  Serial.printf("└ Время работы: %lu сек\n", millis() / 1000);
}

// 🔄 Смена режима работы
void changeMode(String mode) {
  if (mode == "auto") {
    currentMode = MODE_AUTO;
    Serial.println("✅ Переключен в автоматический режим");
  } else if (mode == "manual") {
    currentMode = MODE_MANUAL;
    Serial.println("✅ Переключен в ручной режим");
  } else if (mode == "schedule") {
    currentMode = MODE_SCHEDULE;
    Serial.println("✅ Переключен в режим по расписанию");
  } else if (mode == "energy") {
    currentMode = MODE_ENERGY_SAVE;
    Serial.println("✅ Переключен в энергосберегающий режим");
  } else {
    Serial.println("❌ Неизвестный режим. Доступны: auto, manual, schedule, energy");
  }
}

Блок 4: “Интеграция с умным домом” (10 минут)

🌐 “Отправка данных освещенности на сервер”

Интеграция с IoT системой школы:

// 📡 ИНТЕГРАЦИЯ С ШКОЛЬНОЙ IoT СИСТЕМОЙ

#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

// 🌐 Настройки для отправки данных
const char* serverURL = "http://192.168.1.100/api/light-data";
unsigned long lastDataSend = 0;
const unsigned long DATA_SEND_INTERVAL = 30000; // Каждые 30 секунд

// 📊 Структура данных для отправки
struct LightData {
  String deviceName;
  String studentName;
  int lightLevel;        // 0-100%
  int rawValue;          // 0-4095
  bool autoLightOn;      // Состояние автоматического освещения
  String lightMode;      // Текущий режим
  float averageLight;    // Средняя освещенность за период
  int toggleCount;       // Количество переключений
};

LightData currentData;

// 📤 Функция отправки данных на сервер
void sendLightDataToServer() {
  if (WiFi.status() != WL_CONNECTED) return;
  
  // 📊 Подготавливаем данные
  currentData.deviceName = "ESP32_5А_LightSensor_" + String(ESP.getChipId());
  currentData.studentName = "Команда_1"; // Заменить на реальное имя
  currentData.lightLevel = readLightPercent();
  currentData.rawValue = analogRead(LIGHT_SENSOR_PIN);
  currentData.autoLightOn = lightSystemOn;
  currentData.lightMode = getModeString(currentMode);
  
  // 📋 Формируем JSON
  String jsonData = createLightJSON();
  
  // 🚀 Отправляем данные
  HTTPClient http;
  http.begin(serverURL);
  http.addHeader("Content-Type", "application/json");
  
  int responseCode = http.POST(jsonData);
  
  if (responseCode == 200) {
    Serial.println("📤 Данные освещенности отправлены на сервер");
  } else {
    Serial.printf("❌ Ошибка отправки: %d\n", responseCode);
  }
  
  http.end();
}

// 📋 Создание JSON с данными освещенности
String createLightJSON() {
  StaticJsonDocument<512> doc;
  
  doc["device"] = currentData.deviceName;
  doc["student"] = currentData.studentName;
  doc["sensor_type"] = "light";
  doc["light_level"] = currentData.lightLevel;
  doc["raw_value"] = currentData.rawValue;
  doc["auto_light_on"] = currentData.autoLightOn;
  doc["mode"] = currentData.lightMode;
  doc["timestamp"] = millis();
  doc["location"] = "Кабинет информатики";
  
  String jsonString;
  serializeJson(doc, jsonString);
  return jsonString;
}

// 📊 Сбор статистики для аналитики
void collectLightStatistics() {
  static int measurementCount = 0;
  static long lightSum = 0;
  static int lastToggleCount = 0;
  
  measurementCount++;
  lightSum += readLightPercent();
  
  // 📈 Каждые 10 измерений обновляем среднее
  if (measurementCount >= 10) {
    currentData.averageLight = (float)lightSum / measurementCount;
    measurementCount = 0;
    lightSum = 0;
  }
  
  // 🔄 Подсчет переключений системы освещения
  static bool lastLightState = false;
  if (lightSystemOn != lastLightState) {
    currentData.toggleCount++;
    lastLightState = lightSystemOn;
  }
}

📱 “Веб-интерфейс для мониторинга освещения”

Отображение данных на школьном дашборде:

🖥️ ВЕБ-ПАНЕЛЬ МОНИТОРИНГА ОСВЕЩЕНИЯ:

┌─────────────────────────────────────────────────┐
│ 💡 СИСТЕМА ОСВЕЩЕНИЯ - КЛАСС 5А                │
│ Обновлено: 2025-05-27 15:30:04                  │
├─────────────────────────────────────────────────┤
│ 📊 АКТИВНЫЕ ДАТЧИКИ ОСВЕЩЕННОСТИ: 6            │
│                                                 │
│ 🤖 ESP32_Команда1 | Иван Петров               │
│    💡 Освещенность: 45% | Авто-свет: ВЫКЛ      │
│    📈 Средняя за час: 52% | Переключений: 3    │
│                                                 │
│ 🤖 ESP32_Команда2 | Мария Сидорова            │
│    💡 Освещенность: 23% | Авто-свет: ВКЛ       │
│    📈 Средняя за час: 38% | Переключений: 5    │
├─────────────────────────────────────────────────┤
│ 📈 [График освещенности класса за день]        │
│ 💡 [График работы автоматического освещения]   │
│ ⚡ [Статистика энергопотребления]               │
├─────────────────────────────────────────────────┤
│ 🎛️ УПРАВЛЕНИЕ:                                 │
│ [Настроить пороги] [Режим экономии] [Расписание]│
└─────────────────────────────────────────────────┘

🎯 АНАЛИТИКА ОСВЕЩЕНИЯ:
- Среднее время работы авто-света: 2.3 часа/день
- Экономия электроэнергии: 23% по сравнению с ручным режимом  
- Пиковая освещенность: 89% (окно, 12:15)
- Минимальная освещенность: 8% (под партой, 14:23)

🎨 Творческое задание: “Умная система освещения класса” (12 минут)

🏠 “Создание интеллектуальной системы освещения”

Техническое задание для команд:

🎯 ПРОЕКТ "УМНОЕ ОСВЕЩЕНИЕ КЛАССА 5А":

Обязательные функции:
✅ Автоматическое включение/выключение по освещенности
✅ Плавное изменение яркости (fade in/out)
✅ Система предотвращения мигания (гистерезис)
✅ Калибровка под условия класса
✅ Отправка данных на школьный сервер

Дополнительные функции (выбрать 2-3):
🌅 Режим "Рассвет" - имитация естественного освещения
⚡ Энергосберегающий режим с детекцией активности
📅 Программируемое расписание работы
🎨 Цветовая индикация уровня освещенности (RGB)
🔊 Звуковые уведомления о критических изменениях
📊 Детальная статистика и аналитика
🎮 Управление через Serial команды
📱 Мобильное приложение (web-интерфейс)

📋 “Паспорт умной системы освещения”

Документация проекта:

📄 ПАСПОРТ СИСТЕМЫ ОСВЕЩЕНИЯ
Команда: _________________ Дата: 2025-05-27

🎯 НАЗВАНИЕ: "LightMaster [название_команды]"

⚙️ ТЕХНИЧЕСКИЕ ХАРАКТЕРИСТИКИ:
- Датчик: Фоторезистор + делитель напряжения
- Диапазон измерений: 0-100% освещенности
- Точность: ±5% после калибровки
- Время отклика: _____ секунд
- Плавность изменения: _____ секунд fade
- Гистерезис: _____% (предотвращение мигания)

🔧 СХЕМА И ПОДКЛЮЧЕНИЕ:
[Рисунок схемы подключения]
- Фоторезистор: между +3.3V и GPIO 34
- Постоянный резистор: _____ кОм
- Исполнительное устройство: GPIO _____

💻 ПРОГРАММНЫЕ ВОЗМОЖНОСТИ:
□ Базовая автоматика вкл/выкл
□ Плавное изменение яркости
□ Система гистерезиса
□ Автоматическая калибровка
□ Отправка данных на сервер
□ Дополнительная функция 1: _______________
□ Дополнительная функция 2: _______________
□ Дополнительная функция 3: _______________

📊 КАЛИБРОВКА И ТЕСТИРОВАНИЕ:
Условия калибровки:
- Максимальная освещенность: прямой солнечный свет
- Минимальная освещенность: закрытый датчик
- Диапазон сырых значений: _____ - _____
- Диапазон в процентах: 0% - 100%

Тестовые сценарии:
□ Постепенное затемнение комнаты
□ Резкое включение/выключение света
□ Частичное закрытие окна
□ Движение тени по датчику
□ Длительная работа (>30 минут)

🌟 УНИКАЛЬНЫЕ ОСОБЕННОСТИ:
Наша "фишка": ____________________________
__________________________________________

Отличие от других команд: _______________
__________________________________________

📈 РЕЗУЛЬТАТЫ ИСПЫТАНИЙ:
Время работы без сбоев: _____ минут
Количество ложных срабатываний: _____
Энергоэффективность: ____% экономии
Скорость реакции на изменения: _____ сек

✅ ПРОВЕРКА ФУНКЦИОНАЛЬНОСТИ:
□ Система включается в темноте
□ Система выключается при достаточном свете  
□ Нет мигания при пограничных условиях
□ Плавное изменение яркости работает
□ Данные корректно отправляются на сервер
□ Все дополнительные функции работают

🏆 САМООЦЕНКА ПРОЕКТА:
Техническая сложность: ⭐⭐⭐⭐⭐
Креативность решения: ⭐⭐⭐⭐⭐
Стабильность работы: ⭐⭐⭐⭐⭐
Пользовательский интерфейс: ⭐⭐⭐⭐⭐
Общая оценка: ⭐⭐⭐⭐⭐

🎪 “Выставка систем умного освещения”

Презентация и демонстрация:

  • Каждая команда демонстрирует свою систему (4 минуты)
  • Показывает реакцию на изменение освещенности
  • Демонстрирует уникальные функции
  • Проводит сравнительные тесты с другими командами
  • Объясняет техническое решение и алгоритмы

📝 Рефлексия и закрепление (5 минут)

💡 “Викторина световых технологий”

Быстрые вопросы с демонстрацией:

❓ ПОКАЖИ НА ДАТЧИКЕ:
1. Где сопротивление больше - на свету или в темноте? (закрыть/открыть)
2. Сколько процентов должно быть для включения света? (показать пальцами)
3. Что такое гистерезис? (показать руками "зону неопределенности")
4. Зачем нужна плавность? (плавно поднять/опустить руку)

📊 “Шкала мастерства умного освещения”

🎚️ УРОВЕНЬ ВЛАДЕНИЯ СВЕТОВЫМИ СИСТЕМАМИ:

🏆 Инженер освещения (100%):
"Создаю сложные системы, понимаю алгоритмы, интегрирую с IoT"

🥇 Программист автоматики (75%):
"Программирую автоматические системы, настраиваю пороги и режимы"

🥈 Техник-электронщик (50%):
"Подключаю датчики освещенности, понимаю принципы работы"

🥉 Световой новичок (25%):
"Знаю что такое фоторезистор и автоматическое освещение"

Покажите рукой свой уровень!

💭 “Световые размышления”

Каждый ученик завершает фразу:

  • “Автоматическое освещение полезно потому что…”
  • “Самое сложное в датчиках света…”
  • “В моем доме я бы установил…”
  • “Удивило меня то что…”

🏠 Домашнее задание

💡 “Домашний световой инженер”

Основное задание:

  1. Исследование домашнего освещения

    • Измерить освещенность в разных комнатах в разное время
    • Найти места, где нужно автоматическое освещение
    • Посчитать потенциальную экономию энергии
  2. Эксперименты с программой

    • Настроить пороги под домашние условия
    • Добавить новый режим работы (например, “Чтение”)
    • Попробовать разные алгоритмы плавности
  3. Дневник светового инженера

📔 МОЙ ДНЕВНИК СВЕТОВОГО ИНЖЕНЕРА - УРОК 13

💡 ГЛАВНЫЕ ОТКРЫТИЯ:
- Фоторезистор работает так: ________________
- Делитель напряжения нужен для: ____________
- Гистерезис предотвращает: _________________

🔧 МОЯ СИСТЕМА ОСВЕЩЕНИЯ:
Порог включения: ____%
Порог выключения: ____%
Время плавности: ____ секунд
Самая крутая функция: ______________________

🏠 ДОМАШНИЕ ИЗМЕРЕНИЯ:
Кухня утром: ____%    |  Кухня вечером: ____%
Спальня днем: ____%   |  Спальня ночью: ____%
Коридор: ____%        |  Ванная: ____%

Где нужна автоматика: _______________________
Потенциальная экономия: ____% электричества

💻 ПРОГРАММНЫЕ ДОСТИЖЕНИЯ:
Сложность моего алгоритма: ⭐⭐⭐⭐⭐
Какую ошибку исправил: ______________________
Новая функция которую добавил: ______________

🌟 ИДЕИ ДЛЯ РАЗВИТИЯ:
1. _________________________________________
2. _________________________________________
3. _________________________________________

🔬 Исследовательское задание (для увлеченных):

  • Изучить профессиональные датчики освещенности (люксметры)
  • Найти информацию о стандартах освещенности для разных помещений
  • Исследовать системы умного освещения в продаже

🎨 Творческое задание:

  • Нарисовать план умного дома с системой автоматического освещения
  • Создать инфографику “Экономия энергии с умным освещением”

📊 Критерии оценивания

“Отлично” (5):

  • Понимает принципы работы фоторезисторов и делителей напряжения
  • Правильно калибрует датчик освещенности под конкретные условия
  • Создает стабильную систему автоматического освещения с гистерезисом
  • Программирует дополнительные режимы работы и функции
  • Интегрирует систему с IoT платформой школы
  • Демонстрирует творческий подход к решению задач освещения

“Хорошо” (4):

  • Понимает основы работы световых датчиков
  • Подключает и программирует базовую систему автоматического освещения
  • Выполняет калибровку датчика
  • Создает работающую систему с основными функциями
  • Понимает необходимость предотвращения ложных срабатываний

“Удовлетворительно” (3):

  • Имеет общее представление о датчиках освещенности
  • С помощью создает простую систему включения света в темноте
  • Понимает базовые принципы автоматизации
  • Участвует в групповой работе над проектом

🛠️ Материалы и оборудование

Для каждой команды (3-4 человека):

  • ESP32 DevKit плата
  • Фоторезистор (LDR) 5-10 кОм
  • Резистор 10 кОм (для делителя напряжения)
  • Светодиод + резистор 220 Ом (для индикации)
  • Макетная плата и провода
  • Мультиметр для диагностики

Для демонстраций учителем:

  • Различные источники света (фонарик, лампа, солнечный свет)
  • Люксметр для эталонных измерений
  • Осциллограф для демонстрации аналоговых сигналов
  • Различные типы фоторезисторов для сравнения

Программное обеспечение:

  • Arduino IDE с библиотеками для работы с аналоговыми датчиками
  • Serial Plotter для визуализации изменений освещенности
  • Веб-интерфейс школьного сервера для мониторинга

Дополнительные компоненты (для продвинутых проектов):

  • RGB светодиод для цветовой индикации
  • Потенциометр для ручной настройки порогов
  • LCD дисплей для отображения текущих значений
  • Реле для управления внешними нагрузками
  • PIR датчик движения для комбинированных систем

🔍 Методические заметки для учителя

Подготовка к уроку:

  1. Тестирование датчиков: Проверить все фоторезисторы на различия в характеристиках
  2. Условия освещения: Подготовить возможность изменения освещенности в классе
  3. Эталонные измерения: Подготовить люксметр для сравнения с самодельными датчиками
  4. Схемы подключения: Создать крупные наглядные схемы делителей напряжения

Возможные сложности:

Проблема: Большой разброс характеристик фоторезисторов Решение: Обязательная индивидуальная калибровка каждого датчика

Проблема: Нестабильность показаний из-за внешнего освещения Решение: Использование усреднения, экранирование датчиков

Проблема: Сложность понимания концепции гистерезиса Решение: Физическая демонстрация с термостатом или другими примерами

Безопасность:

  • Контроль яркости источников света (не использовать слишком яркие)
  • Правильное подключение питания к делителям напряжения
  • Осторожность при работе с паяльными принадлежностями (если используются)

Дифференциация обучения:

  • Для продвинутых: изучение цифровых датчиков освещенности, сложные алгоритмы
  • Для начинающих: готовые схемы, упрощенные пороговые алгоритмы
  • Для визуалов: графики изменения освещенности, схемы и диаграммы
  • Для практиков: больше экспериментов с различными источниками света

Связь с реальным миром:

  • Уличное освещение с датчиками движения и света
  • Системы умного дома
  • Автомобильные фары с автоматическим включением
  • Энергосберегающие технологии в офисах и торговых центрах

Межпредметные связи:

  • Физика: оптика, полупроводники, фотоэффект
  • Экология: энергосбережение, влияние искусственного освещения
  • Математика: работа с процентами, пропорции, графики функций
  • ОБЖ: правильное освещение рабочих мест

Развитие проекта:

  • Добавление датчиков движения для комплексных систем
  • Интеграция с системами климат-контроля
  • Создание мобильного приложения для управления
  • Анализ больших данных об освещенности для оптимизации