188 lines
11 KiB
C++
188 lines
11 KiB
C++
#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
|
|
}
|