#include "pitches.h" // загрузить ноты из pitches.h #include "Servo.h" // загрузить стандартную библиотеку Servo.h Servo myservo; // создать объект сервопривода myservo для его контроя const int redLED = 4; // красный пин светодиода const int greenLED = 5; // зелёный пин светодиода const int blueLED = 6; // синий пин светодиода const int buzzer = 7; // сигнальный пин пищалки const int servo = 9; // контрольный пин сервопривода const int encDT = 2; // пин правого поворота (DT) поворотного регулятора const int encCLK = 3; // пин левого поворота (CLK) поворотного регулятора const int encSW = 8; // пин нажатия (SW) поворотного регулятора volatile unsigned int encPos = 32768; // счётчик позиции поворотного регулятора unsigned int lastReportedPos = 32768; // последнее записанное значение позиции поворотного регулятора static boolean rotating = false; // управление поворотом регулятора boolean right_set = false; // переменная процедуры правого поворота регулятора boolean left_set = false; // переменная процедуры левого поворота регулятора int pos = 0; // переменная позиции сервопривода int posnote = 0; // переменная ноты на которую указывает сервопривод int playednote = 0; // переменная хранящая последнюю сыгранную ноту int gamma[] = {NOTE_B3, NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5}; // си3-до5 void setup() { // функция выполняемая при запуске Serial.begin(9600); // инициализация серийного монитора pinMode(LED_BUILTIN, OUTPUT); // определение встроенного светодиода digitalWrite(LED_BUILTIN, LOW); // выключить встроенный светодиод подав напряжение низкого уровня pinMode(buzzer, OUTPUT); // определение пищалки на выходной сигнал pinMode(encDT, INPUT_PULLUP); // определение правого поворота регулятора на вход с подтягивающим резистором pinMode(encCLK, INPUT_PULLUP); // определение левого поворота регулятора на вход с подтягивающим резистором pinMode(encSW, INPUT_PULLUP); // определение нажатия регулятора на вход с подтягивающим резистором attachInterrupt(0, encRight, CHANGE); // контакт регулятора на прерывании 0 (право) attachInterrupt(1, encLeft, CHANGE); // контакт регулятора на прерывании 1 (лево) // randomSeed(analogRead(0)); // устновка случайного семени в зависимости от напряжения на незанетом пине initAll(); // вызов функции иниализации пищалки, светодиода и севпривода randomNote(); // вызов функции проигрывания случайной ноты } void loop() { // функция выполняемая постоянно rotating = true; // указание состояния поворота регулятора if (lastReportedPos != encPos) { // если последнее записанное значение поворота регулятора неравно нынешнему положению // Serial.print("POS:"); Serial.print(pos); Serial.print("IN:"); Serial.println(encPos, DEC); // вывод значений для отладки if (lastReportedPos < encPos) { // если последнее записанное значение поворота регулятора меньше нынешнего if (pos > 10) rotateRight (pos, (pos-30)); // если позиция севопривода больше 10 - повернуть вправо на 30 градусов } if (lastReportedPos > encPos) { // если последнее записанное значение поворота регулятора больше нынешнего if (pos < 170) rotateLeft (pos, (pos+30)); // если позиция севопривода меньше 170 - повернуть влево на 30 градусов } lastReportedPos = encPos; // последнему записанному значению присвоить нынешнее значение регулятора } if (digitalRead(encSW) == LOW ) { // если нажата кнопка posnote = ((((pos / 30) + 1) - 8) * (-1)); // вычисление ноты на которую указывает сервопривод // Serial.print("NOTE:"); Serial.println(posnote); // вывод значений для отладки if (posnote == playednote) { // если сервопривод указывает на последнюю сыгранную ноту int blinking; // объявление временной переменной мерцания светодиода for (blinking = 0; blinking < 10; blinking += 1) { // цикл 10 шагов мерцания от 0 до 9 colourGreen(); // зелёный свет светодиода delay(200); // задержка в 200 миллисекунд colourBlue(); // синий свет светодиода delay(200); // задержка в 200 миллисекунд } colourOff(); // выключить свечение светодиода delay(1000); // задержка в 1000 миллисекунд randomNote(); // вызов функции проигрывания случайной ноты } else { // иначе colourRed(); // красный свет светодиода delay(1000); // задержка в 1000 миллисекунд colourOff(); // выключить свечение светодиода } } } void colourRandom() { // функция случайного цвета светодиода analogWrite(redLED, random(0,255)); // случайное значение красного analogWrite(greenLED, random(0,255)); // случайное значение зелёного analogWrite(blueLED, random(0,255)); // случайное значение синего } void colourRed() { // функция красного цвета светодиода analogWrite(redLED, 255); // максимальное значение красного analogWrite(greenLED, 0); // минимальное значение зелёного analogWrite(blueLED, 0); // минимальное значение синего } void colourGreen() { // функция зелёного цвета светодиода analogWrite(redLED, 0); // минимальное значение красного analogWrite(greenLED, 255); // максимальное значение зелёного analogWrite(blueLED, 0); // минимальное значение синего } void colourBlue() { // функция синего цвета светодиода analogWrite(redLED, 0); // минимальное значение красного analogWrite(greenLED, 0); // минимальное значение зелёного analogWrite(blueLED, 255); // максимальное значение синего } void colourOff() { // функция отсутствия цвета светодиода analogWrite(redLED, 0); // минимальное значение красного analogWrite(greenLED, 0); // минимальное значение зелёного analogWrite(blueLED, 0); // минимальное значение синего } void rotateLeft(int posFrom, int posTo) { // функция поворота сервопривода влево delay(32); // подождать 32 миллисекундыы myservo.attach(servo); // присоединиться к сервоприводу delay(32); // подождать 32 миллисекунды for (pos = posFrom; pos < posTo; pos += 1) { // цикл увеличения позиции с posFrom до postTo с шагом в 1 градус myservo.write(pos); // сообщить сервоприводу переместиться в позицию pos delay(15); // подождать 15 миллисекунд для достижения позиции } // Serial.print("LEFTfrom:"); Serial.print(posFrom); Serial.print("to:"); Serial.print(posTo); Serial.print("cur:"); Serial.println(pos); // вывод значений для отладки delay(32); // подождать 32 миллисекунды myservo.detach(); // отсоединиться от сервопривода delay(32); // подождать 32 миллисекунды } void rotateRight(int posFrom, int posTo) { // функция поворота сервопривода вправо delay(32); // подождать 32 миллисекунды myservo.attach(servo); // присоединиться к сервоприводу delay(32); // подождать 32 миллисекунды for (pos = posFrom; pos > posTo; pos -= 1) { // цикл уменьшения позиции с posFrom до postTo с шагом в 1 градус myservo.write(pos); // сообщить сервоприводу переместиться в позицию pos delay(15); // подождать 15 миллисекунд для достижения позиции } // Serial.print("RIGHTfrom:"); Serial.print(posFrom); Serial.print("to:"); Serial.print(posTo); Serial.print("cur:"); Serial.println(pos); // вывод значений для отладки delay(32); // подождать 32 миллисекунды myservo.detach(); // отсоединиться от сервопривода delay(32); // подождать 32 миллисекунды } void initAll() { // функция иниализации пищалки, светодиода и севпривода int gammavar; // обявление временной переменной нотной гаммы for (gammavar = 1; gammavar <= 8; gammavar += 1) { // цикл увеличение ноты от 1 до 8 colourRandom(); // случайный цвет светодиода tone(buzzer, gamma[gammavar]); // подать на пищалку соответствующий тон гаммы delay(200); // подождать 200 миллисекунд noTone(buzzer); // нет больше тона на пищалке delay(10); // подождать 10 миллисекунд } for (gammavar = 7; gammavar >= 1; gammavar -= 1) { // цикл уменьшения ноты от 7 до 1 colourRandom(); // случайный цвет светодиода tone(buzzer, gamma[gammavar]); // подать на пищалку соответствующий тон гаммы delay(200); // подождать 200 миллисекунд noTone(buzzer); // нет больше тона на пищалке delay(10); // подождать 10 миллисекунд } colourRandom(); // случайный цвет светодиода delay(500); // подождать 500 миллисекунд colourRandom(); // случайный цвет светодиода rotateLeft (0, 180); // повернуть сервопривод налево на 180 градусов colourRandom(); // случайный цвет светодиода delay(500); // подождать 500 миллисекунд colourRandom(); // случайный цвет светодиода rotateRight (180, 0); // повернуть сервопривод направо на 180 градусов colourRandom(); // случайный цвет светодиода delay(500); // подождать 500 миллисекунд colourRandom(); // случайный цвет светодиода delay (1000); // подождать 1000 миллисекунд colourOff(); // выключить свечение светодиода } void encRight(){ // обработка прерывния поворотного регулятора на прерывании 0 (право) if (rotating) delay (1); // подождать миллисекунду, пока поворот не закончится if (digitalRead(encDT) != right_set) { // если физическое значение регулятора неравно переменной процедуры правого поворота регулятора right_set = !right_set; // изменить значение переменной процедуры правого поворота регулятора на обратное if (right_set && !left_set) // если происходит поворот вправо и не происходит вопорота влево (для регулировки) encPos += 1; // увеличить счётчик позиции поворотного регулятора на 1 rotating = false; // больше нет вращения до завершения постоянно выполняемой функции loop() } } void encLeft(){ // обработка прерывния поворотного регулятора на прерывании 1 (лево) if (rotating) delay (1); // подождать миллисекунду, пока поворот не закончится if (digitalRead(encCLK) != left_set) { // если физическое значение регулятора неравно переменной процедуры левого поворота регулятора left_set = !left_set; // изменить значение переменной процедуры левого поворота регулятора на обратное if (left_set && !right_set) // если происходит поворот влево и не происходит вопорота вправо (для регулировки) encPos -= 1; // уменьшить счётчик позиции поворотного регулятора на 1 rotating = false; // больше нет вращения до завершения постоянно выполняемой функции loop() } } void randomNote() { // функция проигрывания случайной ноты delay(200); // подождать 200 миллисекунд playednote = random(1,7); // сгенерировать случайное значение от 1 до 7 для переменной хранящей последнюю сыгранную ноту tone(buzzer, gamma[playednote]); // подать на пищалку соответствующий тон переменной хранящей последнюю сыгранную ноту delay(2000); // подождать 2000 миллисекунд noTone(buzzer); // нет больше тона на пищалке delay(200); // подождать 200 миллисекунд }