Note Hearing Trainer Door Marc Neeleman

by MarcoSpecial in Circuits > Arduino

1124 Views, 4 Favorites, 0 Comments

Note Hearing Trainer Door Marc Neeleman

Showcase Zonder Commentaar
IMG_20220811_153824371.jpg

Ik heb een doos gemaakt die je door middel van een spelvorm laat oefenen met het herkennen van muzieknoten. Wanneer je de doos aanzet zal het aan de doos verbonden keyboard een willekeurige noot afspelen. De speler kan met behulp van de 8 knoppen op de doos laten weten welke noot deze denkt gehoord te hebben. Dan komt er weer een nieuwe noot en kan de speler weer opnieuw raden. De doos laat ook zien hoeveel procent van de noten je goed/fout hebt beantwoord. Deze score reset elke keer dat je de doos uitzet.

Supplies

Electronica:

Arduino Uno

MIDI connector Digikey CP-2350-ND

Druksensor

Servo Motor

Batterijbox 9v (6x1 AA)

(3x) Prototyping board

(8x) Drukknoppen

(10x) 220 Ohm resistor

Jumper Wires

(Breadboard)


Hardware:

Piano Keyboard met MIDI IN port


Software:

Arduino IDE

Arduino MIDI library


Gereedschap & Behuizing:

Boormachine met boortjes

Houtveil

Soldeerset

Ducttape

Dubbelzijdige tape

Kist of Doos

(Stiften)

Eerdere Ideëen

Piano Controller Prototype - Synthesia
IMG_20220531_210247065.jpg
IMG_20220718_115512137.jpg

Ik heb een aantal verschillende ideëen gehad, maar een overeenkomst in al deze ideëen is dat ik graag iets met een piano wilde doen. Daarom had ik al snel de MIDI connector gekocht.

Mijn originele plan was om input van een piano door te geven aan mijn arduino, die dit dan vervolgens kon doorgeven aan Unity. Zo kon ik een game spelen die mijn piano keyboard als controller gebruikt. Ik was van plan om een programma te maken waarin je zelf liedjes kan importeren en dit liedje vervolgens kan oefenen. In Unity zou er dan gecontroleerd worden hoe goed je het liedje meespeelt. Ook zou ik hier een metronoom bij maken met behulp van een servomotor, waarmee je ook de snelheid van het liedje kon aanpassen. Na het inslaan van alle onderdelen merkte ik echter dat het MIDI input circuit niet werkte, het lukte mij niet om de input van mijn piano aan arduino door te geven. Ik heb meerdere reserve onderdelen gekocht en variaties van onderdelen, maar na veel pogingen werkte het nog steeds niet.

Vervolgens keek ik of ik succesvol een MIDI output circuit kon bouwen. Dit lukte, dus ik kon nu noten op mijn piano afspelen. Toen bedacht ik wat ik hier mee zou kunnen doen. Een van mijn experimenten was een piano die zelf liedjes speelt, maar dit was niet interactief.

Een kennis kwam met het idee van een pratende piano: Aan elke noot zou ik een letter toewijzen, en mijn keyboard zou vervolgens alle noten die in een woord of zin staan zeggen. Dit idee sprak mij erg aan, maar zou dan alleen werken voor mensen die goed noten kunnen herkennen op gehoor... Daarom kwam ik vervolgens op het idee om mensen hiermee te laten oefenen!

Het Plan + Aanpak

ITTT Music Hearing Idee.png

Hierboven is een schets te zien van een zijaanzicht van de doos. Dit is hoe de interface van de doos er ongeveer uit komt te zien. We gebruiken de druksensor als aanknop, en zorgen dat het spel pas begint als deze aan is gezet. De piano, die kan worden aangesloten aan de MIDI Connector (niet weergegeven in dit plaatje), zal een noot tussen C4 en C5 afspelen. Daarom hebben we 8 drukknoppen nodig: Voor elke pianonoot één.

Het percentage van goede/foute antwoorden van de speler wordt weergegeven door een servo motor: Een hoek van 0 graden betekent dat de speler 0% goed heeft, een hoek van 180 betekent dat de speler 100% goed heeft.

De MIDI connector zal aan een andere zijkant van de doos uitsteken.

Alle Electronica Aansluiten

Circuit.png
SCHEMATIC_Midi_Output.png
IMG_20220802_174630566.jpg
IMG_20220802_172542311.jpg
IMG_20220809_152949997.jpg

Het belangrijkste component van de electronica is het verbinden van de MIDI connector. Deze zorgt ervoor dat de arduino signalen door kan geven aan een keyboard met een MIDI IN port, en de piano dus bijvoorbeeld noten kan laten afspelen. De middelste pin (2) van de MIDI connector mis verbonden met de ground, pin 4 (zie afbeelding 2) is met een weerstand aan verbonden aan de stroom. Voor het overgeven van input aan de piano is pin 5 met de TX pin van de arduino verbonden.

Vervolgens zijn er 8 knoppen en een druksensor verbonden aan de arduino. Ook heb ik een servo motor aangesloten. Al deze onderdelen zijn met de 5V en de ground pin van de arduino verbinden en aan een digitale of analoge arduino pin.

MIDI Output Programmeren

Het programma zorgt ervoor dat we daadwerkelijk signalen kunnen doorgeven aan de piano en deze signalen op het juiste moment doorgeven. Om te testen of ik de MIDI connector goed had aangesloten, begon ik met een simpele test: om de seconde liet ik een noot afspelen. Deze testcode kwam van NotesandVolts.com.

/** 
  Code from NotesAndVolts.com
  Comments by Marc Neeleman
**/

#include <MIDI.h> // Imports the arduino MIDI library

#define LED 13

MIDI_CREATE_DEFAULT_INSTANCE(); // Setup

void setup()
{
  pinMode(LED, OUTPUT);
  MIDI.begin(MIDI_CHANNEL_OFF); // Setup for piano output
}

void loop()
{
  digitalWrite(LED, HIGH);  // Turn LED on arduino board on
  MIDI.sendNoteOn(60, 127, 1);  // Play the middle C note (with ID 60) on the piano
  delay(1000);           
  MIDI.sendNoteOff(60, 0, 1); // Stop playing the middle C note (with ID 60) on the piano
  digitalWrite(LED, LOW); // Turn LED on arduino board off
  delay(1000);
}

Als de MIDI connector goed is aangesloten zou deze nu steeds de middel C moeten afspelen op het keyboard.

Nu zou mijn piano uit zichzelf vanalles kunnen spelen, zoals liedjes of soundeffects.

Game Programmeren

Al deze onderdelen kunnen we met behulp van code vervolgens aansturen om een game te maken. In deze game moeten een aantal dingen gebeuren:

  1. Door middel van de druksensor kan de game aan en uit worden gezet.
  2. Er wordt een willekeurige noot op de piano gespeeld wanneer de game aan gaat.
  3. De speler kan aangeven welke noot deze denk te herkennen door op de corresponderende knop te drukken.
  4. Na het indrukken van een knop wordt gecheckt of de speler het goed had. Vervolgens wordt er een geluidseffect afgespeeld op de piano, en wordt er een
  5. De servo motor geeft aan hoeveel procent van de noten de speler goed heeft geraden. Na elke vraag wordt de motor bijgesteld. Bij het opnieuw opstarten wordt dit percentage gereset.

Hieronder staat de code voor het volledige programma, met comments die uitleggen waar elk stuk code voor zorgt.

/** Note Hearing Trainer by Marc Neeleman
Description:
This program uses a MIDI connector, pressure sensor, a servo motor and 8 buttons to create an interactive game, in which the player keeps trying recognize piano notes.
*/

#include <MIDI.h>   // Library used for using the piano
#include <Servo.h>  // Library used to control the servo motor

#define PressurePin A0
#define servoPin 3

// Piano Notes
#define C4 60   // C4 has the ID 60, C#4 is 61, D4 is 62 etc..
#define D4 62
#define E4 64
#define F4 65
#define G4 67
#define A4 69
#define B4 71
#define C5 72

// Box Buttons
#define ButtonC4 6
#define ButtonD4 7
#define ButtonE4 8
#define ButtonF4 9
#define ButtonG4 10
#define ButtonA4 11
#define ButtonB4 12
#define ButtonC5 13

Servo servo;

bool isOn;
int previousNote = 0;

// Score & #Questions
int currentQuestion = 1;
int correctAnswers = 0;
int incorrectAnswers = 0;
float correctRatio;       // Percentage of correct answers

MIDI_CREATE_DEFAULT_INSTANCE(); // Setup

// Setup and Loop //

void setup() {
  Serial.begin(9600);
  servo.attach(servoPin);
  pinMode(PressurePin, OUTPUT);
  MIDI.begin(MIDI_CHANNEL_OFF); // Setup
  randomSeed(analogRead(A5));   // Use output from unused analog pin as random seed, since this output is quite random itself.
  isOn = false;
}

void loop() {
  float pressure = analogRead(PressurePin);

  if (pressure > 6) {
    pressOnSwitch();
    delay(1000);
  }

  if (isOn) {
    checkButtonPress(); // Checks if the player is pressing one of the buttons 
  }
}

// Logic for starting the game //

// Turns the game on/off and starts the game if it is turned on
void pressOnSwitch() {  
  isOn = !isOn;
  if (isOn) {start();}
}

void start() {
  resetVariables();
  nextQuestion();
}

// Sets all variables to its default values
void resetVariables() {
  previousNote = 0;

  currentQuestion = 0;
  correctAnswers = 0;
  incorrectAnswers = 0;
  correctRatio = 1;
  moveServo();
}

// Game goes on to the next question
void nextQuestion() {
  currentQuestion++;
  playRandomNote(1000);
}

// Checks if the player is pressing one of 8 the buttons
void checkButtonPress() {
  if (digitalRead(ButtonC4)) onPlayerAnswer(C4);
  else if (digitalRead(ButtonD4)) onPlayerAnswer(D4);
  else if (digitalRead(ButtonE4)) onPlayerAnswer(E4);
  else if (digitalRead(ButtonF4)) onPlayerAnswer(F4);
  else if (digitalRead(ButtonG4)) onPlayerAnswer(G4);
  else if (digitalRead(ButtonA4)) onPlayerAnswer(A4);
  else if (digitalRead(ButtonB4)) onPlayerAnswer(B4);
  else if (digitalRead(ButtonC5)) onPlayerAnswer(C5);
}

// Player Answer Logic //

// Check if the player answered correctly and update the score
void onPlayerAnswer(int noteID) {
  if (noteID == previousNote) {
    onCorrectAnswer();
  } else {
    onIncorrectAnswer();
  }

  // Adjust Servo motor based on Score
  updateScore();
  nextQuestion();
}

void onCorrectAnswer() {
  correctAnswers++;
  playCorrectEffect();
}

void onIncorrectAnswer() {
  incorrectAnswers++;
  playIncorrectEffect();
}

// Servo Motor

void updateScore() {
  correctRatio = (float) correctAnswers/(float) currentQuestion;
  moveServo();
}

void moveServo() {
  int servoAngle = correctRatio * (float) 180;
  servo.write(servoAngle);
}

// Sound Effects //

void playCorrectEffect() {
  playNote(72, 125);
  playNote(79, 125);
  playNote(84, 1000);
}

void playIncorrectEffect() {
  playNote(48, 250);
  playNote(47, 250);
  playNote(46, 750);
}

// Plays a specific note
void playNote(int noteID, int noteLength) {
  MIDI.sendNoteOn(noteID, 60, 1);
  delay(noteLength);
  MIDI.sendNoteOff(noteID, 60, 1);
}

// Random Note Logic //

// Plays a random note from C4 to C5 on the piano
void playRandomNote(int noteLength) {
  int newNote = returnRandomNote();
  while (newNote == previousNote) {
    // Make sure the next note is different
    newNote = returnRandomNote();
  }

  // Turn new randomNumber note on
  MIDI.sendNoteOn(newNote, 60, 1);
  previousNote = newNote;

  // Delay and turn the note off
  delay(noteLength);
  MIDI.sendNoteOff(newNote, 60, 1);
}

// Returns a note from C4 to C5 randomly
int returnRandomNote() {
  float randomNumber = random(0, 8);

  if (randomNumber < 1) {
    return C4;
  }
  else if (randomNumber < 2) {
    return D4;
  }
  else if (randomNumber < 3) {
    return E4;
  }
  else if (randomNumber < 4) {
    return F4;
  }
  else if (randomNumber < 5) {
    return G4;
  }
  else if (randomNumber < 6) {
    return A4;
  }
  else if (randomNumber < 7) {
    return B4;
  }
  else {
    return C5;
  }
}


Na het aansluiten van de arduino aan een laptop en het uploaden van deze code zou de constructie zich moeten gedragen zoals in de introductievideo.

Solderen

IMG_20220803_124951010.jpg
IMG_20220806_170526560.jpg
IMG_20220806_170408797.jpg
IMG_20220803_125016725_BURST000_COVER_TOP.jpg

Vervolgens heb ik alle bedrading aan elkaar gesoldeerd. Ik heb hierbij gelet op de lengte van de draden en de gewenste positie van de prototyping board in de behuizing, zodat alle gebruikte draden zijn vastgesoldeerd. Alle knopjes zitten op een apart bordje, zodat ik hier makkelijk mee kon werken bij het maken van de behuizing. Ook de druksensor zit samen met de knopjes. De MIDI connector en de servo motor zijn aan een apart bordje gesoldeerd. Zo kan de MIDI kabel aan de achterkant of een van de zijkanten worden van de doos worden aangesloten.

Behuizing Maken

IMG_20220811_153824371.jpg
IMG_20220811_153816200.jpg
IMG_20220811_153832128.jpg
IMG_20220809_180523174.jpg
IMG_20220809_152852777.jpg
IMG_20220809_152921175.jpg
IMG_20220810_144003739.jpg
IMG_20220809_152949997.jpg

Tot slot heb ik de behuizing gemaakt. Ik ben begonnen met het maken van een kartonnen prototype, om te testen hoe mijn constructie in een doos zou passen (Zie foto 5+6). In de blokker had ik een theedoos gevonden die goed geschikt was voor deze installatie. Voordat ik begon met boren had ik een schets (Zie foto 4) gemaakt waarin ik de diameter en onderlinge afstanden van alle gaten had genoteerd. Daarna heb ik op de doos afgetekend waar alle gaten geboord moesten worden en begon ik met boren.

Ik begon met het boren van de gaten voor de knoppen, maar omdat ik meteen begon met een boortje van 10mm boorde ik behoorlijk scheef. Later kwam ik erachter dat ik beter eerst met een kleinere boor kon beginnen en vervolgens het rechte gat groter kon maken. Na het boren heb ik wat gaten geveild om ze netter te maken vanaf de buitenkant en om eventuele gaten groter te maken, zodat onderdelen hier makkelijker doorheen zouden passen.

Na het boren en veilen heb ik de borden met de drukknoppen stevig vastgeplakt met ducttape. De arduino, batterijhouder en het andere bord heb ik met dubbelzijdige tape aan de bodem van de doos geplakt. De servomotor bleef al stevig in het goede gat hangen, maar voor de zekerheid heb ik deze ook vastgetaped. Ook heb ik de MIDI connector stevig aan de wand van de doos getaped, zodat ik gemakkelijk de MIDI kabel hiermee kon verbinden. Test tijdens deze stap regelmatig of alles nog werkt!

Tot slot heb ik de doos met een stift versierd om duidelijk te maken wat elk onderdeel doet.

Reflectie & Conclusie

De doos is nu klaar voor gebruik! Sluit de batterijhouder aan de arduino aan en test of alles nog werkt. Je hebt nu je eigen Music Hearing Box.

Verbeterpunten Eindresultaat:

Als ik mijn persoonlijke eindresultaat nog zou aanpassen, zou ik de knopjes en drukknop de volgende keer op een langer prototyping board plaatsen in plaats van op twee verschillende borden, omdat dit betrouwbaarder zou zijn. Hierdoor kan ik dit bordje namelijk ook steviger aan de behuizing bevestigen. Ook zou ik bij het boren beginnen met kleinere boortjes, zodat de gaten rechter zijn. Ik zou de volgende keer ook betere knopjes gebruiken, zodat je deze gemakkelijker in de behuizing kan indrukken. Hierdoor zou de afwerking professioneler overkomen.

Leerpunten:

Ik heb door dit project een hoop nieuwe vaardigheden geleerd. Ten eerste weet ik bij het kopen van nieuwe onderdelen wat er voor nodig is om het te gebruiken en weet ik waar ik kan vinden hoe je het onderdeel kan gebruiken. Ik kan stroomcircuits samenstellen en vervolgens de arduino en code gebruiken om de aangesloten onderdelen aan te sturen. Zo weet ik dus hoe onderdelen onderling met elkaar samenwerken.

Bovendien heb ik voor het eerst gesoldeerd. Voor een oud idee van dit project had ik al een bordje gesoldeerd, en voor dit project heb ik vervolgens ook onderdelen op 3 aparte bordjes gesoldeerd. In het begin was ik erg langzaam en slordig, maar ik merkte bij de laatste keer solderen dat ik een stuk zorgvuldiger en sneller was. Ook dacht ik bij het solderen al na over hoe dit in de behuizing zou passen.

Ik zag het meest tegen de behuizing op, maar heb ik uiteindelijk toch een geschikte doos kunnen vinden en met een beetje hulp van mijn opa de juiste gaten geboord. Zo kon ik alle elektronica in de doos stoppen en mijn project netjes afwerken.

Maar mijn grootste leerpunt van dit project is hoe belangrijk het is om een plan af te werken voordat je het volledig gaat uitwerken. Ik ging namelijk te vroeg door op één idee en had hier al veel werk in gestopt, totdat ik erachter kwam dat ik dit idee niet kon uitvoeren. Hierdoor begon ik in de zomervakantie eigenlijk weer opnieuw met brainstormen. Dit keer heb ik echter eerst een aantal ideëen overwogen en uitgedacht, voordat ik overging naar het uitvoeren van het plan.

Ik vond het leuk om een keer met bedrading en fysieke componenten te werken voor de verandering en ik ben blij dat het mij uiteindelijk gelukt is om hier iets leuks mee te maken!