Inhoudsopgave:

Guitar Hero Arduino-project: 12 stappen (met afbeeldingen)
Guitar Hero Arduino-project: 12 stappen (met afbeeldingen)

Video: Guitar Hero Arduino-project: 12 stappen (met afbeeldingen)

Video: Guitar Hero Arduino-project: 12 stappen (met afbeeldingen)
Video: How Arduino is open-sourcing imagination | Massimo Banzi 2024, Juli-
Anonim
Guitar Hero Arduino-project
Guitar Hero Arduino-project
Guitar Hero Arduino-project
Guitar Hero Arduino-project
Guitar Hero Arduino-project
Guitar Hero Arduino-project

Wij zijn Maarten Vrebos, Justin Cavanas en Wannes Stroobandt en we studeren multimedia & communicatietechnologie. Audiovisual & IT Principles hebben wij een Guitar Hero-gitaar gehackt en gebruikt als behuizing voor onze MIDI-controller. Het was onze bedoeling om de bestaande knoppen op de intern te vervangen. Onze controller zal vastgehouden en bespeeld worden als een normale gitaar. Aangezien we iets hebben gehackt hebben we er niet veel extra materiaal in verwerken.

In de afbeelding kan u onze allereerste schets op papier zien van een foto van de gitaar die als behuizing zal worden gebruikt.

Wij hebben ons voor dit project gebaseerd op volgende bronnen:

slapyak.wordpress.com/guitar-hero-midi-con…

www.instructables.com/id/Converting-a-rescu…

gizmodo.com/391834/turn-your-guitar-hero-g…

Benodigdheden voor dit project

  • 6 kleine drukknoppen
  • 7 weerstanden van 1kohm
  • 1 gele LED 1
  • blauwe LED
  • 1 Arduino Uno R3
  • 1 groene LED
  • 2 rode LED's
  • 1 schuifschakelaar
  • 1 breadboard
  • 1 potentiometer
  • 1 protobord
  • 1 Guitar Hero gitaar
  • Voldoende bedrading
  • Materiaal om te solderen/dremelen/
  • Schroevendraaier

Stap 1: Componenten Verzamelen

Componenten Verzamelen
Componenten Verzamelen

Voor ons prototype (op breadboard) hebben we volgende componenten gebruikt:

6 drukknoppen

7 1kohm-weerstanden

1 gele LED

1 blauwe LED

1 Arduino Uno R3

1 groene LED

2 rode LED

1 Schuifschakelaar

1 Breadboard

1 Potentiometer

Stap 2: Prototype Bouwen

Prototype Bouwen
Prototype Bouwen
Prototype Bouwen
Prototype Bouwen
Prototype Bouwen
Prototype Bouwen

Om ons prototype te bouwen hebben we al onze componenten gebruikt op een breadboard, deze breadboard dient dan als testobject zodat we niet meteen in de behuizing moeten werken. Dit prototype hebben we ook gedigitaliseerd via tinkercad.com, op deze manier hadden we een duidelijk overzicht van ons prototype dat elk groepslid ook kon bewerken.

Er worden 5 kleine drukknoppen gebruikt die worden gebruikt als 5 snaren en een grote drukknop die in combinatie met één van meerdere 'snaren' moet worden gebruikt om een auditief effect te krijgen. De verschillende LED-lampjes dienen gewoon als visuele controle om er zeker van te zijn dat de interactie effectief werkt.

Stap 3: Codeprototype

Codeprototype
Codeprototype

Globale afmetingen

In het eerste deel van de code initialiseer je globale realiteit voor de pins van arduino waar alle drukknoppen mee verbonden zijn.

// zet pincodes waar mainButton(snaar) en andere buttons aan verbonden zijn:const int mainButton = A1; // gitaar snaar const int lightSensor = A0; const int knopPin1 = 2; // nummer van pushbutton1 const int buttonPin2 = 3; // nummer van pushbutton2const int buttonPin3 = 4; // nummer van pushbutton3const int buttonPin4 = 5; // nummer van pushbutton4const int buttonPin5 = 6; // nummer van drukknop5

Hierna worden er twee arrays ontwikkeld voor de namen van de pushbuttons en hun pinnummer.

const int aantalKnoppen = 5;const String namenKnoppen[aantalKnoppen] = {"knop 1", "knop 2", "knop 3", "knop 4", "knop 5"}; const int knopPinnen[aantalKnoppen] = {2, 3, 4, 5, 6};

En dan nog realistische voor de pinnen van de lichtjes.

const int ledPin1 = 13; // het nummer van de LED-pin 13

const int ledPin2 = 12; // het aantal LED-pins 12 const int ledPin3 = 11; // het aantal LED-pins 11 const int ledPin4 = 10; // het aantal LED-pins 10 const int ledPin5 = 9; // het aantal LED-pin 9 const int potPin = A5; // het aantal LED-pins A5

De laatste globale? voor dienen als 'states' (zijn de drukknoppen van niet potentiometer, lichtsensor).

// initialiseer buttonStates voor de knoppen (ingedrukt of niet)int mainButtonState = 0; int knopState1 = 0; int knopState2 = 0; int knopState3 = 0; int knopState4 = 0; int knopState5 = 0; int lightSensorState = 0; int potWaarde = 0; int lightValue = 0;

Opstelling

Nu volgt de void setup functie. Deze is van het type void (geeft waarde terug) en de instructies worden niet uitgevoerd maar 1 keer uitgevoerd.

Bij elke functie is commentaar geschreven wat er concreet gedaan wordt. Extra uitleg over wat een specifieke functie doet is te vinden in de arduino reference

void setup () { // datasnelheid per seconde (baud) voor seriele datatransmissie Serial.begin (9600); // Initialiseer de ledPin als output pinMode(ledPin1, OUTPUT); pinMode (ledPin2, UITGANG); pinMode (ledPin3, UITGANG); pinMode (ledPin4, UITGANG); pinMode (ledPin5, UITGANG); // initialiseer alle drukknoppen als invoer: pinMode(mainButton, INPUT); pinMode (knopPin1, INPUT); pinMode (knopPin2, INPUT); pinMode (knopPin3, INPUT); pinMode (knopPin4, INPUT); pinMode (knopPin5, INPUT); pinMode (potPin, INPUT); pinMode (lichtsensor, INGANG); }

Nietige functie

Na de setup functie, de instructies worden uitgevoerd uitgevoerd.

void loop() { // lees de staat van de pushbuttons uit (ingedrukt of niet) mainButtonState = digitalRead(mainButton); buttonState1 = digitalRead (buttonPin1); buttonState2 = digitalRead (buttonPin2); buttonState3 = digitalRead (buttonPin3); buttonState4 = digitalRead (buttonPin4); buttonState5 = digitalRead (buttonPin5);

// alle statussen van drukknoppen in een array

int buttonStates = {buttonState1, buttonState2, buttonState3, buttonState4, buttonState5};

// leest de waarde uit van de potentiometer en de lichtsensor

potValue = analoog lezen (potPin); lightValue = analoog lezen (lichtsensor);

// declareer een array mainStates en geef die de standaard waarden 0 in.

int mainStates = {0, 0, 0, 0, 0};

// loop over de array aantalKnoppen

for(int i = 0; i <aantalKnoppen; i++){ pinMode(knopPinnen, INPUT); // initialiseer alle knopPinnen als input digitalRead(knopPinnen); // lees de waarde van alle knoppinnen uit // indien de hoofdschakelaar (snaar) is, print alle knopnamen, alle knopstaten if(mainButtonState == HIGH){ Serial.print(namenKnoppen); Serieel.print(", "); Serial.println(buttonStates); } }

Stap 4: Prototype Uittesten

Nadat het prototype gebouwd is volgens ons model en de code geschreven is in Processing, is het tijd om het prototype uit te testen. Op de video is te zien dat alle knoppen een reactie geven op de bijhorende ledjes en dat ook combinaties van knoppen mogelijk zijn.

In de tweede video is te zien hoe onze tremolo werkt aan de hand van een potentiometer in de gitaar en hoe de waarden worden uitgelezen in Processing.

Stap 5: Behuizing "ontmantelen" En Kijken Welke Componenten Gebruikt Gaande Worden

Behuizing
Behuizing
Behuizing
Behuizing
Behuizing
Behuizing
Behuizing
Behuizing

Als de code correct werkte op het prototype zijn we begonnen met het "ontmantelen" van onze Guitar Hero-gitaar. We hebben de gitaar opengemaakt met een schroevendraaier en bekeken originele delen we onze nog gaan kunnen hergebruiken voor deze hebben we onze eigen drukknoppen in de bestaande knoppen hebben gekregen (zie volgende stap). We hebben de tremolo ook gebruikt voor ons ruwe en voor onze hoofdbutton hebben we ook de originele twee buttons gebruikt(zie vierde foto). De LEDjes zullen verdwijnen (deze waren enkel ter indicatie zodat we zagen dat alle knoppen correct werkten.

Stap 6: Werkende originele knoppen + Dremelen

Werking Originele Knoppen + Dremelen
Werking Originele Knoppen + Dremelen

Op de bijhorende video is de wijze te zien de twee originele knoppen werken als een soort van schakelaar die wij gebruiken om een effect te creëren bij combinatie van knoppen.

Om onze eigen knoppen te verwerken in de originele knoppen hebben we de binnenkant van de originelen er grotendeels uitgehaald zoals te zien is op de foto.

Stap 7: Bedrading Solderen + Knopen Vastlijmen

Bedrading Solderen + Knopen Vastlijmen
Bedrading Solderen + Knopen Vastlijmen
Bedrading Solderen + Knopen Vastlijmen
Bedrading Solderen + Knopen Vastlijmen
Bedrading Solderen + Knopen Vastlijmen
Bedrading Solderen + Knopen Vastlijmen

Omdat we niet meer met een breadboard werken moeten de draden gesoldeerd worden om zo de verschillende componenten met elkaar te verbinden. Nadat dit gebeurd is kunnen we de buttons vastlijmen zoals te zien is op de foto's. Eens dit is gebeurd kunnen we doorgaan naar de volgende stap.

Stap 8: Plaats Maken in De Behuizing

Plaats Maken in De Behuizing
Plaats Maken in De Behuizing
Plaats Maken in De Behuizing
Plaats Maken in De Behuizing
Plaats Maken in De Behuizing
Plaats Maken in De Behuizing

Omdat dit Guitar Hero-model redelijk krap was om mee te werken hebben we extra plaats moeten maken d.m.v. dremelen. Zo hebben we uit de achterkant van de gitaar een hele strook verwijderd zodat er meer plaats ontstaat voor de bedrading in de gitaar. Omdat er overal in de binnenkant obstakels waren, waaronder veel buisjes om de vijzen in te bevestigen, hebben we ook verwijderd om optimaal van de gegeven ruimte gebruik te kunnen maken. Op de vierde en vijfde foto is te zien dat we in de achterkant van de gitaar een doorgang hebben gecreëerd voor de draden die naar de gaan omdat de gitaar niet meer te sluiten was. En op de foto is te zien dat we de laatste draden die rechtstreeks verbonden zijn met de Arduino door een gat in de onderkant van de gitaar de behuizing verlaten.

Stap 9: Bedrading Aansluiten Op Protobord

Bedrading Aansluiten Op Protobord
Bedrading Aansluiten Op Protobord
Bedrading Aansluiten Op Protobord
Bedrading Aansluiten Op Protobord
Bedrading Aansluiten Op Protobord
Bedrading Aansluiten Op Protobord
Bedrading Aansluiten Op Protobord
Bedrading Aansluiten Op Protobord

Om alle componenten met elkaar te verbinden hebben we gebruik gemaakt van een protobord. Dit is een feitelijk op net dezelfde manier werkt als een breadbord, maar dan betrouwbaarder en uitgevoerd. We hebben de bedrading aan het bordje gesoldeerd zoals te zien is op de derde foto. Dit bord is het centrale punt van onze verbindingen en samenkomen(zie foto 2).

Stap 10: Verstevigen

Verstevigen
Verstevigen

Als finishing touch is het verstandig om de verliezen te verstevigen voor extra stabiliteit. Op deze foto is te zien hoe we het deel dat we hebben uitgehaald d.m.v. dremelen achteraan de knoppen verstevigen met stukjes karton.

Stap 11: Code Voor Het Communiceren Met Reaper

Code Voor Het Communiceren Met Reaper
Code Voor Het Communiceren Met Reaper
Code Voor Het Communiceren Met Reaper
Code Voor Het Communiceren Met Reaper
Code Voor Het Communiceren Met Reaper
Code Voor Het Communiceren Met Reaper
Code Voor Het Communiceren Met Reaper
Code Voor Het Communiceren Met Reaper

Deze code is opgedeeld in twee delen, het eerste deel is in de arduino IDE (interactive development environment) geschreven. Die code wordt verplaatst naar arduino zelf en dient om alle waarden van de sensoren van de midi controller uit te lezen en door te sturen.

De verwerking is het tweede deel. Deze code dient om alles wat arduino doorstuurt te ontvangen en door te sturen naar Reaper.

Arduino

/* Deze code is een basisschets om te communiceren met Processing via Serial.

Het is een blauwdruk waarin je je eigen code kunt zetten

gespecificeerd voor uw eigen knoppen, potentiometers of sensoren.

Het heeft een handdruk om ervoor te zorgen dat we contact hebben

en het formaat waarin we communiceren is bepaald

Het is belangrijk om het bericht op dezelfde manier op te bouwen, zodat Processing het weet te deconstrueren en correcte OSC-berichten naar onze DAW te sturen

gemaakt voor werkcollege AV&IT

okt 2017

*

/ baudrate

const lange baudrate = 115200;

// tijd om te wachten in ms tussen peilingen naar de pinnen

const int loopPauseTime = 200; // milliseconden

// begin- en eindwaarden voor het bericht verzonden op Serial

const String startString = "*", endString = "#";

const char contactCharacter = '|';

// pin-ID's

// andere globale variabelen

const int aantalKnoppen = 5; const String namenKnoppen[aantalKnoppen] = {"knop 1", "knop 2", "knop 3", "knop 4", "knop 5"}; const int knopPinnen[aantalKnoppen] = {2, 3, 4, 5, 6}; const int mainButton = A1;

int mainButtonState = 0;

int potWaarde = 0;

// analoge sensoren

const int potPin = A5; // pin voor tremolo

// Deze functie hebben we nodig om contact te maken met de Processing sketch

// Bewaar het hier void establishmentContact() { while (Serial.available() <= 0) { Serial.print(contactCharacter); // stuur een char en wacht op een reactie… delay(loopPauseTime); } Serieel.lezen(); }

ongeldige setup() {

// stel de pinModes in voor alle pinnen voor (int i = 0; i <aantalKnoppen; i++) {pinMode(knopPinnen, INPUT); } pinMode (hoofdknop, INPUT); // uncomment als je sensoren gebruikt die werken op 3V in plaats van 5V // je moet de 'ext' pin ook bedraden naar 3.3V // analogReference(EXTERNAL);

// initialiseer seriële communicatie

Serieel.begin(baudrate); terwijl (!Serial); // wacht op handdruk establishmentContact(); }

lege lus() {

// STAP 1: LEES KNOPPEN // ondervraag alle pinnen en wijs de meting toe aan het juiste bereik int buttonStates[aantalKnoppen]; /* buttonStates[0] = digitalRead(knopPinnen[0]); buttonStates[1] = digitalRead(knopPinnen[1]); buttonStates[2] = digitalRead(knopPinnen[2]); buttonStates[3] = digitalRead(knopPinnen[3]); buttonStates[4] = digitalRead(knopPinnen[4]); */ mainButtonState = digitalRead (mainButton); for(int i = 0; i < aantalKnoppen; i++){ buttonStates = digitalRead(knopPinnen); } potValue = analoog lezen (potPin); // voorbeelden: // float v0 = map (bpm, 0, 1023, 60, 250); // als je een genormaliseerde float wilt gebruiken (bijv. voor volume) // float v1 = map(analogRead(pin2), fromMin, fromMax, 0, 100) / 100.0;

// STAP 2: SCHRIJF BERICHT

Serial.print (startString); // start een berichtenreeks voor(int i = 0; i <aantalKnoppen; i++){ if(mainButtonState == HIGH){ Serial.print(namenKnoppen); Serieel.print(", "); Serial.print(buttonStates); if(i <aantalKnoppen - 1){ Serial.print(", "); } }else{ buttonStates = 0; Serial.print(namenKnoppen); Serieel.print(", "); Serial.print(buttonStates); if(i < aantalKnoppen - 1){ Serial.print(", "); } } } Serie.print(", "); Serial.print("tremolo"); Serieel.print(", "); Serial.print(map(potValue, 0, 1023, 0, 100)); // schrijf het einde van het bericht Serial.print (endString);

// even wachten..

vertraging (loopPauseTime); }

Verwerken

Disclaimer: Niet alle code van de processing sketch staat hier in geschreven, voor de volledige code zie het bestand: ProcessingSoundControl_handout_v6_1.pde in bijlage

De volgende instructies moeten worden aangepast (indien nodig):

// Baudrate moet hetzelfde zijn zoals in de arduino sketch

uiteindelijke int baudrate = 115200;

// Zoek naar het IP-adres in reaper (zie screenshots in bijlage)

// Processing stuurt naar dit andres en reaper luistert hier naar //

//final String remoteIP = "192.168.1.43"; // bijv. "127.0.0.1";

final String remoteIP = "10.3.209.60";

// Noteer de sendPort en vul deze in in Reaper.

// Dit is de poort waar Processing naartoe stuurt en waar Reaper naar luistert.

definitieve int listenPort = 12000, verzendpoort = 12000;

// De listenPort hier is om actief te debuggen.

// de portNames zijn hier ook om te debuggen.

//final String portName = "/dev/ttyACM0";

final String portName = "COM5"; // "/dev/ttyUSB0";

///////////////////// EINDE van GEBRUIKERSPARAMETERS ///////////////////////// ////

importverwerking.serienummer.*;

import java.util.*;

importeer oscP5.*;

import netP5.*;

OscP5 oscP5;

NetAddress myRemoteLocation;

Seriële communicatiepoort; // De seriële poort

boolean messageArrived = false;

Tekenreeks inkomend = "", IncomingOSCMessage = "";

laatste teken startChar = '*', endChar = '#'; final char contactCharacter = '|';

// Om er zeker van te zijn dat we alleen de parameters (waarden) verzenden die veranderen

// deze globale variabelen worden hier vermeld, maar mogen // hier niet worden geïnitialiseerd! HashMap oude Params, nieuwe Params, toSendParams;

// We moeten het bericht bij elke komma splitsen

void processIncoming () { String resVec = inkomende.split(", "); // we krijgen naam + waardeparen // dus voor elke naam (+2)… try{ for (int i = 0; i< resVec.length; i+=2) { float value = Float.parseFloat(resVec[i+ 1]); // plaats ze in de nieuwe hashtabel newParams.put(resVec, value); } } // als er een fout optreedt, laten we deze bekijken en afsluiten. catch(Uitzondering ex){ println("Uitzonderingsbericht: " + ex); printArray(resVec); Uitgang(); } }

// Om onze berichten te filteren

/* We zorgen ervoor dat er alleen een OSC-out bericht is wanneer * het invoerbericht (Serial) verandert * Dat wil zeggen: als we aan de knop draaien/drukken en het verandert van waarde. * Dus we filteren de binnenkomende waarden die daadwerkelijk veranderen * let op: we zullen springende waarden niet vermijden * zoals afkomstig zijn van bijvoorbeeld versnellingsmeters of afstandssensoren * je zult deze zelf moeten gladstrijken in Arduino */ void filterParams () { toSendParams = new Hash kaart(); for (String key: newParams.keySet()) { // als de sleutel al aanwezig is if (oldParams.containsKey(key)) { // key aanwezig en waarde niet hetzelfde, update dan if (!oldParams.get(key)).equals(newParams.get(key))) { toSendParams.put(key, newParams.get(key)); } } else{ // key is niet aanwezig in oude parameters, dus zet het maar! toSendParams.put(sleutel, newParams.get(sleutel)); } oldParams.put(key, newParams.get(key)); } }

ongeldig makeOSC() {

for (String key: toSendParams.keySet()) { OscMessage myMessage = new OscMessage("/"+ key); myMessage.add(toSendParams.get(key)); /* stuur het bericht */ oscP5.send(myMessage, myRemoteLocation); } }

void translateMessage() {

procesInkomend(); filterParams(); maakOSC(); } // Als we willen afdrukken naar het venster void ShowIncoming() { // om het inkomende bericht te zien, zoals ingesteld in de HashMap-tekst ("Incoming from Arduino", 20, 20); int y = 20; for (String key: newParams.keySet()) { y = y+20; tekst(toets, 20, y); text(newParams.get(key), 300, y); } }

void showOsc() {

tekst (Inkomend OSCM-bericht, 300, 200); InkomendOSCMessage =""; }

ongeldige setup() {

grootte (1000, 800); // Fasegrootte vullen (255); achtergrond(0); oldParams = nieuwe HashMap(); newParams = nieuwe HashMap(); //printArray(Serial.list()); commsPort = nieuw serieel (dit, poortnaam, baudrate);

/* start oscP5, luisteren naar inkomende berichten */

oscP5 = nieuwe OscP5 (dit, listenPort);

/* myRemoteLocation is een NetAddress. een NetAddress heeft 2 parameters, * een ip-adres en een poortnummer.myRemoteLocation wordt gebruikt als parameter in * oscP5.send() bij het verzenden van osc-pakketten naar een andere computer, apparaat, * toepassing. gebruik zie hieronder. voor testdoeleinden zijn de luisterpoort * en de poort van het externe locatieadres hetzelfde, vandaar dat u * berichten terugstuurt naar deze schets. */ myRemoteLocation = nieuw NetAddress(remoteIP, sendPort); }

nietig tekenen() {

if (messageArrived) { background(0); translateMessage(); ToonInkomend(); messageArrived= false; } showOsc(); }

void serialEvent (Seriële commsPort) {

// lees een byte van de seriële poort: char inChar = commsPort.readChar(); switch (inChar) { case contactCharacter: commsPort.write (contactCharacter); // vraag om meer println("beginnend…"); pauze; case startChar: inkomend= ""; pauze; case endChar: messageArrived = waar; //println ("einde bericht"); pauze; standaard: inkomend += inChar; pauze; } }

/* inkomende osc-berichten worden doorgestuurd naar de oscEvent-methode. */

void oscEvent (OscMessage theOscMessage) { float value = theOscMessage.get(0).floatValue(); // haal het 1e osc-argument op

Inkomend OSCM-bericht += "\n" +

String.format("### heeft een osc-bericht ontvangen: " + " addrpattern: " + theOscMessage.addrPattern() + ": %f", value); println (Inkomend OSCM-bericht); }

Stap 12: Controller Uittesten

Nu alles is aangesloten, alle code is geschreven en alles is dubbelcheckt is eindelijk de tijd om de controller z'n werk te laten doen. Zoek een paar leuke effecten op Reaper en geniet van de voltooide Guitar Hero MIDI Controller!

Aanbevolen: