Модуль 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/MG90S | Відкривання кришки/заслінки |
| 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 мають бути з’єднані.
Логіка роботи
- Після старту пристрій зчитує поточний час з DS3231.
- У масиві задано кілька щоденних годівель (наприклад, 08:00 та 19:30).
- Щохвилини пристрій порівнює час; при збігу:
- вмикається LED-індикація,
- сервопривід плавно відкриває заслінку, витримує паузу, закриває,
- на LCD оновлюється «Наст. годівля».
Скетч Arduino
#include <Wire.h>#include <RTClib.h>#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);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(); static int lastMinute = -1; if (now.minute() != lastMinute) { lastMinute = now.minute(); for (uint8_t i = 0; i < FEEDS; i++) fedThisMinute[i] = false; updateNextFeedOnLCD(now); } 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);}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.
Механіка та калібрування
- Використовуйте заслінку з мінімальним тертям. Для важчих заслінок — металевий сервопривід (MG90S) або редукторний.
- Підберіть кути
OPEN_ANGLE/CLOSE_ANGLE, щоб отвір відкривався повністю, але серво не впирався. - Налаштовуйте
OPEN_MSдля досягнення потрібної порції корму.
Безпека та надійність
- Живіть серво від окремого 5В блока ≥ 1 А. Обов’язково з’єднайте GND з Arduino.
- Додайте електроліт 470–1000 мкФ біля серво для стабільності.
- Додайте кнопку «ручного режиму» для тестів.
- Пружина на закриття допоможе уникнути перевантажень.
Поширені помилки
- Arduino перезавантажується: слабкий блок живлення, спільна лінія живлення серво та контролера.
- Час «пливе»: не ініціалізовано DS3231. Використайте
rtc.adjust(...)один раз. - Серво не рухається: неправильне підключення або кути.
Розширення
- Меню на LCD для зміни часу без перепрошивки.
- Ваговий датчик 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 (повторний) для стабільної роботи тривоги та підберіть регуляторами чутливість і час утримання.
Логіка роботи
- Система має два стани: Охорона увімкнена (ARMED) та вимкнена (DISARMED). Для простоти стартуємо в ARMED.
- Фіксація руху (OUT=HIGH) → затримка фільтрації (дребезг/помилкові) → Тривога: увімкнути реле/сирену, мигати LED, показати попередження.
- Після тривоги — охолодження (cooldown), щоб уникнути безперервних спрацювань.
- (Опц.) Кнопкою можна перемикати 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);
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;
digitalWrite(LED_PIN, (now/500)%2);
if (USE_LCD && (now/2000)%2==0) lcdShow("ARMED", "Waiting motion");
}
break;
case ALARM:
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.
План роботи
- Виберіть ідею проєкту.
- Складіть список необхідних компонентів.
- Зберіть схему на макетній платі.
- Напишіть і завантажте програму в Arduino.
- Протестуйте та усуньте помилки.
- За бажання — зберіть проєкт у корпусі.
Поради
- Використовуйте вже вивчені модулі та команди.
- Для фінального проєкту можна комбінувати кілька датчиків.
- Обов’язково враховуйте живлення та безпеку пристрою.
Контрольні запитання
- Які три обов’язкові частини має містити фінальний проєкт?
- Як можна вдосконалити проєкт у майбутньому?
- Чим корисна відладка під час збірки?
Авторський курс з Arduino для початківців. Використання матеріалів на комерційних сайтах дозволяється з посиланням на джерело.





