toneroulette/toneroulette.ino

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
}