// Подключаем библиотеку для работы с мелодиями в формате RTTTL #include // Подключаем библиотеку для работы с ИК-приёмником #include // Подключаем библиотеку для работы со светодиодными матрицами #include // Даём понятное имя пину 3 с пищалкой constexpr uint8_t BUZZER_PIN = 3; // Даём понятное имя пину 2 с ИК-приёмником constexpr uint8_t IR_RECEIVE_PIN = 2; // Создаём объект матрицы левого глаза // на шине I²C с адресом 0x60 (указан по умолчанию) TroykaLedMatrix matrixL; // Создаём объект матрицы правого глаза // на шине I²C с адресом 0x63 TroykaLedMatrix matrixR(0x63); // Создаём константу для хранения базовой частоты constexpr int FREQUENCY = 2000; // Создаём константы для хранения минимальной и максимальной частоты constexpr int MIN_FREQUENCY = FREQUENCY - (0.25 * FREQUENCY); constexpr int MAX_FREQUENCY = FREQUENCY + (0.25 * FREQUENCY); // Создаём иконку «Взгляд прямо» в шестнадцатеричной системе HEX // Иконка для левого и правого глаза одинаковая // Эмоции рисуем в редакторе изображений для LED-матрицы // https://amperka.github.io/led-matrix-editor/ constexpr uint8_t ICON_EYE_STRAIGHT[] PROGMEM { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e }; // Создаём иконку «Глаза выключены» в шестнадцатеричной системе HEX // Иконка для левого и правого глаза одинаковая constexpr uint8_t ICON_EYE_OFF[] PROGMEM { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; void setup() { // Инициализируем матрицы matrixL.begin(); matrixR.begin(); // Очищаем матрицы matrixL.clear(); matrixR.clear(); // Настраиваем пин с пищалкой в режим выхода pinMode(BUZZER_PIN, OUTPUT); // Инициализируем ИК-приёмник IrReceiver.begin(IR_RECEIVE_PIN); // Передаём случайное число с пина A1 // для последующей генерации случайных чисел randomSeed(analogRead(A1)); } void loop() { // Переходим в функцию обработки ИК-приёмника remoteHandler(); } // Функция отображения иконки на матрицах void drawIcon(uint8_t* iconEyeL, uint8_t* iconEyeR) { matrixL.drawBitmapF(iconEyeL); matrixR.drawBitmapF(iconEyeR); } // Функция обработки ИК-приёмника void remoteHandler() { // Если пришёл новый сигнал на ИК-приёмник, декодируем его if (IrReceiver.decode()) { // Создаём переменную и присваиваем ей декодируемый код кнопки uint32_t code = IrReceiver.decodedIRData.command; // Если код кнопки равен 0, пришёл шум и игнорируем его if (code == 0x00) { // Разрешаем обрабатывать следующий сигнал IrReceiver.resume(); // Выходим из функции return; } // Отключаем ИК-приёмник IrReceiver.stop(); // Вызываем функцию генератора последовательных длинных семплов toneLongSamples(); // Вызываем функцию генератора непоследовательных коротких семплов toneShortSamples(); // Запускаем ИК-приёмник IrReceiver.start(); // Разрешаем обрабатывать команды с ИК-приёмника IrReceiver.resume(); } } // Функция генерации последовательных длинных семплов void toneLongSamples() { // Генерируем случайное количество семплов от 1 до 6 int countSamples = random(1, 7); // Перебираем нумерацию семплов в цикле for (int i = 0; i < countSamples; i++) { // Генерируем случайное число: true или false bool typeSamples = random(0, 2); // Если тип семпла true if (typeSamples) { // Вызываем функцию генерации тона toneSlowDownFastUp: // Сначала медленный убывающий тон со случайными задержками // Затем быстрый возрастающий тон со случайными задержками toneSlowDownFastUp(); } else { // Если тип семпла false // Вызываем функцию генерации тона toneSlowUpFastDown: // Сначала медленный возрастающий тон со случайными задержками // Затем быстрый убывающий тон со случайными задержками toneSlowUpFastDown(); } } } // Функция генерации непоследовательных коротких семплов void toneShortSamples() { // Генерируем случайное количество семплов от 3 до 9 int countSamples = random(3, 10); // Генерируем случайную частоту на базе FREQUENCY int frequency = random(MIN_FREQUENCY, MAX_FREQUENCY); for (int i = 0; i <= countSamples; i++) { // Активируем глаза drawIcon(ICON_EYE_STRAIGHT, ICON_EYE_STRAIGHT); // Генерируем случайный интервал на базе FREQUENCY int range = random(-FREQUENCY, FREQUENCY); tone(BUZZER_PIN, frequency + range); // Выполняем случайную задержку от 70 до 170 мс delay(random(70, 170)); // Деактивируем глаза drawIcon(ICON_EYE_OFF, ICON_EYE_OFF); // Выключаем звук noTone(BUZZER_PIN); // Выполняем случайную задержку от 0 до 30 мс delay(random(0, 30)); } } // Функция генерации звуковой последовательности // Сначала медленный убывающий тон со случайными задержками // Затем быстрый возрастающий тон со случайными задержками void toneSlowDownFastUp() { // Генерируем случайную частоту на базе FREQUENCY int frequency = random(MIN_FREQUENCY, MAX_FREQUENCY); // Активируем глаза drawIcon(ICON_EYE_STRAIGHT, ICON_EYE_STRAIGHT); // Генерируем медленный понижающий тон со случайными задержками for (int range = 0; range <= random(100, 1000); range++) { tone(BUZZER_PIN, (range * 2)); delayMicroseconds(random(0, 1000)); } // Деактивируем глаза drawIcon(ICON_EYE_OFF, ICON_EYE_OFF); // Генерируем быстрый повышающий тон со случайными задержками for (int range = 0; range <= random(100, 1000); range++) { tone(BUZZER_PIN, frequency + (range * 10)); delayMicroseconds(random(0, 1000)); } } // Функция генерации звуковой последовательности // Сначала медленный возрастающий тон со случайными задержками // Затем быстрый убывающий тон со случайными задержками void toneSlowUpFastDown() { // Генерируем случайную частоту на базе FREQUENCY int frequency = random(MIN_FREQUENCY, MAX_FREQUENCY); // Активируем глаза drawIcon(ICON_EYE_STRAIGHT, ICON_EYE_STRAIGHT); // Генерируем медленный возрастающий тон со случайными задержками for (int range = 0; range <= random(100, 1000); range++) { tone(BUZZER_PIN, (range * 2)); delayMicroseconds(random(0, 1000)); } // Деактивируем глаза drawIcon(ICON_EYE_OFF, ICON_EYE_OFF); // Генерируем быстрый понижающий тон со случайными задержками for (int range = 0; range <= random(100, 1000); range++) { tone(BUZZER_PIN, (range * 10)); delayMicroseconds(random(0, 1000)); } }