Mijn zoon is een grote fan van The Simpsons (en ik denk dat, zo ben ik). Ik heb dit als een cadeau voor hem voor kerst.
Wat we hier hebben is een Simpson's lunchbox, die, wanneer de rode schakelaar wordt ingedrukt, zal in willekeurige volgorde afspelen een van 413 wav-bestanden die zijn opgeslagen op de SD-kaart die wordt gebruikt door de Adafruit waveshield.
Een video van het in gebruik volgt.
De gebruikte materialen zijn:
-Arduino UNO
-Adafruit Wave Shield Kit v1.1
-2GB SD kaart
-Simpsons Lunchbox - van Amazon.com
-2 9 volt batterijen en 2 houders - radio shack
-3 LEDs
-een 8 ohm speaker
-een DPDT schakelaar
-een paar condensatoren, weerstanden en een LM386 chip voor een kleine versterker als het geluid uit de wave shield is niet luid genoeg voor de spreker.
-sommige draden
Ik gebruikte ook een SD-kaartlezer en een programma genaamd Switch-it om de wav-bestanden decomprimeren.
Stappen:
1. kocht een Arduino Uno - vele bronnen hiervoor - ongeveer $25,00
2. kocht een Adafruit Waveshield Kit - ongeveer 22.00 uur.
Dit moet worden gemonteerd en de instructies zijn hier:
http://www.ladyada.net/make/waveshield/make.html
(Dit zijn makkelijk te volgen instructies met veel goede foto's)
3. kocht een 2gb SD-kaart worden gebruikt in het schild van de Golf
4. heeft een internet zoeken naar: "Simpsons wav" en vond een paar sites die vrij een goede verzameling van wav bestand fragmenten uit de Simpsons hadden. Ik was in staat (met hulp van mijn zoon) meer dan 400 bestanden downloaden en opslaan op de SD-kaart.
-Merk op de wave shield niet houdt gecomprimeerde bestanden zodat sommige van de bestanden die nodig zijn om te worden gedecomprimeerd die ik deed met behulp van een freeware software genaamd "Switch-it".
5. aangezien het geluid van de wave shield OK voor hoofdtelefoon is, maar niet luid genoeg voor de spreker was, heb ik de output van de wave shield gestuurd om een kleine LM386 versterker die ik gebouwd met behulp van de volgende instructies.
http://www.rason.org/projects/icamps/icamps.htm
6. Toegevoegde LED's aan dat de macht is op (kant switch) en om aan te geven wanneer het is ok om een nieuw bestand te vragen.
(Opmerking: Ik heb toegevoegd een functie die wanneer men de rode schakelaar drukt wanneer de groene LED knippert, alle wave-bestanden zullen worden afgespeeld)
7. enkele andere opmerkingen:
-in principe de code wacht tot de rode schakelaar ingedrukt worden.
het genereert dan een randow nummer tussen 1 en 413 (het aantal wave-bestanden). Dan worden gelezen via de wave-bestanden en een teller verhoogd totdat de willekeurig getal is bereikt. Het speelt vervolgens dat bestand. Dit betekent dat het aantal bestanden is hard gecodeerd in de code. Waarschijnlijk is er een manier dat het cijfer van de code uit hoeveel bestanden er zijn.
-Soms faalt het een bestand ik denk omdat het ook niet graag stereo bestanden af te spelen.
8. de code:
-gekopieerd uit verschillende bronnen en zo in de code vermeld. In het bijzonder begonnen ben ik met code die op de site van Adafruit en zo nodig bewerkt.
/*
idee is om te spelen een willekeurige wav-bestand telkens wanneer die de knop pers is
v2 nu probeert toe te voegen knop en andere code
v2 werkt goed
V3 - toevoegen van de mogelijkheid om te spelen alle nummers door de knop ingedrukt tijdens het knipperen
*/
#include
#include
Kaart van de SdReader; Dit object bevat de gegevens voor de kaart
FatVolume vol; Dit houdt de informatie voor de partitie op de kaart
FatReader wortel; Dit bevat de informatie voor de hoofdmap van volume
WaveHC Golf; Dit is de enige Golf (audio) object, omdat we zullen slechts één filter tegelijk spelen
uint8_t dirLevel; inspringing van niveau voor bestand/map namen (voor prettyprinting)
dir_t dirBuf; buffer voor de map leest
#define DEBOUNCE 5 / / button debouncer
Const int buttonPin = 8; het nummer van de drukknop pin
int buttonState = 0; variabele voor het lezen van de drukknop status
voor rsndom spelen
lange randNumber;
lange ct = 0;
nodig voor het afspelen van alle
int playAll = 0;
int numPress = 0; variabele voor het lezen van de drukknop status
int xx = 0;
lange firstTime = 1;
moet dit gelijk aan numberr van wav-bestanden op sd-kaart wijzigen
lange numWavs = 413;
Const int ledPin = 7; het nummer van de LED-pin
Variabelen zal veranderen:
int ledState = hoog; ledState gebruikt voor het instellen van de LED
/*
* Het definiëren van macro om foutberichten in het flash-geheugen
*/
#define error(msg) error_P(PSTR(msg))
Functioneren van de definities (we definiëren hen hier, maar de code is hieronder)
leegte spelen (FatReader & dir);
deze handige functie geeft het aantal bytes in het RAM, momenteel gratis groot voor debugging!
int freeRam(void)
{
extern int __bss_end;
extern int * __brkval;
int free_memory;
Als (__brkval (int) == 0) {}
FREE_MEMORY = ((int) & free_memory)-((int) & __bss_end);
}
else {}
FREE_MEMORY = ((int) & free_memory)-((int) __brkval);
}
Return free_memory;
}
//////////////////////////////////// SETUP
VOID Setup {}
Serial.begin(9600); Seriële bibliotheek 9600 bps voor foutopsporing instellen
Als u analoge input pincode 0 niet opvolgende middellage, willekeurige analoog
lawaai zal leiden tot de aanroep van randomSeed() te genereren
verschillende zaad nummers elke keer de schets wordt uitgevoerd.
randomSeed() zal dan de random-functie shuffle.
randomSeed(analogRead(3));
Initialiseer de drukknop pin als input:
pinMode (buttonPin, INPUT);
de digitale pincode instellen als output:
pinMode (ledPin, OUTPUT);
digitalWrite(ledPin,HIGH);
putstring_nl ("\nWave test!"); zeggen dat we wakker!
putstring ("vrije RAM:"); Dit kan helpen met het opsporen van fouten, uit RAM lopend is slecht
Serial.println(FreeRam());
Als (! card.init()) {//play met 8 MHz spi (standaard sneller!)
fout ("Card init. mislukt!"); Er ging iets mis, laat uitprinten waarom
}
inschakelen optimaliseren lees - sommige kaarten kunnen timeout. Uitschakelen als u problemen ondervindt
card.partialBlockRead(true);
Nu gaan we voor een FAT-partitie!
uint8_t deel;
voor (deel = 0; deel < 5; deel ++) {/ / Wij hebben maximaal 5 "slots" om in te kijken
Als (vol.init (kaart, deel))
breken; We vonden een, laat borgtocht
}
Als (deel == 5) {/ / als we uiteindelijk niet het vinden van een :(
fout ("geen geldige FAT-partitie!"); Er ging iets mis, laat uitprinten waarom
}
Laat de gebruiker te vertellen over wat we gevonden
putstring ("Using partitie");
Serial.Print (deel, DEC);
putstring (", type is vet");
Serial.println(vol.fatType(), DEC); FAT16 of FAT32?
Probeert te openen van de root directory
Als (! root.openRoot(vol)) {}
fout kan niet ("open root dir!"); Er ging iets mis,
}
Oef! Daar kregen we voorbij de harde delen.
putstring_nl ("bestanden gevonden (* = gefragmenteerd):");
Afdrukken van alle bestanden in alle mappen.
root.ls(LS_R | LS_FLAG_FRAGMENTED);
digitalWrite(ledPin,HIGH);
}
//////////////////////////////////// LOOP
void loop {}
korte lus 3 seconden alleen de eerste keer
Als de knop ingedrukt meer dan eens, p [leggen alle golven
Serial.println (firstTime);
delay(1000);
Als (firstTime == 1) {}
doen
{
digitalWrite(ledPin,HIGH);
delay(250);
digitalWrite(ledPin,LOW);
delay(250);
numPress = digitalRead(buttonPin);
Als (numPress == HIGH) {}
playAll ++;
firstTime ++;
}
XX ++;
Serial.println (xx);
} terwijl (xx < 10);
firstTime ++;
}
Serial.println (firstTime);
Serial.println (playAll);
delay(1000);
Lees de stand van de drukknop waarde:
buttonState = digitalRead(buttonPin);
digitalWrite(ledPin,HIGH);
Controleer als de drukknop ingedrukt is.
Als het is, is de buttonState hoog:
Als (buttonState == HIGH) {}
CT = 0;
dwz een wav-bestand afspelen gaat u verder met de code
digitalWrite(ledPin,LOW);
afdrukken van een willekeurig getal van 1 tot 60
randNumber = willekeurige (1, numWavs);
Serial.println(randNumber);
delay(50);
root.Rewind();
Play(root);
}
else {}
niets doen
}
}
/////////////////////////////////// HELPERS
/*
* afdrukken foutbericht en stoppen
*/
VOID error_P (const char * str) {}
PgmPrint ("fout:");
SerialPrint_P(str);
sdErrorCheck();
while(1);
}
/*
* afdrukken foutbericht en stoppen als SD i/o-fout, zeer geschikt voor het opsporen van fouten!
*/
ongeldig sdErrorCheck(void) {}
Als (! card.errorCode()) keren;
PgmPrint ("\r\nSD I/O fout:");
Serial.Print(Card.ErrorCode(), HEX);
PgmPrint (",");
Serial.println(Card.errorData(), HEX);
while(1);
}
/*
* spelen recursief - mogelijk stackoverloop als submappen ook genest
*/
leegte spelen (FatReader & dir) {}
FatReader bestand;
terwijl (dir.readDir(dirBuf) > 0) {/ / Lees elk bestand in de directory een tegelijk
Overslaan van het als niet een submap en niet een. WAV-bestand
if (!. DIR_IS_SUBDIR(dirBuf)
& & strncmp_P ((char *) & dirBuf.name[8], PSTR("WAV"), 3)) {}
blijven;
}
Serial.println(); leeghalen van een nieuwe regel
voor (uint8_t ik = 0; ik < dirLevel; i ++) {}
Serial.write(' '); Dit is voor prettyprinting, spaties vooraan zetten
}
Als (! file.open (vol, dirBuf)) {/ / open het bestand in de directory
fout ("file.open mislukt"); Er ging iets mis
}
Als (file.isDir()) {/ / controleren als we een nieuwe map geopend
putstring ("Subdir:");
printEntryName(dirBuf);
Serial.println();
dirLevel += 2; meer spaties toevoegen
bestanden in de submap afspelen
Play(File); recursieve!
dirLevel-= 2;
}
else {}
AHA! We vonden een bestand dat niet van een map
putstring ("Playing");
printEntryName(dirBuf); Print het uit
Als (! wave.create(file)) {/ / figuur, is het een goede WAV?
putstring ("niet een geldig WAV"); OK overslaan
} else {}
Serial.println();
Hoera IS het een goede WAV!
CT ++;
Serial.println(randNumber);
Serial.println(CT);
Hier is waar we spelen het bestand
echter alleen willen dat het een wav-bestand dat wordt geselecteerd door willekeurig getal
Als ((randNumber == ct) || (playAll > 1)) {
Wave.Play();
wat lawaai maken!
uint8_t n = 0;
terwijl (wave.isplaying) {/ / spelen optreedt in interrupts, dus we stippen in realtime afdrukken
putstring(".");
Als (! () ++ n % 32))Serial.println();
delay(100);
}
digitalWrite(ledPin,HIGH);
}
sdErrorCheck(); alles OK?
Als (wave.errors)Serial.println(wave.errors); Golf decodeerfouten
}
}
}
}