#include "pitches.h" // include tones from pitches.h #include "Servo.h" // include pitches standard Servo.h library Servo myservo; // create servo object to control a servo const int redLED = 4; // red pin of LED const int greenLED = 5; // green pin of LED const int blueLED = 6; // blue pin of LED const int buzzer = 7; // signal pin of buzzer const int servo = 9; // control pin of servo const int encDT = 2; // pin of the right rotation of encoder (DT) const int encCLK = 3; // pin of the left rotation of encoder (CLK) const int encSW = 8; // pin of the switch of encoder (SW) volatile unsigned int encPos = 32768; // encoder position counter unsigned int lastReportedPos = 32768; // the last recorded position value of encoder static boolean rotating = false; // encoder rotation control boolean right_set = false; // variable for the procedure of right turn of encoder boolean left_set = false; // variable for the procedure of left turn of encoder int pos = 0; // variable to store servo position int posnote = 0; // variable of the note to which servo is pointing int playednote = 0; // variable storing the last note played int gamma[] = {NOTE_B3, NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5}; // ti3-do5 void setup() { // function performed at start-up Serial.begin(9600); // serial monitor initialisation pinMode(LED_BUILTIN, OUTPUT); // definition of built-in LED digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW pinMode(buzzer, OUTPUT); // definition of buzzer to output signal pinMode(encDT, INPUT_PULLUP); // definition of right turn of encoder as input pullup pinMode(encCLK, INPUT_PULLUP); // definition of left turn of encoder as input pullup pinMode(encSW, INPUT_PULLUP); // definition of switch of encoder as input pullup attachInterrupt(0, encRight, CHANGE); // encoder pin on interrupt 0 (right) attachInterrupt(1, encLeft, CHANGE); // encoder pin on interrupt 1 (left) // randomSeed(analogRead(0)); // setting a random seed depending on the voltage on an unswitched pin initAll(); // call for function of the initialisation of buzzer, LED and servo randomNote(); // call random note play function } void loop() { // ongoing function rotating = true; // encoder rotating state set if (lastReportedPos != encPos) { // if the last recorded encoder position is not equal to the current position // Serial.print("POS:"); Serial.print(pos); Serial.print("IN:"); Serial.println(encPos, DEC); // output values for debug if (lastReportedPos < encPos) { // if the last recorded encoder position is less than the present value if (pos > 10) rotateRight (pos, (pos-30)); // if servo position is greater than 10 - turn right 30 degrees } if (lastReportedPos > encPos) { // if the last recorded encoder position is greater than the present value if (pos < 170) rotateLeft (pos, (pos+30)); // if servo position is less than 170 - turn left 30 degrees } lastReportedPos = encPos; // assign current encoder position to the last recorded position } if (digitalRead(encSW) == LOW ) { // if encoder switch is pressed posnote = ((((pos / 30) + 1) - 8) * (-1)); // calculating the note indicated by servo // Serial.print("NOTE:"); Serial.println(posnote); // output values for debug if (posnote == playednote) { // if servo points to the last played note int blinking; // declaration of LED blinking variable for (blinking = 0; blinking < 10; blinking += 1) { // cycle 10 blinking steps from 0 to 9 colourGreen(); // green LED light delay(200); // 200 millisecond delay colourBlue(); // blue LED light delay(200); // 200 millisecond delay } colourOff(); // switch off LED light delay(1000); // 1000 millisecond delay randomNote(); // call the random note play function } else { // else colourRed(); // red LED light delay(1000); // 1000 millisecond delay colourOff(); // switch off LED light } } } void colourRandom() { // random colour LED function analogWrite(redLED, random(0,255)); // random value of red analogWrite(greenLED, random(0,255)); // random value of green analogWrite(blueLED, random(0,255)); // random value of blue } void colourRed() { // red colour LED function analogWrite(redLED, 255); // maximum value of red analogWrite(greenLED, 0); // minumum value of green analogWrite(blueLED, 0); // minumum value of blue } void colourGreen() { // green colour LED function analogWrite(redLED, 0); // minumum value of red analogWrite(greenLED, 255); // maximum value of green analogWrite(blueLED, 0); // minumum value of blue } void colourBlue() { // blue colour LED function analogWrite(redLED, 0); // minumum value of red analogWrite(greenLED, 0); // minumum value of green analogWrite(blueLED, 255); // maximum value of blue } void colourOff() { // no colour LED function analogWrite(redLED, 0); // minumum value of red analogWrite(greenLED, 0); // minumum value of green analogWrite(blueLED, 0); // minumum value of blue } void rotateLeft(int posFrom, int posTo) { // servo's left turn function delay(32); // 32 millisecond delay myservo.attach(servo); // attaching to servo delay(32); // 32 millisecond delay for (pos = posFrom; pos < posTo; pos += 1) { // cycle of increasing position from posFrom to postTo in 1-degree increments myservo.write(pos); // tell servo to go to position in variable pos delay(15); // 15 millisecond delay } // Serial.print("LEFTfrom:"); Serial.print(posFrom); Serial.print("to:"); Serial.print(posTo); Serial.print("cur:"); Serial.println(pos); // output values for debug delay(32); // 32 millisecond delay myservo.detach(); // detaching from servo delay(32); // 32 millisecond delay } void rotateRight(int posFrom, int posTo) { // servo's right turn function delay(32); // 32 millisecond delay myservo.attach(servo); // attaching to servo delay(32); // 32 millisecond delay for (pos = posFrom; pos > posTo; pos -= 1) { // cycle of reduction position from posFrom to postTo in 1-degree increments myservo.write(pos); // tell servo to go to position in variable pos delay(15); // 15 millisecond delay } // Serial.print("RIGHTfrom:"); Serial.print(posFrom); Serial.print("to:"); Serial.print(posTo); Serial.print("cur:"); Serial.println(pos); // output values for debug delay(32); // 32 millisecond delay myservo.detach(); // detaching from servo delay(32); // 32 millisecond delay } void initAll() { // function of the initialisation of buzzer, LED and servo int gammavar; // declaration of temporary gamma variable for (gammavar = 1; gammavar <= 8; gammavar += 1) { // note increase cycle from 1 to 8 colourRandom(); // random LED light tone(buzzer, gamma[gammavar]); // sending the appropriate tone to buzzer delay(200); // 200 millisecond delay noTone(buzzer); // no more tone on buzzer delay(10); // 10 millisecond delay } for (gammavar = 7; gammavar >= 1; gammavar -= 1) { // note decrease cycle from 7 to 1 colourRandom(); // random LED light tone(buzzer, gamma[gammavar]); // sending the appropriate tone to buzzer delay(200); // 200 millisecond delay noTone(buzzer); // no more tone on buzzer delay(10); // 10 millisecond delay } colourRandom(); // random LED light delay(500); // 500 millisecond delay colourRandom(); // random LED light rotateLeft (0, 180); // turn servo 180 degrees to left colourRandom(); // random LED light delay(500); // 500 millisecond delay colourRandom(); // random LED light rotateRight (180, 0); // turn servo 180 degrees to right colourRandom(); // random LED light delay(500); // 500 millisecond delay colourRandom(); // random LED light delay (1000); // 1000 millisecond delay colourOff(); // switch off LED light } void encRight(){ // processing encoder interrupt 0 (right) if (rotating) delay (1); // wait a millisecond for the turn to end if (digitalRead(encDT) != right_set) { // if physical encoder value is not equal to the variable of the encoder right turn procedure right_set = !right_set; // change value of encoder right turn procedure variable to the opposite value if (right_set && !left_set) // if turning to the right occurs and not turning to the left (to adjust) encPos += 1; // increase encoder position counter by 1 rotating = false; // no more debouncing until loop() hits again } } void encLeft(){ // processing encoder interrupt 1 (left) if (rotating) delay (1); // wait a millisecond for the turn to end if (digitalRead(encCLK) != left_set) { // if physical encoder value is not equal to the variable of the encoder left turn procedure left_set = !left_set; // change value of encoder left turn procedure variable to the opposite value if (left_set && !right_set) // if turning to the left occurs and not turning to the right (to adjust) encPos -= 1; // decrease encoder position counter by 1 rotating = false; // no more debouncing until loop() hits again } } void randomNote() { // random note play function delay(200); // 200 millisecond delay playednote = random(1,7); // generate random value from 1 to 7 for the variable storing the last note played tone(buzzer, gamma[playednote]); // sending the appropriate tone to buzzer delay(2000); // 2000 millisecond delay noTone(buzzer); // no more tone on buzzer delay(200); // 200 millisecond delay }