Главная страница » Arduino » Сборник полезных скетчей для Arduino: 7 прошивок, которые реально пригодятся
Сборник полезных скетчей для Arduino: 7 прошивок, которые реально пригодятся
Arduino

Сборник полезных скетчей для Arduino: 7 прошивок, которые реально пригодятся

06.09.2026 152
Сборник полезных скетчей для Arduino: 7 прошивок, которые реально пригодятся

7 реально рабочих скетчей для Arduino: датчики DS18B20, энкодеры, RTC DS3231, кнопки, SD-карты, реле и Bluetooth. Код, схемы подключения и типичные ошибки.

Arduino — это, пожалуй, самый дружелюбный вход в мир микроконтроллеров. Но рано или поздно наступает момент, когда мигание светодиодом перестаёт вдохновлять, и хочется собрать что-то действительно полезное. Проблема в том, что в интернете полно разрозненных примеров, которые либо не работают «из коробки», либо требуют глубокой переработки под конкретную задачу.

В этой статье я собрал семь скетчей, которые закрывают самые частые сценарии использования Arduino в DIY-проектах. Это не просто копипаст из документации, а рабочие заготовки с пояснениями: как они устроены, где типичные грабли и как перестроить их под свою задачу. Все скетчи написаны для Arduino Uno/Nano, но легко портируются на любую плату с ATmega328P или ATmega2560.


1. Универсальный опрос нескольких датчиков DS18B20

Датчики температуры DS18B20 — настоящая классика. Они дёшевы, точны и, главное, позволяют вешать на один провод до десятка штук одновременно. Но новички часто спотыкаются о работу с адресами датчиков.

Скетч

#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 2  // пин данных

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void setup() {
  Serial.begin(9600);
  sensors.begin();

  // Выводим количество найденных датчиков
  Serial.print("Found sensors: ");
  Serial.println(sensors.getDeviceCount());
}

void loop() {
  sensors.requestTemperatures();

  for (int i = 0; i < sensors.getDeviceCount(); i++) {
    float temp = sensors.getTempCByIndex(i);
    Serial.print("Sensor ");
    Serial.print(i);
    Serial.print(": ");
    Serial.print(temp);
    Serial.println(" C");
  }

  delay(5000);
}

Как перестроить под себя

Если вы хотите обращаться к датчикам по их уникальному адресу (а не по порядковому номеру), сначала нужно получить адреса. Добавьте в setup():

DeviceAddress tempAddr;
for (int i = 0; i < sensors.getDeviceCount(); i++) {
  if (sensors.getAddress(tempAddr, i)) {
    Serial.print("Address of sensor ");
    Serial.print(i);
    Serial.print(": ");
    for (int j = 0; j < 8; j++) {
      Serial.print(tempAddr[j], HEX);
      if (j < 7) Serial.print(", ");
    }
    Serial.println();
  }
}

Затем можно жёстко прописать адреса в коде и опрашивать конкретные датчики:

DeviceAddress sensor1 = {0x28, 0xFF, 0x1A, 0x2B, 0x03, 0x00, 0x00, 0x6E};
float temp = sensors.getTempC(sensor1);

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

  • Неправильный пин. DS18B20 подключается к цифровому пину, а не к аналоговому. Если используете пин A0, в коде нужно писать 0, а не A0.
  • Забытый подтягивающий резистор. Между линией данных и питанием 5V обязателен резистор 4.7 кОм. Без него датчик будет работать нестабильно или не определится вовсе.
  • Питание от 3.3V. DS18B20 работает от 3.3V, но на длинных проводах возможны сбои. Лучше использовать 5V.

2. Плавное управление яркостью светодиода с энкодером

Энкодеры — это не только «крутилки» для громкости. С их помощью удобно управлять яркостью, температурой уставки или любым другим параметром. Главное преимущество — бесконечное вращение и мгновенный отклик.

Скетч

#include <Encoder.h>

#define ENC_PIN_A 2
#define ENC_PIN_B 3
#define LED_PIN 9

Encoder myEnc(ENC_PIN_A, ENC_PIN_B);
int brightness = 0;
long lastPosition = -999;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  long newPosition = myEnc.read();

  if (newPosition != lastPosition) {
    // Каждый щелчок энкодера меняет яркость на 5 единиц
    int delta = (newPosition - lastPosition) > 0 ? 5 : -5;
    brightness = constrain(brightness + delta, 0, 255);

    analogWrite(LED_PIN, brightness);
    Serial.print("Brightness: ");
    Serial.println(brightness);

    lastPosition = newPosition;
  }
}

Важный нюанс

Энкодеры с кнопкой (типа KY-040) требуют обработки дребезга контактов. Библиотека Encoder.h справляется с этим аппаратно, если использовать пины с прерываниями (на Uno это пины 2 и 3). Если повесить энкодер на другие пины, библиотека переключится в режим опроса, и возможны пропуски щелчков при быстром вращении.

Как перестроить под себя

Вместо светодиода можно управлять сервоприводом или яркостью LED-ленты через транзистор. Для сервопривода:

#include <Servo.h>
Servo myservo;
int angle = 90;

// В setup():
myservo.attach(9);

// В loop() вместо analogWrite:
angle = constrain(angle + delta, 0, 180);
myservo.write(angle);

3. Таймер реального времени с будильником на DS3231

Модуль часов реального времени DS3231 — обязательный компонент для проектов, где нужно знать точное время: автоматический полив, кормушка для кота, метеостанция. В отличие от дешёвых DS1307, DS3231 имеет встроенный термокомпенсированный кварц и не «убегает» на минуты в месяц.

Скетч

#include <Wire.h>
#include <DS3231.h>

DS3231 rtc;

// Настройки будильника
const int alarmHour = 7;
const int alarmMinute = 30;
bool alarmTriggered = false;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  rtc.begin();

  // Установка времени (раскомментируйте при первом запуске)
  // rtc.setHour(12);
  // rtc.setMinute(0);
  // rtc.setSecond(0);
}

void loop() {
  int hour = rtc.getHour();
  int minute = rtc.getMinute();
  int second = rtc.getSecond();

  // Проверяем совпадение времени будильника
  if (hour == alarmHour && minute == alarmMinute && second == 0 && !alarmTriggered) {
    Serial.println("ALARM!");
    // Здесь можно включить реле, сервопривод или отправить команду
    alarmTriggered = true;
  }

  // Сбрасываем флаг на следующую минуту
  if (minute != alarmMinute) {
    alarmTriggered = false;
  }

  delay(1000);
}

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

  • Сброс времени при каждом включении. Если раскомментировать строки установки времени, часы будут сбрасываться при каждом перезапуске. Устанавливайте время один раз, затем закомментируйте строки и прошейте плату заново.
  • Путаница с форматом времени. DS3231 может работать в 12-часовом формате. Убедитесь, что вы не переключили его в этот режим случайно. По умолчанию библиотека использует 24-часовой формат.

Проверка результата

Откройте монитор порта. Если часы идут — вы увидите текущее время. Для проверки будильника временно поставьте время на минуту вперёд от текущего и убедитесь, что срабатывание происходит ровно в заданную секунду.


4. Обработка нескольких кнопок без задержек

Казалось бы, что может быть проще кнопки? Но при опросе нескольких кнопок новички часто используют delay(), что блокирует выполнение всего скетча. Антидребезг тоже часто делают «на глаз», что приводит к ложным срабатываниям.

Скетч

const int buttonPins[] = {2, 3, 4, 5};
const int buttonCount = 4;

bool lastButtonState[4] = {HIGH, HIGH, HIGH, HIGH};
bool buttonState[4] = {HIGH, HIGH, HIGH, HIGH};
unsigned long lastDebounceTime[4] = {0, 0, 0, 0};
const unsigned long debounceDelay = 50;

void setup() {
  Serial.begin(9600);
  for (int i = 0; i < buttonCount; i++) {
    pinMode(buttonPins[i], INPUT_PULLUP);
  }
}

void loop() {
  for (int i = 0; i < buttonCount; i++) {
    bool reading = digitalRead(buttonPins[i]);

    if (reading != lastButtonState[i]) {
      lastDebounceTime[i] = millis();
    }

    if ((millis() - lastDebounceTime[i]) > debounceDelay) {
      if (reading != buttonState[i]) {
        buttonState[i] = reading;

        // Кнопка нажата (состояние LOW при INPUT_PULLUP)
        if (buttonState[i] == LOW) {
          Serial.print("Button ");
          Serial.print(i);
          Serial.println(" pressed");
          // Здесь — ваша логика
        }
      }
    }

    lastButtonState[i] = reading;
  }
}

Почему это работает

Вместо delay() используется millis() — функция, которая возвращает количество миллисекунд с момента запуска. Это позволяет опрашивать кнопки «в фоне», не блокируя остальную логику программы.

Как перестроить под себя

Если нужно обрабатывать длительное удержание кнопки (например, для включения/выключения), добавьте проверку времени удержания:

const unsigned long longPressTime = 1000;
unsigned long pressStartTime[4] = {0, 0, 0, 0};
bool isPressed[4] = {false, false, false, false};

// Внутри условия buttonState[i] == LOW:
if (!isPressed[i]) {
  pressStartTime[i] = millis();
  isPressed[i] = true;
} else if (millis() - pressStartTime[i] > longPressTime) {
  Serial.print("Button ");
  Serial.print(i);
  Serial.println(" long pressed");
  isPressed[i] = false;  // чтобы не срабатывало повторно
}

// При отпускании:
if (buttonState[i] == HIGH && isPressed[i]) {
  isPressed[i] = false;
  // Короткое нажатие
}

5. Логирование данных на SD-карту

Запись показаний датчиков на SD-карту — классика для метеостанций и систем мониторинга. Но есть подводный камень: карты памяти любят «умирать» от внезапного отключения питания. Правильный подход — буферизация данных и запись пачками.

Скетч

#include <SPI.h>
#include <SD.h>

const int chipSelect = 4;
const unsigned long logInterval = 60000;  // 1 минута
unsigned long lastLogTime = 0;

// Буфер для накопления данных
String logBuffer = "";
const int bufferSize = 5;  // записываем каждые 5 записей

void setup() {
  Serial.begin(9600);

  if (!SD.begin(chipSelect)) {
    Serial.println("SD card initialization failed!");
    return;
  }

  // Создаём файл и пишем заголовок
  File dataFile = SD.open("datalog.csv", FILE_WRITE);
  if (dataFile) {
    dataFile.println("timestamp,temperature,humidity");
    dataFile.close();
  }
}

void loop() {
  if (millis() - lastLogTime >= logInterval) {
    lastLogTime = millis();

    // Здесь получаем данные с датчиков
    float temperature = 25.3;  // пример
    float humidity = 60.1;     // пример

    // Формируем строку лога
    String dataString = String(millis()) + "," + 
                        String(temperature) + "," + 
                        String(humidity);

    logBuffer += dataString + "n";

    // Если буфер заполнен — записываем на SD
    if (logBuffer.length() >= bufferSize * 20) {
      File dataFile = SD.open("datalog.csv", FILE_WRITE);
      if (dataFile) {
        dataFile.print(logBuffer);
        dataFile.close();
        logBuffer = "";
        Serial.println("Data flushed to SD");
      } else {
        Serial.println("Error opening datalog.csv");
      }
    }
  }
}

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

  • Неправильный пин chipSelect. На Arduino Uno модуль SD подключается по SPI: пин 11 (MOSI), 12 (MISO), 13 (SCK). Пин CS может быть любым, но часто используется 4 или 10.
  • Файловая система. Arduino поддерживает FAT16 и FAT32. Если карта не определяется — отформатируйте её в FAT32.
  • Потеря данных при отключении питания. Буферизация снижает риск, но не устраняет его полностью. Для критичных проектов используйте внешний RTC с энергонезависимой памятью или записывайте данные реже.

Подробнее про работу с SD-картами в Arduino я рассказывал в статье Arduino и SD-карта: логируем данные датчиков на microSD.


6. Управление реле по расписанию с ручным приоритетом

Этот скетч — основа для умного полива, освещения или обогрева. Логика такая: есть расписание (например, включить в 7:00, выключить в 7:30), но если вы нажали кнопку вручную — ручное управление имеет приоритет до следующего запланированного события.

Скетч

#include <Wire.h>
#include <DS3231.h>

DS3231 rtc;

const int relayPin = 8;
const int buttonPin = 2;

// Расписание
const int onHour = 7;
const int onMinute = 0;
const int offHour = 7;
const int offMinute = 30;

bool manualOverride = false;
bool relayState = false;
bool lastButtonState = HIGH;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  rtc.begin();

  pinMode(relayPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);

  digitalWrite(relayPin, LOW);
}

void loop() {
  int hour = rtc.getHour();
  int minute = rtc.getMinute();

  // Проверяем кнопку
  bool reading = digitalRead(buttonPin);
  if (reading == LOW && lastButtonState == HIGH) {
    // Антидребезг
    delay(50);
    if (digitalRead(buttonPin) == LOW) {
      manualOverride = !manualOverride;
      relayState = !relayState;
      digitalWrite(relayPin, relayState ? HIGH : LOW);
      Serial.println("Manual override toggled");
    }
  }
  lastButtonState = reading;

  // Если нет ручного управления — работаем по расписанию
  if (!manualOverride) {
    int currentMinutes = hour * 60 + minute;
    int onMinutes = onHour * 60 + onMinute;
    int offMinutes = offHour * 60 + offMinute;

    if (currentMinutes >= onMinutes && currentMinutes < offMinutes) {
      if (!relayState) {
        relayState = true;
        digitalWrite(relayPin, HIGH);
        Serial.println("Relay ON by schedule");
      }
    } else {
      if (relayState) {
        relayState = false;
        digitalWrite(relayPin, LOW);
        Serial.println("Relay OFF by schedule");
      }
    }
  }

  delay(100);
}

Как перестроить под себя

Если нужно несколько интервалов в течение дня, замените одиночные onHour/offHour на массивы:

const int scheduleCount = 3;
const int scheduleOn[][2] = {{7, 0}, {13, 0}, {18, 0}};
const int scheduleOff[][2] = {{8, 0}, {14, 0}, {19, 30}};

И проверяйте попадание текущего времени в любой из интервалов.


7. Дистанционное управление через Bluetooth (HC-05/HC-06)

Bluetooth-модули HC-05/HC-06 — самый простой способ сделать проект управляемым со смартфона. Никакого Wi-Fi и сложных протоколов — просто UART.

Скетч

#include <SoftwareSerial.h>

#define BT_RX 10
#define BT_TX 11

SoftwareSerial bluetooth(BT_RX, BT_TX);

const int relayPin = 8;
const int ledPin = 9;

void setup() {
  Serial.begin(9600);
  bluetooth.begin(9600);

  pinMode(relayPin, OUTPUT);
  pinMode(ledPin, OUTPUT);

  digitalWrite(relayPin, LOW);
  digitalWrite(ledPin, LOW);

  Serial.println("Bluetooth device ready");
}

void loop() {
  if (bluetooth.available()) {
    char command = bluetooth.read();

    switch (command) {
      case '1':  // Включить реле
        digitalWrite(relayPin, HIGH);
        bluetooth.println("Relay ON");
        break;
      case '0':  // Выключить реле
        digitalWrite(relayPin, LOW);
        bluetooth.println("Relay OFF");
        break;
      case 'L':  // Включить светодиод
        digitalWrite(ledPin, HIGH);
        bluetooth.println("LED ON");
        break;
      case 'l':  // Выключить светодиод
        digitalWrite(ledPin, LOW);
        bluetooth.println("LED OFF");
        break;
      case 'S':  // Запрос статуса
        bluetooth.print("Relay: ");
        bluetooth.println(digitalRead(relayPin) ? "ON" : "OFF");
        bluetooth.print("LED: ");
        bluetooth.println(digitalRead(ledPin) ? "ON" : "OFF");
        break;
      default:
        bluetooth.println("Unknown command");
        break;
    }
  }
}

Настройка модуля HC-05

Перед первым использованием модуль нужно настроить. Подключите его к Arduino, зажмите кнопку на модуле и подайте питание — модуль войдёт в режим AT-команд. Затем отправьте:

AT+NAME=MyDevice
AT+UART=9600,0,0
AT+ROLE=0

После этого перезагрузите модуль. Пароль по умолчанию — 1234.

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

  • Перепутанные RX/TX. RX модуля подключается к TX Arduino (пин 11), а TX модуля — к RX Arduino (пин 10). Это самая частая ошибка.
  • Неправильная скорость. HC-05 по умолчанию работает на 9600 бод, но некоторые модули приходят с другими настройками. Проверьте через AT-команды.
  • Питание. Bluetooth-модули чувствительны к питанию. Если Arduino питается от USB — проблем нет, но от батареек возможны сбои.

Бонус: как сделать прошивку перестраиваемой

Все скетчи выше — это заготовки. Чтобы адаптировать их под свою задачу, следуйте простым правилам:

  1. Выносите настройки в начало кода. Пины, интервалы, пороговые значения — всё должно быть в константах с понятными именами.
  2. Используйте millis() вместо delay(). Это позволит выполнять несколько задач одновременно.
  3. Добавляйте вывод в Serial. Это ваш главный инструмент отладки. Если что-то не работает — первым делом смотрите монитор порта.
  4. Проверяйте питание. Arduino от USB — это одно, а от батареек — совсем другое. Многие «странные» ошибки связаны именно с нестабильным питанием.

Заключение

Эти семь скетчей покрывают большинство базовых сценариев: от опроса датчиков до дистанционного управления. Не бойтесь экспериментировать — берите заготовку, меняйте пины, добавляйте свою логику и смотрите, что получается. Если что-то пошло не так, монитор порта и логика «что изменилось перед сбоем» помогут найти причину.

Для более сложных проектов на ESP32 с подключением к Home Assistant обратите внимание на конструктор ESPHome — он генерирует готовый YAML-конфиг под вашу задачу: Конструктор ESPHome для ESP32. А если планируете строить умный дом на Arduino и ESP32, почитайте про MQTT брокер Mosquitto — это основа для связи всех устройств между собой.

Удачных экспериментов!

Понравилась статья?

Поставьте лайк и сохраните полезный материал в закладки.

Комментарии (0)
Добавить комментарий
Прокомментировать
Кликните на изображение чтобы обновить код, если он неразборчив
Пишем скетчи своими руками для Arduino — с нуля
Arduino
07.09.2026
Пишем скетчи своими руками для Arduino — с нуля
Учимся писать скетчи для Arduino самостоятельно: структура программы, типы данных, работа с кнопками и датчиками, отладка через Serial и создание кода с помощью
Простая глушилка FM радио на Arduino: разбираемся, как это работает
Arduino
06.09.2026
Простая глушилка FM радио на Arduino: разбираемся, как это работает
Разбираем, как Arduino создаёт помехи в FM-диапазоне. Схема, скетч, объяснение принципов работы гармоник и предупреждение о законности.
Arduino и SD-карта: логируем данные датчиков на microSD
Arduino
31.03.2026
Arduino и SD-карта: логируем данные датчиков на microSD
Пошаговое руководство по созданию автономного логгера данных на Arduino. Узнайте, как подключить SD-модуль, записывать показания датчиков в файл и избегать типичных
Arduino для начинающих: первый скетч и основы программирования
Arduino
31.03.2026
Arduino для начинающих: первый скетч и основы программирования
Подробное руководство по Arduino для новичков: от установки IDE до первого мигающего светодиода. Узнайте, как писать и загружать скетчи, работать с пинами и
Arduino и сервоприводы: от мигания светодиода до роборуки
Arduino
31.03.2026
Arduino и сервоприводы: от мигания светодиода до роборуки
Подробное руководство по работе с сервоприводами на Arduino. Подключение, скетчи, управление несколькими серво, создание программируемой роборуки. Советы по питанию и
Arduino и OLED дисплей SSD1306: выводим данные красиво
Arduino
31.03.2026
Arduino и OLED дисплей SSD1306: выводим данные красиво
Подробное руководство по подключению OLED дисплея SSD1306 к Arduino. Установка библиотек, примеры кода, создание интерфейсов и отладка. Оживите свои проекты!

Войдите в аккаунт, чтобы пользоваться закладками, сообщениями и другими возможностями сайта.