Модуль 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 разметка не поддерживается! Используйте обычный текст.
    Плохо           Хорошо
Arduino NANO шилд на DIN-рейку без корпуса

Arduino NANO шилд на DIN-рейку без корпуса

Главный модуль для построения домашней или промышленной системы автоматического управления на основе..

557.49грн.

Шестерня для зубчатого ремня на 36 зубьев под ось 5 мм

Шестерня для зубчатого ремня на 36 зубьев под ось 5 мм

Используется для передачи и редукции крутящего момента от двигателя до оси 5 ммКоличество зубьев 36 ..

79.68грн.

Силовой MOSFET транзистор IRF520 N-канальный

Силовой MOSFET транзистор IRF520 N-канальный

MOSFET транзистор 3-го поколенияИспользуется для скоростной коммутации мощных исполнительных механиз..

28.43грн.

Автоматическое открытие окна по температуре — проект на Arduino

Автоматическое открытие окна по температуре — проект на Arduino

Сколько раз вы просыпались от холода летом или осенью, забыв закрыть окно перед сном? Слишком жарк..

Модуль MP3-плеера GW

Модуль MP3-плеера GW

Полностью автономный mp3-плеер с питанием 5 В. Миниатюрный, имеет на борту кнопки управления. Читает..

89.24грн.