Содержание

Электронное приложение к набору «IO.KIT Робот Ампи: Голова»

На этой странице ты найдёшь все нужные материалы для проектов набора Робот Ампи: Голова из серии IO.KIT:

Обрати внимание

Для сборки и функционирования головы робота Ампи тебе понадобится IO.KIT Базовый!

Схема

Проекты

Прежде чем приступать к экспериментам, нужно подготовить свой компьютер:

Драйвер чипа CH340

Установи драйвер CH340 для Windows или Linux, чтобы твой компьютер мог корректно распознать и прошить плату Iskra Nano.

№1. Электронные глаза

Активируй светодиодные глаза робота Ампи.

SampleEyes.ino
  1. // Подключаем библиотеку для работы со светодиодными матрицами
  2. #include <TroykaLedMatrix.h>
  3.  
  4. // Создаём объект матрицы левого глаза
  5. // на шине I²C с адресом 0x60 (указан по умолчанию)
  6. TroykaLedMatrix matrixL;
  7. // Создаём объект матрицы правого глаза
  8. // на шине I²C с адресом 0x63
  9. TroykaLedMatrix matrixR(0x63);
  10.  
  11. // Создаём иконку «Взгляд прямо» в шестнадцатеричной системе HEX
  12. // Иконка для левого и правого глаза одинаковая
  13. // Эмоции рисуем в редакторе изображений для LED-матрицы
  14. // https://amperka.github.io/led-matrix-editor/
  15. constexpr uint8_t ICON_EYE_STRAIGHT[] {
  16. 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e
  17. };
  18.  
  19. void setup() {
  20. // Инициализируем матрицы
  21. matrixL.begin();
  22. matrixR.begin();
  23. // Очищаем матрицы
  24. matrixL.clear();
  25. matrixR.clear();
  26. // Устанавливаем яркость матриц
  27. matrixL.setCurrentLimit(ROW_CURRENT_05MA);
  28. matrixR.setCurrentLimit(ROW_CURRENT_05MA);
  29. // Отображаем на матрицах иконку «Взгляд прямо»
  30. matrixL.drawBitmap(ICON_EYE_STRAIGHT);
  31. matrixR.drawBitmap(ICON_EYE_STRAIGHT);
  32. }
  33.  
  34. void loop() {
  35. }

«Электронные глаза» в редакторе изображений для LED-матрицы

№2. Осмотр местности

LookAround.ino
  1. // Подключаем библиотеку для работы со светодиодными матрицами
  2. #include <TroykaLedMatrix.h>
  3.  
  4. // Создаём объект матрицы левого глаза
  5. // на шине I²C с адресом 0x60 (указан по умолчанию)
  6. TroykaLedMatrix matrixL;
  7. // Создаём объект матрицы правого глаза
  8. // на шине I²C с адресом 0x63
  9. TroykaLedMatrix matrixR(0x63);
  10.  
  11. // Создаём массив иконок анимации «Осмотр местности по сторонам» в шестнадцатеричной системе HEX
  12. // Массив иконок для левого и правого глаза одинаковый
  13. // Эмоции рисуем в редакторе изображений для LED-матрицы
  14. // https://amperka.github.io/led-matrix-editor/
  15. constexpr uint8_t ICON_EYE_LOOK_AROUND[][8] {
  16. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  17. { 0x7e, 0x81, 0x81, 0x87, 0x87, 0x81, 0x81, 0x7e },
  18. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  19. { 0x7e, 0x81, 0x81, 0xe1, 0xe1, 0x81, 0x81, 0x7e },
  20. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  21. { 0x7e, 0x99, 0x99, 0x81, 0x81, 0x81, 0x81, 0x7e },
  22. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  23. { 0x7e, 0x81, 0x81, 0x81, 0x81, 0x99, 0x99, 0x7e }
  24. };
  25.  
  26. // Создаём массив иконок анимации «Осмотр местности по углам» в шестнадцатеричной системе HEX
  27. // Массив иконок для левого и правого глаза одинаковый
  28. constexpr uint8_t ICON_EYE_LOOK_CORNER[][8] {
  29. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  30. { 0x7e, 0x87, 0x87, 0x81, 0x81, 0x81, 0x81, 0x7e },
  31. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  32. { 0x7e, 0x81, 0x81, 0x81, 0x81, 0x87, 0x87, 0x7e },
  33. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  34. { 0x7e, 0x81, 0x81, 0x81, 0x81, 0xe1, 0xe1, 0x7e },
  35. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  36. { 0x7e, 0xe1, 0xe1, 0x81, 0x81, 0x81, 0x81, 0x7e }
  37. };
  38.  
  39. // Вычисляем количество кадров в массиве «Осмотр местности»
  40. constexpr uint8_t COUNT_FRAMES_LOOK_AROUND = sizeof(ICON_EYE_LOOK_AROUND)
  41. / sizeof(ICON_EYE_LOOK_AROUND[0]);
  42.  
  43. // Вычисляем количество кадров в массиве «Осмотр местности по диагонали»
  44. constexpr uint8_t COUNT_FRAMES_LOOK_CORNER = sizeof(ICON_EYE_LOOK_CORNER)
  45. / sizeof(ICON_EYE_LOOK_CORNER[0]);
  46.  
  47. void setup() {
  48. // Инициализируем матрицы
  49. matrixL.begin();
  50. matrixR.begin();
  51. // Очищаем матрицы
  52. matrixL.clear();
  53. matrixR.clear();
  54. }
  55.  
  56. void loop() {
  57. // Перебираем массив «Осмотр местности» по кадрам
  58. for (int i = 0; i < COUNT_FRAMES_LOOK_AROUND; i++) {
  59. // Отображаем на матрицах текущий кадр
  60. matrixL.drawBitmap(ICON_EYE_LOOK_AROUND[i]);
  61. matrixR.drawBitmap(ICON_EYE_LOOK_AROUND[i]);
  62. // Ждём 500 мс
  63. delay(500);
  64. }
  65. }

№3. Отображение эмоций

Emotions.ino
  1. // Подключаем библиотеку для работы со светодиодными матрицами
  2. #include <TroykaLedMatrix.h>
  3.  
  4. // Создаём объект матрицы левого глаза
  5. // на шине I²C с адресом 0x60 (указан по умолчанию)
  6. TroykaLedMatrix matrixL;
  7. // Создаём объект матрицы правого глаза
  8. // на шине I²C с адресом 0x63
  9. TroykaLedMatrix matrixR(0x63);
  10.  
  11. // Создаём структуру анимации
  12. struct AnimationFrame {
  13. uint8_t* iconEyeL;
  14. uint8_t* iconEyeR;
  15. int timeFrame;
  16. };
  17.  
  18. // Создаём массив иконок анимации «Моргание» в шестнадцатеричной системе HEX
  19. // Массив иконок для левого и правого глаза одинаковый
  20. // Эмоции рисуем в редакторе изображений для LED-матрицы
  21. // https://amperka.github.io/led-matrix-editor/
  22. constexpr uint8_t ICON_EYE_BLINK[][8] PROGMEM {
  23. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  24. { 0x00, 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x7e },
  25. { 0x00, 0x00, 0x7e, 0x81, 0x99, 0x99, 0x81, 0x7e },
  26. { 0x00, 0x00, 0x00, 0x7e, 0x99, 0x99, 0x7e, 0x00 },
  27. { 0x00, 0x00, 0x00, 0x00, 0x7e, 0x99, 0x7e, 0x00 },
  28. { 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00 },
  29. { 0x00, 0x00, 0x00, 0x00, 0x7e, 0x99, 0x7e, 0x00 },
  30. { 0x00, 0x00, 0x00, 0x7e, 0x99, 0x99, 0x7e, 0x00 },
  31. { 0x00, 0x00, 0x7e, 0x81, 0x99, 0x99, 0x81, 0x7e },
  32. { 0x00, 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x7e },
  33. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e }
  34. };
  35.  
  36. // Создаём массив иконок анимации «Злость»
  37. // в шестнадцатеричной системе HEX для левого глаза
  38. constexpr uint8_t ICON_EYE_ANGRY_L[][8] PROGMEM {
  39. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  40. { 0x78, 0x84, 0x82, 0x9a, 0x9a, 0x82, 0x82, 0x7c },
  41. { 0x70, 0x88, 0x84, 0x9a, 0x9a, 0x82, 0x82, 0x7c },
  42. { 0x60, 0x90, 0x88, 0x9c, 0x9a, 0x82, 0x82, 0x7c },
  43. { 0x40, 0xa0, 0x90, 0x88, 0xb4, 0xb2, 0x82, 0x7c },
  44. { 0x80, 0xc0, 0xa0, 0x90, 0xa8, 0xb4, 0x82, 0x7c },
  45. { 0x40, 0xa0, 0x90, 0x88, 0xb4, 0xb2, 0x82, 0x7c },
  46. { 0x60, 0x90, 0x88, 0x9c, 0x9a, 0x82, 0x82, 0x7c },
  47. { 0x70, 0x88, 0x84, 0x9a, 0x9a, 0x82, 0x82, 0x7c },
  48. { 0x78, 0x84, 0x82, 0x9a, 0x9a, 0x82, 0x82, 0x7c },
  49. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e }
  50. };
  51.  
  52. // Создаём массив иконок анимации «Злость»
  53. // в шестнадцатеричной системе HEX для правого глаза
  54. constexpr uint8_t ICON_EYE_ANGRY_R[][8] PROGMEM {
  55. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  56. { 0x1e, 0x21, 0x41, 0x59, 0x59, 0x41, 0x41, 0x3e },
  57. { 0x0e, 0x11, 0x21, 0x59, 0x59, 0x41, 0x41, 0x3e },
  58. { 0x06, 0x09, 0x11, 0x39, 0x59, 0x41, 0x41, 0x3e },
  59. { 0x02, 0x05, 0x09, 0x11, 0x2d, 0x4d, 0x41, 0x3e },
  60. { 0x01, 0x03, 0x05, 0x09, 0x15, 0x2d, 0x41, 0x3e },
  61. { 0x02, 0x05, 0x09, 0x11, 0x2d, 0x4d, 0x41, 0x3e },
  62. { 0x06, 0x09, 0x11, 0x39, 0x59, 0x41, 0x41, 0x3e },
  63. { 0x0e, 0x11, 0x21, 0x59, 0x59, 0x41, 0x41, 0x3e },
  64. { 0x1e, 0x21, 0x41, 0x59, 0x59, 0x41, 0x41, 0x3e }
  65. };
  66.  
  67. // Создаём массив иконок анимации «Грусть»
  68. // в шестнадцатеричной системе HEX для левого глаза
  69. constexpr uint8_t ICON_EYE_SAD_L[][8] PROGMEM {
  70. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  71. { 0x3e, 0x41, 0x81, 0x99, 0x99, 0x81, 0x82, 0x7c },
  72. { 0x1e, 0x21, 0x41, 0x99, 0x99, 0x81, 0x82, 0x7c },
  73. { 0x0e, 0x11, 0x21, 0x41, 0x8d, 0x8d, 0x82, 0x7c },
  74. { 0x0e, 0x11, 0x21, 0x41, 0x4d, 0x4d, 0x42, 0x3c },
  75. { 0x06, 0x09, 0x11, 0x21, 0x4d, 0x4d, 0x42, 0x3c },
  76. { 0x0e, 0x11, 0x21, 0x41, 0x4d, 0x4d, 0x42, 0x3c },
  77. { 0x0e, 0x11, 0x21, 0x41, 0x8d, 0x8d, 0x82, 0x7c },
  78. { 0x1e, 0x21, 0x41, 0x99, 0x99, 0x81, 0x82, 0x7c },
  79. { 0x3e, 0x41, 0x81, 0x99, 0x99, 0x81, 0x82, 0x7c },
  80. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e }
  81. };
  82.  
  83. // Создаём массив иконок анимации «Грусть»
  84. // в шестнадцатеричной системе HEX для правого глаза
  85. constexpr uint8_t ICON_EYE_SAD_R[][8] PROGMEM {
  86. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  87. { 0x7c, 0x82, 0x81, 0x99, 0x99, 0x81, 0x41, 0x3e },
  88. { 0x78, 0x84, 0x82, 0x99, 0x99, 0x81, 0x41, 0x3e },
  89. { 0x70, 0x88, 0x84, 0x82, 0xb1, 0xb1, 0x41, 0x3e },
  90. { 0x70, 0x88, 0x84, 0x82, 0xb2, 0xb2, 0x42, 0x3c },
  91. { 0x60, 0x90, 0x88, 0x84, 0xb2, 0xb2, 0x42, 0x3c },
  92. { 0x70, 0x88, 0x84, 0x82, 0xb2, 0xb2, 0x42, 0x3c },
  93. { 0x70, 0x88, 0x84, 0x82, 0xb1, 0xb1, 0x41, 0x3e },
  94. { 0x78, 0x84, 0x82, 0x99, 0x99, 0x81, 0x41, 0x3e },
  95. { 0x7c, 0x82, 0x81, 0x99, 0x99, 0x81, 0x41, 0x3e },
  96. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e }
  97. };
  98.  
  99. // Создаём массив иконок анимации «Радость» в шестнадцатеричной системе HEX
  100. // Массив иконок для левого и правого глаза одинаковый
  101. constexpr uint8_t ICON_EYE_HAPPY[][8] PROGMEM {
  102. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  103. { 0x00, 0x7e, 0x81, 0x99, 0x99, 0x81, 0x7e, 0x00 },
  104. { 0x00, 0x7e, 0x81, 0x99, 0x99, 0xff, 0x00, 0x00 },
  105. { 0x00, 0x7e, 0xdb, 0x99, 0xff, 0x81, 0x00, 0x00 },
  106. { 0x00, 0x3c, 0x5a, 0xff, 0xc3, 0x81, 0x00, 0x00 },
  107. { 0x00, 0x3c, 0x7e, 0xc3, 0xc3, 0x81, 0x00, 0x00 },
  108. { 0x00, 0x3c, 0x5a, 0xff, 0xc3, 0x81, 0x00, 0x00 },
  109. { 0x00, 0x7e, 0xdb, 0x99, 0xff, 0x81, 0x00, 0x00 },
  110. { 0x00, 0x7e, 0x81, 0x99, 0x99, 0xff, 0x00, 0x00 },
  111. { 0x00, 0x7e, 0x81, 0x99, 0x99, 0x81, 0x7e, 0x00 },
  112. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e }
  113. };
  114.  
  115. // Создаём массив иконок анимации «Удивление» в шестнадцатеричной системе HEX
  116. // Массив иконок для левого и правого глаза одинаковый
  117. constexpr uint8_t ICON_EYE_AMAZED[][8] PROGMEM {
  118. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  119. { 0x7e, 0x81, 0x99, 0xbd, 0xbd, 0x99, 0x81, 0x7e },
  120. { 0x7e, 0x81, 0xbd, 0xbd, 0xbd, 0xbd, 0x81, 0x7e },
  121. { 0x7e, 0x81, 0x99, 0xbd, 0xbd, 0x99, 0x81, 0x7e },
  122. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e }
  123. };
  124.  
  125. // Создаём массив иконок анимации «Любовь» в шестнадцатеричной системе HEX
  126. // Массив иконок для левого и правого глаза одинаковый
  127. constexpr uint8_t ICON_EYE_LOVE[][8] PROGMEM {
  128. { 0x66, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x18 },
  129. { 0x00, 0x00, 0x24, 0x7e, 0x7e, 0x3c, 0x18, 0x00 }
  130. };
  131.  
  132. // Создаём массив иконок анимации Сон» в шестнадцатеричной системе HEX
  133. // Массив иконок для левого и правого глаза одинаковый
  134. constexpr uint8_t ICON_EYE_SLEEP[][8] PROGMEM {
  135. { 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00 },
  136. { 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, 0x7e, 0x00 }
  137. };
  138.  
  139. // Создаём анимацию «Моргание»
  140. AnimationFrame animationBlink[] = {
  141. { ICON_EYE_BLINK[0], ICON_EYE_BLINK[0], 500 },
  142. { ICON_EYE_BLINK[1], ICON_EYE_BLINK[1], 25 },
  143. { ICON_EYE_BLINK[2], ICON_EYE_BLINK[2], 25 },
  144. { ICON_EYE_BLINK[3], ICON_EYE_BLINK[3], 25 },
  145. { ICON_EYE_BLINK[4], ICON_EYE_BLINK[4], 25 },
  146. { ICON_EYE_BLINK[5], ICON_EYE_BLINK[5], 25 },
  147. { ICON_EYE_BLINK[6], ICON_EYE_BLINK[6], 25 },
  148. { ICON_EYE_BLINK[7], ICON_EYE_BLINK[7], 25 },
  149. { ICON_EYE_BLINK[8], ICON_EYE_BLINK[8], 25 },
  150. { ICON_EYE_BLINK[9], ICON_EYE_BLINK[9], 25 },
  151. { ICON_EYE_BLINK[10], ICON_EYE_BLINK[10], 500 }
  152. };
  153.  
  154. // Создаём анимацию «Злость»
  155. AnimationFrame animationAngry[] = {
  156. { ICON_EYE_ANGRY_L[0], ICON_EYE_ANGRY_R[0], 500 },
  157. { ICON_EYE_ANGRY_L[1], ICON_EYE_ANGRY_R[1], 50 },
  158. { ICON_EYE_ANGRY_L[2], ICON_EYE_ANGRY_R[2], 50 },
  159. { ICON_EYE_ANGRY_L[3], ICON_EYE_ANGRY_R[3], 50 },
  160. { ICON_EYE_ANGRY_L[4], ICON_EYE_ANGRY_R[4], 50 },
  161. { ICON_EYE_ANGRY_L[5], ICON_EYE_ANGRY_R[5], 2000 },
  162. { ICON_EYE_ANGRY_L[6], ICON_EYE_ANGRY_R[6], 50 },
  163. { ICON_EYE_ANGRY_L[7], ICON_EYE_ANGRY_R[7], 50 },
  164. { ICON_EYE_ANGRY_L[8], ICON_EYE_ANGRY_R[8], 50 },
  165. { ICON_EYE_ANGRY_L[9], ICON_EYE_ANGRY_R[9], 50 },
  166. { ICON_EYE_ANGRY_L[10], ICON_EYE_ANGRY_R[10], 500 }
  167. };
  168.  
  169. // Создаём анимацию «Грусть»
  170. AnimationFrame animationSad[] = {
  171. { ICON_EYE_SAD_L[0], ICON_EYE_SAD_R[0], 500 },
  172. { ICON_EYE_SAD_L[1], ICON_EYE_SAD_R[1], 50 },
  173. { ICON_EYE_SAD_L[2], ICON_EYE_SAD_R[2], 50 },
  174. { ICON_EYE_SAD_L[3], ICON_EYE_SAD_R[3], 50 },
  175. { ICON_EYE_SAD_L[4], ICON_EYE_SAD_R[4], 50 },
  176. { ICON_EYE_SAD_L[5], ICON_EYE_SAD_R[5], 3000 },
  177. { ICON_EYE_SAD_L[6], ICON_EYE_SAD_R[6], 50 },
  178. { ICON_EYE_SAD_L[7], ICON_EYE_SAD_R[7], 50 },
  179. { ICON_EYE_SAD_L[8], ICON_EYE_SAD_R[8], 50 },
  180. { ICON_EYE_SAD_L[9], ICON_EYE_SAD_R[9], 50 },
  181. { ICON_EYE_SAD_L[10], ICON_EYE_SAD_R[10], 500 }
  182. };
  183.  
  184. // Создаём анимацию «Радость»
  185. AnimationFrame animationHappy[] = {
  186. { ICON_EYE_HAPPY[0], ICON_EYE_HAPPY[0], 500 },
  187. { ICON_EYE_HAPPY[1], ICON_EYE_HAPPY[1], 40 },
  188. { ICON_EYE_HAPPY[2], ICON_EYE_HAPPY[2], 40 },
  189. { ICON_EYE_HAPPY[3], ICON_EYE_HAPPY[3], 40 },
  190. { ICON_EYE_HAPPY[4], ICON_EYE_HAPPY[4], 40 },
  191. { ICON_EYE_HAPPY[5], ICON_EYE_HAPPY[5], 2000 },
  192. { ICON_EYE_HAPPY[6], ICON_EYE_HAPPY[6], 40 },
  193. { ICON_EYE_HAPPY[7], ICON_EYE_HAPPY[7], 40 },
  194. { ICON_EYE_HAPPY[8], ICON_EYE_HAPPY[8], 40 },
  195. { ICON_EYE_HAPPY[9], ICON_EYE_HAPPY[9], 40 },
  196. { ICON_EYE_HAPPY[10], ICON_EYE_HAPPY[10], 500 }
  197. };
  198.  
  199. // Создаём анимацию «Удивление»
  200. AnimationFrame animationAmazed[] = {
  201. { ICON_EYE_AMAZED[0], ICON_EYE_AMAZED[0], 500 },
  202. { ICON_EYE_AMAZED[1], ICON_EYE_AMAZED[1], 100 },
  203. { ICON_EYE_AMAZED[2], ICON_EYE_AMAZED[2], 2000 },
  204. { ICON_EYE_AMAZED[3], ICON_EYE_AMAZED[3], 100 },
  205. { ICON_EYE_AMAZED[4], ICON_EYE_AMAZED[4], 500 }
  206. };
  207.  
  208. // Создаём анимацию «Любовь»
  209. AnimationFrame animationLove[] = {
  210. { ICON_EYE_LOVE[0], ICON_EYE_LOVE[0], 1000 },
  211. { ICON_EYE_LOVE[1], ICON_EYE_LOVE[1], 300 }
  212. };
  213.  
  214. // Создаём анимацию «Сон»
  215. AnimationFrame animationSleep[] = {
  216. { ICON_EYE_SLEEP[0], ICON_EYE_SLEEP[0], 750 },
  217. { ICON_EYE_SLEEP[1], ICON_EYE_SLEEP[1], 750 }
  218. };
  219.  
  220. // Вычисляем количество кадров в анимации «Моргание»
  221. constexpr uint8_t COUNT_FRAMES_BLINK = sizeof(animationBlink) / sizeof(AnimationFrame);
  222. // Вычисляем количество кадров в анимации «Злость»
  223. constexpr uint8_t COUNT_FRAMES_ANGRY = sizeof(animationAngry) / sizeof(AnimationFrame);
  224. // Вычисляем количество кадров в анимации «Грусть»
  225. constexpr uint8_t COUNT_FRAMES_SAD = sizeof(animationSad) / sizeof(AnimationFrame);
  226. // Вычисляем количество кадров в анимации «Радость»
  227. constexpr uint8_t COUNT_FRAMES_HAPPY = sizeof(animationHappy) / sizeof(AnimationFrame);
  228. // Вычисляем количество кадров в анимации «Удивление»
  229. constexpr uint8_t COUNT_FRAMES_AMAZED = sizeof(animationAmazed) / sizeof(AnimationFrame);
  230. // Вычисляем количество кадров в анимации «Бьющее серде»
  231. constexpr uint8_t COUNT_FRAMES_LOVE = sizeof(animationLove) / sizeof(AnimationFrame);
  232. // Вычисляем количество кадров в анимации «Сон»
  233. constexpr uint8_t COUNT_FRAMES_SLEEP = sizeof(animationSleep) / sizeof(AnimationFrame);
  234.  
  235. // Создаём константу для хранения повторений эмоции
  236. constexpr uint8_t COUNT_REPEAT_EMOTION = 3;
  237.  
  238. void setup() {
  239. // Инициализируем матрицы
  240. matrixL.begin();
  241. matrixR.begin();
  242. // Очищаем матрицы
  243. matrixL.clear();
  244. matrixR.clear();
  245. }
  246.  
  247. void loop() {
  248. // Перебираем количество повторений анимации «Моргание»
  249. for (int i = 0; i < COUNT_REPEAT_EMOTION; i++) {
  250. // Отображаем анимацию «Моргание»
  251. drawAnimation(animationBlink, COUNT_FRAMES_BLINK);
  252. }
  253.  
  254. // Перебираем количество повторений анимации «Злость»
  255. for (int i = 0; i < COUNT_REPEAT_EMOTION; i++) {
  256. // Отображаем анимацию «Злость»
  257. drawAnimation(animationAngry, COUNT_FRAMES_ANGRY);
  258. }
  259.  
  260. // Перебираем количество повторений анимации «Грусть»
  261. for (int i = 0; i < COUNT_REPEAT_EMOTION; i++) {
  262. // Отображаем анимацию «Грусть»
  263. drawAnimation(animationSad, COUNT_FRAMES_SAD);
  264. }
  265.  
  266. // Перебираем количество повторений анимации «Радость»
  267. for (int i = 0; i < COUNT_REPEAT_EMOTION; i++) {
  268. // Отображаем анимацию «Радость»
  269. drawAnimation(animationHappy, COUNT_FRAMES_HAPPY);
  270. }
  271.  
  272. // Перебираем количество повторений анимации «Удивление»
  273. for (int i = 0; i < COUNT_REPEAT_EMOTION; i++) {
  274. // Отображаем анимацию «Удивление»
  275. drawAnimation(animationAmazed, COUNT_FRAMES_AMAZED);
  276. }
  277.  
  278. // Перебираем количество повторений анимации «Любовь»
  279. for (int i = 0; i < COUNT_REPEAT_EMOTION; i++) {
  280. // Отображаем анимацию «Любовь»
  281. drawAnimation(animationLove, COUNT_FRAMES_LOVE);
  282. }
  283. }
  284.  
  285. // Функция отображения анимации на матрицах
  286. void drawAnimation(AnimationFrame* animationFrame, int countFrames) {
  287. // Перебираем анимацию по кадрам
  288. for (int indexFrame = 0; indexFrame < countFrames; indexFrame++) {
  289. // Отображаем на матрицах текущий кадр
  290. matrixL.drawBitmapF(animationFrame[indexFrame].iconEyeL);
  291. matrixR.drawBitmapF(animationFrame[indexFrame].iconEyeR);
  292. // Ждём время задержки текущего кадра
  293. delay(animationFrame[indexFrame].timeFrame);
  294. }
  295. }

№4. Эмоции со звуком

EmotionSound.ino
  1. // Подключаем библиотеку для работы с мелодиями в формате RTTTL
  2. #include <anyrtttl.h>
  3.  
  4. // Подключаем библиотеку для работы с таймером millis
  5. #include <TimerMs.h>
  6.  
  7. // Подключаем библиотеку для работы со светодиодными матрицами
  8. #include <TroykaLedMatrix.h>
  9.  
  10. // Даём понятное имя пину 3 с пищалкой
  11. constexpr uint8_t BUZZER_PIN = 3;
  12.  
  13. // Создаём объект для работы с таймером
  14. TimerMs timer;
  15.  
  16. // Создаём объект матрицы левого глаза
  17. // на шине I²C с адресом 0x60 (указан по умолчанию)
  18. TroykaLedMatrix matrixL;
  19. // Создаём объект матрицы правого глаза
  20. // на шине I²C с адресом 0x63
  21. TroykaLedMatrix matrixR(0x63);
  22.  
  23. // Создаём массив данных мелодии «Моргание» в формате RTTTL
  24. constexpr uint8_t melodyBlink[] PROGMEM = "Blink:d=4,o=4,b=120:"
  25. "16e,16p,16g,16p,16e,16p,16g,16p,";
  26.  
  27. // Создаём массив данных мелодии «Злость» в формате RTTTL
  28. constexpr uint8_t melodyAngry[] PROGMEM = "Angry:d=4,o=4,b=200:"
  29. "16g,16g,16f#,16f#,16e,16e,16d#,16d#,"
  30. "16c,16c,16b4,16b4,16a4,16a4,16g4,16g4";
  31.  
  32. // Создаём массив данных мелодии «Грусть» в формате RTTTL
  33. constexpr uint8_t melodySad[] PROGMEM = "Sad:d=4,o=4,b=25:"
  34. "16g,16a#,16d,16f,"
  35. "16d,16c,16a#";
  36.  
  37. constexpr uint8_t melodyHappy[] PROGMEM = "Happy:d=4,o=4,b=140:"
  38. "8c4,8e4,8g4,8c4,8e4,8g4,8c4,8e4"
  39. "8g4,8c4,8e4,8g4";
  40.  
  41. // Создаём массив данных мелодии «Удивление» в формате RTTTL
  42. constexpr uint8_t melodyAmazed[] PROGMEM = "Amazed:d=4,o=4,b=180:"
  43. "16c,16d,16e,16f,16g,16a,16b,16c,"
  44. "16b,16a,16g,16f,16e,16d,16c,16d";
  45.  
  46. // Создаём массив данных мелодии «Любовь» в формате RTTTL
  47. constexpr uint8_t melodyLove[] PROGMEM = "Love:d=4,o=4,b=100:"
  48. "8g,8p,8g,8p,8a,8p,8g,8p,"
  49. "8g,8p,8g,8p,8f,8e,8d";
  50.  
  51. // Создаём массив данных мелодии «Сонливость» в формате RTTTL
  52. constexpr uint8_t melodySleep[] PROGMEM = "Sleep:d=4,o=4,b=45:"
  53. "8c,8c,8d,8e,8d,8c,8d,8e";
  54.  
  55. // Создаём перечисление эмоций с соответствующей переменной
  56. enum Emotion {
  57. EMOTION_BLINK,
  58. EMOTION_ANGRY,
  59. EMOTION_SAD,
  60. EMOTION_HAPPY,
  61. EMOTION_AMAZED,
  62. EMOTION_LOVE,
  63. EMOTION_SLEEP,
  64. } emotion;
  65.  
  66. // Создаём структуру анимации
  67. struct AnimationFrame {
  68. uint8_t* iconEyeL;
  69. uint8_t* iconEyeR;
  70. int timeFrame;
  71. };
  72.  
  73. // Создаём объект структуры анимации
  74. AnimationFrame* animationFrame;
  75.  
  76. // Создаём массив иконок анимации «Моргание» в шестнадцатеричной системе HEX
  77. // Массив иконок для левого и правого глаза одинаковый
  78. // Эмоции рисуем в редакторе изображений для LED-матрицы
  79. // https://amperka.github.io/led-matrix-editor/
  80. constexpr uint8_t ICON_EYE_BLINK[][8] PROGMEM {
  81. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  82. { 0x00, 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x7e },
  83. { 0x00, 0x00, 0x7e, 0x81, 0x99, 0x99, 0x81, 0x7e },
  84. { 0x00, 0x00, 0x00, 0x7e, 0x99, 0x99, 0x7e, 0x00 },
  85. { 0x00, 0x00, 0x00, 0x00, 0x7e, 0x99, 0x7e, 0x00 },
  86. { 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00 },
  87. { 0x00, 0x00, 0x00, 0x00, 0x7e, 0x99, 0x7e, 0x00 },
  88. { 0x00, 0x00, 0x00, 0x7e, 0x99, 0x99, 0x7e, 0x00 },
  89. { 0x00, 0x00, 0x7e, 0x81, 0x99, 0x99, 0x81, 0x7e },
  90. { 0x00, 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x7e },
  91. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e }
  92. };
  93.  
  94. // Создаём массив иконок анимации «Злость»
  95. // в шестнадцатеричной системе HEX для левого глаза
  96. constexpr uint8_t ICON_EYE_ANGRY_L[][8] PROGMEM {
  97. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  98. { 0x78, 0x84, 0x82, 0x9a, 0x9a, 0x82, 0x82, 0x7c },
  99. { 0x70, 0x88, 0x84, 0x9a, 0x9a, 0x82, 0x82, 0x7c },
  100. { 0x60, 0x90, 0x88, 0x9c, 0x9a, 0x82, 0x82, 0x7c },
  101. { 0x40, 0xa0, 0x90, 0x88, 0xb4, 0xb2, 0x82, 0x7c },
  102. { 0x80, 0xc0, 0xa0, 0x90, 0xa8, 0xb4, 0x82, 0x7c },
  103. { 0x40, 0xa0, 0x90, 0x88, 0xb4, 0xb2, 0x82, 0x7c },
  104. { 0x60, 0x90, 0x88, 0x9c, 0x9a, 0x82, 0x82, 0x7c },
  105. { 0x70, 0x88, 0x84, 0x9a, 0x9a, 0x82, 0x82, 0x7c },
  106. { 0x78, 0x84, 0x82, 0x9a, 0x9a, 0x82, 0x82, 0x7c },
  107. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e }
  108. };
  109.  
  110. // Создаём массив иконок анимации «Злость»
  111. // в шестнадцатеричной системе HEX для правого глаза
  112. constexpr uint8_t ICON_EYE_ANGRY_R[][8] PROGMEM {
  113. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  114. { 0x1e, 0x21, 0x41, 0x59, 0x59, 0x41, 0x41, 0x3e },
  115. { 0x0e, 0x11, 0x21, 0x59, 0x59, 0x41, 0x41, 0x3e },
  116. { 0x06, 0x09, 0x11, 0x39, 0x59, 0x41, 0x41, 0x3e },
  117. { 0x02, 0x05, 0x09, 0x11, 0x2d, 0x4d, 0x41, 0x3e },
  118. { 0x01, 0x03, 0x05, 0x09, 0x15, 0x2d, 0x41, 0x3e },
  119. { 0x02, 0x05, 0x09, 0x11, 0x2d, 0x4d, 0x41, 0x3e },
  120. { 0x06, 0x09, 0x11, 0x39, 0x59, 0x41, 0x41, 0x3e },
  121. { 0x0e, 0x11, 0x21, 0x59, 0x59, 0x41, 0x41, 0x3e },
  122. { 0x1e, 0x21, 0x41, 0x59, 0x59, 0x41, 0x41, 0x3e }
  123. };
  124.  
  125. // Создаём массив иконок анимации «Грусть»
  126. // в шестнадцатеричной системе HEX для левого глаза
  127. constexpr uint8_t ICON_EYE_SAD_L[][8] PROGMEM {
  128. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  129. { 0x3e, 0x41, 0x81, 0x99, 0x99, 0x81, 0x82, 0x7c },
  130. { 0x1e, 0x21, 0x41, 0x99, 0x99, 0x81, 0x82, 0x7c },
  131. { 0x0e, 0x11, 0x21, 0x41, 0x8d, 0x8d, 0x82, 0x7c },
  132. { 0x0e, 0x11, 0x21, 0x41, 0x4d, 0x4d, 0x42, 0x3c },
  133. { 0x06, 0x09, 0x11, 0x21, 0x4d, 0x4d, 0x42, 0x3c },
  134. { 0x0e, 0x11, 0x21, 0x41, 0x4d, 0x4d, 0x42, 0x3c },
  135. { 0x0e, 0x11, 0x21, 0x41, 0x8d, 0x8d, 0x82, 0x7c },
  136. { 0x1e, 0x21, 0x41, 0x99, 0x99, 0x81, 0x82, 0x7c },
  137. { 0x3e, 0x41, 0x81, 0x99, 0x99, 0x81, 0x82, 0x7c },
  138. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e }
  139. };
  140.  
  141. // Создаём массив иконок анимации «Грусть»
  142. // в шестнадцатеричной системе HEX для правого глаза
  143. constexpr uint8_t ICON_EYE_SAD_R[][8] PROGMEM {
  144. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  145. { 0x7c, 0x82, 0x81, 0x99, 0x99, 0x81, 0x41, 0x3e },
  146. { 0x78, 0x84, 0x82, 0x99, 0x99, 0x81, 0x41, 0x3e },
  147. { 0x70, 0x88, 0x84, 0x82, 0xb1, 0xb1, 0x41, 0x3e },
  148. { 0x70, 0x88, 0x84, 0x82, 0xb2, 0xb2, 0x42, 0x3c },
  149. { 0x60, 0x90, 0x88, 0x84, 0xb2, 0xb2, 0x42, 0x3c },
  150. { 0x70, 0x88, 0x84, 0x82, 0xb2, 0xb2, 0x42, 0x3c },
  151. { 0x70, 0x88, 0x84, 0x82, 0xb1, 0xb1, 0x41, 0x3e },
  152. { 0x78, 0x84, 0x82, 0x99, 0x99, 0x81, 0x41, 0x3e },
  153. { 0x7c, 0x82, 0x81, 0x99, 0x99, 0x81, 0x41, 0x3e },
  154. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e }
  155. };
  156.  
  157. // Создаём массив иконок анимации «Радость» в шестнадцатеричной системе HEX
  158. // Массив иконок для левого и правого глаза одинаковый
  159. constexpr uint8_t ICON_EYE_HAPPY[][8] PROGMEM {
  160. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  161. { 0x00, 0x7e, 0x81, 0x99, 0x99, 0x81, 0x7e, 0x00 },
  162. { 0x00, 0x7e, 0x81, 0x99, 0x99, 0xff, 0x00, 0x00 },
  163. { 0x00, 0x7e, 0xdb, 0x99, 0xff, 0x81, 0x00, 0x00 },
  164. { 0x00, 0x3c, 0x5a, 0xff, 0xc3, 0x81, 0x00, 0x00 },
  165. { 0x00, 0x3c, 0x7e, 0xc3, 0xc3, 0x81, 0x00, 0x00 },
  166. { 0x00, 0x3c, 0x5a, 0xff, 0xc3, 0x81, 0x00, 0x00 },
  167. { 0x00, 0x7e, 0xdb, 0x99, 0xff, 0x81, 0x00, 0x00 },
  168. { 0x00, 0x7e, 0x81, 0x99, 0x99, 0xff, 0x00, 0x00 },
  169. { 0x00, 0x7e, 0x81, 0x99, 0x99, 0x81, 0x7e, 0x00 },
  170. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e }
  171. };
  172.  
  173. // Создаём массив иконок анимации «Удивление» в шестнадцатеричной системе HEX
  174. // Массив иконок для левого и правого глаза одинаковый
  175. constexpr uint8_t ICON_EYE_AMAZED[][8] PROGMEM {
  176. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  177. { 0x7e, 0x81, 0x99, 0xbd, 0xbd, 0x99, 0x81, 0x7e },
  178. { 0x7e, 0x81, 0xbd, 0xbd, 0xbd, 0xbd, 0x81, 0x7e },
  179. { 0x7e, 0x81, 0x99, 0xbd, 0xbd, 0x99, 0x81, 0x7e },
  180. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e }
  181. };
  182.  
  183. // Создаём массив иконок анимации «Любовь» в шестнадцатеричной системе HEX
  184. // Массив иконок для левого и правого глаза одинаковый
  185. constexpr uint8_t ICON_EYE_LOVE[][8] PROGMEM {
  186. { 0x66, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x18 },
  187. { 0x00, 0x00, 0x24, 0x7e, 0x7e, 0x3c, 0x18, 0x00 }
  188. };
  189.  
  190. // Создаём массив иконок анимации Сон» в шестнадцатеричной системе HEX
  191. // Массив иконок для левого и правого глаза одинаковый
  192. constexpr uint8_t ICON_EYE_SLEEP[][8] PROGMEM {
  193. { 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00 },
  194. { 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, 0x7e, 0x00 }
  195. };
  196.  
  197. // Создаём анимацию «Моргание»
  198. AnimationFrame animationBlink[] = {
  199. { ICON_EYE_BLINK[0], ICON_EYE_BLINK[0], 500 },
  200. { ICON_EYE_BLINK[1], ICON_EYE_BLINK[1], 25 },
  201. { ICON_EYE_BLINK[2], ICON_EYE_BLINK[2], 25 },
  202. { ICON_EYE_BLINK[3], ICON_EYE_BLINK[3], 25 },
  203. { ICON_EYE_BLINK[4], ICON_EYE_BLINK[4], 25 },
  204. { ICON_EYE_BLINK[5], ICON_EYE_BLINK[5], 25 },
  205. { ICON_EYE_BLINK[6], ICON_EYE_BLINK[6], 25 },
  206. { ICON_EYE_BLINK[7], ICON_EYE_BLINK[7], 25 },
  207. { ICON_EYE_BLINK[8], ICON_EYE_BLINK[8], 25 },
  208. { ICON_EYE_BLINK[9], ICON_EYE_BLINK[9], 25 },
  209. { ICON_EYE_BLINK[10], ICON_EYE_BLINK[10], 500 }
  210. };
  211.  
  212. // Создаём анимацию «Злость»
  213. AnimationFrame animationAngry[] = {
  214. { ICON_EYE_ANGRY_L[0], ICON_EYE_ANGRY_R[0], 500 },
  215. { ICON_EYE_ANGRY_L[1], ICON_EYE_ANGRY_R[1], 50 },
  216. { ICON_EYE_ANGRY_L[2], ICON_EYE_ANGRY_R[2], 50 },
  217. { ICON_EYE_ANGRY_L[3], ICON_EYE_ANGRY_R[3], 50 },
  218. { ICON_EYE_ANGRY_L[4], ICON_EYE_ANGRY_R[4], 50 },
  219. { ICON_EYE_ANGRY_L[5], ICON_EYE_ANGRY_R[5], 2000 },
  220. { ICON_EYE_ANGRY_L[6], ICON_EYE_ANGRY_R[6], 50 },
  221. { ICON_EYE_ANGRY_L[7], ICON_EYE_ANGRY_R[7], 50 },
  222. { ICON_EYE_ANGRY_L[8], ICON_EYE_ANGRY_R[8], 50 },
  223. { ICON_EYE_ANGRY_L[9], ICON_EYE_ANGRY_R[9], 50 },
  224. { ICON_EYE_ANGRY_L[10], ICON_EYE_ANGRY_R[10], 500 }
  225. };
  226.  
  227. // Создаём анимацию «Грусть»
  228. AnimationFrame animationSad[] = {
  229. { ICON_EYE_SAD_L[0], ICON_EYE_SAD_R[0], 500 },
  230. { ICON_EYE_SAD_L[1], ICON_EYE_SAD_R[1], 50 },
  231. { ICON_EYE_SAD_L[2], ICON_EYE_SAD_R[2], 50 },
  232. { ICON_EYE_SAD_L[3], ICON_EYE_SAD_R[3], 50 },
  233. { ICON_EYE_SAD_L[4], ICON_EYE_SAD_R[4], 50 },
  234. { ICON_EYE_SAD_L[5], ICON_EYE_SAD_R[5], 3000 },
  235. { ICON_EYE_SAD_L[6], ICON_EYE_SAD_R[6], 50 },
  236. { ICON_EYE_SAD_L[7], ICON_EYE_SAD_R[7], 50 },
  237. { ICON_EYE_SAD_L[8], ICON_EYE_SAD_R[8], 50 },
  238. { ICON_EYE_SAD_L[9], ICON_EYE_SAD_R[9], 50 },
  239. { ICON_EYE_SAD_L[10], ICON_EYE_SAD_R[10], 500 }
  240. };
  241.  
  242. // Создаём анимацию «Радость»
  243. AnimationFrame animationHappy[] = {
  244. { ICON_EYE_HAPPY[0], ICON_EYE_HAPPY[0], 500 },
  245. { ICON_EYE_HAPPY[1], ICON_EYE_HAPPY[1], 40 },
  246. { ICON_EYE_HAPPY[2], ICON_EYE_HAPPY[2], 40 },
  247. { ICON_EYE_HAPPY[3], ICON_EYE_HAPPY[3], 40 },
  248. { ICON_EYE_HAPPY[4], ICON_EYE_HAPPY[4], 40 },
  249. { ICON_EYE_HAPPY[5], ICON_EYE_HAPPY[5], 2000 },
  250. { ICON_EYE_HAPPY[6], ICON_EYE_HAPPY[6], 40 },
  251. { ICON_EYE_HAPPY[7], ICON_EYE_HAPPY[7], 40 },
  252. { ICON_EYE_HAPPY[8], ICON_EYE_HAPPY[8], 40 },
  253. { ICON_EYE_HAPPY[9], ICON_EYE_HAPPY[9], 40 },
  254. { ICON_EYE_HAPPY[10], ICON_EYE_HAPPY[10], 500 }
  255. };
  256.  
  257. // Создаём анимацию «Удивление»
  258. AnimationFrame animationAmazed[] = {
  259. { ICON_EYE_AMAZED[0], ICON_EYE_AMAZED[0], 500 },
  260. { ICON_EYE_AMAZED[1], ICON_EYE_AMAZED[1], 100 },
  261. { ICON_EYE_AMAZED[2], ICON_EYE_AMAZED[2], 2000 },
  262. { ICON_EYE_AMAZED[3], ICON_EYE_AMAZED[3], 100 },
  263. { ICON_EYE_AMAZED[4], ICON_EYE_AMAZED[4], 500 }
  264. };
  265.  
  266. // Создаём анимацию «Любовь»
  267. AnimationFrame animationLove[] = {
  268. { ICON_EYE_LOVE[0], ICON_EYE_LOVE[0], 1000 },
  269. { ICON_EYE_LOVE[1], ICON_EYE_LOVE[1], 300 },
  270. { ICON_EYE_LOVE[0], ICON_EYE_LOVE[0], 1000 },
  271. { ICON_EYE_LOVE[1], ICON_EYE_LOVE[1], 300 },
  272. { ICON_EYE_LOVE[0], ICON_EYE_LOVE[0], 1000 },
  273. { ICON_EYE_LOVE[1], ICON_EYE_LOVE[1], 300 },
  274. { ICON_EYE_LOVE[0], ICON_EYE_LOVE[0], 1000 },
  275. { ICON_EYE_LOVE[1], ICON_EYE_LOVE[1], 300 },
  276. };
  277.  
  278. // Создаём анимацию «Сон»
  279. AnimationFrame animationSleep[] = {
  280. { ICON_EYE_SLEEP[0], ICON_EYE_SLEEP[0], 750 },
  281. { ICON_EYE_SLEEP[1], ICON_EYE_SLEEP[1], 750 },
  282. { ICON_EYE_SLEEP[0], ICON_EYE_SLEEP[0], 750 },
  283. { ICON_EYE_SLEEP[1], ICON_EYE_SLEEP[1], 750 },
  284. { ICON_EYE_SLEEP[0], ICON_EYE_SLEEP[0], 750 },
  285. { ICON_EYE_SLEEP[1], ICON_EYE_SLEEP[1], 750 },
  286. { ICON_EYE_SLEEP[0], ICON_EYE_SLEEP[0], 750 },
  287. { ICON_EYE_SLEEP[1], ICON_EYE_SLEEP[1], 750 }
  288. };
  289.  
  290. // Вычисляем количество кадров в анимации «Моргание»
  291. constexpr uint8_t COUNT_FRAMES_BLINK = sizeof(animationBlink) / sizeof(AnimationFrame);
  292. // Вычисляем количество кадров в анимации «Злость»
  293. constexpr uint8_t COUNT_FRAMES_ANGRY = sizeof(animationAngry) / sizeof(AnimationFrame);
  294. // Вычисляем количество кадров в анимации «Грусть»
  295. constexpr uint8_t COUNT_FRAMES_SAD = sizeof(animationSad) / sizeof(AnimationFrame);
  296. // Вычисляем количество кадров в анимации «Радость»
  297. constexpr uint8_t COUNT_FRAMES_HAPPY = sizeof(animationHappy) / sizeof(AnimationFrame);
  298. // Вычисляем количество кадров в анимации «Удивление»
  299. constexpr uint8_t COUNT_FRAMES_AMAZED = sizeof(animationAmazed) / sizeof(AnimationFrame);
  300. // Вычисляем количество кадров в анимации «Любовь»
  301. constexpr uint8_t COUNT_FRAMES_LOVE = sizeof(animationLove) / sizeof(AnimationFrame);
  302. // Вычисляем количество кадров в анимации «Сон»
  303. constexpr uint8_t COUNT_FRAMES_SLEEP = sizeof(animationSleep) / sizeof(AnimationFrame);
  304.  
  305. // Создаём константу для хранения общего количества повторений эмоции
  306. constexpr int COUNT_REPEAT_EMOTION = 3;
  307.  
  308. // Создаём переменную для хранения текущего счётчика количества повторений эмоции
  309. int countRepeatEmotion;
  310.  
  311. // Создаём переменную для хранения счётчика текущего кадра
  312. int indexFrame;
  313. // Создаём переменную для хранения количества кадров
  314. int countFrames;
  315. // Создаём переменную для хранения флага последнего кадра
  316. bool lastFrame;
  317.  
  318. void setup() {
  319. // Инициализируем матрицы
  320. matrixL.begin();
  321. matrixR.begin();
  322. // Очищаем матрицы
  323. matrixL.clear();
  324. matrixR.clear();
  325. // Настраиваем пин с пищалкой в режим выхода
  326. pinMode(BUZZER_PIN, OUTPUT);
  327. // Сбрасываем все настройки переменных по умолчанию
  328. resetState();
  329. // Устанавливаем таймер в режим остановки после срабатывания
  330. timer.setTimerMode();
  331. // Передаём случайное число с пина A1
  332. // для последующей генерации случайных чисел
  333. randomSeed(analogRead(A1));
  334. // Устанавливаем анимацию «Моргание»
  335. setEmotion(EMOTION_BLINK);
  336. }
  337.  
  338. void loop() {
  339. // Переходим в функцию обработки эмоций
  340. emotionHandler();
  341. }
  342.  
  343. // Функция обработки эмоций
  344. void emotionHandler() {
  345. // Вызываем функцию обновление анимации
  346. updateEmotion();
  347. // Разрешаем играть выбранный трек
  348. anyrtttl::nonblocking::play();
  349. }
  350.  
  351. // Функция установки текущей эмоции
  352. void setEmotion(Emotion emotionNow) {
  353. // Обновляем полученную эмоцию
  354. emotion = emotionNow;
  355. // Проверяем состояние текущей эмоции
  356. switch (emotion) {
  357. // Эмоция «Моргание»
  358. case EMOTION_BLINK:
  359. // Устанавливаем анимацию, кол-во кадров и мелодию для эмоции «Моргание»
  360. animationFrame = animationBlink;
  361. countFrames = COUNT_FRAMES_BLINK;
  362. anyrtttl::nonblocking::begin_P(BUZZER_PIN, melodyBlink);
  363. break;
  364. // Эмоция «Злость»
  365. case EMOTION_ANGRY:
  366. // Устанавливаем анимацию, кол-во кадров и мелодию для эмоции «Злость»
  367. animationFrame = animationAngry;
  368. countFrames = COUNT_FRAMES_ANGRY;
  369. anyrtttl::nonblocking::begin_P(BUZZER_PIN, melodyAngry);
  370. break;
  371. // Эмоция «Грусть»
  372. case EMOTION_SAD:
  373. // Устанавливаем анимацию, кол-во кадров и мелодию для эмоции «Грусть»
  374. animationFrame = animationSad;
  375. countFrames = COUNT_FRAMES_SAD;
  376. anyrtttl::nonblocking::begin_P(BUZZER_PIN, melodySad);
  377. break;
  378. // Эмоция «Радость»
  379. case EMOTION_HAPPY:
  380. // Устанавливаем анимацию, кол-во кадров и мелодию для эмоции «Радость»
  381. animationFrame = animationHappy;
  382. countFrames = COUNT_FRAMES_HAPPY;
  383. anyrtttl::nonblocking::begin_P(BUZZER_PIN, melodyHappy);
  384. break;
  385. // Эмоция «Удивление»
  386. case EMOTION_AMAZED:
  387. // Устанавливаем анимацию, кол-во кадров и мелодию для эмоции «Удивление»
  388. animationFrame = animationAmazed;
  389. countFrames = COUNT_FRAMES_AMAZED;
  390. anyrtttl::nonblocking::begin_P(BUZZER_PIN, melodyAmazed);
  391. break;
  392. // Эмоция «Любовь»
  393. case EMOTION_LOVE:
  394. // Устанавливаем анимацию, кол-во кадров и мелодию для эмоции «Любовь»
  395. animationFrame = animationLove;
  396. countFrames = COUNT_FRAMES_LOVE;
  397. anyrtttl::nonblocking::begin_P(BUZZER_PIN, melodyLove);
  398. break;
  399. // Эмоция «Сон»
  400. case EMOTION_SLEEP:
  401. // Устанавливаем анимацию, кол-во кадров и мелодию для эмоции «Сон»
  402. animationFrame = animationSleep;
  403. countFrames = COUNT_FRAMES_SLEEP;
  404. anyrtttl::nonblocking::begin_P(BUZZER_PIN, melodySleep);
  405. break;
  406. }
  407. // Устанавливаем в таймер значение счетчика 0
  408. timer.setTime(0);
  409. // Запускаем таймер
  410. timer.start();
  411. }
  412.  
  413. // Функция переключения на следующую эмоцию
  414. // Для активации смены эмоции, необходимо вызвать функцию установки эмоции setEmotion()
  415. void nextEmotion() {
  416. if (emotion == EMOTION_BLINK) {
  417. emotion = EMOTION_ANGRY;
  418. } else if (emotion == EMOTION_ANGRY) {
  419. emotion = EMOTION_SAD;
  420. } else if (emotion == EMOTION_SAD) {
  421. emotion = EMOTION_HAPPY;
  422. } else if (emotion == EMOTION_HAPPY) {
  423. emotion = EMOTION_AMAZED;
  424. } else if (emotion == EMOTION_AMAZED) {
  425. emotion = EMOTION_LOVE;
  426. } else if (emotion == EMOTION_LOVE) {
  427. emotion = EMOTION_SLEEP;
  428. } else if (emotion == EMOTION_SLEEP) {
  429. emotion = EMOTION_BLINK;
  430. }
  431. }
  432.  
  433. // Функция выбора случайной эмоции
  434. // Для активации смены эмоции, необходимо вызвать функцию установки эмоции setEmotion()
  435. void randomEmotion() {
  436. emotion = random(0, 8);
  437. if (emotion == 0) {
  438. emotion = EMOTION_BLINK;
  439. } else if (emotion == 1) {
  440. emotion = EMOTION_ANGRY;
  441. } else if (emotion == 2) {
  442. emotion = EMOTION_SAD;
  443. } else if (emotion == 3) {
  444. emotion = EMOTION_HAPPY;
  445. } else if (emotion == 4) {
  446. emotion = EMOTION_AMAZED;
  447. } else if (emotion == 5) {
  448. emotion = EMOTION_LOVE;
  449. } else if (emotion == 6) {
  450. emotion = EMOTION_SLEEP;
  451. } else if (emotion == 7) {
  452. emotion = EMOTION_BLINK;
  453. }
  454. }
  455.  
  456. // Функция обновления эмоции
  457. void updateEmotion() {
  458. // Если таймер досчитал до конца
  459. if (timer.tick()) {
  460. // Если флаг последнего кадра в состоянии «не активен»
  461. if (lastFrame == false) {
  462. // Отображаем текущий кадр анимации
  463. matrixL.drawBitmapF(animationFrame[indexFrame].iconEyeL);
  464. matrixR.drawBitmapF(animationFrame[indexFrame].iconEyeR);
  465. // Устанавливаем в таймер значение счетчика задержки текущего кадра анимации
  466. timer.setTime(animationFrame[indexFrame].timeFrame);
  467. // Запускаем таймер
  468. timer.start();
  469. // Если текущий кадр не последний в анимации
  470. if (indexFrame < countFrames - 1) {
  471. // Переходим на следующий кадр
  472. indexFrame++;
  473. } else {
  474. // Устанавливаем флаг последнего кадра в состояние «активен»
  475. lastFrame = true;
  476. }
  477. } else {
  478. // Останавливаем таймер
  479. timer.stop();
  480. // Проверяем сколько раз повторялась текущая анимация
  481. if (countRepeatEmotion < COUNT_REPEAT_EMOTION - 1) {
  482. // Увеличиваем счётчик повторения текущей анимации
  483. countRepeatEmotion++;
  484. } else {
  485. // Вызываем функцию переключение на следующую эмоцию
  486. nextEmotion();
  487. // Обнуляем счётчик повторения текущей анимации
  488. countRepeatEmotion = 0;
  489. }
  490. // Устанавливаем текущую анимацию
  491. setEmotion(emotion);
  492. // Устанавливаем флаг последнего кадра в состояние «не активен»
  493. lastFrame = false;
  494. // Обнуляем счётчик кадров
  495. indexFrame = 0;
  496. }
  497. }
  498. }
  499.  
  500. // Функция сброса всех настроек переменных по умолчанию
  501. void resetState() {
  502. // Обнуляем переменную для хранения количества повторений эмоции
  503. countRepeatEmotion = 0;
  504. // Обнуляем счётчик кадра
  505. indexFrame = 0;
  506. // Устанавливаем флаг последнего кадра в состояние «не активен»
  507. lastFrame = false;
  508. }

№5. Обзор влево-вправо

HeadLeftRight.ino
  1. // Подключаем библиотеку для работы с сервоприводом
  2. #include <Servo.h>
  3.  
  4. // Создаём объект сервопривода
  5. Servo servoYaw;
  6.  
  7. // Даём понятное имя пину A3 с сервоприводом
  8. constexpr uint8_t SERVO_YAW_PIN = A3;
  9.  
  10. // Задаём максимально доступные углы поворота сервопривода головы влево-вправо
  11. constexpr uint8_t MAX_ANGLE_YAW_R = 0;
  12. constexpr uint8_t MAX_ANGLE_YAW_L = 180;
  13.  
  14. // Вычисляем средний угол поворота сервопривода головы влево-вправо
  15. constexpr uint8_t MID_ANGLE_YAW = (MAX_ANGLE_YAW_R + MAX_ANGLE_YAW_L) / 2;
  16.  
  17. // Создаём константу для хранения паузы между поворотом вала сервопривода
  18. constexpr uint8_t DELAY_SWEEP_SERVO_YAW = 20;
  19.  
  20. void setup() {
  21. // Подключаем сервомотор
  22. servoYaw.attach(SERVO_YAW_PIN);
  23. }
  24.  
  25. void loop() {
  26. // Перебираем значения угла сервы от max слева до max справа
  27. for (int pos = MAX_ANGLE_YAW_R; pos <= MAX_ANGLE_YAW_L; pos++) {
  28. // Отправляем текущий угол на сервопривод
  29. servoYaw.write(pos);
  30. // Выжидаем паузу
  31. delay(DELAY_SWEEP_SERVO_YAW);
  32. }
  33. // Перебираем значения угла сервы от max справа до max слева
  34. for (int pos = MAX_ANGLE_YAW_L; pos >= MAX_ANGLE_YAW_R; pos--) {
  35. // Отправляем текущий угол на сервопривод
  36. servoYaw.write(pos);
  37. // Выжидаем паузу
  38. delay(DELAY_SWEEP_SERVO_YAW);
  39. }
  40. }

№6. Обзор вверх-вниз

HeadUpDown.ino
  1. // Подключаем библиотеку для работы с сервоприводом
  2. #include <Servo.h>
  3.  
  4. // Создаём объект сервопривода
  5. Servo servoPitch;
  6.  
  7. // Даём понятное имя пину A0 с сервоприводом
  8. constexpr uint8_t SERVO_PITCH_PIN = A0;
  9.  
  10. // Задаём максимально доступные углы поворота сервопривода головы вверх-вниз
  11. constexpr uint8_t MAX_ANGLE_PITCH_DOWN = 60;
  12. constexpr uint8_t MAX_ANGLE_PITCH_UP = 120;
  13.  
  14. // Вычисляем средний угол поворота сервопривода головы вверх-вниз
  15. constexpr uint8_t MID_ANGLE_PITCH = (MAX_ANGLE_PITCH_DOWN + MAX_ANGLE_PITCH_UP) / 2;
  16.  
  17. // Создаём константу для хранения паузы между поворотом вала сервопривода
  18. constexpr uint8_t DELAY_SWEEP_SERVO_PITCH = 20;
  19.  
  20. void setup() {
  21. // Подключаем сервомотор
  22. servoPitch.attach(SERVO_PITCH_PIN);
  23. }
  24.  
  25. void loop() {
  26. // Перебираем значения угла сервы от max вниз до max вверх
  27. for (int pos = MAX_ANGLE_PITCH_DOWN; pos <= MAX_ANGLE_PITCH_UP; pos++) {
  28. // Отправляем текущий угол на сервопривод
  29. servoPitch.write(pos);
  30. // Выжидаем паузу
  31. delay(DELAY_SWEEP_SERVO_PITCH);
  32. }
  33. // Перебираем значения угла сервы от max вверх до max вниз
  34. for (int pos = MAX_ANGLE_PITCH_UP; pos >= MAX_ANGLE_PITCH_DOWN; pos--) {
  35. // Отправляем текущий угол на сервопривод
  36. servoPitch.write(pos);
  37. // Выжидаем паузу
  38. delay(DELAY_SWEEP_SERVO_PITCH);
  39. }
  40. }

№7. Консольный ИК-приёмник

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

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

  • Если полученные коды совпадают, можно смело пользоваться нашими скетчами .ino без изменений.
  • Если коды не совпали, значит тебе попался пульт другой модификации. Ничего страшного!

Запиши фактические коды кнопок в таблицу. Они пригодятся тебе для подстановки в последующие проекты с ИК-пультом и приёмником.

Имя кнопки Код кнопки
Целевой По факту
Power 0x0B
0x07
0x1B
🔴 0x00
🟢 0x03
🔵 0x01
x 0x09
0x05
0x02
0x0A
0x06
0x1A
0x08
0x1C
0x19
0x18
0x1D
0x04
X 0x0C
Y 0x0D
Z 0x0E
IrConsole.ino
  1. // Подключаем библиотеку для работы с ИК-приёмником
  2. #include <IRremote.hpp>
  3.  
  4. // Даём понятное имя пину 2 с ИК-приёмником
  5. constexpr uint8_t IR_RECEIVE_PIN = 2;
  6.  
  7. void setup() {
  8. // Открываем монитор Serial-порта
  9. Serial.begin(9600);
  10. // Инициализируем ИК-приёмник
  11. IrReceiver.begin(IR_RECEIVE_PIN);
  12. }
  13.  
  14. void loop() {
  15. // Если пришёл новый сигнал на ИК-приёмник, декодируем его
  16. if (IrReceiver.decode()) {
  17. // Игнорируем повторное нажатие кнопки
  18. if ((IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT)) {
  19. // Разрешаем обрабатывать следующий сигнал
  20. IrReceiver.resume();
  21. // Выходим из всего цикла
  22. return;
  23. }
  24. // Создаём переменную и присваиваем ей декодируемый код кнопки
  25. uint32_t code = IrReceiver.decodedIRData.command;
  26. // Печатем код кнопки в консоль с форматированием
  27. printCode(code);
  28. // Разрешаем обрабатывать следующий сигнал
  29. IrReceiver.resume();
  30. }
  31. }
  32.  
  33. // Функция печати кода кнопки в консоль с форматированием
  34. void printCode(uint32_t code) {
  35. Serial.print("0x");
  36. if (code < 15) {
  37. Serial.print("0");
  38. }
  39. Serial.println(code, HEX);
  40. }

№8. Звёздный бот

StarBot.ino
  1. // Подключаем библиотеку для работы с мелодиями в формате RTTTL
  2. #include <anyrtttl.h>
  3.  
  4. // Подключаем библиотеку для работы с ИК-приёмником
  5. #include <IRremote.hpp>
  6.  
  7. // Подключаем библиотеку для работы со светодиодными матрицами
  8. #include <TroykaLedMatrix.h>
  9.  
  10. // Даём понятное имя пину 3 с пищалкой
  11. constexpr uint8_t BUZZER_PIN = 3;
  12.  
  13. // Даём понятное имя пину 2 с ИК-приёмником
  14. constexpr uint8_t IR_RECEIVE_PIN = 2;
  15.  
  16. // Создаём объект матрицы левого глаза
  17. // на шине I²C с адресом 0x60 (указан по умолчанию)
  18. TroykaLedMatrix matrixL;
  19. // Создаём объект матрицы правого глаза
  20. // на шине I²C с адресом 0x63
  21. TroykaLedMatrix matrixR(0x63);
  22.  
  23. // Создаём константу для хранения базовой частоты
  24. constexpr int FREQUENCY = 2000;
  25.  
  26. // Создаём константы для хранения минимальной и максимальной частоты
  27. constexpr int MIN_FREQUENCY = FREQUENCY - (0.25 * FREQUENCY);
  28. constexpr int MAX_FREQUENCY = FREQUENCY + (0.25 * FREQUENCY);
  29.  
  30. // Создаём иконку «Взгляд прямо» в шестнадцатеричной системе HEX
  31. // Иконка для левого и правого глаза одинаковая
  32. // Эмоции рисуем в редакторе изображений для LED-матрицы
  33. // https://amperka.github.io/led-matrix-editor/
  34. constexpr uint8_t ICON_EYE_STRAIGHT[] PROGMEM {
  35. 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e
  36. };
  37.  
  38. // Создаём иконку «Глаза выключены» в шестнадцатеричной системе HEX
  39. // Иконка для левого и правого глаза одинаковая
  40. constexpr uint8_t ICON_EYE_OFF[] PROGMEM {
  41. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  42. };
  43.  
  44. void setup() {
  45. // Инициализируем матрицы
  46. matrixL.begin();
  47. matrixR.begin();
  48. // Очищаем матрицы
  49. matrixL.clear();
  50. matrixR.clear();
  51. // Настраиваем пин с пищалкой в режим выхода
  52. pinMode(BUZZER_PIN, OUTPUT);
  53. // Инициализируем ИК-приёмник
  54. IrReceiver.begin(IR_RECEIVE_PIN);
  55. // Передаём случайное число с пина A1
  56. // для последующей генерации случайных чисел
  57. randomSeed(analogRead(A1));
  58. }
  59.  
  60. void loop() {
  61. // Переходим в функцию обработки ИК-приёмника
  62. remoteHandler();
  63. }
  64.  
  65. // Функция отображения иконки на матрицах
  66. void drawIcon(uint8_t* iconEyeL, uint8_t* iconEyeR) {
  67. matrixL.drawBitmapF(iconEyeL);
  68. matrixR.drawBitmapF(iconEyeR);
  69. }
  70.  
  71. // Функция обработки ИК-приёмника
  72. void remoteHandler() {
  73. // Если пришёл новый сигнал на ИК-приёмник, декодируем его
  74. if (IrReceiver.decode()) {
  75. // Создаём переменную и присваиваем ей декодируемый код кнопки
  76. uint32_t code = IrReceiver.decodedIRData.command;
  77. // Если код кнопки равен 0, пришёл шум и игнорируем его
  78. if (code == 0x00) {
  79. // Разрешаем обрабатывать следующий сигнал
  80. IrReceiver.resume();
  81. // Выходим из функции
  82. return;
  83. }
  84. // Отключаем ИК-приёмник
  85. IrReceiver.stop();
  86. // Вызываем функцию генератора последовательных длинных семплов
  87. toneLongSamples();
  88. // Вызываем функцию генератора непоследовательных коротких семплов
  89. toneShortSamples();
  90. // Запускаем ИК-приёмник
  91. IrReceiver.start();
  92. // Разрешаем обрабатывать команды с ИК-приёмника
  93. IrReceiver.resume();
  94. }
  95. }
  96.  
  97. // Функция генерации последовательных длинных семплов
  98. void toneLongSamples() {
  99. // Генерируем случайное количество семплов от 1 до 6
  100. int countSamples = random(1, 7);
  101. // Перебираем нумерацию семплов в цикле
  102. for (int i = 0; i < countSamples; i++) {
  103. // Генерируем случайное число: true или false
  104. bool typeSamples = random(0, 2);
  105. // Если тип семпла true
  106. if (typeSamples) {
  107. // Вызываем функцию генерации тона toneSlowDownFastUp:
  108. // Сначала медленный убывающий тон со случайными задержками
  109. // Затем быстрый возрастающий тон со случайными задержками
  110. toneSlowDownFastUp();
  111. } else {
  112. // Если тип семпла false
  113. // Вызываем функцию генерации тона toneSlowUpFastDown:
  114. // Сначала медленный возрастающий тон со случайными задержками
  115. // Затем быстрый убывающий тон со случайными задержками
  116. toneSlowUpFastDown();
  117. }
  118. }
  119. }
  120.  
  121. // Функция генерации непоследовательных коротких семплов
  122. void toneShortSamples() {
  123. // Генерируем случайное количество семплов от 3 до 9
  124. int countSamples = random(3, 10);
  125. // Генерируем случайную частоту на базе FREQUENCY
  126. int frequency = random(MIN_FREQUENCY, MAX_FREQUENCY);
  127. for (int i = 0; i <= countSamples; i++) {
  128. // Активируем глаза
  129. drawIcon(ICON_EYE_STRAIGHT, ICON_EYE_STRAIGHT);
  130. // Генерируем случайный интервал на базе FREQUENCY
  131. int range = random(-FREQUENCY, FREQUENCY);
  132. tone(BUZZER_PIN, frequency + range);
  133. // Выполняем случайную задержку от 70 до 170 мс
  134. delay(random(70, 170));
  135. // Деактивируем глаза
  136. drawIcon(ICON_EYE_OFF, ICON_EYE_OFF);
  137. // Выключаем звук
  138. noTone(BUZZER_PIN);
  139. // Выполняем случайную задержку от 0 до 30 мс
  140. delay(random(0, 30));
  141. }
  142. }
  143.  
  144. // Функция генерации звуковой последовательности
  145. // Сначала медленный убывающий тон со случайными задержками
  146. // Затем быстрый возрастающий тон со случайными задержками
  147. void toneSlowDownFastUp() {
  148. // Генерируем случайную частоту на базе FREQUENCY
  149. int frequency = random(MIN_FREQUENCY, MAX_FREQUENCY);
  150. // Активируем глаза
  151. drawIcon(ICON_EYE_STRAIGHT, ICON_EYE_STRAIGHT);
  152. // Генерируем медленный понижающий тон со случайными задержками
  153. for (int range = 0; range <= random(100, 1000); range++) {
  154. tone(BUZZER_PIN, (range * 2));
  155. delayMicroseconds(random(0, 1000));
  156. }
  157. // Деактивируем глаза
  158. drawIcon(ICON_EYE_OFF, ICON_EYE_OFF);
  159. // Генерируем быстрый повышающий тон со случайными задержками
  160. for (int range = 0; range <= random(100, 1000); range++) {
  161. tone(BUZZER_PIN, frequency + (range * 10));
  162. delayMicroseconds(random(0, 1000));
  163. }
  164. }
  165.  
  166. // Функция генерации звуковой последовательности
  167. // Сначала медленный возрастающий тон со случайными задержками
  168. // Затем быстрый убывающий тон со случайными задержками
  169. void toneSlowUpFastDown() {
  170. // Генерируем случайную частоту на базе FREQUENCY
  171. int frequency = random(MIN_FREQUENCY, MAX_FREQUENCY);
  172. // Активируем глаза
  173. drawIcon(ICON_EYE_STRAIGHT, ICON_EYE_STRAIGHT);
  174. // Генерируем медленный возрастающий тон со случайными задержками
  175. for (int range = 0; range <= random(100, 1000); range++) {
  176. tone(BUZZER_PIN, (range * 2));
  177. delayMicroseconds(random(0, 1000));
  178. }
  179. // Деактивируем глаза
  180. drawIcon(ICON_EYE_OFF, ICON_EYE_OFF);
  181. // Генерируем быстрый понижающий тон со случайными задержками
  182. for (int range = 0; range <= random(100, 1000); range++) {
  183. tone(BUZZER_PIN, (range * 10));
  184. delayMicroseconds(random(0, 1000));
  185. }
  186. }

№9. Эмо-бот

Изменение кода кнопок пульта

Вернись к шпаргалке с таблицей из эксперимента №7 «Консольный ИК-приёмник» и подставь фактические коды кнопок твоего пульта в строках 6270, когда откроешь скетч IrEmotions.ino в Arduino IDE.

  1. enum Emotion {
  2. EMOTION_BLINK = 0x1C,
  3. EMOTION_ANGRY = 0x02,
  4. EMOTION_SAD = 0xC,
  5. EMOTION_HAPPY = 0x0D,
  6. EMOTION_AMAZED = 0x05,
  7. EMOTION_LOVE = 0x09,
  8. EMOTION_SLEEP = 0x0E,
  9. } emotion;
IrEmotions.ino
  1. // Подключаем библиотеку для работы с мелодиями в формате RTTTL
  2. #include <anyrtttl.h>
  3.  
  4. // Подключаем библиотеку для работы с ИК-приёмником
  5. #include <IRremote.hpp>
  6.  
  7. // Подключаем библиотеку для работы с таймером millis
  8. #include <TimerMs.h>
  9.  
  10. // Подключаем библиотеку для работы со светодиодными матрицами
  11. #include <TroykaLedMatrix.h>
  12.  
  13. // Даём понятное имя пину 3 с пищалкой
  14. constexpr uint8_t BUZZER_PIN = 3;
  15.  
  16. // Даём понятное имя пину 2 с ИК-приёмником
  17. constexpr uint8_t IR_RECEIVE_PIN = 2;
  18.  
  19. // Создаём объект для работы с таймером
  20. TimerMs timer;
  21.  
  22. // Создаём объект матрицы левого глаза
  23. // на шине I²C с адресом 0x60 (указан по умолчанию)
  24. TroykaLedMatrix matrixL;
  25. // Создаём объект матрицы правого глаза
  26. // на шине I²C с адресом 0x63
  27. TroykaLedMatrix matrixR(0x63);
  28.  
  29. // Создаём массив данных мелодии «Моргание» в формате RTTTL
  30. constexpr uint8_t melodyBlink[] PROGMEM = "Blink:d=4,o=4,b=120:"
  31. "16e,16p,16g,16p,16e,16p,16g,16p,";
  32.  
  33. // Создаём массив данных мелодии «Злость» в формате RTTTL
  34. constexpr uint8_t melodyAngry[] PROGMEM = "Angry:d=4,o=4,b=200:"
  35. "16g,16g,16f#,16f#,16e,16e,16d#,16d#,"
  36. "16c,16c,16b4,16b4,16a4,16a4,16g4,16g4";
  37.  
  38. // Создаём массив данных мелодии «Грусть» в формате RTTTL
  39. constexpr uint8_t melodySad[] PROGMEM = "Sad:d=4,o=4,b=25:"
  40. "16g,16a#,16d,16f,"
  41. "16d,16c,16a#";
  42.  
  43. constexpr uint8_t melodyHappy[] PROGMEM = "Happy:d=4,o=4,b=140:"
  44. "8c4,8e4,8g4,8c4,8e4,8g4,8c4,8e4"
  45. "8g4,8c4,8e4,8g4";
  46.  
  47. // Создаём массив данных мелодии «Удивление» в формате RTTTL
  48. constexpr uint8_t melodyAmazed[] PROGMEM = "Amazed:d=4,o=4,b=180:"
  49. "16c,16d,16e,16f,16g,16a,16b,16c,"
  50. "16b,16a,16g,16f,16e,16d,16c,16d";
  51.  
  52. // Создаём массив данных мелодии «Любовь» в формате RTTTL
  53. constexpr uint8_t melodyLove[] PROGMEM = "Love:d=4,o=4,b=100:"
  54. "8g,8p,8g,8p,8a,8p,8g,8p,"
  55. "8g,8p,8g,8p,8f,8e,8d";
  56.  
  57. // Создаём массив данных мелодии «Сонливость» в формате RTTTL
  58. constexpr uint8_t melodySleep[] PROGMEM = "Sleep:d=4,o=4,b=45:"
  59. "8c,8c,8d,8e,8d,8c,8d,8e";
  60.  
  61. // Создаём перечисление эмоций с соответствующей переменной
  62. enum Emotion {
  63. EMOTION_BLINK = 0x1C,
  64. EMOTION_ANGRY = 0x02,
  65. EMOTION_SAD = 0xC,
  66. EMOTION_HAPPY = 0x0D,
  67. EMOTION_AMAZED = 0x05,
  68. EMOTION_LOVE = 0x09,
  69. EMOTION_SLEEP = 0x0E,
  70. } emotion;
  71.  
  72. // Создаём структуру анимации
  73. struct AnimationFrame {
  74. uint8_t* iconEyeL;
  75. uint8_t* iconEyeR;
  76. int timeFrame;
  77. };
  78.  
  79. // Создаём объект структуры анимации
  80. AnimationFrame* animationFrame;
  81.  
  82. // Создаём иконку «Взгляд прямо» в шестнадцатеричной системе HEX
  83. // Иконка для левого и правого глаза одинаковая
  84. // Эмоции рисуем в редакторе изображений для LED-матрицы
  85. // https://amperka.github.io/led-matrix-editor/
  86. constexpr uint8_t ICON_EYE_STRAIGHT[] PROGMEM {
  87. 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e
  88. };
  89.  
  90. // Создаём иконку «Глаза выключены» в шестнадцатеричной системе HEX
  91. // Иконка для левого и правого глаза одинаковая
  92. constexpr uint8_t ICON_EYE_OFF[] PROGMEM {
  93. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  94. };
  95.  
  96. // Создаём массив иконок анимации «Моргание» в шестнадцатеричной системе HEX
  97. // Массив иконок для левого и правого глаза одинаковый
  98. constexpr uint8_t ICON_EYE_BLINK[][8] PROGMEM {
  99. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  100. { 0x00, 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x7e },
  101. { 0x00, 0x00, 0x7e, 0x81, 0x99, 0x99, 0x81, 0x7e },
  102. { 0x00, 0x00, 0x00, 0x7e, 0x99, 0x99, 0x7e, 0x00 },
  103. { 0x00, 0x00, 0x00, 0x00, 0x7e, 0x99, 0x7e, 0x00 },
  104. { 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00 },
  105. { 0x00, 0x00, 0x00, 0x00, 0x7e, 0x99, 0x7e, 0x00 },
  106. { 0x00, 0x00, 0x00, 0x7e, 0x99, 0x99, 0x7e, 0x00 },
  107. { 0x00, 0x00, 0x7e, 0x81, 0x99, 0x99, 0x81, 0x7e },
  108. { 0x00, 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x7e },
  109. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e }
  110. };
  111.  
  112. // Создаём массив иконок анимации «Злость»
  113. // в шестнадцатеричной системе HEX для левого глаза
  114. constexpr uint8_t ICON_EYE_ANGRY_L[][8] PROGMEM {
  115. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  116. { 0x78, 0x84, 0x82, 0x9a, 0x9a, 0x82, 0x82, 0x7c },
  117. { 0x70, 0x88, 0x84, 0x9a, 0x9a, 0x82, 0x82, 0x7c },
  118. { 0x60, 0x90, 0x88, 0x9c, 0x9a, 0x82, 0x82, 0x7c },
  119. { 0x40, 0xa0, 0x90, 0x88, 0xb4, 0xb2, 0x82, 0x7c },
  120. { 0x80, 0xc0, 0xa0, 0x90, 0xa8, 0xb4, 0x82, 0x7c },
  121. { 0x40, 0xa0, 0x90, 0x88, 0xb4, 0xb2, 0x82, 0x7c },
  122. { 0x60, 0x90, 0x88, 0x9c, 0x9a, 0x82, 0x82, 0x7c },
  123. { 0x70, 0x88, 0x84, 0x9a, 0x9a, 0x82, 0x82, 0x7c },
  124. { 0x78, 0x84, 0x82, 0x9a, 0x9a, 0x82, 0x82, 0x7c },
  125. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e }
  126. };
  127.  
  128. // Создаём массив иконок анимации «Злость»
  129. // в шестнадцатеричной системе HEX для правого глаза
  130. constexpr uint8_t ICON_EYE_ANGRY_R[][8] PROGMEM {
  131. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  132. { 0x1e, 0x21, 0x41, 0x59, 0x59, 0x41, 0x41, 0x3e },
  133. { 0x0e, 0x11, 0x21, 0x59, 0x59, 0x41, 0x41, 0x3e },
  134. { 0x06, 0x09, 0x11, 0x39, 0x59, 0x41, 0x41, 0x3e },
  135. { 0x02, 0x05, 0x09, 0x11, 0x2d, 0x4d, 0x41, 0x3e },
  136. { 0x01, 0x03, 0x05, 0x09, 0x15, 0x2d, 0x41, 0x3e },
  137. { 0x02, 0x05, 0x09, 0x11, 0x2d, 0x4d, 0x41, 0x3e },
  138. { 0x06, 0x09, 0x11, 0x39, 0x59, 0x41, 0x41, 0x3e },
  139. { 0x0e, 0x11, 0x21, 0x59, 0x59, 0x41, 0x41, 0x3e },
  140. { 0x1e, 0x21, 0x41, 0x59, 0x59, 0x41, 0x41, 0x3e }
  141. };
  142.  
  143. // Создаём массив иконок анимации «Грусть»
  144. // в шестнадцатеричной системе HEX для левого глаза
  145. constexpr uint8_t ICON_EYE_SAD_L[][8] PROGMEM {
  146. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  147. { 0x3e, 0x41, 0x81, 0x99, 0x99, 0x81, 0x82, 0x7c },
  148. { 0x1e, 0x21, 0x41, 0x99, 0x99, 0x81, 0x82, 0x7c },
  149. { 0x0e, 0x11, 0x21, 0x41, 0x8d, 0x8d, 0x82, 0x7c },
  150. { 0x0e, 0x11, 0x21, 0x41, 0x4d, 0x4d, 0x42, 0x3c },
  151. { 0x06, 0x09, 0x11, 0x21, 0x4d, 0x4d, 0x42, 0x3c },
  152. { 0x0e, 0x11, 0x21, 0x41, 0x4d, 0x4d, 0x42, 0x3c },
  153. { 0x0e, 0x11, 0x21, 0x41, 0x8d, 0x8d, 0x82, 0x7c },
  154. { 0x1e, 0x21, 0x41, 0x99, 0x99, 0x81, 0x82, 0x7c },
  155. { 0x3e, 0x41, 0x81, 0x99, 0x99, 0x81, 0x82, 0x7c },
  156. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e }
  157. };
  158.  
  159. // Создаём массив иконок анимации «Грусть»
  160. // в шестнадцатеричной системе HEX для правого глаза
  161. constexpr uint8_t ICON_EYE_SAD_R[][8] PROGMEM {
  162. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  163. { 0x7c, 0x82, 0x81, 0x99, 0x99, 0x81, 0x41, 0x3e },
  164. { 0x78, 0x84, 0x82, 0x99, 0x99, 0x81, 0x41, 0x3e },
  165. { 0x70, 0x88, 0x84, 0x82, 0xb1, 0xb1, 0x41, 0x3e },
  166. { 0x70, 0x88, 0x84, 0x82, 0xb2, 0xb2, 0x42, 0x3c },
  167. { 0x60, 0x90, 0x88, 0x84, 0xb2, 0xb2, 0x42, 0x3c },
  168. { 0x70, 0x88, 0x84, 0x82, 0xb2, 0xb2, 0x42, 0x3c },
  169. { 0x70, 0x88, 0x84, 0x82, 0xb1, 0xb1, 0x41, 0x3e },
  170. { 0x78, 0x84, 0x82, 0x99, 0x99, 0x81, 0x41, 0x3e },
  171. { 0x7c, 0x82, 0x81, 0x99, 0x99, 0x81, 0x41, 0x3e },
  172. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e }
  173. };
  174.  
  175. // Создаём массив иконок анимации «Радость» в шестнадцатеричной системе HEX
  176. // Массив иконок для левого и правого глаза одинаковый
  177. constexpr uint8_t ICON_EYE_HAPPY[][8] PROGMEM {
  178. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  179. { 0x00, 0x7e, 0x81, 0x99, 0x99, 0x81, 0x7e, 0x00 },
  180. { 0x00, 0x7e, 0x81, 0x99, 0x99, 0xff, 0x00, 0x00 },
  181. { 0x00, 0x7e, 0xdb, 0x99, 0xff, 0x81, 0x00, 0x00 },
  182. { 0x00, 0x3c, 0x5a, 0xff, 0xc3, 0x81, 0x00, 0x00 },
  183. { 0x00, 0x3c, 0x7e, 0xc3, 0xc3, 0x81, 0x00, 0x00 },
  184. { 0x00, 0x3c, 0x5a, 0xff, 0xc3, 0x81, 0x00, 0x00 },
  185. { 0x00, 0x7e, 0xdb, 0x99, 0xff, 0x81, 0x00, 0x00 },
  186. { 0x00, 0x7e, 0x81, 0x99, 0x99, 0xff, 0x00, 0x00 },
  187. { 0x00, 0x7e, 0x81, 0x99, 0x99, 0x81, 0x7e, 0x00 },
  188. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e }
  189. };
  190.  
  191. // Создаём массив иконок анимации «Удивление» в шестнадцатеричной системе HEX
  192. // Массив иконок для левого и правого глаза одинаковый
  193. constexpr uint8_t ICON_EYE_AMAZED[][8] PROGMEM {
  194. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e },
  195. { 0x7e, 0x81, 0x99, 0xbd, 0xbd, 0x99, 0x81, 0x7e },
  196. { 0x7e, 0x81, 0xbd, 0xbd, 0xbd, 0xbd, 0x81, 0x7e },
  197. { 0x7e, 0x81, 0x99, 0xbd, 0xbd, 0x99, 0x81, 0x7e },
  198. { 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e }
  199. };
  200.  
  201. // Создаём массив иконок анимации «Любовь» в шестнадцатеричной системе HEX
  202. // Массив иконок для левого и правого глаза одинаковый
  203. constexpr uint8_t ICON_EYE_LOVE[][8] PROGMEM {
  204. { 0x66, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x18 },
  205. { 0x00, 0x00, 0x24, 0x7e, 0x7e, 0x3c, 0x18, 0x00 }
  206. };
  207.  
  208. // Создаём массив иконок анимации Сон» в шестнадцатеричной системе HEX
  209. // Массив иконок для левого и правого глаза одинаковый
  210. constexpr uint8_t ICON_EYE_SLEEP[][8] PROGMEM {
  211. { 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00 },
  212. { 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, 0x7e, 0x00 }
  213. };
  214.  
  215. // Создаём анимацию «Моргание»
  216. AnimationFrame animationBlink[] = {
  217. { ICON_EYE_BLINK[0], ICON_EYE_BLINK[0], 500 },
  218. { ICON_EYE_BLINK[1], ICON_EYE_BLINK[1], 25 },
  219. { ICON_EYE_BLINK[2], ICON_EYE_BLINK[2], 25 },
  220. { ICON_EYE_BLINK[3], ICON_EYE_BLINK[3], 25 },
  221. { ICON_EYE_BLINK[4], ICON_EYE_BLINK[4], 25 },
  222. { ICON_EYE_BLINK[5], ICON_EYE_BLINK[5], 25 },
  223. { ICON_EYE_BLINK[6], ICON_EYE_BLINK[6], 25 },
  224. { ICON_EYE_BLINK[7], ICON_EYE_BLINK[7], 25 },
  225. { ICON_EYE_BLINK[8], ICON_EYE_BLINK[8], 25 },
  226. { ICON_EYE_BLINK[9], ICON_EYE_BLINK[9], 25 },
  227. { ICON_EYE_BLINK[10], ICON_EYE_BLINK[10], 500 }
  228. };
  229.  
  230. // Создаём анимацию «Злость»
  231. AnimationFrame animationAngry[] = {
  232. { ICON_EYE_ANGRY_L[0], ICON_EYE_ANGRY_R[0], 500 },
  233. { ICON_EYE_ANGRY_L[1], ICON_EYE_ANGRY_R[1], 50 },
  234. { ICON_EYE_ANGRY_L[2], ICON_EYE_ANGRY_R[2], 50 },
  235. { ICON_EYE_ANGRY_L[3], ICON_EYE_ANGRY_R[3], 50 },
  236. { ICON_EYE_ANGRY_L[4], ICON_EYE_ANGRY_R[4], 50 },
  237. { ICON_EYE_ANGRY_L[5], ICON_EYE_ANGRY_R[5], 2000 },
  238. { ICON_EYE_ANGRY_L[6], ICON_EYE_ANGRY_R[6], 50 },
  239. { ICON_EYE_ANGRY_L[7], ICON_EYE_ANGRY_R[7], 50 },
  240. { ICON_EYE_ANGRY_L[8], ICON_EYE_ANGRY_R[8], 50 },
  241. { ICON_EYE_ANGRY_L[9], ICON_EYE_ANGRY_R[9], 50 },
  242. { ICON_EYE_ANGRY_L[10], ICON_EYE_ANGRY_R[10], 500 }
  243. };
  244.  
  245. // Создаём анимацию «Грусть»
  246. AnimationFrame animationSad[] = {
  247. { ICON_EYE_SAD_L[0], ICON_EYE_SAD_R[0], 500 },
  248. { ICON_EYE_SAD_L[1], ICON_EYE_SAD_R[1], 50 },
  249. { ICON_EYE_SAD_L[2], ICON_EYE_SAD_R[2], 50 },
  250. { ICON_EYE_SAD_L[3], ICON_EYE_SAD_R[3], 50 },
  251. { ICON_EYE_SAD_L[4], ICON_EYE_SAD_R[4], 50 },
  252. { ICON_EYE_SAD_L[5], ICON_EYE_SAD_R[5], 3000 },
  253. { ICON_EYE_SAD_L[6], ICON_EYE_SAD_R[6], 50 },
  254. { ICON_EYE_SAD_L[7], ICON_EYE_SAD_R[7], 50 },
  255. { ICON_EYE_SAD_L[8], ICON_EYE_SAD_R[8], 50 },
  256. { ICON_EYE_SAD_L[9], ICON_EYE_SAD_R[9], 50 },
  257. { ICON_EYE_SAD_L[10], ICON_EYE_SAD_R[10], 500 }
  258. };
  259.  
  260. // Создаём анимацию «Радость»
  261. AnimationFrame animationHappy[] = {
  262. { ICON_EYE_HAPPY[0], ICON_EYE_HAPPY[0], 500 },
  263. { ICON_EYE_HAPPY[1], ICON_EYE_HAPPY[1], 40 },
  264. { ICON_EYE_HAPPY[2], ICON_EYE_HAPPY[2], 40 },
  265. { ICON_EYE_HAPPY[3], ICON_EYE_HAPPY[3], 40 },
  266. { ICON_EYE_HAPPY[4], ICON_EYE_HAPPY[4], 40 },
  267. { ICON_EYE_HAPPY[5], ICON_EYE_HAPPY[5], 2000 },
  268. { ICON_EYE_HAPPY[6], ICON_EYE_HAPPY[6], 40 },
  269. { ICON_EYE_HAPPY[7], ICON_EYE_HAPPY[7], 40 },
  270. { ICON_EYE_HAPPY[8], ICON_EYE_HAPPY[8], 40 },
  271. { ICON_EYE_HAPPY[9], ICON_EYE_HAPPY[9], 40 },
  272. { ICON_EYE_HAPPY[10], ICON_EYE_HAPPY[10], 500 }
  273. };
  274.  
  275. // Создаём анимацию «Удивление»
  276. AnimationFrame animationAmazed[] = {
  277. { ICON_EYE_AMAZED[0], ICON_EYE_AMAZED[0], 500 },
  278. { ICON_EYE_AMAZED[1], ICON_EYE_AMAZED[1], 100 },
  279. { ICON_EYE_AMAZED[2], ICON_EYE_AMAZED[2], 2000 },
  280. { ICON_EYE_AMAZED[3], ICON_EYE_AMAZED[3], 100 },
  281. { ICON_EYE_AMAZED[4], ICON_EYE_AMAZED[4], 500 }
  282. };
  283.  
  284. // Создаём анимацию «Любовь»
  285. AnimationFrame animationLove[] = {
  286. { ICON_EYE_LOVE[0], ICON_EYE_LOVE[0], 1000 },
  287. { ICON_EYE_LOVE[1], ICON_EYE_LOVE[1], 300 },
  288. { ICON_EYE_LOVE[0], ICON_EYE_LOVE[0], 1000 },
  289. { ICON_EYE_LOVE[1], ICON_EYE_LOVE[1], 300 },
  290. { ICON_EYE_LOVE[0], ICON_EYE_LOVE[0], 1000 },
  291. { ICON_EYE_LOVE[1], ICON_EYE_LOVE[1], 300 },
  292. { ICON_EYE_LOVE[0], ICON_EYE_LOVE[0], 1000 },
  293. { ICON_EYE_LOVE[1], ICON_EYE_LOVE[1], 300 },
  294. };
  295.  
  296. // Создаём анимацию «Сон»
  297. AnimationFrame animationSleep[] = {
  298. { ICON_EYE_SLEEP[0], ICON_EYE_SLEEP[0], 750 },
  299. { ICON_EYE_SLEEP[1], ICON_EYE_SLEEP[1], 750 },
  300. { ICON_EYE_SLEEP[0], ICON_EYE_SLEEP[0], 750 },
  301. { ICON_EYE_SLEEP[1], ICON_EYE_SLEEP[1], 750 },
  302. { ICON_EYE_SLEEP[0], ICON_EYE_SLEEP[0], 750 },
  303. { ICON_EYE_SLEEP[1], ICON_EYE_SLEEP[1], 750 },
  304. { ICON_EYE_SLEEP[0], ICON_EYE_SLEEP[0], 750 },
  305. { ICON_EYE_SLEEP[1], ICON_EYE_SLEEP[1], 750 },
  306. };
  307.  
  308. // Вычисляем количество кадров в анимации «Моргание»
  309. constexpr uint8_t COUNT_FRAMES_BLINK = sizeof(animationBlink) / sizeof(AnimationFrame);
  310. // Вычисляем количество кадров в анимации «Злость»
  311. constexpr uint8_t COUNT_FRAMES_ANGRY = sizeof(animationAngry) / sizeof(AnimationFrame);
  312. // Вычисляем количество кадров в анимации «Грусть»
  313. constexpr uint8_t COUNT_FRAMES_SAD = sizeof(animationSad) / sizeof(AnimationFrame);
  314. // Вычисляем количество кадров в анимации «Радость»
  315. constexpr uint8_t COUNT_FRAMES_HAPPY = sizeof(animationHappy) / sizeof(AnimationFrame);
  316. // Вычисляем количество кадров в анимации «Удивление»
  317. constexpr uint8_t COUNT_FRAMES_AMAZED = sizeof(animationAmazed) / sizeof(AnimationFrame);
  318. // Вычисляем количество кадров в анимации «Любовь»
  319. constexpr uint8_t COUNT_FRAMES_LOVE = sizeof(animationLove) / sizeof(AnimationFrame);
  320. // Вычисляем количество кадров в анимации «Сон»
  321. constexpr uint8_t COUNT_FRAMES_SLEEP = sizeof(animationSleep) / sizeof(AnimationFrame);
  322.  
  323. // Создаём переменную для хранения счётчика текущего кадра
  324. int indexFrame;
  325. // Создаём переменную для хранения количества кадров
  326. int countFrames;
  327. // Создаём переменную для хранения флага последнего кадра
  328. bool lastFrame;
  329.  
  330. void setup() {
  331. // Инициализируем матрицы
  332. matrixL.begin();
  333. matrixR.begin();
  334. // Очищаем матрицы
  335. matrixL.clear();
  336. matrixR.clear();
  337. // Инициализируем ИК-приёмник
  338. IrReceiver.begin(IR_RECEIVE_PIN);
  339. // Сбрасываем все настройки переменных по умолчанию
  340. resetState();
  341. // Устанавливаем таймер в режим остановки после срабатывания
  342. timer.setTimerMode();
  343. }
  344.  
  345. void loop() {
  346. // Переходим в функцию обработки эмоций
  347. emotionHandler();
  348. // Переходим в функцию обработки ИК-приёмника
  349. remoteHandler();
  350. }
  351.  
  352. // Функция отображения иконки на матрицах
  353. void drawIcon(uint8_t* iconEyeL, uint8_t* iconEyeR) {
  354. matrixL.drawBitmapF(iconEyeL);
  355. matrixR.drawBitmapF(iconEyeR);
  356. }
  357.  
  358. // Функция обработки эмоций
  359. void emotionHandler() {
  360. // Вызываем функцию обновление анимации
  361. updateEmotion();
  362. // Разрешаем играть выбранный трек
  363. anyrtttl::nonblocking::play();
  364. }
  365.  
  366. // Функция обработки ИК-приёмника
  367. void remoteHandler() {
  368. // Если пришёл новый сигнал на ИК-приёмник, декодируем его
  369. if (IrReceiver.decode()) {
  370. // Создаём переменную и присваиваем ей декодируемый код кнопки
  371. uint32_t code = IrReceiver.decodedIRData.command;
  372. // Проверяем код кнопки
  373. switch (code) {
  374. // Если нажата кнопка с кодом эмоции «Моргание»
  375. case EMOTION_BLINK:
  376. setEmotion(EMOTION_BLINK);
  377. break;
  378. // Если нажата кнопка с кодом эмоции «Злость»
  379. case EMOTION_ANGRY:
  380. // Отображаем анимацию «Злость»
  381. setEmotion(EMOTION_ANGRY);
  382. break;
  383. // Если нажата кнопка с кодом эмоции «Грусть»
  384. case EMOTION_SAD:
  385. // Отображаем анимацию «Грусть»
  386. setEmotion(EMOTION_SAD);
  387. break;
  388. // Если нажата кнопка с кодом эмоции «Радость»
  389. case EMOTION_HAPPY:
  390. // Отображаем анимацию «Радость»
  391. setEmotion(EMOTION_HAPPY);
  392. break;
  393. // Если нажата кнопка с кодом эмоции «Удивление
  394. case EMOTION_AMAZED:
  395. // Отображаем анимацию «Удивление»
  396. setEmotion(EMOTION_AMAZED);
  397. break;
  398. // Если нажата кнопка с кодом эмоции «Любовь»
  399. case EMOTION_LOVE:
  400. // Отображаем анимацию «Любовь»
  401. setEmotion(EMOTION_LOVE);
  402. break;
  403. // Если нажата кнопка с кодом эмоции «Сон»
  404. case EMOTION_SLEEP:
  405. // Отображаем анимацию «Сон»
  406. setEmotion(EMOTION_SLEEP);
  407. break;
  408. }
  409. // Разрешаем обрабатывать следующий сигнал
  410. IrReceiver.resume();
  411. }
  412. }
  413.  
  414. // Функция установки текущей эмоции
  415. void setEmotion(Emotion emotionNow) {
  416. // Обновляем полученную эмоцию
  417. emotion = emotionNow;
  418. // Проверяем состояние текущей эмоции
  419. switch (emotion) {
  420. // Эмоция «Моргание»
  421. case EMOTION_BLINK:
  422. // Устанавливаем анимацию, кол-во кадров и мелодию для эмоции «Моргание»
  423. animationFrame = animationBlink;
  424. countFrames = COUNT_FRAMES_BLINK;
  425. anyrtttl::nonblocking::begin_P(BUZZER_PIN, melodyBlink);
  426. break;
  427. // Эмоция «Злость»
  428. case EMOTION_ANGRY:
  429. // Устанавливаем анимацию, кол-во кадров и мелодию для эмоции «Злость»
  430. animationFrame = animationAngry;
  431. countFrames = COUNT_FRAMES_ANGRY;
  432. anyrtttl::nonblocking::begin_P(BUZZER_PIN, melodyAngry);
  433. break;
  434. // Эмоция «Грусть»
  435. case EMOTION_SAD:
  436. // Устанавливаем анимацию, кол-во кадров и мелодию для эмоции «Грусть»
  437. animationFrame = animationSad;
  438. countFrames = COUNT_FRAMES_SAD;
  439. anyrtttl::nonblocking::begin_P(BUZZER_PIN, melodySad);
  440. break;
  441. // Эмоция «Радость»
  442. case EMOTION_HAPPY:
  443. // Устанавливаем анимацию, кол-во кадров и мелодию для эмоции «Радость»
  444. animationFrame = animationHappy;
  445. countFrames = COUNT_FRAMES_HAPPY;
  446. anyrtttl::nonblocking::begin_P(BUZZER_PIN, melodyHappy);
  447. break;
  448. // Эмоция «Удивление»
  449. case EMOTION_AMAZED:
  450. // Устанавливаем анимацию, кол-во кадров и мелодию для эмоции «Удивление»
  451. animationFrame = animationAmazed;
  452. countFrames = COUNT_FRAMES_AMAZED;
  453. anyrtttl::nonblocking::begin_P(BUZZER_PIN, melodyAmazed);
  454. break;
  455. // Эмоция «Любовь»
  456. case EMOTION_LOVE:
  457. // Устанавливаем анимацию, кол-во кадров и мелодию для эмоции «Любовь»
  458. animationFrame = animationLove;
  459. countFrames = COUNT_FRAMES_LOVE;
  460. anyrtttl::nonblocking::begin_P(BUZZER_PIN, melodyLove);
  461. break;
  462. // Эмоция «Сон»
  463. case EMOTION_SLEEP:
  464. // Устанавливаем анимацию, кол-во кадров и мелодию для эмоции «Сон»
  465. animationFrame = animationSleep;
  466. countFrames = COUNT_FRAMES_SLEEP;
  467. anyrtttl::nonblocking::begin_P(BUZZER_PIN, melodySleep);
  468. break;
  469. }
  470. // Отключаем ИК-приёмник
  471. IrReceiver.stop();
  472. // Устанавливаем в таймер значение счетчика 0
  473. timer.setTime(0);
  474. // Запускаем таймер
  475. timer.start();
  476. }
  477.  
  478. // Функция обновления эмоции
  479. void updateEmotion() {
  480. // Если таймер досчитал до конца
  481. if (timer.tick()) {
  482. // Если флаг последнего кадра в состоянии «не активен»
  483. if (lastFrame == false) {
  484. // Отображаем текущий кадр анимации
  485. matrixL.drawBitmapF(animationFrame[indexFrame].iconEyeL);
  486. matrixR.drawBitmapF(animationFrame[indexFrame].iconEyeR);
  487. // Устанавливаем в таймер значение счетчика задержки текущего кадра анимации
  488. timer.setTime(animationFrame[indexFrame].timeFrame);
  489. // Запускаем таймер
  490. timer.start();
  491. // Если текущий кадр не последний в анимации
  492. if (indexFrame < countFrames - 1) {
  493. // Переходим на следующий кадр
  494. indexFrame++;
  495. } else {
  496. // Устанавливаем флаг последнего кадра в состояние «активен»
  497. lastFrame = true;
  498. }
  499. } else {
  500. // Останавливаем таймер
  501. timer.stop();
  502. // Запускаем ИК-приёмник
  503. IrReceiver.start();
  504. // Сбрасываем все настройки по умолчанию
  505. resetState();
  506. }
  507. }
  508. }
  509.  
  510. // Функция сброса всех настроек по умолчанию
  511. void resetState() {
  512. // Обнуляем счётчик кадра
  513. indexFrame = 0;
  514. // Устанавливаем флаг последнего кадра в состояние «не активен»
  515. lastFrame = false;
  516. // Отображаем на матрицах иконку «Взгляд прямо»
  517. drawIcon(ICON_EYE_STRAIGHT, ICON_EYE_STRAIGHT);
  518. }

№10. Робоголова

Изменение кода кнопок пульта

Вернись к шпаргалке с таблицей из эксперимента №7 «Консольный ИК-приёмник» и подставь фактические коды кнопок твоего пульта в строках 144157, когда откроешь скетч RobotHead.ino в Arduino IDE.

  1. enum CODE {
  2. POWER = 0x0B,
  3. LEFT = 0x08,
  4. RIGHT = 0x19,
  5. UP = 0x06,
  6. DOWN = 0x1D,
  7. UP_LEFT = 0x0A,
  8. UP_RIGHT = 0x1A,
  9. DOWN_LEFT = 0x18,
  10. DOWN_RIGHT = 0x04,
  11. RED = 0x00,
  12. GREEN = 0x03,
  13. BLUE = 0x01
  14. } code;
RobotHead.ino
  1. // Подключаем библиотеку для работы с мелодиями в формате RTTTL
  2. #include <anyrtttl.h>
  3.  
  4. // Подключаем библиотеку для работы с ИК-приёмником
  5. #include <IRremote.hpp>
  6.  
  7. // Подключаем библиотеку для работы с сервоприводом
  8. #include <Servo.h>
  9.  
  10. // Подключаем библиотеку для работы с таймером millis
  11. #include <TimerMs.h>
  12.  
  13. // Подключаем библиотеку для работы со светодиодными матрицами
  14. #include <TroykaLedMatrix.h>
  15.  
  16. // Даём понятное имя пину 3 с пищалкой
  17. constexpr uint8_t BUZZER_PIN = 3;
  18.  
  19. // Даём понятное имя пину 2 с ИК-приёмником
  20. constexpr uint8_t IR_RECEIVE_PIN = 2;
  21.  
  22. // Даём понятное имя пину A3 с сервоприводом
  23. constexpr uint8_t SERVO_YAW_PIN = A3;
  24. // Даём понятное имя пину A0 с сервоприводом
  25. constexpr uint8_t SERVO_PITCH_PIN = A0;
  26.  
  27. // Создаём объект сервопривода влево-вправо
  28. Servo servoYaw;
  29. // Создаём объект сервопривода вверх-вниз
  30. Servo servoPitch;
  31.  
  32. // Создаём объект для работы с таймером
  33. TimerMs timer;
  34.  
  35. // Создаём объект матрицы левого глаза
  36. // на шине I²C с адресом 0x60 (указан по умолчанию)
  37. TroykaLedMatrix matrixL;
  38. // Создаём объект матрицы правого глаза
  39. // на шине I²C с адресом 0x63
  40. TroykaLedMatrix matrixR(0x63);
  41.  
  42. // Создаём константу для хранения базовой частоты
  43. constexpr int FREQUENCY = 2000;
  44.  
  45. // Создаём константы для хранения минимальной и максимальной частоты
  46. constexpr int MIN_FREQUENCY = FREQUENCY - (0.25 * FREQUENCY);
  47. constexpr int MAX_FREQUENCY = FREQUENCY + (0.25 * FREQUENCY);
  48.  
  49. // Задаём максимально доступные углы поворота сервопривода головы влево-вправо
  50. constexpr uint8_t MAX_ANGLE_YAW_R = 0;
  51. constexpr uint8_t MAX_ANGLE_YAW_L = 180;
  52.  
  53. // Задаём максимально доступные углы поворота сервопривода головы вверх-вниз
  54. constexpr uint8_t MAX_ANGLE_PITCH_DOWN = 60;
  55. constexpr uint8_t MAX_ANGLE_PITCH_UP = 120;
  56.  
  57. // Вычисляем средний угол поворота сервопривода головы влево-вправо
  58. constexpr uint8_t MID_ANGLE_YAW = (MAX_ANGLE_YAW_R + MAX_ANGLE_YAW_L) / 2;
  59.  
  60. // Вычисляем средний угол поворота сервопривода головы вверх-вниз
  61. constexpr uint8_t MID_ANGLE_PITCH = (MAX_ANGLE_PITCH_DOWN + MAX_ANGLE_PITCH_UP) / 2;
  62.  
  63. // Создаём переменную для хранения текущего положения сервопривода головы влево-вправо
  64. uint8_t angleYaw = MID_ANGLE_YAW;
  65. // Создаём переменную для хранения текущего положения сервопривода головы вверх-вниз
  66. uint8_t anglePitch = MID_ANGLE_PITCH;
  67.  
  68. // Создаём константу для хранения паузы между поворотом вала сервопривода
  69. constexpr uint8_t ANGLE_RANGE = 2;
  70.  
  71. // Создаём иконку «Взгляд прямо» в шестнадцатеричной системе HEX
  72. // Иконка для левого и правого глаза одинаковая
  73. // Эмоции рисуем в редакторе изображений для LED-матрицы
  74. // https://amperka.github.io/led-matrix-editor/
  75. constexpr uint8_t ICON_EYE_STRAIGHT[] PROGMEM {
  76. 0x7e, 0x81, 0x81, 0x99, 0x99, 0x81, 0x81, 0x7e
  77. };
  78.  
  79. // Создаём иконку «Взгляд влево» в шестнадцатеричной системе HEX
  80. // Иконка для левого и правого глаза одинаковая
  81. constexpr uint8_t ICON_EYE_LEFT[] PROGMEM {
  82. 0x7e, 0x81, 0x81, 0xe1, 0xe1, 0x81, 0x81, 0x7e
  83. };
  84.  
  85. // Создаём иконку «Взгляд вправо» в шестнадцатеричной системе HEX
  86. // Иконка для левого и правого глаза одинаковая
  87. constexpr uint8_t ICON_EYE_RIGHT[] PROGMEM {
  88. 0x7e, 0x81, 0x81, 0x87, 0x87, 0x81, 0x81, 0x7e
  89. };
  90.  
  91. // Создаём иконку «Взгляд вверх» в шестнадцатеричной системе HEX
  92. // Иконка для левого и правого глаза одинаковая
  93. constexpr uint8_t ICON_EYE_UP[] PROGMEM {
  94. 0x7e, 0x99, 0x99, 0x81, 0x81, 0x81, 0x81, 0x7e
  95. };
  96.  
  97. // Создаём иконку «Взгляд вниз» в шестнадцатеричной системе HEX
  98. // Иконка для левого и правого глаза одинаковая
  99. constexpr uint8_t ICON_EYE_DOWN[] PROGMEM {
  100. 0x7e, 0x81, 0x81, 0x81, 0x81, 0x99, 0x99, 0x7e
  101. };
  102.  
  103. // Создаём иконку «Взгляд вверх-влево» в шестнадцатеричной системе HEX
  104. // Иконка для левого и правого глаза одинаковая
  105. constexpr uint8_t ICON_EYE_UP_LEFT[] PROGMEM {
  106. 0x7e, 0xe1, 0xe1, 0x81, 0x81, 0x81, 0x81, 0x7e
  107. };
  108.  
  109. // Создаём иконку «Взгляд вверх-вправо» в шестнадцатеричной системе HEX
  110. // Иконка для левого и правого глаза одинаковая
  111. constexpr uint8_t ICON_EYE_UP_RIGHT[] PROGMEM {
  112. 0x7e, 0x87, 0x87, 0x81, 0x81, 0x81, 0x81, 0x7e
  113. };
  114.  
  115. // Создаём иконку «Взгляд вниз-влево» в шестнадцатеричной системе HEX
  116. // Иконка для левого и правого глаза одинаковая
  117. constexpr uint8_t ICON_EYE_DOWN_LEFT[] PROGMEM {
  118. 0x7e, 0x81, 0x81, 0x81, 0x81, 0xe1, 0xe1, 0x7e
  119. };
  120.  
  121. // Создаём иконку «Взгляд вниз-вправо» в шестнадцатеричной системе HEX
  122. // Иконка для левого и правого глаза одинаковая
  123. constexpr uint8_t ICON_EYE_DOWN_RIGHT[] PROGMEM {
  124. 0x7e, 0x81, 0x81, 0x81, 0x81, 0x87, 0x87, 0x7e
  125. };
  126.  
  127. // Создаём иконку «Глаза выключены» в шестнадцатеричной системе HEX
  128. // Иконка для левого и правого глаза одинаковая
  129. constexpr uint8_t ICON_EYE_OFF[] PROGMEM {
  130. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  131. };
  132.  
  133. // Создаём константу для хранения статуса слежения глазами за поворотом робоголовы
  134. constexpr bool STATE_LOOK_TURN = false;
  135.  
  136. // Создаём перечисление состояний робота с соответствующей переменной
  137. enum {
  138. ROBOT_ON, // Робот включен
  139. ROBOT_OFF, // Робот выключен
  140. } robotState;
  141.  
  142. // Создаём перечисление кодов и ИК-пульта с соответствующей переменной
  143. enum CODE {
  144. POWER = 0x0B,
  145. LEFT = 0x08,
  146. RIGHT = 0x19,
  147. UP = 0x06,
  148. DOWN = 0x1D,
  149. UP_LEFT = 0x0A,
  150. UP_RIGHT = 0x1A,
  151. DOWN_LEFT = 0x18,
  152. DOWN_RIGHT = 0x04,
  153. RED = 0x00,
  154. GREEN = 0x03,
  155. BLUE = 0x01
  156. } code;
  157.  
  158. void setup() {
  159. // Подключаем сервомоторы головы влево-вправо и вниз-вверх
  160. servoYaw.attach(SERVO_YAW_PIN);
  161. servoPitch.attach(SERVO_PITCH_PIN);
  162. // Приравниваем текущим положениям вала сервоприводов
  163. // влево-вправо и вверх-вниз среднее значение
  164. angleYaw = MID_ANGLE_YAW;
  165. anglePitch = MID_ANGLE_PITCH;
  166. // Устанавливаем углы сервоприводов по умолчанию
  167. servoYaw.write(angleYaw);
  168. servoPitch.write(anglePitch);
  169. // Инициализируем ИК-приёмник
  170. IrReceiver.begin(IR_RECEIVE_PIN);
  171. // Инициализируем матрицы
  172. matrixL.begin();
  173. matrixR.begin();
  174. // Очищаем матрицы
  175. matrixL.clear();
  176. matrixR.clear();
  177. // Отображаем на матрицах иконку «Взгляд прямо»
  178. drawIcon(ICON_EYE_STRAIGHT, ICON_EYE_STRAIGHT);
  179. // Устанавливаем таймер в режим остановки после срабатывания
  180. timer.setTimerMode();
  181. // Передаём случайное число с пина A1
  182. // для последующей генерации случайных чисел
  183. randomSeed(analogRead(A1));
  184. // Устанавливаем режим «Робот включен»
  185. robotState = ROBOT_ON;
  186. }
  187.  
  188. void loop() {
  189. // Если робот включен
  190. if (robotState == ROBOT_ON) {
  191. // Переходим в функцию обработки режима «Робот включен»
  192. handleRobotOn();
  193. }
  194. // Если робот выключен
  195. if (robotState == ROBOT_OFF) {
  196. // Переходим в функцию обработки режима «Робот выключен»
  197. handleRobotOff();
  198. }
  199. }
  200.  
  201. // Функция отображения иконки поворотов на матрицах
  202. void drawIconTurn(uint8_t* iconEyeL, uint8_t* iconEyeR) {
  203. // Если статус активности слежение глаз за поворотом включен
  204. if (STATE_LOOK_TURN) {
  205. // Отображаем на матрицах полученные иконки
  206. matrixL.drawBitmapF(iconEyeL);
  207. matrixR.drawBitmapF(iconEyeR);
  208. }
  209. }
  210.  
  211. // Функция отображения иконки на матрицах
  212. void drawIcon(uint8_t* iconEyeL, uint8_t* iconEyeR) {
  213. // Отображаем на матрицах полученные иконки
  214. matrixL.drawBitmapF(iconEyeL);
  215. matrixR.drawBitmapF(iconEyeR);
  216. }
  217.  
  218. // Функция обработки режима «Робот выключен»
  219. void handleRobotOff() {
  220. // Выключаем глаза
  221. drawIcon(ICON_EYE_OFF, ICON_EYE_OFF);
  222. // Если робот выключен
  223. while (robotState == ROBOT_OFF) {
  224. // Переходим в функцию обработки ИК-приёмника в режиме «Робот выключен»
  225. remoteHandlerRobotOff();
  226. }
  227. }
  228.  
  229. // Функция обработки режима «Робот включен»
  230. void handleRobotOn() {
  231. // Включаем глаза
  232. drawIcon(ICON_EYE_STRAIGHT, ICON_EYE_STRAIGHT);
  233. // Если робот включен
  234. while (robotState == ROBOT_ON) {
  235. // Переходим в функцию обработки ИК-приёмника в режиме «Робот включен»
  236. remoteHandlerRobotOn();
  237. }
  238. }
  239.  
  240. // Функция обработки ИК-приёмника в режиме «Робот выключен»
  241. void remoteHandlerRobotOff() {
  242. // Если пришёл новый сигнал на ИК-приёмник, декодируем его
  243. if (IrReceiver.decode()) {
  244. // Создаём переменную и присваиваем ей декодируемый код кнопки
  245. uint32_t code = IrReceiver.decodedIRData.command;
  246. // Если нажата кнопка «Включение/выключение»
  247. if (code == POWER) {
  248. // Даём роботу 500 мс на включение
  249. delay(500);
  250. // Включаем робота
  251. robotState = ROBOT_ON;
  252. }
  253. // Разрешаем обрабатывать следующий сигнал
  254. IrReceiver.resume();
  255. }
  256. }
  257.  
  258. // Функция обработки ИК-приёмника в режиме «Робот включен»
  259. void remoteHandlerRobotOn() {
  260. // Если пришёл новый сигнал на ИК-приёмник, декодируем его
  261. if (IrReceiver.decode()) {
  262. // Создаём переменную и присваиваем ей декодируемый код кнопки
  263. uint32_t code = IrReceiver.decodedIRData.command;
  264. // Устанавливаем в таймер значение счетчика 500
  265. timer.setTime(500);
  266. // Запускаем таймер
  267. timer.start();
  268. // Выбираем действие в зависимости от текущего режима игры
  269. switch (code) {
  270. // Если нажата кнопка «Включение/выключение»
  271. case POWER:
  272. // Даём роботу 500 мс на выключение
  273. delay(500);
  274. // Выключаем робота
  275. robotState = ROBOT_OFF;
  276. break;
  277. // Если нажата кнопка «Влево»
  278. case LEFT:
  279. // Обновляем переменную положение головы влево-вправо
  280. angleYaw = angleYaw + ANGLE_RANGE;
  281. // Обновляем положения вала влево-вправо
  282. servoYaw.write(angleYaw);
  283. // Отображаем на матрицах иконку «Взгляд влево»
  284. drawIconTurn(ICON_EYE_LEFT, ICON_EYE_LEFT);
  285. break;
  286. // Если нажата кнопка «Вправо»
  287. case RIGHT:
  288. // Обновляем переменную положение головы влево-вправо
  289. angleYaw = angleYaw - ANGLE_RANGE;
  290. // Обновляем положения вала влево-вправо
  291. servoYaw.write(angleYaw);
  292. // Отображаем на матрицах иконку «Взгляд вправо»
  293. drawIconTurn(ICON_EYE_RIGHT, ICON_EYE_RIGHT);
  294. break;
  295. // Если нажата кнопка «Вверх»
  296. case UP:
  297. // Обновляем переменную положение головы вверх-вниз
  298. anglePitch = anglePitch + ANGLE_RANGE;
  299. // Обновляем положения вала вверх-вниз
  300. servoPitch.write(anglePitch);
  301. // Отображаем на матрицах иконку «Взгляд вверх»
  302. drawIconTurn(ICON_EYE_UP, ICON_EYE_UP);
  303. break;
  304. // Если нажата кнопка «Вниз»
  305. case DOWN:
  306. // Обновляем переменную положение головы вверх-вниз
  307. anglePitch = anglePitch - ANGLE_RANGE;
  308. // Обновляем положения вала вверх-вниз
  309. servoPitch.write(anglePitch);
  310. // Отображаем на матрицах иконку «Взгляд вниз»
  311. drawIconTurn(ICON_EYE_DOWN, ICON_EYE_DOWN);
  312. break;
  313. // Если нажата кнопка «Вверх-влево»
  314. case UP_LEFT:
  315. // Обновляем переменную положение головы влево-вправо
  316. angleYaw = angleYaw + ANGLE_RANGE;
  317. // Обновляем переменную положение головы вверх-вниз
  318. anglePitch = anglePitch + ANGLE_RANGE;
  319. // Обновляем положения вала влево-вправо
  320. servoYaw.write(angleYaw);
  321. // Обновляем положения вала вверх-вниз
  322. servoPitch.write(anglePitch);
  323. // Отображаем на матрицах иконку «Взгляд вверх-влево»
  324. drawIconTurn(ICON_EYE_UP_LEFT, ICON_EYE_UP_LEFT);
  325. break;
  326. // Если нажата кнопка «Вверх-вправо»
  327. case UP_RIGHT:
  328. // Обновляем переменную положение головы влево-вправо
  329. angleYaw = angleYaw - ANGLE_RANGE;
  330. // Обновляем переменную положение головы вверх-вниз
  331. anglePitch = anglePitch + ANGLE_RANGE;
  332. // Обновляем положения вала влево-вправо
  333. servoYaw.write(angleYaw);
  334. // Обновляем положения вала вверх-вниз
  335. servoPitch.write(anglePitch);
  336. // Отображаем на матрицах иконку «Взгляд вверх-влево»
  337. drawIconTurn(ICON_EYE_UP_RIGHT, ICON_EYE_UP_RIGHT);
  338. break;
  339. // Если нажата кнопка «Вниз-влево»
  340. case DOWN_LEFT:
  341. // Обновляем переменную положение головы влево-вправо
  342. angleYaw = angleYaw + ANGLE_RANGE;
  343. // Обновляем переменную положение головы вверх-вниз
  344. anglePitch = anglePitch - ANGLE_RANGE;
  345. // Обновляем положения вала влево-вправо
  346. servoYaw.write(angleYaw);
  347. // Обновляем положения вала вверх-вниз
  348. servoPitch.write(anglePitch);
  349. // Отображаем на матрицах иконку «Взгляд вниз-влево»
  350. drawIconTurn(ICON_EYE_DOWN_LEFT, ICON_EYE_DOWN_LEFT);
  351. break;
  352. // Если нажата кнопка «Вниз-вправо»
  353. case DOWN_RIGHT:
  354. // Обновляем переменную положение головы влево-вправо
  355. angleYaw = angleYaw - ANGLE_RANGE;
  356. // Обновляем переменную положение головы вверх-вниз
  357. anglePitch = anglePitch - ANGLE_RANGE;
  358. // Обновляем положения вала влево-вправо
  359. servoYaw.write(angleYaw);
  360. // Обновляем положения вала вверх-вниз
  361. servoPitch.write(anglePitch);
  362. // Отображаем на матрицах иконку «Взгляд вниз-влево»
  363. drawIconTurn(ICON_EYE_DOWN_RIGHT, ICON_EYE_DOWN_RIGHT);
  364. break;
  365. case RED:
  366. // Отключаем ИК-приёмник
  367. IrReceiver.stop();
  368. // Вызываем функцию генератора последовательных длинных семплов
  369. toneLongSamples();
  370. // Вызываем функцию генератора непоследовательных коротких семплов
  371. toneShortSamples();
  372. // Запускаем ИК-приёмник
  373. IrReceiver.start();
  374. break;
  375. case GREEN:
  376. // Отключаем ИК-приёмник
  377. IrReceiver.stop();
  378. // Вызываем функцию генератора последовательных длинных семплов
  379. toneLongSamples();
  380. // Вызываем функцию генератора непоследовательных коротких семплов
  381. toneShortSamples();
  382. // Запускаем ИК-приёмник
  383. IrReceiver.start();
  384. break;
  385. case BLUE:
  386. // Отключаем ИК-приёмник
  387. IrReceiver.stop();
  388. // Вызываем функцию генератора последовательных длинных семплов
  389. toneLongSamples();
  390. // Вызываем функцию генератора непоследовательных коротких семплов
  391. toneShortSamples();
  392. // Запускаем ИК-приёмник
  393. IrReceiver.start();
  394. break;
  395. }
  396. // Разрешаем обрабатывать следующий сигнал
  397. IrReceiver.resume();
  398. }
  399. // Если таймер досчитал до конца
  400. if (timer.tick()) {
  401. // Отображаем на матрицах иконку «Взгляд прямо»
  402. drawIcon(ICON_EYE_STRAIGHT, ICON_EYE_STRAIGHT);
  403. }
  404. }
  405.  
  406. // Функция генерации последовательных длинных семплов
  407. void toneLongSamples() {
  408. // Генерируем случайное количество семплов от 1 до 6
  409. int countSamples = random(1, 7);
  410. // Перебираем нумерацию семплов в цикле
  411. for (int i = 0; i < countSamples; i++) {
  412. // Генерируем случайное число: true или false
  413. bool typeSamples = random(0, 2);
  414. // Если тип семпла true
  415. if (typeSamples) {
  416. // Вызываем функцию генерации тона toneSlowDownFastUp:
  417. // Сначала медленный убывающий тон со случайными задержками
  418. // Затем быстрый возрастающий тон со случайными задержками
  419. toneSlowDownFastUp();
  420. } else {
  421. // Если тип семпла false
  422. // Вызываем функцию генерации тона toneSlowUpFastDown:
  423. // Сначала медленный возрастающий тон со случайными задержками
  424. // Затем быстрый убывающий тон со случайными задержками
  425. toneSlowUpFastDown();
  426. }
  427. }
  428. }
  429.  
  430. // Функция генерации непоследовательных коротких семплов
  431. void toneShortSamples() {
  432. // Генерируем случайное количество семплов от 3 до 9
  433. int countSamples = random(3, 10);
  434. // Генерируем случайную частоту на базе FREQUENCY
  435. int frequency = random(MIN_FREQUENCY, MAX_FREQUENCY);
  436. for (int i = 0; i <= countSamples; i++) {
  437. // Активируем глаза
  438. drawIcon(ICON_EYE_STRAIGHT, ICON_EYE_STRAIGHT);
  439. // Генерируем случайный интервал на базе FREQUENCY
  440. int range = random(-FREQUENCY, FREQUENCY);
  441. tone(BUZZER_PIN, frequency + range);
  442. // Выполняем случайную задержку от 70 до 170 мс
  443. delay(random(70, 170));
  444. // Деактивируем глаза
  445. drawIcon(ICON_EYE_OFF, ICON_EYE_OFF);
  446. // Выключаем звук
  447. noTone(BUZZER_PIN);
  448. // Выполняем случайную задержку от 0 до 30 мс
  449. delay(random(0, 30));
  450. }
  451. }
  452.  
  453. // Функция генерации звуковой последовательности
  454. // Сначала медленный убывающий тон со случайными задержками
  455. // Затем быстрый возрастающий тон со случайными задержками
  456. void toneSlowDownFastUp() {
  457. // Генерируем случайную частоту на базе FREQUENCY
  458. int frequency = random(MIN_FREQUENCY, MAX_FREQUENCY);
  459. // Активируем глаза
  460. drawIcon(ICON_EYE_STRAIGHT, ICON_EYE_STRAIGHT);
  461. // Генерируем медленный понижающий тон со случайными задержками
  462. for (int range = 0; range <= random(100, 1000); range++) {
  463. tone(BUZZER_PIN, frequency - (range * 2));
  464. delayMicroseconds(random(0, 1000));
  465. }
  466. // Деактивируем глаза
  467. drawIcon(ICON_EYE_OFF, ICON_EYE_OFF);
  468. // Генерируем быстрый повышающий тон со случайными задержками
  469. for (int range = 0; range <= random(100, 1000); range++) {
  470. tone(BUZZER_PIN, frequency + (range * 10));
  471. delayMicroseconds(random(0, 1000));
  472. }
  473. }
  474.  
  475. // Функция генерации звуковой последовательности
  476. // Сначала медленный возрастающий тон со случайными задержками
  477. // Затем быстрый убывающий тон со случайными задержками
  478. void toneSlowUpFastDown() {
  479. // Генерируем случайную частоту на базе FREQUENCY
  480. int frequency = random(MIN_FREQUENCY, MAX_FREQUENCY);
  481. // Активируем глаза
  482. drawIcon(ICON_EYE_STRAIGHT, ICON_EYE_STRAIGHT);
  483. // Генерируем медленный возрастающий тон со случайными задержками
  484. for (int range = 0; range <= random(100, 1000); range++) {
  485. tone(BUZZER_PIN, frequency + (range * 2));
  486. delayMicroseconds(random(0, 1000));
  487. }
  488. // Деактивируем глаза
  489. drawIcon(ICON_EYE_OFF, ICON_EYE_OFF);
  490. // Генерируем быстрый понижающий тон со случайными задержками
  491. for (int range = 0; range <= random(100, 1000); range++) {
  492. tone(BUZZER_PIN, frequency - (range * 10));
  493. delayMicroseconds(random(0, 1000));
  494. }
  495. }

Ресурсы

Софт

Библиотеки