188 lines
17 KiB
Arduino
188 lines
17 KiB
Arduino
|
#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 миллисекунд
|
|||
|
}
|