Stap 3: De code en Wav-bestanden
De code Is van Adafruit en het is fatsoenlijke partijen en is gewijzigd. Ik heb een 4e knop en geluid byte toegevoegd. Ik veranderde het geluid bytes naar mijn eigen en veranderde ik de ogen van ronde driehoek.Dit Instructable wordt ervan uitgegaan dat u al weet hoe te werken met de arduino, (installeren code, bibliotheek, etc)
DE CODE.
U kunt kopiëren en plak de code hieronder in naar de arduino ide of klik op het bestand.
Pompoen gezicht kostuum
Deze sketch is iets veranderd van het origineel
schepper zoals hieronder gezien. Geniet van!
'wavface' in het volgende voorbeeld schets voor Adafruit I2C 8 x 8 LED rugzakken
en Wave Shield:
//
www.adafruit.com/products/870 www.adafruit.com/products/1049
www.adafruit.com/products/871 www.adafruit.com/products/1050
www.adafruit.com/products/872 www.adafruit.com/products/1051
www.adafruit.com/products/959 www.adafruit.com/products/1052
www.adafruit.com/products/94
//
Adafruit_LEDBackpack, Adafruit_GFX bibliotheken en WaveHC vereist
bibliotheken.
//
Deze schets toont animatie ruwweg gesynchroniseerd met vooraf opgenomen
toespraak. Het is vrij complex en kan worden overweldigend voor beginner
programmeurs, die kunnen willen beginnen met het voorbeeld van de 'matrix8x8'
en dan 'roboface' voordat u door middel van deze code. Ook veel
van de opmerkingen met betrekking tot de animatie gezicht zijn ontdaan
hier voor beknoptheid... verwijzen naar de schets van de 'roboface' als u een
vragen die de werking van dat deel.
//
Extra hardware vereist: geluiden worden geactiveerd met behulp van drie
normaal-open kortstondige knoppen aangesloten op Digital pinnen 6, 7, 8
en GND. (bijvoorbeeld www.adafruit.com/products/1009)
//
Adafruit investeert tijd en middelen verstrekken van dit open source-code,
u kan ondersteunen Adafruit en open-source hardware door de aankoop van
producten van Adafruit!
//
Geschreven door P. Burgess voor Adafruit industrieën, onderdelen aangepast van
'PiSpeakHC' schets met de WaveHC bibliotheek opgenomen.
BSD-licentie, alle bovenstaande tekst moet worden opgenomen in eventuele herverdeling.
#include < Arduino.h >
#include < Wire.h >
#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"
#include < WaveHC.h >
#include < WaveUtil.h >
Deze WAV-bestanden moeten worden in het niveau van de hoofdsite van de SD kaart:
PROGMEM-char
[wav0] = "HALLOW~1.wav",
[wav1] = "LOOKIN~1.wav",
[wav2] = "THISPM~1.wav",
[wav3] = "TRKORTRT.wav", / / toegevoegd dit lijn 8/3/13
* wavname [] = {wav0, wav1, wav2, wav3}; toegevoegde wav3 aan deze lijn 8/3/13
PROGMEM maakt frequente verschijningen tijdens deze code, de reden hiervoor is dat
de SD kaart bibliotheek vereist gobs van kostbare RAM (weinig te verlaten
onze eigen sketch). PROGMEM laat ons vaste gegevens plaatsen in het programma flash geheugen,
die is aanzienlijk ruimer. Tekenreeks tabellen zijn vervelende paritcularly.
Zie www.arduino.cc/en/Reference/PROGMEM voor meer info.
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
FatReader bestand; Dit object vertegenwoordigt het WAV-bestand voor een zin
WaveHC Golf; Een object één Golf--slechts één geluid wordt tegelijk gespeeld
Macro om foutberichten in het flash-geheugen
#define error(msg) error_P(PSTR(msg))
Omdat de twee ogen delen matrices hetzelfde adres, slechts vier
Matrix-objecten zijn nodig voor de vijf displays:
#define MATRIX_EYES 0
#define MATRIX_MOUTH_LEFT 1
#define MATRIX_MOUTH_MIDDLE 2
#define MATRIX_MOUTH_RIGHT 3
Adafruit_8x8matrix matrix [4]; Array van Adafruit_8x8matrix objecten
In plaats van het toewijzen van adressen van de matrix achter elkaar in een lus, elke
heeft een plek in deze array. Dit maakt het makkelijker als u per ongeluk
installeren van één of meer matrices in de verkeerde fysieke positie--
volgorde van de adressen in deze tabel en u kunt nog steeds verwijzen naar
matrices door bovenstaande index, geen andere code of bedrading moet veranderen.
Const uint8_t PROGMEM matrixAddr [] = {0x70, 0x71, 0x72, 0x73};
Const uint8_t PROGMEM / / Bitmaps worden opgeslagen in het programmageheugen
[blinkImg] [8] = {/ / Eye animatieframes
{B00000001, / / volledig open oog
B00000011,
B00000111,
B00001111,
B00011111,
B00111111,
B01111111,
B11111111},
{B00000000,
B00000001,
B00000011,
B00000111,
B00001111,
B00011111,
B00111111,
B01111111},
{B00000000,
B00000000,
B00000001,
B00000011,
B00000111,
B00001111,
B00011111,
B00111111},
{B00000000,
B00000000,
B00000000,
B00000001,
B00000011,
B00000111,
B00001111,
B00011111},
{B00000000,
B00000000,
B00000000,
B00000000,
B00000001,
B00000011,
B00000111,
B00001111},
{B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000001,
B00000011,
B00000111},
{B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000001,
B00000011},
{B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000001},
{B00000000, / / volledig gesloten oog
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000}},
[mouthImg] [24] = {/ / mond animatieframes
{B00000000, B00000000, B00000000, / / mond positie A
B00000000, B00000000, B00000000,
B01111111, B11111111, B11111110,
B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000},
{B00000000, B00000000, B00000000, / / mond positie B
B00000000, B00000000, B00000000,
B00111111, B11111111, B11111100,
B00000111, B00000000, B11100000,
B00000000, B11111111, B00000000,
B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000},
{B00000000, B00000000, B00000000, / / mond positie C
B00000000, B00000000, B00000000,
B00111111, B11111111, B11111100,
B00001000, B00000000, B00010000,
B00000110, B00000000, B01100000,
B00000001, B11000011, B10000000,
B00000000, B00111100, B00000000,
B00000000, B00000000, B00000000},
{B00000000, B00000000, B00000000, / / mond positie D
B00000000, B00000000, B00000000,
B00111111, B11111111, B11111100,
B00100000, B00000000, B00000100,
B00010000, B00000000, B00001000,
B00001100, B00000000, B00110000,
B00000011, B10000001, B11000000,
B00000000, B01111110, B00000000},
{B00000000, B00000000, B00000000, / / mond positie E
B00000000, B00111100, B00000000,
B00011111, B11000011, B11111000,
B00000011, B10000001, B11000000,
B00000000, B01111110, B00000000,
B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000},
{B00000000, B00111100, B00000000, / / mond positie F
B00000000, B11000011, B00000000,
B00001111, B00000000, B11110000,
B00000001, B00000000, B10000000,
B00000000, B11000011, B00000000,
B00000000, B00111100, B00000000,
B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000}};
Animatiereeksen overeenkomt met elke WAV. Eerste nummer in
elk paar is een mond bitmap index. Tweede getal is de wachtruimte
tijd (in frames). 255 merken einde van de lijst.
Er is geen 'magie' hier, de software is niet afleiden van mond
positie van het geluid... de tabellen met de hand werden bepaald
net als tekenaars doen. Verdere uitleg hier:
http://www.idleworm.com/How/ANM/03t/talk1.shtml
Const uint8_t PROGMEM
[seq1] = {0, 2, 2, 5, 5, 3, 3, 7, / / "Happy Halloween" / / aangesloten naar wav 0 hierboven
4, 5, 3, 4, 2, 5, 4, 3, 255},
[seq2] = {0, 1, 3, 5, 1, 5, 4, 2, / / "Hay, wat kijk je naar?" aangesloten naar wav 1 boven
3, 2, 1, 2, 4, 4, 1, 3,
4: 2, 255},
[seq3] = {0, 1, 1, 2, 3, 6, 2, 5, / / "die twee heeft duimen en wil snoep, dit pompoen" / / aangesloten naar wav 2 hierboven
0, 1, 4, 4, 5, 2, 1, 5,
3, 6, 1, 4, 5, 3, 4, 2,
3, 6, 4, 2, 255},
[seq4] = {3, 2, 2, 5, 5, 3, 3, 7, / / "Trick Or Treat" / / aangesloten naar wav 3 hierboven
4, 5, 255},
* anim [] = {seq1, seq2, seq3, seq4}; toegevoegd seq 4 hier 8/3/13
uint8_t
blinkIndex [PROGMEM] = {1, 2, 3, 4, 3, 2, 1} / / bitmap volgorde knipperen
blinkCountdown = 100, / / aftellen naar volgende knipperen (in frames)
gazeCountdown = 75, / / aftellen naar volgende oog beweging
gazeFrames 50, = / / duur van de beweging van de ogen (kleinere = sneller)
mouthPos = 0, / / huidige nummer voor mond image
mouthCountdown = 10, / / aftellen naar volgende mond wijzigen
newPos = 255, / / nieuwe mond positie voor de huidige frame
* seq, / / Animation sequence momenteel wordt afgespeeld
idx, / / Current array index binnen animatiereeks
prevBtn 99, = / / Button # ingedrukt op de laatste loop iteratie
btnCount = 0; Aantal iteraties dezelfde knop heeft plaatsgevonden
int8_t
eyeX = 3, eyeY = 3, / / huidige eye positie
newX = 3, newY = 3, / / volgende eye positie
dX = 0, dY = 0; Afstand voorafgaand aan de nieuwe positie
VOID Setup {}
Serial.begin(9600);
PgmPrintln ("WAV gezicht");
if(!Card.init()) fout ("Card init. mislukt!");
if(!vol.init(Card)) fout ("geen partitie!");
if(!root.openRoot(vol)) fout kon niet ("open dir");
PgmPrintln ("bestanden gevonden:");
root.ls();
Zaad random getal-generator van een niet-gebruikte analoge ingang:
randomSeed(analogRead(A0));
Instantiëren en elke matrix-object te initialiseren:
voor (uint8_t ik = 0; ik < 4; i ++) {}
matrix [i] = Adafruit_8x8matrix();
matrix [i] .begin (pgm_read_byte (& matrixAddr[i]));
}
Inschakelen van pull-up weerstanden op vier (gewijzigd in vier) knop ingangen.
Andere uiteinde van ieder knop vervolgens verbindt met GND.
voor (uint8_t ik = 6; ik < = 9; i ++) {//i < = 8 gewijzigd tot en met 9 8/3/13
pinMode (i, ingang);
digitalWrite (i, hoge); Pullup inschakelen
}
}
void loop {}
uint8_t i;
Eyeball in stand van blinkyness (geen leerling) tekenen.
matrix[MATRIX_EYES].Clear();
matrix [MATRIX_EYES]-.drawBitmap (0, 0,
blinkImg [
(blinkCountdown < sizeof(blinkIndex))? Momenteel knipperen?
pgm_read_byte (& blinkIndex[blinkCountdown]): / / Ja, opzoeken bitmap #
0 / / nee, show bitmap 0
], 8, 8, LED_ON);
Decrement knipperen teller. Aan einde, willekeurige tijd instellen voor volgende knipperen.
Als (--blinkCountdown == 0) blinkCountdown = willekeurige (5, 180);
Als (--gazeCountdown < = gazeFrames) {}
Ogen zijn in beweging - leerling tekenen op interim positie
matrix [MATRIX_EYES] .fillRect)
newX - (dX * gazeCountdown / gazeFrames),
newY - (dY * gazeCountdown / gazeFrames),
2, 2, LED_OFF);
if(gazeCountdown == 0) {/ / laatst frame?
eyeX = newX; eyeY = newY; Ja. Wat is nieuw oud, dan...
{/ / willekeurige posities kiezen totdat een binnen de cirkel oog is
newX = random(7); newY = random(7);
dX = newX - 3; dY = newY - 3;
} terwijl ((dX * dX + dY * dY) > = 10); Dank u Pythagoras
dX = newX - eyeX; Horizontale afstand verplaatsen
dY = newY - eyeY; Verticale afstand verplaatsen
gazeFrames = willekeurige (3, 15); Duur van de beweging van de ogen
gazeCountdown = willekeurige (gazeFrames, 120); Tellen tot het einde van volgende beweging
}
} else {}
Niet in beweging nog--trekken leerling op huidige statische positie
matrix [MATRIX_EYES] .fillRect (eyeX, eyeY, 2, 2, LED_OFF);
}
Scan knoppen 6, 7, 8, 9, op zoek naar de eerste knop ingedrukt... toegevoegd #9 8/3/13
voor (ik = 0; (ik < 4) & & (digitalRead(i+6) == HIGH); i++); (ik < 3 gewijzigd tot en met 4 8/3/13
if(i < 4) {/ / iets gedrukt? Ja! (ik < 3 gewijzigd tot en met 4 8/3/13
if(i == prevBtn) {/ / dezelfde als de laatste keer dat we gecontroleerd? Goed!
Als (++ btnCount == 4) {/ / 3 passen naar 'debounce' knop input / / == veranderd van 3 naar 4
playfile ((char *) pgm_read_word(&wavname[i])); Start WAV
Opzoeken animatie opeenvolging # overeenkomt met deze WAV...
SEQ = (uint8_t *) pgm_read_word(&anim[i]);
idx = 0; Beginnen bij de eerste byte van de gegevens
newPos = pgm_read_byte (& seq[idx++]); Eerste mond pos
mouthCountdown = pgm_read_byte (& seq[idx++]); Houd tijd voor pos
}
} anders btnCount = 0; Andere knop dan vóór - start tellen over
prevBtn = i;
} anders prevBtn = 99; Geen knoppen ingedrukt
Als (newPos! = 255) {/ / de monding in beweging Is?
Als (--mouthCountdown == 0) {/ / frames naar volgende positie tellen
newPos = pgm_read_byte (& seq[idx++]); Nieuwe mond positie
if(newPos == 255) {/ / einde van de lijst?
mouthPos = 0; Ja, het instellen van mond naar neutrale positie
} else {}
mouthPos = newPos; Instellen van de mond naar nieuwe positie
mouthCountdown = pgm_read_byte (& seq[idx++]); Lezen houden tijd
}
}
} anders mouthPos = 0; Mond niet in beweging--ingesteld op neutrale positie
drawMouth(mouthImg[mouthPos]);
Alle matrices in één snelle keer vernieuwen
voor (uint8_t ik = 0; ik < 4; i ++) matrix[i].writeDisplay();
vertraging(20);
}
Mond afbeelding aanzuigen en drie aangrenzende beeldschermen
VOID drawMouth (const uint8_t * img) {}
voor (uint8_t ik = 0; ik < 3; i ++) {}
matrix [MATRIX_MOUTH_LEFT + i].clear();
matrix [MATRIX_MOUTH_LEFT + i] .drawBitmap (i * -8, 0, img, 24, 8, LED_ON);
}
}
VOID error_P (const char * str) {}
PgmPrint ("fout:");
SerialPrint_P(str);
sdErrorCheck();
while(1);
}
afdrukken foutbericht en stoppen als SD i/o-fout
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);
}
Open en start het afspelen van een WAV-bestand
VOID playfile (const char * naam) {}
char bestandsnaam [13]; 8.3 + NUL
if(Wave.isplaying) wave.stop(); Stop WAV eersteklasser
strcpy_P (filename, naam); De naam van de kopie uit PROGMEM in RAM
Als (! file.open (root, bestandsnaam)) {}
PgmPrint kon niet ("open bestand");
Serial.Print(filename);
terugkeer;
}
if(!Wave.Create(File)) {}
PgmPrintln ("niet een geldig WAV");
terugkeer;
}
Wave.Play();
}