Загрузка данных
Ответы на контрольные вопросы
* Принцип работы датчика DHT22 и возвращаемые данные
Внутри корпуса DHT22 установлены емкостный сенсор влажности, термистор (терморезистор) для измерения температуры и встроенный микроконтроллер. Микроконтроллер датчика преобразует аналоговые сигналы с обоих чувствительных элементов в цифровую форму и отправляет их по однопроводному цифровому протоколу (1-Wire-подобный протокол) пакетом из 40 бит (16 бит влажности, 16 бит температуры и 8 бит контрольной суммы). Датчик возвращает два параметра: относительную влажность воздуха (в процентах от 0 до 100% с точностью 0,1%) и температуру окружающей среды (в градусах Цельсия в диапазоне от -40 до +80 °C с точностью 0,1 °C).
* Отличие методов readTemperature() и readHumidity()
Оба метода запрашивают единый 40-битный пакет данных от датчика, но извлекают и масштабируют разные части этого пакета:
* readHumidity() считывает первые 16 бит пакета, преобразует их в число с плавающей точкой (float) и возвращает значение относительной влажности воздуха в процентах.
* readTemperature() считывает следующие 16 бит (учитывая знаковый бит отрицательных температур), масштабирует их и возвращает температуру в градусах Цельсия (по умолчанию) либо Фаренгейта (если передать аргумент true).
* Назначение функции isnan()
Функция isnan() (is Not a Number) проверяет, является ли переданная переменная с плавающей точкой специальным значением NaN (не число). Если при опросе датчика произошел физический сбой (обрыв провода, отсутствие питания, таймаут шины данных или ошибка контрольной суммы), библиотека возвращает NaN. Проверка if (isnan(h) || isnan(t)) позволяет вовремя обнаружить аварию датчика и не допустить выполнения некорректных математических сравнений в логике управления.
* Принцип работы библиотеки Servo.h
Библиотека генерирует широтно-импульсный модулированный сигнал (ШИМ / PPM) с помощью встроенных аппаратных таймеров микроконтроллера (в случае Arduino Uno используется Timer 1). На управляющий пин сервопривода циклически подаются прямоугольные импульсы с фиксированным периодом повторения 20 мс (частота 50 Гц). Длительность положительного импульса определяет требуемый угол поворота вала: импульс длительностью около 1000 мкс соответствует углу 0^\circ, 1500 мкс — 90^\circ, а 2000 мкс — 180^\circ. Метод write(angle) пересчитывает угол в градусах в соответствующую длительность импульса в микросекундах.
* Почему сервопривод задает угол, а обычный двигатель постоянного тока — нет
Сервопривод представляет собой замкнутую систему автоматического регулирования с отрицательной обратной связью. В одном корпусе объединены двигатель постоянного тока, понижающий редуктор, датчик положения выходного вала (потенциометр) и плата управления (компаратор/драйвер). Встроенная схема сравнивает фактическое положение вала по потенциометру с целевым сигналом от контроллера и вращает мотор ровно до тех пор, пока рассогласование не станет равным нулю. Обычный двигатель постоянного тока — это разомкнутая система: он просто вращается при подаче напряжения, у него нет внутреннего датчика угла и встроенного контроллера, поэтому без внешнего энкодера и управляющего алгоритма зафиксировать точный угол невозможно.
* Назначение функции tone()
Функция tone(pin, frequency) предназначена для генерации аппаратного меандра (прямоугольного сигнала) заданной частоты с коэффициентом заполнения 50% на указанном цифровом выводе. Сигнал заставляет мембрану пассивного пьезозуммера колебаться с заданной частотой, создавая звук определенной высоты (тональности). Для выключения звука используется парная функция noTone(pin).
* Влияние резистора на работу светодиода
Светодиод — полупроводниковый прибор с нелинейной вольт-амперной характеристикой и крайне малым внутренним сопротивлением в открытом состоянии. Резистор выполняет роль токоограничивающего элемента. Без резистора ток через p-n-переход лавинообразно превысит допустимый максимум (для обычных индикаторных светодиодов — 20 мА), что приведет к тепловому пробою светодиода и выходу из строя выходного каскада цифрового пина Arduino (максимум 40 мА). При этом чрезмерно высокое сопротивление резистора слишком сильно снизит ток, сделав свечение светодиода тусклым.
* Применение конструкции if, else if и else
Конструкция с взаимоисключающими ветвлениями обеспечивает строгий приоритет режимов и гарантирует выполнение ровно одной управляющей ветки за проход цикла:
* Сначала проверяются наиболее критические состояния (ошибка датчика или аварийный перегрев выше 32 °C).
* Если верхнее условие выполнено, контроллер отрабатывает его блок и пропускает все последующие else if и else.
* Это исключает логические конфликты — например, если температура выше 32 °C, она одновременно выше и 27 °C, но сработает именно аварийный режим, а не режим умеренного охлаждения. Ветка else охватывает штатный режим, когда ни одно предупредительное условие не наступило.
* Недостаток использования delay(2000)
Функция delay() является блокирующей. На время ее выполнения (2000 мс) процессор микроконтроллера останавливается в пустом цикле, переставая выполнять остальной код. В этот интервал времени контроллер не может реагировать на нажатия кнопок, обновлять анимацию светодиодов, менять параметры звука или оперативно обрабатывать прерывания. В реальных управляющих системах вместо delay() используют неблокирующий тайминг на основе системного счетчика миллисекунд millis().
* Что такое гистерезис, зачем он нужен и как его реализовать
* Зачем нужен: В окрестностях порогового значения (например, ровно 27^\circ\text{C}) температура может колебаться на десятые доли градуса из-за шумов датчика или движения воздуха. Без гистерезиса заслонка и сигнализация будут непрерывно переключаться туда-обратно («дребезг» исполнительного механизма), что приведет к быстрому механическому износу редуктора сервопривода и перегреву электроники.
* Суть: Вводятся два раздельных порога: верхний порог включения (например, открытие при T > 27^\circ\text{C}) и нижний порог выключения (закрытие только при остывании ниже 25^\circ\text{C}). Разница между порогами (2^\circ\text{C}) называется петлей гистерезиса.
* Как реализовать: В код вводится логическая переменная состояния заслонки (bool isVentOpen), а переключение выполняется по раздельной логике:
static bool isVentOpen = false;
if (!isVentOpen && t > 27.0) {
isVentOpen = true; // Включаем охлаждение при превышении 27 °C
damperServo.write(90);
} else if (isVentOpen && t < 25.0) {
isVentOpen = false; // Выключаем охлаждение только после остывания ниже 25 °C
damperServo.write(10);
}