Модуль 8 — Финальный проект (курс для начинающих)

Цель модуля: применить все полученные знания и навыки для создания законченного проекта на Arduino, который включает как минимум один датчик, одно исполнительное устройство и систему вывода информации.


Задача

Необходимо собрать устройство, которое использует:

  • Минимум 1 датчик (температуры, влажности, освещенности, движения и т.д.)
  • Минимум 1 исполнительное устройство (светодиод, мотор, реле)
  • Вывод информации (светодиоды или дисплей)

Возможные проекты

1. Мини-метеостанция

Датчик: DHT11 или DHT22 (температура и влажность)
Вывод информации: LCD 1602 или OLED дисплей
Исполнительное устройство: светодиод, загорающийся при превышении температуры

#include <DHT.h>
#include <LiquidCrystal_I2C.h>

DHT dht(2, DHT11);
LiquidCrystal_I2C lcd(0x27, 16, 2);
int ledPin = 7;

void setup() {
  dht.begin();
  lcd.init();
  lcd.backlight();
  pinMode(ledPin, OUTPUT);
}

void loop() {
  float t = dht.readTemperature();
  float h = dht.readHumidity();

  lcd.setCursor(0,0);
  lcd.print("Temp: "); lcd.print(t); lcd.print("C");
  lcd.setCursor(0,1);
  lcd.print("Hum: "); lcd.print(h); lcd.print("%");

  if (t > 28) digitalWrite(ledPin, HIGH);
  else digitalWrite(ledPin, LOW);

  delay(2000);
}

2. Автоматическая кормушка

Идея: устройство раз в заданное время открывает крышку кормового отсека с помощью сервопривода. DS3231 отвечает за точное время, LED или LCD показывает статус и ближайшую кормёжку.

Комплектующие

Компонент Примечание
Arduino Uno/Nano Контроллер
RTC DS3231 (I2C) Точные часы; адрес I2C обычно 0x68
Сервопривод SG90/МG90S Открывание крышки/заслонки
LED + резистор 220–330 Ω Индикация выдачи
(Опционально) LCD 1602 I2C Вывод времени и статуса
Отдельный БП 5 В ≥ 1 А Питание сервопривода (общая земля!)
Провода, макетная плата, крепёж Монтаж

Подключение

  • DS3231: VCC → 5V, GND → GND, SDA → A4, SCL → A5 (для Uno/Nano).
  • Сервопривод: красный → +5V БП, коричневый/чёрный → GND (общий с Arduino), оранжевый/жёлтый (сигнал) → D9.
  • LED: через резистор к D7, второй вывод на GND.
  • LCD 1602 I2C (опц.): VCC → 5V, GND → GND, SDA → A4, SCL → A5.

Важно: питание сервопривода — от отдельного 5В‑источника. GND БП сервопривода и GND Arduino должны быть соединены.

Логика работы

  1. На старте устройство считывает текущее время с DS3231.
  2. В массиве заданы несколько ежедневных кормёжек (например, 08:00 и 19:30).
  3. Каждую минуту устройство сравнивает время; при совпадении:
    • включается LED-индикация,
    • серво плавно открывает заслонку, выдерживает паузу, закрывает,
    • на LCD обновляется «След. кормёжка».

Скетч Arduino

#include <Wire.h>
#include <RTClib.h>          // библиотека для DS3231
#include <Servo.h>
#include <LiquidCrystal_I2C.h> // закомментируйте, если без дисплея

// ===== НАСТРОЙКИ =====
const int SERVO_PIN = 9;
const int LED_PIN   = 7;
const int OPEN_ANGLE  = 100;   // угол открытия заслонки
const int CLOSE_ANGLE = 0;     // угол закрытия
const int OPEN_MS     = 1500;  // сколько держать открытой, мс

// Время кормёжек (24-часовой формат)
const uint8_t FEEDS = 2;
uint8_t feedHour[FEEDS]   = {8, 19};
uint8_t feedMinute[FEEDS] = {0, 30};

// ===== ОБЪЕКТЫ =====
RTC_DS3231 rtc;
Servo gate;
LiquidCrystal_I2C lcd(0x27, 16, 2); // если без LCD, закомментируйте все строки с lcd

// Чтобы не кормить дважды в одну минуту
bool fedThisMinute[FEEDS] = {false, false};

void setup() {
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);

  gate.attach(SERVO_PIN);
  gate.write(CLOSE_ANGLE);

  Wire.begin();
  rtc.begin();

  // *** Однократно раскомментируйте для установки времени по ПК:
  // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

  lcd.init(); lcd.backlight();
  lcd.setCursor(0,0); lcd.print("Auto Feeder");
  lcd.setCursor(0,1); lcd.print("Init...");

  delay(800);
  updateNextFeedOnLCD();
}

void loop() {
  DateTime now = rtc.now();

  // Сброс маркеров "кормление было в минуту X" при смене минуты
  static int lastMinute = -1;
  if (now.minute() != lastMinute) {
    lastMinute = now.minute();
    for (uint8_t i = 0; i < FEEDS; i++) fedThisMinute[i] = false;
    updateNextFeedOnLCD(now);   // реже обновляем LCD
  }

  // Проверка расписания (точность до минуты)
  for (uint8_t i = 0; i < FEEDS; i++) {
    if (!fedThisMinute[i] &&
        now.hour() == feedHour[i] &&
        now.minute() == feedMinute[i]) {
      performFeeding(i);
      fedThisMinute[i] = true;
    }
  }

  delay(200); // экономим CPU, достаточно опроса несколько раз в секунду
}

void performFeeding(uint8_t idx) {
  // Индикация
  digitalWrite(LED_PIN, HIGH);
  lcd.clear();
  lcd.setCursor(0,0); lcd.print("Feeding #"); lcd.print(idx+1);
  lcd.setCursor(0,1); lcd.print("Opening...");

  // Плавное открытие
  for (int a = CLOSE_ANGLE; a <= OPEN_ANGLE; a += 3) {
    gate.write(a);
    delay(15);
  }
  delay(OPEN_MS);

  // Плавное закрытие
  for (int a = OPEN_ANGLE; a >= CLOSE_ANGLE; a -= 3) {
    gate.write(a);
    delay(15);
  }

  digitalWrite(LED_PIN, LOW);
  updateNextFeedOnLCD(); // показать следующее время
}

void updateNextFeedOnLCD() {
  updateNextFeedOnLCD(rtc.now());
}

void updateNextFeedOnLCD(const DateTime &now) {
  // Найти ближайшую будущую кормёжку
  int best = -1;
  long bestDelta = 24L*60L + 1;
  long curMin = now.hour()*60L + now.minute();

  for (uint8_t i = 0; i < FEEDS; i++) {
    long t = feedHour[i]*60L + feedMinute[i];
    long delta = t - curMin;
    if (delta < 0) delta += 24L*60L; // на следующий день
    if (delta < bestDelta) { bestDelta = delta; best = i; }
  }

  char buf[6];
  sprintf(buf, "%02d:%02d", feedHour[best], feedMinute[best]);

  lcd.clear();
  lcd.setCursor(0,0); lcd.print("Next feed:");
  lcd.setCursor(0,1); lcd.print(buf);
}

Как изменить расписание

Вверху скетча отредактируйте массивы feedHour[] и feedMinute[]. Количество кормёжек задаётся константой FEEDS. Например, три раза в день: 07:30, 13:00, 21:15.

Механика и калибровка

  • Используйте заслонку/шибер с минимальным трением. Для тяжёлых заслонок лучше сервопривод металлизированный (MG90S) или редукторный.
  • Подберите углы OPEN_ANGLE/CLOSE_ANGLE так, чтобы отверстие открывалось полностью, но серво не упирался в ограничители.
  • При первой настройке уменьшайте OPEN_MS и постепенно увеличивайте до нужной порции корма.

Безопасность и надёжность

  • Сервопривод запитывайте от отдельного 5В блока ≥ 1 А. Обязательно общий GND с Arduino.
  • Провода питания серво делайте короткими и толстыми; при длинных — добавьте электролит 470–1000 мкФ у серво.
  • Продумайте «ручной режим»: дополнительная кнопка на пине D4 может вызывать performFeeding() для тестов.
  • Защитите механизм от заклинивания: лёгкая пружина на закрытие уменьшит нагрузку на серво.

Типичные ошибки

  • Дёргается дисплей/перезагрузка Arduino: недостаток тока у БП, общая линия 5 В для серво и платы — разнесите питание, соедините только GND.
  • Время «плавает»: не инициализирован DS3231. Однократно раскомментируйте строку rtc.adjust(...) в setup() для установки времени.
  • Серво не движется: перепутан сигнальный провод, неверный пин, неверные углы.

Расширения

  • Меню на LCD для изменения времени без перепрошивки (кнопки «вверх/вниз/ок» на A1–A3).
  • Логика «кормить N грамм»: ставим весовой датчик HX711 и подбираем длительность открытия до целевого веса.
  • Уведомления в Telegram/MQTT при выдаче корма (ESP8266/ESP32).

3. Сигнализация на движение

Идея: при обнаружении движения PIR‑датчиком (например, HC‑SR501) устройство включает сирену (или лампу через реле), мигает светодиодом и выводит предупреждение на дисплей.

Комплектующие

КомпонентНазначение / примечание
Arduino Uno/NanoКонтроллер системы
PIR HC‑SR501Выход OUT — цифровой сигнал HIGH при движении; на плате есть регуляторы чувствительности и времени удержания
Модуль реле 5 ВУправление лампой/сиреной. Лучше взять реле‑модуль с оптронами
Светодиод + резистор 220–330 ΩИндикация тревоги
(Опц.) LCD 1602 I2CТекстовые сообщения: «Охрана», «Движение», «Тревога»
БЗ 5 В ≥ 1 АСтабильное питание, общая земля для всех модулей
Провода, макетная плата/корпусМонтаж та безопасное размещение

Схема подключения

  • PIR: VCC → 5V, GND → GND, OUT → D2.
  • Реле: IN → D8, VCC → 5V, GND → GND. НО/НЗ контакты реле подключаются к вашей нагрузке (сирена/лампа). С сетевым напряжением работайте только при наличии навыков и соблюдая ПУЭ!
  • LED: через резистор к D13 (или другой пин), второй вывод → GND.
  • LCD 1602 I2C (опц.): VCC → 5V, GND → GND, SDA → A4, SCL → A5.

Совет: на PIR‑модуле выставьте режим H (повторный) для стабильной работы тревоги и подберите регуляторами чувствительность и время удержания.

Логика работы

  1. Система имеет два состояния: Охрана включена (ARMED) и выключена (DISARMED). Для простоты стартуем в ARMED.
  2. Фиксация движения (OUT=HIGH) → задержка фильтрации (дребезг/ложные) → Тревога: включить реле/сирену, мигать LED, показать предупреждение.
  3. После тревоги — охлаждение (cooldown), чтобы не «дребезжать» тревогами подряд.
  4. (Опц.) Кнопкой можно переключать ARMED/DISARMED; здесь опустим для краткости.

Базовый скетч (с поддержкой LCD по флагу)

#include <Wire.h>
#include <LiquidCrystal_I2C.h> // если дисплея нет, установите USE_LCD false

// ====== НАСТРОЙКИ ======
const bool USE_LCD = true;          // поставить false, если LCD нет
const uint8_t PIR_PIN   = 2;        // вход PIR
const uint8_t RELAY_PIN = 8;        // выход на реле
const uint8_t LED_PIN   = 13;       // индикация тревоги

// задержки, мс
const unsigned long TRIGGER_FILTER_MS = 80;    // антиложный фильтр
const unsigned long ALARM_DURATION_MS = 10000; // длительность тревоги
const unsigned long COOLDOWN_MS       = 5000;  // пауза после тревоги

LiquidCrystal_I2C lcd(0x27, 16, 2);

enum State { ARMED, ALARM, COOLDOWN };
State state = ARMED;

unsigned long tState = 0;           // таймер текущего состояния
unsigned long tMotionStart = 0;     // таймер подтверждения движения

void lcdInitIfUsed() {
  if (!USE_LCD) return;
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0,0); lcd.print("PIR Security");
  lcd.setCursor(0,1); lcd.print("ARMED");
}

void lcdShow(const char* l1, const char* l2) {
  if (!USE_LCD) return;
  lcd.clear();
  lcd.setCursor(0,0); lcd.print(l1);
  lcd.setCursor(0,1); lcd.print(l2);
}

void setup() {
  pinMode(PIR_PIN,   INPUT);       // у HC-SR501 уже своя подтяжка
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(LED_PIN,   OUTPUT);

  digitalWrite(RELAY_PIN, LOW);
  digitalWrite(LED_PIN,   LOW);

  lcdInitIfUsed();
}

void loop() {
  bool motion = digitalRead(PIR_PIN) == HIGH;
  unsigned long now = millis();

  switch (state) {
    case ARMED:
      if (motion) {
        if (tMotionStart == 0) tMotionStart = now;
        // подтверждаем движение по истечении фильтра
        if (now - tMotionStart >= TRIGGER_FILTER_MS) {
          // Тревога
          digitalWrite(RELAY_PIN, HIGH);  // включить сирену/лампу
          lcdShow("ALARM!", "Motion detect"); // текст
          tState = now;
          state = ALARM;
        }
      } else {
        tMotionStart = 0;
        // моргаем LED редким миганием — "охрана активна"
        digitalWrite(LED_PIN, (now/500)%2);
        if (USE_LCD && (now/2000)%2==0) lcdShow("ARMED", "Waiting motion");
      }
      break;

    case ALARM:
      // быстрое мигание LED во время тревоги
      digitalWrite(LED_PIN, (now/150)%2);
      if (now - tState >= ALARM_DURATION_MS) {
        // Выключить сирену/лампу и перейти в охлаждение
        digitalWrite(RELAY_PIN, LOW);
        digitalWrite(LED_PIN, LOW);
        lcdShow("COOLDOWN", "Please wait...");
        tState = now;
        state = COOLDOWN;
      }
      break;

    case COOLDOWN:
      // блокируем повторные срабатывания на время "охлаждения"
      if (now - tState >= COOLDOWN_MS) {
        state = ARMED;
        tMotionStart = 0;
        lcdShow("ARMED", "Ready");
      }
      break;
  }
}

Как добавить дисплей позже

Если хотите сначала протестировать без экрана, установите USE_LCD = false — сообщения просто не будут выводиться, остальная логика сохранится.

Рекомендации по настройке PIR

  • Перемычку установите в режим H (Repeatable) — выход остаётся HIGH при непрерывном движении.
  • Регулятор TIME (на плате) задаёт длительность удержания OUT=HIGH после срабатывания. Для системы с программным таймером ставьте среднее значение.
  • Регулятор SENS — чувствительность. Уменьшите при ложных срабатываниях.

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

  • При работе с сетевым напряжением подключайте лампу/сирену только через реле‑модуль, соблюдая изоляцию и расстояния. Корпус — негорючий.
  • Обеспечьте общую землю для Arduino, PIR и реле. Питание берите с запасом по току.
  • Если вместо реле используется транзисторная схема для 12 В сирены — ставьте обратный диод параллельно катушке/нагрузке.

Расширения

  • Кнопка «Охрана»: переключение ARMED/DISARMED (например, пин D4 с INPUT_PULLUP).
  • Запись событий: метка времени с DS3231, вывод на LCD или в Serial.
  • Тихая тревога: вместо сирены — только подсветка/сообщение.
  • Уведомления: отправка в Telegram/MQTT (ESP8266/ESP32).

Типичные ошибки

  • Сирена «дребезжит»: уменьшите чувствительность PIR, увеличьте TRIGGER_FILTER_MS и/или ALARM_DURATION_MS.
  • LCD пустой: неверный адрес I2C. Просканируйте шину (часто 0x27 или 0x3F).
  • Реле щёлкает при старте: инициализируйте пин как OUTPUT и сразу ставьте LOW.

План работы

  1. Выберите идею проекта.
  2. Составьте список необходимых компонентов.
  3. Соберите схему на макетной плате.
  4. Напишите и загрузите программу в Arduino.
  5. Протестируйте и устраните ошибки.
  6. При желании — соберите проект в корпусе.

Советы

  • Старайтесь использовать уже изученные модули и команды.
  • Для финального проекта можно комбинировать несколько датчиков.
  • Обязательно подумайте о питании и безопасности устройства.

Контрольные вопросы

  1. Какие три обязательные части должен содержать финальный проект?
  2. Как можно улучшить проект в будущем?
  3. Чем полезна отладка в процессе сборки?

Авторский курс по Arduino для начинающих. Использование материалов на коммерческих сайтах допускается с указанием источника.

<< Проекты << Все товары >> Статьи, уроки >>

Написать отзыв

Примечание: HTML разметка не поддерживается! Используйте обычный текст.
    Плохо           Хорошо
Модуль Bluetooth SPP-C

Модуль Bluetooth SPP-C

Протокол связи : Bluetooth спецификация v2.1+EDRРадиус действия : до 10 метров (уровень мощности 2)Н..

112.48грн.

Кнопка металлическая герметичная 16мм (латунь, IP65, 3A, без фиксации)

Кнопка металлическая герметичная 16мм (латунь, IP65, 3A, без фиксации)

Надёжная влагозащищённая кнопка без фиксации диаметром 16 мм. Изготовлена из латуни с никелевым покр..

82.91грн.

Датчик влажности и температуры DHT21

Датчик влажности и температуры DHT21

Датчик влажности и температуры DHT21 (AM2301) – точный цифровой сенсор для Arduino и других микрокон..

261.32грн.

Обзор плат Arduino

Обзор плат Arduino

Оригинальный Arduino был разработан для одной специфической задачи, и справился с этой задачей в сов..

Датчик температуры аналоговый 10К

Датчик температуры аналоговый 10К

Датчик температуры аналоговый NTC 10K Аналоговый датчик температуры NTC 10K ±1% — это высокоточный ..

44.68грн.