Difference between revisions of "Group6"
Ilja.sofia (talk | contribs) |
H.Hottinga (talk | contribs) |
||
(15 intermediate revisions by 3 users not shown) | |||
Line 15: | Line 15: | ||
<span style='width:90%; font-size:12px; font-family:calibri'> | <span style='width:90%; font-size:12px; font-family:calibri'> | ||
<u>CONCEPT</u> | <u>CONCEPT</u> | ||
− | <br> | + | <br>Ontwerp een robot die in staat is een nummer (muziekstuk) te visualiseren. |
+ | <br>Gedurende het nummer doet de robot haar werk. Na afloop wordt het resultaat gepresenteerd aan de rest van de klas. | ||
+ | <br>Zij vormen de jury en zullen bepalen welke robot het beste resultaat heeft geleverd. | ||
+ | <br> | ||
+ | <span style='width:90%; font-size:12px; font-family:calibri'> | ||
+ | <br>- Formaat: A2 posterformaat (staand, witte achtergrond) | ||
+ | <br>- Methode: vrij, zolang de robot het werk doet | ||
+ | <br>(er mag dus geen directe handeling van mensen aan te pas komen, de robot moet het visuele werk tot stand brengen) | ||
Line 66: | Line 73: | ||
<br><u>Timo</u>: programmeren, arduino, technische uitleg | <br><u>Timo</u>: programmeren, arduino, technische uitleg | ||
<br><u>Hiske</u>: banden, manusje van alles, proces uitleg | <br><u>Hiske</u>: banden, manusje van alles, proces uitleg | ||
− | <br><u>Hans</u>: frame, concept, | + | <br><u>Hans</u>: frame, concept, concept uitleg |
− | <br><u>Ilja</u>: frame, concept, | + | <br><u>Ilja</u>: frame, concept, wiki documentatie |
<span style='width:90%; font-size:18px; font-family:calibri; color: 000; display:block; padding:20px; color:fff; background:#fff; border-bottom: solid; border-bottom-color: 000; border-width: 1px; text-transform: uppercase;'> | <span style='width:90%; font-size:18px; font-family:calibri; color: 000; display:block; padding:20px; color:fff; background:#fff; border-bottom: solid; border-bottom-color: 000; border-width: 1px; text-transform: uppercase;'> | ||
Line 73: | Line 80: | ||
<span style='width:90%; font-size:12px; font-family:calibri'> | <span style='width:90%; font-size:12px; font-family:calibri'> | ||
− | + | Om de robot verschillende muziekstijlen te kunnen laten visualiseren zijn we als eerste muziek gaan ontleden. In grote lijnen bestaat muziek uit; frequentie, ritme en volume. | |
+ | Het eerste concept was om de muziek op te delen in vier verschillende frequenties. Door deze vier lagen de input te laten zijn zou de output, ook opgedeeld in vier verschillende visuele uitingen, een indruk kunnen geven van de muziek. | ||
+ | Echter bleek dit na enig experiment zeer moeilijk haalbaar. | ||
+ | We zijn verder gegaan met het gegeven ritme. | ||
+ | Het vernieuwde concept is voort geborduurd op het vertalen van ritme naar beeld. Door het ritme met code te detecteren en om te zetten naar beweging van een servo ontstond de mogelijkheid om de robot op elk willekeurig ritme te laten werken. | ||
+ | We hebben ervoor gekozen om de servo druk uit te laten oefenen op een inktreservoir. De programmering vertaalde het ritme zo, dat bij iedere beat de inktreservoiren ingedrukt werden en dus inkt vrij lieten. Tijdens de presentatie bleken er echter nog wat kinderziektes in te zitten omdat we tijdens het proces geen tijd hebben overgehouden voor visuele tests. | ||
<span style='width:90%; font-size:18px; font-family:calibri; color: 000; display:block; padding:20px; color:fff; background:#fff; border-bottom: solid; border-bottom-color: 000; border-width: 1px; text-transform: uppercase;'> | <span style='width:90%; font-size:18px; font-family:calibri; color: 000; display:block; padding:20px; color:fff; background:#fff; border-bottom: solid; border-bottom-color: 000; border-width: 1px; text-transform: uppercase;'> | ||
Line 79: | Line 91: | ||
<span style='width:90%; font-size:12px; font-family:calibri'> | <span style='width:90%; font-size:12px; font-family:calibri'> | ||
− | + | Om op gang te komen zijn we eerst begonnen met het maken van een idee, wat wilden we nu eigenlijk maken? | |
+ | Eenmaal het concept bedacht kon het maken van een robot dan eindelijk beginnen. Gelukkig had Timo wel het een en ander verstand van robots, want persoonlijk wist ik mijn god niet hoe we moesten beginnen met het maken van een robot. | ||
+ | Na het concept zijn we aan de slag gegaan met de arduino waarna uiteindelijk te taken automatisch verdeeld werden. | ||
+ | Ikzelf had onder andere aan de ‘rupsbanden’ gewerkt. Dit idee leek makkelijker dan gedacht, er was namelijk een tandwiel met een aansluitende ketting voor nodig. Aangezien een fietsketting en tandwiel te zwaar waren moest ik naar een alternatief zoeken, wat later een elastiek werd waar een gelasercut tandwieltje in bleef hangen. | ||
+ | Ilja en Hans waren in de tussentijd aan het werk met het frame, wat ook geen makkelijk klusje was. | ||
+ | |||
[[File:ROBO3.JPG|400px]] | [[File:ROBO3.JPG|400px]] | ||
Line 92: | Line 109: | ||
[[File:ROBO11.JPG|400px]] | [[File:ROBO11.JPG|400px]] | ||
+ | |||
+ | [[File:Tanwieltjes.jpg|400px]] | ||
+ | |||
+ | [[File:Elastiek.jpg|400px]] | ||
[[File:ROBO12.JPG|400px]] | [[File:ROBO12.JPG|400px]] | ||
Line 115: | Line 136: | ||
<span style='width:90%; font-size:12px; font-family:calibri'> | <span style='width:90%; font-size:12px; font-family:calibri'> | ||
− | + | Zoals boven beschreven werkte te robot aan de hand van muziek analyse die de servo's deed bewegen om de inkt reservoirs in te drukken. De techniek daarachter bestaat uit twee delen, een computer die met Processing muziek analyseert, en een Arduino die de servo's aanstuurd. Deze twee delen communiceren met elkaar draadloos via een serieele bluetooth verbinding. | |
+ | <br> | ||
+ | De Arduino's in- en outputs zijn gelinkt aan een Bluesmirf bluetooth modem. Een computer kan via bluetooth verbinding maken met de Bluesmirf en via een serieele poort data heen en weer sturen die de Arduino aanstuurd. Deze serieele data word opgemaakt in Processing aan de hand van de muziek analyse en toegestuurd naar de Arduino die deze data vertaald in het aansturen van de servo's. | ||
+ | <br> | ||
+ | In Processing wordt met de Minim audio library het audiospectrum geanalyseerd. Van iedere frequentie van de muziek kan de waarde uitgelezen worden. Dit zijn 512 frequenties in ons geval, maar niet alle frequenties geven altijd een mooie waarde. Daarom word een gemiddelde berekend van een bepaald stuk van de frequenties, zoals de lage, midden of hoge tonen aan de hand van meerdere 'for' loops die van die delen een berekening maakt voor de servo's. Deze berekening zet de waardes van de analyse om naar een bereik van 20 tot 70 voor de servo. Deze uiteindelijke waarden worden per gedetecteerde beat van Minim doorgestuurd over de seriele poort naar de Arduino. Omdat we uiteindelijk maar twee servo's gebruiken worden alleen de lage en midden tonen berekend en doorgestuurd. Dit gaat in een regel van 3 bytes waarvan de tweede en derde byte ieder de waarde voor een servo bevatten. De eerste byte is een teken voor de Arduino dat er data is om uit te lezen. In de Arduino word de regel van bytes uitgelezen en de tweede en derde byte doorgeven aan servo 1 en servo 2. | ||
+ | <br><br> | ||
+ | Hieronder de code van Processing. Deze is gebasseerd op een van de voorbeelden van de Minim library. | ||
+ | <nowiki>//import Minim library | ||
+ | import ddf.minim.*; | ||
+ | |||
+ | //for displaying the sound's frequency | ||
+ | import ddf.minim.analysis.*; | ||
+ | |||
+ | //serial library | ||
+ | import processing.serial.*; | ||
+ | |||
+ | Minim minim; | ||
+ | BeatDetect beat; | ||
+ | BeatListener bl; | ||
+ | |||
+ | //to make it play song files | ||
+ | AudioPlayer song; | ||
+ | |||
+ | //for displaying the sound's frequency | ||
+ | FFT fft; | ||
+ | |||
+ | //declaring the serial port | ||
+ | Serial myPort; | ||
+ | |||
+ | //variables for calculating the servo values | ||
+ | int bass; | ||
+ | int bassAverage; | ||
+ | int bassMem; | ||
+ | int endBass; | ||
+ | |||
+ | int mid; | ||
+ | int midAverage; | ||
+ | int midMem; | ||
+ | int endMid; | ||
+ | |||
+ | //minimum and maximum values for the servo's | ||
+ | int min = 20; | ||
+ | int max = 70; | ||
+ | |||
+ | void setup() { | ||
+ | |||
+ | //sketch size | ||
+ | size(800, 600); | ||
+ | |||
+ | minim = new Minim(this); | ||
+ | println(Serial.list()); | ||
+ | |||
+ | //connect to the bluetooth modem | ||
+ | myPort = new Serial(this, "/dev/tty.Rambler-E87E-SPP", 9600); | ||
+ | |||
+ | //load the song | ||
+ | song = minim.loadFile("Voyager.mp3"); | ||
+ | song.play(); | ||
+ | |||
+ | fft = new FFT(song.bufferSize(), song.sampleRate()); | ||
+ | beat = new BeatDetect(song.bufferSize(), song.sampleRate()); | ||
+ | bl = new BeatListener(beat, song); | ||
+ | } | ||
+ | |||
+ | |||
+ | void draw() { | ||
+ | //draw the audio spectrum interface | ||
+ | background(#00E3FF); | ||
+ | |||
+ | fft.forward(song.mix); | ||
+ | |||
+ | //line characteristics | ||
+ | strokeWeight(1.3); | ||
+ | stroke(#FFF700); | ||
+ | |||
+ | //processing's transform tool | ||
+ | pushMatrix(); | ||
+ | translate(200, 0); | ||
+ | |||
+ | //draw the frequency spectrum as a series of vertical lines | ||
+ | //I multiple the value of getBand by 4 | ||
+ | //so that we can see the lines better | ||
+ | for (int i = 0; i < 512; i++) | ||
+ | { | ||
+ | line(i, height*4/5, i, height*4/5 - fft.getBand(i)*4); | ||
+ | } | ||
+ | |||
+ | //give the Arduino it's first byte | ||
+ | myPort.write(0); | ||
+ | |||
+ | //read the first 40 frequencies | ||
+ | for (int i = 0; i < 40; i++) | ||
+ | { | ||
+ | bassAverage += fft.getBand(i); | ||
+ | } | ||
+ | |||
+ | //create the average value | ||
+ | bass = (bassAverage / 10) *4; | ||
+ | bassAverage = 0; | ||
+ | |||
+ | //when a beat is detected, calculate the servo value | ||
+ | //and send it in the second byte | ||
+ | if ( beat.isSnare() ) { | ||
+ | bassMem = bass; | ||
+ | bassMem = constrain(bassMem, 0, 100); | ||
+ | endBass = Math.round(map(bassMem, 0, 200, min, max)); | ||
+ | myPort.write(endBass); | ||
+ | } else { | ||
+ | //if there is no beat, let the servo return to its minimum | ||
+ | if (bassMem > 1) bassMem -= 5; | ||
+ | bassMem = constrain(bassMem, 0, 100); | ||
+ | endBass = Math.round(map(bassMem, 0, 200, min, max)); | ||
+ | myPort.write(endBass); | ||
+ | } | ||
+ | |||
+ | //debug line | ||
+ | println("bass " + endBass); | ||
+ | |||
+ | //do the same as above, but for frequncies 150 to 190 | ||
+ | for (int i = 0; i < 40; i++) | ||
+ | { | ||
+ | midAverage += fft.getBand(i+150); | ||
+ | } | ||
+ | |||
+ | mid = (midAverage / 10) *20; | ||
+ | midAverage = 0; | ||
+ | if ( beat.isSnare() ) { | ||
+ | midMem = mid; | ||
+ | midMem = constrain(midMem, 0,100); | ||
+ | endMid = Math.round(map(midMem, 0, 200, min, max)); | ||
+ | myPort.write(endMid); | ||
+ | } else { | ||
+ | if (midMem > 1) midMem -= 5; | ||
+ | midMem = constrain(midMem, 0, 100); | ||
+ | endMid = Math.round(map(midMem, 0, 200, min, max)); | ||
+ | myPort.write(endMid); | ||
+ | } | ||
+ | //debug line | ||
+ | println("mid " + endMid); | ||
+ | |||
+ | //closing the transform tool | ||
+ | popMatrix(); | ||
+ | |||
+ | //changing the line color | ||
+ | stroke(#FF0000); | ||
+ | |||
+ | //tell the Arduino the end of the given line of bytes | ||
+ | myPort.write('\n'); | ||
+ | |||
+ | |||
+ | //draw the audio interface | ||
+ | //the waveform is drawn by connecting neighbor values with a line. | ||
+ | //The values in the buffers are between -1 and 1. | ||
+ | //If we don't scale them up our waveform will look like a straight line. | ||
+ | //Thus each of the values is multiplied by 50 | ||
+ | for (int i = 200; i < song.left.size () - 1; i++) | ||
+ | { | ||
+ | line(i, 50 + song.left.get(i)*50, i+1, 50 + song.left.get(i+1)*50); | ||
+ | line(i, 150 + song.right.get(i)*50, i+1, 150 + song.right.get(i+1)*50); | ||
+ | line(i, 250 + song.mix.get(i)*50, i+1, 250 + song.mix.get(i+1)*50); | ||
+ | } | ||
+ | |||
+ | //blue rectangle on the left | ||
+ | noStroke(); | ||
+ | fill(#0024FF); | ||
+ | rect(0, 0, 200, height); | ||
+ | |||
+ | //text | ||
+ | textSize(24); | ||
+ | fill(255); | ||
+ | text("left amplitude", 0, 50); | ||
+ | text("right amplitude", 0, 150); | ||
+ | text("mixed amplitude", 0, 250); | ||
+ | text("frequency", 0, height*4/5); | ||
+ | } | ||
+ | |||
+ | void stop() | ||
+ | { | ||
+ | //close the AudioPlayer you got from Minim.loadFile() | ||
+ | song.close(); | ||
+ | |||
+ | minim.stop(); | ||
+ | |||
+ | //close the serial port | ||
+ | myPort.stop(); | ||
+ | |||
+ | //this calls the stop method that | ||
+ | //you are overriding by defining your own | ||
+ | //it must be called so that your application | ||
+ | //can do all the cleanup it would normally do | ||
+ | super.stop(); | ||
+ | } | ||
+ | --------------------------------------------------------------------- | ||
+ | //The BeatListener Class | ||
+ | |||
+ | class BeatListener implements AudioListener | ||
+ | { | ||
+ | private BeatDetect beat; | ||
+ | private AudioPlayer source; | ||
+ | |||
+ | BeatListener(BeatDetect beat, AudioPlayer source) | ||
+ | { | ||
+ | this.source = source; | ||
+ | this.source.addListener(this); | ||
+ | this.beat = beat; | ||
+ | } | ||
+ | |||
+ | void samples(float[] samps) | ||
+ | { | ||
+ | beat.detect(source.mix); | ||
+ | } | ||
+ | |||
+ | void samples(float[] sampsL, float[] sampsR) | ||
+ | { | ||
+ | beat.detect(source.mix); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </nowiki> | ||
+ | De Arduino code voor het binnenhalen van data en het aansturen van de servo's. | ||
+ | <nowiki>//The servo library | ||
+ | #include <Servo.h> | ||
+ | |||
+ | Servo myservo1; // create servo object to control a servo | ||
+ | Servo myservo2; | ||
+ | |||
+ | byte byteRead; | ||
+ | byte bass; | ||
+ | |||
+ | char incomingByte; | ||
+ | |||
+ | void setup() { | ||
+ | // Turn the Serial Protocol ON | ||
+ | Serial.begin(9600); | ||
+ | myservo1.attach(9); // attaches the servo on pin 9 to the servo object | ||
+ | myservo2.attach(10); // attaches the servo on pin 10 to the servo object | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | /* check if data has been sent from the computer: */ | ||
+ | if (Serial.available() > 0) { // something came across serial | ||
+ | char buffer[] = {' ',' ',' ',' '}; // Receive up to 4 bytes | ||
+ | while (!Serial.available()); // Wait for characters | ||
+ | Serial.readBytesUntil('\n', buffer, 4); // Stop when the end of the line of bytes is reached | ||
+ | |||
+ | myservo1.write((buffer[1])); // take the second byte and give it to the servo | ||
+ | myservo2.write((buffer[2])); // take the third byte and give it to the servo | ||
+ | delay(0.1); | ||
+ | } | ||
+ | } | ||
+ | </nowiki> | ||
+ | [[File:RobotBoard.jpg | 500px]] | ||
+ | |||
+ | <span style='width:90%; font-size:18px; font-family:calibri; color: 000; display:block; padding:20px; color:fff; background:#fff; border-bottom: solid; border-bottom-color: 000; border-width: 1px; text-transform: uppercase;'> | ||
+ | r e f l e c t i e.</span> | ||
+ | |||
+ | <span style='width:90%; font-size:12px; font-family:calibri'> | ||
+ | Betere en helderdere vertaling van ritme naar beeld. | ||
+ | Het besturingssysteem van de robot ook een output laten zijn in plaats van handmatige besturing. | ||
+ | |||
+ | <span style='width:90%; font-size:12px; font-family:calibri'> | ||
+ | <u>Hans</u> | ||
+ | <br>Voor mij was het de eerste keer om met dergelijke technieken te werken tijdens het proces. De manier van werken, namelijk stap voor stap, hebben we daardoor over het hoofd gezien. Achteraf wilde wij eigenlijk bij stap 10 beginnen, wat met ons gebrek aan ervaring natuurlijk onmogelijk is. Overigens is het enthousiasme ons wel ten goede gekomen. Want door groot te denken verbreed je tenslotte je opties. | ||
+ | De rolverdeling en de samenwerking was binnen het team uitstekend. Ieder had zijn eigen taak (zie rolverdeling) en daarnaast hadden we voldoende bijeenkomsten om te bespreken waar iedereen mee bezig was. De visie over ‘wat willen we nou met de robot’ lag ook vrijwel op een lijn waardoor er snel en makkelijk stappen werden gemaakt in het proces. | ||
+ | Over de planning gedurende het project, tja dat is in iedere reflectie hetzelfde, ruimte voor verbetering! | ||
+ | |||
+ | <span style='width:90%; font-size:12px; font-family:calibri'> | ||
+ | <u>Timo</u> | ||
+ | <br>Met het kleine beetje ervaring wat ik had met Arduino hiervoor was het interessant dit complexere systeem te maken. De grootste mijlpaal was eigenlijk om de data goed om te zetten en deze draadloos te sturen naar de Arduino. Deze is zeker gehaald, maar meer tijd zou nodig zijn om data te perfectioneren en ook te kunnen gebruiken om de wielen van de robot mee aan te sturen. Gedurende het proces heb ik veel kunnen leren over data structuren, het verzenden en ontvangen daarvan en hoe digitale waardes om te zetten naar beweging. | ||
+ | <br>Zoals Hans al toelicht hierboven was de samenwerking in de groep uitstekend en vervulde ieder zijn taak zoals gewenst. De robot was een bijzonder experiment waar veel uit te halen viel en ieder zijn kwaliteit in naar voren kwam. | ||
+ | |||
+ | <span style='width:90%; font-size:12px; font-family:calibri'> | ||
+ | <u>Ilja</u> | ||
+ | <br>We begonnen als groep erg enthousiast en waren het gelijk met elkaar eens dat het een creërende robot zou worden. Zoals Hans al zei, zorgde dit meteen dat we bij stap 10 wilden beginnen. Toen werd ons uitgelegd dat je zoiets in kleine stappen opbouwt. Dit klinkt zo logisch maar was voor mij echt een goede les, het geeft een stuk meer geruststelling en helpt je verder te komen. De planning verliep prima, we zijn vaak bij elkaar gekomen maar natuurlijk de laatste paar dagen verkeerd ingecalculeerd waardoor we pas tijdens de presentatie het volledige project werkend zagen. Dat verliep niet geheel zoals we wilden maar ik vond het heel erg tof wat we als groep bereikt hebben! |
Latest revision as of 06:49, 29 October 2014
R O B O T .
GROEP
Timo van Dijk
Hans Schuttenbeld
Hiske Hottinga
Ilja van Vlaardingen
CONCEPT
Ontwerp een robot die in staat is een nummer (muziekstuk) te visualiseren.
Gedurende het nummer doet de robot haar werk. Na afloop wordt het resultaat gepresenteerd aan de rest van de klas.
Zij vormen de jury en zullen bepalen welke robot het beste resultaat heeft geleverd.
- Formaat: A2 posterformaat (staand, witte achtergrond)
- Methode: vrij, zolang de robot het werk doet
(er mag dus geen directe handeling van mensen aan te pas komen, de robot moet het visuele werk tot stand brengen)
BATTLE
Thuan Tran
Shushanik Moutafian
Bonny van der Sande
Meleny Spits
i n s p i r a t i e .
ZZZ - RUNNING WITH THE BEAST
MYTHBUSTERS PAINT THE MONA LISA
TEKENROBOTS
r o l l e n .
Timo: programmeren, arduino, technische uitleg
Hiske: banden, manusje van alles, proces uitleg
Hans: frame, concept, concept uitleg
Ilja: frame, concept, wiki documentatie
c o n c e p t .
Om de robot verschillende muziekstijlen te kunnen laten visualiseren zijn we als eerste muziek gaan ontleden. In grote lijnen bestaat muziek uit; frequentie, ritme en volume. Het eerste concept was om de muziek op te delen in vier verschillende frequenties. Door deze vier lagen de input te laten zijn zou de output, ook opgedeeld in vier verschillende visuele uitingen, een indruk kunnen geven van de muziek. Echter bleek dit na enig experiment zeer moeilijk haalbaar. We zijn verder gegaan met het gegeven ritme. Het vernieuwde concept is voort geborduurd op het vertalen van ritme naar beeld. Door het ritme met code te detecteren en om te zetten naar beweging van een servo ontstond de mogelijkheid om de robot op elk willekeurig ritme te laten werken. We hebben ervoor gekozen om de servo druk uit te laten oefenen op een inktreservoir. De programmering vertaalde het ritme zo, dat bij iedere beat de inktreservoiren ingedrukt werden en dus inkt vrij lieten. Tijdens de presentatie bleken er echter nog wat kinderziektes in te zitten omdat we tijdens het proces geen tijd hebben overgehouden voor visuele tests.
p r o c e s .
Om op gang te komen zijn we eerst begonnen met het maken van een idee, wat wilden we nu eigenlijk maken? Eenmaal het concept bedacht kon het maken van een robot dan eindelijk beginnen. Gelukkig had Timo wel het een en ander verstand van robots, want persoonlijk wist ik mijn god niet hoe we moesten beginnen met het maken van een robot. Na het concept zijn we aan de slag gegaan met de arduino waarna uiteindelijk te taken automatisch verdeeld werden. Ikzelf had onder andere aan de ‘rupsbanden’ gewerkt. Dit idee leek makkelijker dan gedacht, er was namelijk een tandwiel met een aansluitende ketting voor nodig. Aangezien een fietsketting en tandwiel te zwaar waren moest ik naar een alternatief zoeken, wat later een elastiek werd waar een gelasercut tandwieltje in bleef hangen. Ilja en Hans waren in de tussentijd aan het werk met het frame, wat ook geen makkelijk klusje was.
t e c h n i e k .
Zoals boven beschreven werkte te robot aan de hand van muziek analyse die de servo's deed bewegen om de inkt reservoirs in te drukken. De techniek daarachter bestaat uit twee delen, een computer die met Processing muziek analyseert, en een Arduino die de servo's aanstuurd. Deze twee delen communiceren met elkaar draadloos via een serieele bluetooth verbinding.
De Arduino's in- en outputs zijn gelinkt aan een Bluesmirf bluetooth modem. Een computer kan via bluetooth verbinding maken met de Bluesmirf en via een serieele poort data heen en weer sturen die de Arduino aanstuurd. Deze serieele data word opgemaakt in Processing aan de hand van de muziek analyse en toegestuurd naar de Arduino die deze data vertaald in het aansturen van de servo's.
In Processing wordt met de Minim audio library het audiospectrum geanalyseerd. Van iedere frequentie van de muziek kan de waarde uitgelezen worden. Dit zijn 512 frequenties in ons geval, maar niet alle frequenties geven altijd een mooie waarde. Daarom word een gemiddelde berekend van een bepaald stuk van de frequenties, zoals de lage, midden of hoge tonen aan de hand van meerdere 'for' loops die van die delen een berekening maakt voor de servo's. Deze berekening zet de waardes van de analyse om naar een bereik van 20 tot 70 voor de servo. Deze uiteindelijke waarden worden per gedetecteerde beat van Minim doorgestuurd over de seriele poort naar de Arduino. Omdat we uiteindelijk maar twee servo's gebruiken worden alleen de lage en midden tonen berekend en doorgestuurd. Dit gaat in een regel van 3 bytes waarvan de tweede en derde byte ieder de waarde voor een servo bevatten. De eerste byte is een teken voor de Arduino dat er data is om uit te lezen. In de Arduino word de regel van bytes uitgelezen en de tweede en derde byte doorgeven aan servo 1 en servo 2.
Hieronder de code van Processing. Deze is gebasseerd op een van de voorbeelden van de Minim library.
//import Minim library import ddf.minim.*; //for displaying the sound's frequency import ddf.minim.analysis.*; //serial library import processing.serial.*; Minim minim; BeatDetect beat; BeatListener bl; //to make it play song files AudioPlayer song; //for displaying the sound's frequency FFT fft; //declaring the serial port Serial myPort; //variables for calculating the servo values int bass; int bassAverage; int bassMem; int endBass; int mid; int midAverage; int midMem; int endMid; //minimum and maximum values for the servo's int min = 20; int max = 70; void setup() { //sketch size size(800, 600); minim = new Minim(this); println(Serial.list()); //connect to the bluetooth modem myPort = new Serial(this, "/dev/tty.Rambler-E87E-SPP", 9600); //load the song song = minim.loadFile("Voyager.mp3"); song.play(); fft = new FFT(song.bufferSize(), song.sampleRate()); beat = new BeatDetect(song.bufferSize(), song.sampleRate()); bl = new BeatListener(beat, song); } void draw() { //draw the audio spectrum interface background(#00E3FF); fft.forward(song.mix); //line characteristics strokeWeight(1.3); stroke(#FFF700); //processing's transform tool pushMatrix(); translate(200, 0); //draw the frequency spectrum as a series of vertical lines //I multiple the value of getBand by 4 //so that we can see the lines better for (int i = 0; i < 512; i++) { line(i, height*4/5, i, height*4/5 - fft.getBand(i)*4); } //give the Arduino it's first byte myPort.write(0); //read the first 40 frequencies for (int i = 0; i < 40; i++) { bassAverage += fft.getBand(i); } //create the average value bass = (bassAverage / 10) *4; bassAverage = 0; //when a beat is detected, calculate the servo value //and send it in the second byte if ( beat.isSnare() ) { bassMem = bass; bassMem = constrain(bassMem, 0, 100); endBass = Math.round(map(bassMem, 0, 200, min, max)); myPort.write(endBass); } else { //if there is no beat, let the servo return to its minimum if (bassMem > 1) bassMem -= 5; bassMem = constrain(bassMem, 0, 100); endBass = Math.round(map(bassMem, 0, 200, min, max)); myPort.write(endBass); } //debug line println("bass " + endBass); //do the same as above, but for frequncies 150 to 190 for (int i = 0; i < 40; i++) { midAverage += fft.getBand(i+150); } mid = (midAverage / 10) *20; midAverage = 0; if ( beat.isSnare() ) { midMem = mid; midMem = constrain(midMem, 0,100); endMid = Math.round(map(midMem, 0, 200, min, max)); myPort.write(endMid); } else { if (midMem > 1) midMem -= 5; midMem = constrain(midMem, 0, 100); endMid = Math.round(map(midMem, 0, 200, min, max)); myPort.write(endMid); } //debug line println("mid " + endMid); //closing the transform tool popMatrix(); //changing the line color stroke(#FF0000); //tell the Arduino the end of the given line of bytes myPort.write('\n'); //draw the audio interface //the waveform is drawn by connecting neighbor values with a line. //The values in the buffers are between -1 and 1. //If we don't scale them up our waveform will look like a straight line. //Thus each of the values is multiplied by 50 for (int i = 200; i < song.left.size () - 1; i++) { line(i, 50 + song.left.get(i)*50, i+1, 50 + song.left.get(i+1)*50); line(i, 150 + song.right.get(i)*50, i+1, 150 + song.right.get(i+1)*50); line(i, 250 + song.mix.get(i)*50, i+1, 250 + song.mix.get(i+1)*50); } //blue rectangle on the left noStroke(); fill(#0024FF); rect(0, 0, 200, height); //text textSize(24); fill(255); text("left amplitude", 0, 50); text("right amplitude", 0, 150); text("mixed amplitude", 0, 250); text("frequency", 0, height*4/5); } void stop() { //close the AudioPlayer you got from Minim.loadFile() song.close(); minim.stop(); //close the serial port myPort.stop(); //this calls the stop method that //you are overriding by defining your own //it must be called so that your application //can do all the cleanup it would normally do super.stop(); } --------------------------------------------------------------------- //The BeatListener Class class BeatListener implements AudioListener { private BeatDetect beat; private AudioPlayer source; BeatListener(BeatDetect beat, AudioPlayer source) { this.source = source; this.source.addListener(this); this.beat = beat; } void samples(float[] samps) { beat.detect(source.mix); } void samples(float[] sampsL, float[] sampsR) { beat.detect(source.mix); } }
De Arduino code voor het binnenhalen van data en het aansturen van de servo's.
//The servo library #include <Servo.h> Servo myservo1; // create servo object to control a servo Servo myservo2; byte byteRead; byte bass; char incomingByte; void setup() { // Turn the Serial Protocol ON Serial.begin(9600); myservo1.attach(9); // attaches the servo on pin 9 to the servo object myservo2.attach(10); // attaches the servo on pin 10 to the servo object } void loop() { /* check if data has been sent from the computer: */ if (Serial.available() > 0) { // something came across serial char buffer[] = {' ',' ',' ',' '}; // Receive up to 4 bytes while (!Serial.available()); // Wait for characters Serial.readBytesUntil('\n', buffer, 4); // Stop when the end of the line of bytes is reached myservo1.write((buffer[1])); // take the second byte and give it to the servo myservo2.write((buffer[2])); // take the third byte and give it to the servo delay(0.1); } }
r e f l e c t i e.
Betere en helderdere vertaling van ritme naar beeld. Het besturingssysteem van de robot ook een output laten zijn in plaats van handmatige besturing.
Hans
Voor mij was het de eerste keer om met dergelijke technieken te werken tijdens het proces. De manier van werken, namelijk stap voor stap, hebben we daardoor over het hoofd gezien. Achteraf wilde wij eigenlijk bij stap 10 beginnen, wat met ons gebrek aan ervaring natuurlijk onmogelijk is. Overigens is het enthousiasme ons wel ten goede gekomen. Want door groot te denken verbreed je tenslotte je opties.
De rolverdeling en de samenwerking was binnen het team uitstekend. Ieder had zijn eigen taak (zie rolverdeling) en daarnaast hadden we voldoende bijeenkomsten om te bespreken waar iedereen mee bezig was. De visie over ‘wat willen we nou met de robot’ lag ook vrijwel op een lijn waardoor er snel en makkelijk stappen werden gemaakt in het proces.
Over de planning gedurende het project, tja dat is in iedere reflectie hetzelfde, ruimte voor verbetering!
Timo
Met het kleine beetje ervaring wat ik had met Arduino hiervoor was het interessant dit complexere systeem te maken. De grootste mijlpaal was eigenlijk om de data goed om te zetten en deze draadloos te sturen naar de Arduino. Deze is zeker gehaald, maar meer tijd zou nodig zijn om data te perfectioneren en ook te kunnen gebruiken om de wielen van de robot mee aan te sturen. Gedurende het proces heb ik veel kunnen leren over data structuren, het verzenden en ontvangen daarvan en hoe digitale waardes om te zetten naar beweging.
Zoals Hans al toelicht hierboven was de samenwerking in de groep uitstekend en vervulde ieder zijn taak zoals gewenst. De robot was een bijzonder experiment waar veel uit te halen viel en ieder zijn kwaliteit in naar voren kwam.
Ilja
We begonnen als groep erg enthousiast en waren het gelijk met elkaar eens dat het een creërende robot zou worden. Zoals Hans al zei, zorgde dit meteen dat we bij stap 10 wilden beginnen. Toen werd ons uitgelegd dat je zoiets in kleine stappen opbouwt. Dit klinkt zo logisch maar was voor mij echt een goede les, het geeft een stuk meer geruststelling en helpt je verder te komen. De planning verliep prima, we zijn vaak bij elkaar gekomen maar natuurlijk de laatste paar dagen verkeerd ingecalculeerd waardoor we pas tijdens de presentatie het volledige project werkend zagen. Dat verliep niet geheel zoals we wilden maar ik vond het heel erg tof wat we als groep bereikt hebben!