Умный котик Nyan: Инструкция по сборке, примеры использования и документация

Соберите умного котика Nyan, который станет забавным и полезным предметом на рабочем столе, помощником в тайм-менеджменте или интернет-нотификатором. Набор поможет быстро и весело начать путь в мир хобби-электроники.

Nyan Cat поставляется в разборном виде. Следуйте нашей инструкции, и вы получите готовое к работе устройство!

Видеообзоры

Что в коробке

  1. Светодиоды 5 мм (Troyka-модуль) (красный, жёлтый, зелёный и синий)

Всё необходимое для сборки вместе с корпусом из #Структора мы собрали в готовый набор Nyan.

Сборка корпуса

  1. Вкрутите четыре винта М3 в плашку #струткора, как показано на рисунке.
  2. Переверните плашку корпуса и установите плату Iskra Neo на болты M3.
  3. Закрепите боковые стенки #струткора к общему корпусу.
  4. Соберите из плашек готовый готовый корпус.
  5. Вставьте модули в Slot Shied:
    1. Светодиоды в ячейки B, C, E и F;
    2. Зуммер в ячейку A;
    3. Кнопку в ячейку D.
  6. Закрепите модули винтами М3.
  7. Соберите голову Nyan Cat.
  8. Закрепите голову котика на корпусе.
  9. Nyan Cat собран, теперь можно переходить к программной настройке.

Программная настройка

  1. Подключите плату Iskra Neo к компьютеру по USB. Для коммуникации используйте кабель USB (A — Micro USB).
  2. Скачайте и установите Arduino IDE.

Примеры работы

Рассмотрим несколько примеров по работе с Nyan Cat.

Нян Код

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

nyancat-melody.ino
// Ноты
constexpr uint8_t REST = 0;
constexpr uint8_t NOTE_B0 = 31;
constexpr uint8_t NOTE_C1 = 33;
constexpr uint8_t NOTE_CS1 = 35;
constexpr uint8_t NOTE_D1 = 37;
constexpr uint8_t NOTE_DS1 = 39;
constexpr uint8_t NOTE_E1 = 41;
constexpr uint8_t NOTE_F1 = 44;
constexpr uint8_t NOTE_FS1 = 46;
constexpr uint8_t NOTE_G1 = 49;
constexpr uint8_t NOTE_GS1 = 52;
constexpr uint8_t NOTE_A1 = 55;
constexpr uint8_t NOTE_AS1 = 58;
constexpr uint8_t NOTE_B1 = 62;
constexpr uint8_t NOTE_C2 = 65;
constexpr uint8_t NOTE_CS2 = 69;
constexpr uint8_t NOTE_D2 = 73;
constexpr uint8_t NOTE_DS2 = 78;
constexpr uint8_t NOTE_E2 = 82;
constexpr uint8_t NOTE_F2 = 87;
constexpr uint8_t NOTE_FS2 = 93;
constexpr uint8_t NOTE_G2 = 98;
constexpr uint8_t NOTE_GS2 = 104;
constexpr uint8_t NOTE_A2 = 110;
constexpr uint8_t NOTE_AS2 = 117;
constexpr uint8_t NOTE_B2 = 123;
constexpr uint8_t NOTE_C3 = 131;
constexpr uint8_t NOTE_CS3 = 139;
constexpr uint8_t NOTE_D3 = 147;
constexpr uint8_t NOTE_DS3 = 156;
constexpr uint8_t NOTE_E3 = 165;
constexpr uint8_t NOTE_F3 = 175;
constexpr uint8_t NOTE_FS3 = 185;
constexpr uint8_t NOTE_G3 = 196;
constexpr uint8_t NOTE_GS3 = 208;
constexpr uint8_t NOTE_A3 = 220;
constexpr uint8_t NOTE_AS3 = 233;
constexpr uint8_t NOTE_B3 = 247;
constexpr uint8_t NOTE_C4 = 262;
constexpr uint8_t NOTE_CS4 = 277;
constexpr uint8_t NOTE_D4 = 294;
constexpr uint8_t NOTE_DS4 = 311;
constexpr uint8_t NOTE_E4 = 330;
constexpr uint8_t NOTE_F4 = 349;
constexpr uint8_t NOTE_FS4 = 370;
constexpr uint8_t NOTE_G4 = 392;
constexpr uint8_t NOTE_GS4 = 415;
constexpr uint8_t NOTE_A4 = 440;
constexpr uint8_t NOTE_AS4 = 466;
constexpr uint8_t NOTE_B4 = 494;
constexpr uint8_t NOTE_C5 = 523;
constexpr uint8_t NOTE_CS5 = 554;
constexpr uint8_t NOTE_D5 = 587;
constexpr uint8_t NOTE_DS5 = 622;
constexpr uint8_t NOTE_E5 = 659;
constexpr uint8_t NOTE_F5 = 698;
constexpr uint8_t NOTE_FS5 = 740;
constexpr uint8_t NOTE_G5 = 784;
constexpr uint8_t NOTE_GS5 = 831;
constexpr uint8_t NOTE_A5 = 880;
constexpr uint8_t NOTE_AS5 = 932;
constexpr uint8_t NOTE_B5 = 988;
constexpr uint8_t NOTE_C6 = 1047;
constexpr uint8_t NOTE_CS6 = 1109;
constexpr uint8_t NOTE_D6 = 1175;
constexpr uint8_t NOTE_DS6 = 1245;
constexpr uint8_t NOTE_E6 = 1319;
constexpr uint8_t NOTE_F6 = 1397;
constexpr uint8_t NOTE_FS6 = 1480;
constexpr uint8_t NOTE_G6 = 1568;
constexpr uint8_t NOTE_GS6 = 1661;
constexpr uint8_t NOTE_A6 = 1760;
constexpr uint8_t NOTE_AS6 = 1865;
constexpr uint8_t NOTE_B6 = 1976;
constexpr uint8_t NOTE_C7 = 2093;
constexpr uint8_t NOTE_CS7 = 2217;
constexpr uint8_t NOTE_D7 = 2349;
constexpr uint8_t NOTE_DS7 = 2489;
constexpr uint8_t NOTE_E7 = 2637;
constexpr uint8_t NOTE_F7 = 2794;
constexpr uint8_t NOTE_FS7 = 2960;
constexpr uint8_t NOTE_G7 = 3136;
constexpr uint8_t NOTE_GS7 = 3322;
constexpr uint8_t NOTE_A7 = 3520;
constexpr uint8_t NOTE_AS7 = 3729;
constexpr uint8_t NOTE_B7 = 3951;
constexpr uint8_t NOTE_C8 = 4186;
constexpr uint8_t NOTE_CS8 = 4435;
constexpr uint8_t NOTE_D8 = 4699;
constexpr uint8_t NOTE_DS8 = 4978;
 
// Пины подключенных модулей
constexpr uint8_t LED_R_PIN = 10;
constexpr uint8_t LED_G_PIN = 9;
constexpr uint8_t LED_B_PIN = 4;
constexpr uint8_t LED_Y_PIN = 6;
constexpr uint8_t BUZZER_PIN = 7;
constexpr uint8_t BUTTON_PIN = 8;
 
// Массив с нотами мелодии
int melody[] = {
    NOTE_DS5, NOTE_E5,  NOTE_FS5, 0,        NOTE_B5,  NOTE_E5,  NOTE_DS5,
    NOTE_E5,  NOTE_FS5, NOTE_B5,  NOTE_DS6, NOTE_E6,  NOTE_DS6, NOTE_AS5,
    NOTE_B5,  0,        NOTE_FS5, 0,        NOTE_DS5, NOTE_E5,  NOTE_FS5,
    0,        NOTE_B5,  NOTE_CS6, NOTE_AS5, NOTE_B5,  NOTE_CS6, NOTE_E6,
    NOTE_DS6, NOTE_E6,  NOTE_CS6, NOTE_FS4, NOTE_GS4, NOTE_D4,  NOTE_DS4,
    NOTE_FS2, NOTE_CS4, NOTE_D4,  NOTE_CS4, NOTE_B3,  NOTE_B3,  NOTE_CS4,
    NOTE_D4,  NOTE_D4,  NOTE_CS4, NOTE_B3,  NOTE_CS4, NOTE_DS4, NOTE_FS4,
    NOTE_GS4, NOTE_DS4, NOTE_FS4, NOTE_CS4, NOTE_DS4, NOTE_B3,  NOTE_CS4,
    NOTE_B3,  NOTE_DS4, NOTE_FS4, NOTE_GS4, NOTE_DS4, NOTE_FS4, NOTE_CS4,
    NOTE_DS4, NOTE_B3,  NOTE_D4,  NOTE_DS4, NOTE_D4,  NOTE_CS4, NOTE_B3,
    NOTE_CS4, NOTE_D4,  NOTE_B3,  NOTE_CS4, NOTE_DS4, NOTE_FS4, NOTE_CS4,
    NOTE_D4,  NOTE_CS4, NOTE_B3,  NOTE_CS4, NOTE_B3,  NOTE_CS4, NOTE_FS4,
    NOTE_GS4, NOTE_D4,  NOTE_DS4, NOTE_FS2, NOTE_CS4, NOTE_D4,  NOTE_CS4,
    NOTE_B3,  NOTE_B3,  NOTE_CS4, NOTE_D4,  NOTE_D4,  NOTE_CS4, NOTE_B3,
    NOTE_CS4, NOTE_DS4, NOTE_FS4, NOTE_GS4, NOTE_DS4, NOTE_FS4, NOTE_CS4,
    NOTE_DS4, NOTE_B3,  NOTE_CS4, NOTE_B3,  NOTE_DS4, NOTE_FS4, NOTE_GS4,
    NOTE_DS4, NOTE_FS4, NOTE_CS4, NOTE_DS4, NOTE_B3,  NOTE_D4,  NOTE_DS4,
    NOTE_D4,  NOTE_CS4, NOTE_B3,  NOTE_CS4, NOTE_D4,  NOTE_B3,  NOTE_CS4,
    NOTE_DS4, NOTE_FS4, NOTE_CS4, NOTE_D4,  NOTE_CS4, NOTE_B3,  NOTE_CS4,
    NOTE_B3,  NOTE_B3,  NOTE_B3,  NOTE_FS3, NOTE_GS3, NOTE_B3,  NOTE_FS3,
    NOTE_GS3, NOTE_B3,  NOTE_CS4, NOTE_DS4, NOTE_B3,  NOTE_E4,  NOTE_DS4,
    NOTE_E4,  NOTE_FS4, NOTE_B3,  NOTE_B3,  NOTE_FS3, NOTE_GS3, NOTE_B3,
    NOTE_FS3, NOTE_E4,  NOTE_DS4, NOTE_CS4, NOTE_B3,  NOTE_E3,  NOTE_DS3,
    NOTE_E3,  NOTE_FS3, NOTE_B3,  NOTE_FS3, NOTE_GS3, NOTE_B3,  NOTE_FS3,
    NOTE_GS3, NOTE_B3,  NOTE_B3,  NOTE_CS4, NOTE_DS4, NOTE_B3,  NOTE_FS3,
    NOTE_GS3, NOTE_FS3, NOTE_B3,  NOTE_B3,  NOTE_AS3, NOTE_B3,  NOTE_FS3,
    NOTE_GS3, NOTE_B3,  NOTE_E4,  NOTE_DS4, NOTE_E4,  NOTE_FS4, NOTE_B3,
    NOTE_AS3, NOTE_B3,  NOTE_FS3, NOTE_GS3, NOTE_B3,  NOTE_FS3, NOTE_GS3,
    NOTE_B3,  NOTE_CS4, NOTE_DS4, NOTE_B3,  NOTE_E4,  NOTE_DS4, NOTE_E4,
    NOTE_FS4, NOTE_B3,  NOTE_B3,  NOTE_FS3, NOTE_GS3, NOTE_B3,  NOTE_FS3,
    NOTE_E4,  NOTE_DS4, NOTE_CS4, NOTE_B3,  NOTE_E3,  NOTE_DS3, NOTE_E3,
    NOTE_FS3, NOTE_B3,  NOTE_FS3, NOTE_GS3, NOTE_B3,  NOTE_FS3, NOTE_GS3,
    NOTE_B3,  NOTE_B3,  NOTE_CS4, NOTE_DS4, NOTE_B3,  NOTE_FS3, NOTE_GS3,
    NOTE_FS3, NOTE_B3,  NOTE_B3,  NOTE_AS3, NOTE_B3,  NOTE_FS3, NOTE_GS3,
    NOTE_B3,  NOTE_E4,  NOTE_DS4, NOTE_E4,  NOTE_FS4, NOTE_B3,  NOTE_CS4,
    NOTE_FS4, NOTE_GS4, NOTE_D4,  NOTE_DS4, NOTE_FS2, NOTE_CS4, NOTE_D4,
    NOTE_CS4, NOTE_B3,  NOTE_B3,  NOTE_CS4, NOTE_D4,  NOTE_D4,  NOTE_CS4,
    NOTE_B3,  NOTE_CS4, NOTE_DS4, NOTE_FS4, NOTE_GS4, NOTE_DS4, NOTE_FS4,
    NOTE_CS4, NOTE_DS4, NOTE_B3,  NOTE_CS4, NOTE_B3,  NOTE_DS4, NOTE_FS4,
    NOTE_GS4, NOTE_DS4, NOTE_FS4, NOTE_CS4, NOTE_DS4, NOTE_B3,  NOTE_D4,
    NOTE_DS4, NOTE_D4,  NOTE_CS4, NOTE_B3,  NOTE_CS4, NOTE_D4,  NOTE_B3,
    NOTE_CS4, NOTE_DS4, NOTE_FS4, NOTE_CS4, NOTE_D4,  NOTE_CS4, NOTE_B3,
    NOTE_CS4, NOTE_B3,  NOTE_CS4, NOTE_FS4, NOTE_GS4, NOTE_D4,  NOTE_DS4,
    NOTE_FS2, NOTE_CS4, NOTE_D4,  NOTE_CS4, NOTE_B3,  NOTE_B3,  NOTE_CS4,
    NOTE_D4,  NOTE_D4,  NOTE_CS4, NOTE_B3,  NOTE_CS4, NOTE_DS4, NOTE_FS4,
    NOTE_GS4, NOTE_DS4, NOTE_FS4, NOTE_CS4, NOTE_DS4, NOTE_B3,  NOTE_CS4,
    NOTE_B3,  NOTE_DS4, NOTE_FS4, NOTE_GS4, NOTE_DS4, NOTE_FS4, NOTE_CS4,
    NOTE_DS4, NOTE_B3,  NOTE_D4,  NOTE_DS4, NOTE_D4,  NOTE_CS4, NOTE_B3,
    NOTE_CS4, NOTE_D4,  NOTE_B3,  NOTE_CS4, NOTE_DS4, NOTE_FS4, NOTE_CS4,
    NOTE_D4,  NOTE_CS4, NOTE_B3,  NOTE_CS4, NOTE_B3,  NOTE_B3,  NOTE_B3,
    NOTE_FS3, NOTE_GS3, NOTE_B3,  NOTE_FS3, NOTE_GS3, NOTE_B3,  NOTE_CS4,
    NOTE_DS4, NOTE_B3,  NOTE_E4,  NOTE_DS4, NOTE_E4,  NOTE_FS4, NOTE_B3,
    NOTE_B3,  NOTE_FS3, NOTE_GS3, NOTE_B3,  NOTE_FS3, NOTE_E4,  NOTE_DS4,
    NOTE_CS4, NOTE_B3,  NOTE_E3,  NOTE_DS3, NOTE_E3,  NOTE_FS3, NOTE_B3,
    NOTE_FS3, NOTE_GS3, NOTE_B3,  NOTE_FS3, NOTE_GS3, NOTE_B3,  NOTE_B3,
    NOTE_CS4, NOTE_DS4, NOTE_B3,  NOTE_FS3, NOTE_GS3, NOTE_FS3, NOTE_B3,
    NOTE_B3,  NOTE_AS3, NOTE_B3,  NOTE_FS3, NOTE_GS3, NOTE_B3,  NOTE_E4,
    NOTE_DS4, NOTE_E4,  NOTE_FS4, NOTE_B3,  NOTE_AS3, NOTE_B3,  NOTE_FS3,
    NOTE_GS3, NOTE_B3,  NOTE_FS3, NOTE_GS3, NOTE_B3,  NOTE_CS4, NOTE_DS4,
    NOTE_B3,  NOTE_E4,  NOTE_DS4, NOTE_E4,  NOTE_FS4, NOTE_B3,  NOTE_B3,
    NOTE_FS3, NOTE_GS3, NOTE_B3,  NOTE_FS3, NOTE_E4,  NOTE_DS4, NOTE_CS4,
    NOTE_B3,  NOTE_E3,  NOTE_DS3, NOTE_E3,  NOTE_FS3, NOTE_B3,  NOTE_FS3,
    NOTE_GS3, NOTE_B3,  NOTE_FS3, NOTE_GS3, NOTE_B3,  NOTE_B3,  NOTE_CS4,
    NOTE_DS4, NOTE_B3,  NOTE_FS3, NOTE_GS3, NOTE_FS3, NOTE_B3,  NOTE_B3,
    NOTE_AS3, NOTE_B3,  NOTE_FS3, NOTE_GS3, NOTE_B3,  NOTE_E4,  NOTE_DS4,
    NOTE_E4,  NOTE_FS4, NOTE_B3,  NOTE_CS4,
};
 
// Массив длительности нот в мелодии: 
// 4 = четвертная нота, 8 = восьмая нота, и так далее...
int noteDurations[] = {
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 8,  16, 16, 16, 16, 16, 16, 16, 16, 8,  8,  16, 16, 16, 16, 16,
    16, 8,  8,  8,  8,  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    8,  8,  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8,  16, 16, 16, 16,
    16, 16, 16, 16, 8,  8,  8,  8,  8,  16, 16, 16, 16, 16, 16, 8,  8,  8,  8,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8,  8,  16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 8,  16, 16, 16, 16, 16, 16, 16, 16, 8,
    8,  8,  8,  16, 16, 8,  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8,  8,  16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8,  16, 16, 8,  16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 8,  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8,  8,
    8,  16, 16, 8,  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8,  8,  16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 8,  16, 16, 8,  16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 8,  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8,  8,  8,  8,
    16, 16, 16, 16, 16, 16, 8,  8,  8,  8,  16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 8,  8,  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    8,  16, 16, 16, 16, 16, 16, 16, 16, 8,  8,  8,  8,  8,  16, 16, 16, 16, 16,
    16, 8,  8,  8,  8,  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    8,  8,  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8,  16, 16, 16, 16,
    16, 16, 16, 16, 8,  8,  8,  8,  16, 16, 8,  16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 8,  8,  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8,  16, 16,
    8,  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8,  16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 8,  8,  8,  16, 16, 8,  16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    8,  8,  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8,  16, 16, 8,  16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 8,  16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 8,  8,
};
 
void setup() {
    // Пины со светодиодами в режим выхода
    pinMode(LED_R_PIN, OUTPUT);
    pinMode(LED_Y_PIN, OUTPUT);
    pinMode(LED_G_PIN, OUTPUT);
    pinMode(LED_B_PIN, OUTPUT);
}
 
void loop() {
    // Если была нажата кнопка, запускаем мелодию
    if (checkClick())
        startMelody();
 
    // Гасим светодиоды
    digitalWrite(LED_R_PIN, LOW);
    digitalWrite(LED_G_PIN, LOW);
    digitalWrite(LED_Y_PIN, LOW);
    digitalWrite(LED_B_PIN, LOW);
}
 
void startMelody() {
    // Вычисляем количество нот
    int noteCount = sizeof(melody) / sizeof(int);
    // Переменная для хранения состояния светодиодов
    bool toggleLeds = true;
    // Играем мелодию
    for (int thisNote = 0; thisNote < noteCount; thisNote++) {
        // Если была нажата клавиша - останавливаем мелодию
        if (checkClick())
            return;
        // Каждую новую ноту меняем состояние светодиодов
        digitalWrite(LED_R_PIN, toggleLeds);
        digitalWrite(LED_Y_PIN, toggleLeds);
        digitalWrite(LED_G_PIN, !toggleLeds);
        digitalWrite(LED_B_PIN, !toggleLeds);
        toggleLeds = !toggleLeds;
        // Останавливаем воспроизведение предыдущей ноты
        noTone(BUZZER_PIN);
 
        // Вычислим длительность ноты. Разделим секунду на длительность ноты из массива
        // Четвертная нота = 1000 / 4, восьмая нота 1000 / 8 
        // Скорость можно увеличить, увеличив числитель. Больше подошло 1200
        int noteDuration = 1200 / noteDurations[thisNote];
 
        // Можно увеличить высоту мелодии, умножая ноты на 2, 4, 8
        int octaveMul = 2;
 
        // Воспроизведём ноту
        tone(BUZZER_PIN, octaveMul * melody[thisNote], noteDuration);
 
        // Чтобы отделить ноты друг от друга, добавим небольшую паузу между ними
        // 30% от длины ноты звучат неплохо
        int pauseBetweenNotes = noteDuration * 1.30;
        delay(pauseBetweenNotes);
    }
}
 
// Функция для проверки клика кнопки
bool checkClick() {
    // Переменная для хранения предыдущего состояния кнопки
    static bool buttonWasUp = true;
    bool result = false;
    // Читаем текущее состояние кнопки
    bool buttonIsUp = digitalRead(BUTTON_PIN);
 
    // Если кнопка была не нажата, а теперь нажата
    // значит был клик
    if (buttonWasUp && !buttonIsUp) {
        delay(50);
        result = true;
    }
    buttonWasUp = buttonIsUp;
    return result;
}

Таймер «Помидор»

Помидорная техника используется для повышения продуктивности работы. Вы просто ставите себе таймер на 25 минут и не отвлекаетесь. А ещё с её помощью можно приготовить яичницу.

nyancat-pomodoro-timer.ino
// Пины подключенных модулей
constexpr uint8_t LED_R_PIN = 10;
constexpr uint8_t LED_G_PIN = 9;
constexpr uint8_t LED_B_PIN = 4;
constexpr uint8_t LED_Y_PIN = 6;
constexpr uint8_t BUZZER_PIN = 7;
constexpr uint8_t BUTTON_PIN = 8;
 
// Время таймера в минутах
constexpr uint8_t POMODORO_TIME = 25;
// Количество светодиодов
constexpr uint8_t LED_COUNT = 4;
// Массив пинов со светодиодами
int leds[] = { LED_R_PIN, LED_G_PIN, LED_Y_PIN, LED_B_PIN };
// Переменная для хранения времени таймера в миллисекундах
unsigned long pomodoroTimeInMillis;
// Переменная для хранения времени переключения светодиодов
unsigned long ledSwitchTime;
// Переменная для хранения времени начала работы таймера
unsigned long lastTime = 0;
// Состояние таймера — выключен
bool pomodoroState = false;
 
void setup() {
    // Рассчитаем время таймера в миллисекундах
    pomodoroTimeInMillis = POMODORO_TIME * 60000;
    // Рассчитаем время переключения светодиодов
    ledSwitchTime = pomodoroTimeInMillis / LED_COUNT;
    // Переключим пины светодиодов в состояние выхода
    for (int i = 0; i < LED_COUNT; ++i) {
        pinMode(leds[i], OUTPUT);
    }
}
 
void loop() {
    // Если был клик кнопки
    if (checkClick()) {
        // Запомним текущее время
        lastTime = millis();
        // Переключим состояние таймера вкл/выкл
        pomodoroState = !pomodoroState;
        // Выключим все светодиоды
        for (int i = 0; i < LED_COUNT; ++i) {
            digitalWrite(leds[i], LOW);
        }
    }
    // Если таймер включён
    if (pomodoroState) {
        // Рассчитаем прошедшее время
        unsigned long elapsedTime = millis() - lastTime;
        // Если прошедшее время меньше времени срабатывания таймера
        if (elapsedTime < pomodoroTimeInMillis) {
            // Рассчитаем, какой из светодиодов должен гореть
            unsigned long currentLed = elapsedTime / ledSwitchTime;
            // И зажжём этот светодиод
            digitalWrite(leds[currentLed], HIGH);
            // Если прошедшее время таймера больше времени срабатывания — звеним
        } else {
            finish();
        }
    }
}
 
// Функция для проверки клика кнопки
bool checkClick() {
    // Переменная для хранения предыдущего состояния кнопки
    static bool buttonWasUp = true;
    bool result = false;
    // Читаем текущее состояние кнопки
    bool buttonIsUp = digitalRead(BUTTON_PIN);
    // Если кнопка была не нажата, а теперь нажата
    // значит был клик
    if (buttonWasUp && !buttonIsUp) {
        delay(100);
        result = true;
    }
    buttonWasUp = buttonIsUp;
    return result;
}
 
void finish() {
    // Переменная для хранения переключателя светодиодов
    bool toggle = true;
    // Попиликаем 10 раз
    for (int i = 0; i < 10; i++) {
        tone(BUZZER_PIN, 500 + toggle * 500);
        // Почерёдно моргаем парами светодиодов
        for (int i = 0; i < LED_COUNT; ++i) {
            digitalWrite(leds[i], toggle);
            toggle = !toggle;
        }
        toggle = !toggle;
        delay(100);
    }
    // Отключаем звук
    noTone(BUZZER_PIN);
    // Выключаем таймер
    pomodoroState = false;
}

Что дальше?

Nyan Cat — это только начало пути в мир Arduino. Если вы хотите расширить возможность котика, обратите внимания на следующие проекты:

Выберите свой новый проект на Arduino и Slot Shield. Скучно не будет!

Ресурсы