Prata pumpa kostym (3 / 6 steg)
Steg 3: Koden och Wav-filer
Koden är från Adafruit och det är respektabel parterna och har ändrats. Jag lade till en 4: e knapp och ljud byte. Jag ändrade de ljud byte till mitt eget och jag bytte ögonen från runda till triangeln.Detta Instructable förutsätter att du redan vet hur man arbetar med arduino, (installera kod, biblioteket, etc)
KODEN.
Du kan antingen kopiera och klistra in koden nedan i till arduino ide eller klicka på filen.
Pumpa ansikte kostym
Denna skiss har något ändrats från ursprungliga
skaparen som nedan. Njut av!!
'wavface' exempel skiss för Adafruit I2C 8 x 8 LED ryggsäckar
och Wave sköld:
//
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
//
Kräver Adafruit_LEDBackpack, Adafruit_GFX bibliotek och WaveHC
bibliotek.
//
Denna skiss visar animering ungefär synkroniseras till inspelat
tal. Det är ganska komplicerad och kan vara överväldigande att nybörjare
programmerare, som kanske vill börja med exemplet "matrix8x8"
och sedan "roboface" innan arbetet genom denna kod. Dessutom mycket
av de kommentarer som avser ansikte animeringen har skalats
här för korthetens... hänvisa till "roboface" skiss om du har någon
frågor hur den del fungerar.
//
Extra hårdvara krävs: ljud utlöses med hjälp av tre
normalt-öppen momentan knappar ansluten till Digital stift 6, 7, 8
och GND. (t.ex. www.adafruit.com/products/1009)
//
Adafruit investerar tid och resurser att tillhandahålla detta öppen källkod,
Vänligen stödja Adafruit och öppen hårdvara genom att köpa
produkter från Adafruit!
//
Skrivet av P. Burgess för Adafruit industrier, anpassade delar från
'PiSpeakHC' skiss ingår i WaveHC bibliotek.
BSD-licensen, alla texten ovan måste inkluderas i en omfördelning.
#include < Arduino.h >
#include < Wire.h >
#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"
#include < WaveHC.h >
#include < WaveUtil.h >
Dessa WAV-filer bör vara i rotnivån i SD-kortet:
PROGMEM röding
wav0 [] = "HALLOW~1.wav",
wav1 [] = "LOOKIN~1.wav",
wav2 [] = "THISPM~1.wav",
wav3 [] = "TRKORTRT.wav", / / lagt detta linje 8/3/13
* wavname [] = {wav0, wav1, wav2, wav3}; extra wav3 till denna linje 8/3/13
PROGMEM gör regelbundna framträdanden under denna kod, orsaken är att
SD kort biblioteket kräver gobs av dyrbara RAM (lämnar mycket lite till
vår egen skiss). PROGMEM låter oss lägga fast data i programmet flash-minne,
vilket är betydligt rymligare. Sträng tabeller är paritcularly otäcka.
Se www.arduino.cc/en/Reference/PROGMEM för mer info.
SdReader kort; Detta objekt innehåller information för kortet
FatVolume vol; Detta innehåller information för partitionen på kortet
FatReader rot. Detta innehåller information för volymer rotmapp
FatReader fil. Det här objektet representerar WAV-fil för en fras
WaveHC våg; En enda våg objekt--bara en ljud spelas i taget
Makro att sätta felmeddelanden i flash-minnet
#define error(msg) error_P(PSTR(msg))
Eftersom de två öga delar matriser samma adress, bara fyra
Matrix-objekt behövs för fem bildskärmar:
#define MATRIX_EYES 0
#define MATRIX_MOUTH_LEFT 1
#define MATRIX_MOUTH_MIDDLE 2
#define MATRIX_MOUTH_RIGHT 3
Adafruit_8x8matrix matrix [4]. Matris med Adafruit_8x8matrix objekt
I stället tilldelar matrisen adresser sekventiellt i en loop, varje
har en plats i den här matrisen. Detta gör det lättare om du oavsiktligt
installera en eller flera matriser i fel fysiska position--
sortera adresserna i den här tabellen och du kan fortfarande hänvisar till
matriser av indexet ovan, ingen annan kod eller ledningar behöver förändras.
CONST uint8_t PROGMEM matrixAddr [] = {0x70, 0x71, 0x72, 0x73};
CONST uint8_t PROGMEM / / bitmappar lagras i programminnet
blinkImg [] [8] = {/ / öga animeringsbildrutor
{B00000001, / / helt öppna ögon
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, / / helt stängt öga
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000}},
mouthImg [] [24] = {/ / mun animeringsbildrutor
{B00000000, B00000000, B00000000, / / mun position 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, / / mun läge 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, / / mun läge 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, / / mun läge 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, / / mun position 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, / / mun läge F
B00000000, B11000011, B00000000,
B00001111, B00000000, B11110000,
B00000001, B00000000, B10000000,
B00000000, B11000011, B00000000,
B00000000, B00111100, B00000000,
B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000}};
Animeringssekvenser motsvarar varje WAV. Första siffran i
varje par är en mun bitmapp index. Andra siffran är lastrummet
tid (i bilder). 255 markerar slutet av listan.
Det finns ingen "magic" här, programvaran är inte härleda mun
ståndpunkt från ljudet... tabellerna bestämdes för hand,
precis som animatörer gör det. Ytterligare förklaring här:
http://www.idleworm.com/How/Anm/03t/talk1.shtml
CONST uint8_t PROGMEM
seq1 [] = {0, 2, 2, 5, 5, 3, 3, 7, / / "Happy Halloween" / / ansluten till wav 0 ovan
4, 5, 3, 4, 2, 5, 4, 3, 255},
seq2 [] = {0, 1, 3, 5, 1, 5, 4, 2, / / "Hö, vad glor du på?" / / ansluten till wav 1 ovan
3, 2, 1, 2, 4, 4, 1, 3,
4, 2, 255},
seq3 [] = {0, 1, 1, 2, 3, 6, 2, 5, / / "som har två tummar och vill ha godis, denna pumpa" / / ansluten till wav 2 ovan
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" / / ansluten till wav 3 ovan
4, 5, 255},
* anim [] = {seq1, seq2, seq3, seq4}; lagt till seq 4 här 8/3/13
uint8_t
blinkIndex [PROGMEM] = {1, 2, 3, 4, 3, 2, 1}, / / Blink bitmapp sekvens
blinkCountdown = 100, / / nedräkningen till nästa blink (i bilder)
gazeCountdown = 75 / / nedräkningen till nästa öga rörelse
gazeFrames = 50, / / varaktighet av ögonrörelser (mindre = snabbare)
mouthPos = 0, / / aktuell bild nummer för mun
mouthCountdown = 10, / / nedräkningen till nästa mun ändra
newPos = 255, / / ny mun läge för aktuell bildruta
* seq, / / Animation sekvens för närvarande som spelas upp
IDX, / / Current array index i animeringssekvensen
prevBtn = 99, / / knapp # tryckte på förra loop() iteration
btnCount = 0; Antalet iterationer samma knapp har hållits
int8_t
eyeX = 3, eyeY = 3, / / Current öga position
newX = 3, newY = 3, / / nästa öga position
dX = 0, dY = 0; Avstånd från före ny position
void setup() {
Serial.BEGIN(9600);
PgmPrintln ("WAV ansikte");
IF(!Card.init()) fel ("kort init. misslyckades!");
IF(!Vol.init(Card)) fel ("ingen partition!");
IF(!root.openRoot(Vol)) fel kunde inte ("öppna dir");
PgmPrintln ("filer som hittas:");
root.ls();
Utsäde slumptalsgeneratorn från en oanvänd analog ingång:
randomSeed(analogRead(A0));
Initiera och initiera varje matrix-objekt:
för (uint8_t jag = 0; jag < 4; i ++) {
Matrix [i] = Adafruit_8x8matrix();
Matrix [i] .begin (pgm_read_byte (& matrixAddr[i]));
}
Aktiverar pull-up motstånd på fyra (ändrat till fyra) knappen ingångar.
Andra änden av varje knapp då ansluter till GND.
för (uint8_t jag = 6; jag < = 9; i ++) {//i < = 8 till 9 8/3/13
pinMode (i, ingång);
digitalWrite i, hög. Aktivera pullup
}
}
void loop() {
uint8_t i.
Rita ögongloben i nuvarande delstaten blinkyness (ingen elev).
Matrix[MATRIX_EYES].Clear();
Matrix [MATRIX_EYES] .drawBitmap (0, 0,
blinkImg [
(blinkCountdown < sizeof(blinkIndex))? För närvarande blinkar?
pgm_read_byte (& blinkIndex[blinkCountdown]): / / Ja, slå upp bitmapp #
0 / / Nej, Visa bitmapp 0
], 8, 8, LED_ON);
Dekrement blink counter. Slutet, ange slumpmässig tid för nästa blink.
om (--blinkCountdown == 0) blinkCountdown = random (5, 180);
om (--gazeCountdown < = gazeFrames) {
Ögonen är i rörelse - Rita elev vid mellanliggande position
Matrix [MATRIX_EYES] () .fillRect
newX - (dX * gazeCountdown / gazeFrames),
newY - (dY * gazeCountdown / gazeFrames),
2, 2, LED_OFF);
IF(gazeCountdown == 0) {/ / senast ram?
eyeX = newX; eyeY = newY; Ja. Det är nya gammal, sedan...
göra {/ / plocka slumpmässiga positioner tills en i ögat cirkeln
newX = random(7); newY = random(7);
dX = newX - 3. dY = newY - 3.
} medan ((dX * dX + dY * dY) > = 10); Tack Pythagoras
dX = newX - eyeX; Horisontella avståndet att flytta
dY = newY - eyeY; Vertikala avståndet att flytta
gazeFrames = random (3, 15); Varaktigheten av ögonrörelser
gazeCountdown = random (gazeFrames, 120); Räkna till slutet av nästa rörelse
}
} annat {
Inte i rörelse ännu--Rita elev vid nuvarande statiska position
Matrix [MATRIX_EYES] .fillRect (eyeX, eyeY, 2, 2, LED_OFF);
}
Scan knappar 6, 7, 8, 9 söker första knappen intryckt... lagt till #9 8/3/13
för (jag = 0; (jag < 4) & & (digitalRead(i+6) == hög); i++); (jag < 3 ändras till 4 8/3/13
IF(i < 4) {/ / något tryckte? Ja! (jag < 3 ändras till 4 8/3/13
IF(i == prevBtn) {/ / samma som förra gången vi kollade? Bra!
om (++ btnCount == 4) {/ / 3 pass till "Dämpningstid' knappen ingång / / == ändras från 3 till 4
playfile ((char *) pgm_read_word(&wavname[i])); Starta WAV
Slå upp animation sequence # motsvarande denna WAV...
SEQ = (uint8_t *) pgm_read_word(&anim[i]);
IDX = 0; Börja på första byte data
newPos = pgm_read_byte (& seq[idx++]); Första munnen pos
mouthCountdown = pgm_read_byte (& seq[idx++]); Håll tid för pos
}
} annat btnCount = 0; Annan knapp än före - start räkna över
prevBtn = i.
} annat prevBtn = 99. Inga knappar tryckte
om (newPos! = 255) {/ / är munnen i rörelse?
om (--mouthCountdown == 0) {/ / räkna ner ramar till nästa position
newPos = pgm_read_byte (& seq[idx++]); Ny mun position
IF(newPos == 255) {/ / slutet av listan?
mouthPos = 0; Ja, ange mun till neutralläge
} annat {
mouthPos = newPos; Ställ in munnen till ny position
mouthCountdown = pgm_read_byte (& seq[idx++]); Läs håll time
}
}
} annat mouthPos = 0; Mun inte i rörelse--inställd neutralläge
drawMouth(mouthImg[mouthPos]);
Uppdatera alla matriser i en snabb pass
för (uint8_t jag = 0; jag < 4; i ++) matrix[i].writeDisplay();
Delay(20);
}
Rita mun bild över tre intilliggande skärmar
void drawMouth (const uint8_t * img) {
för (uint8_t jag = 0; jag < 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 ("fel:");
SerialPrint_P(str);
sdErrorCheck();
While(1);
}
skriva ut felmeddelande och stoppa om SD i/o-fel
void sdErrorCheck(void) {
om (! card.errorCode()) återvända;
PgmPrint ("\r\nSD I/O fel:");
Serial.Print(Card.ErrorCode(), HEX);
PgmPrint (",");
Serial.println(Card.errorData(), HEX);
While(1);
}
Öppna och börja spela en WAV-fil
void playfile (const char * namn) {
char filnamn [13]. 8.3 + NUL
IF(Wave.isplaying) wave.stop(); Stoppa någon som spelar WAV
strcpy_P (filnamn, namn); Kopiera namn ur PROGMEM i RAM
om (! file.open (rot, filnamn)) {
PgmPrint kunde inte ("öppna filen");
Serial.Print(filename);
hemkomst.
}
IF(!Wave.Create(File)) {
PgmPrintln ("inte en giltig WAV");
hemkomst.
}
Wave.Play();
}