Indholdsfortegnelse:

Laser Harp Synthesizer på Zybo Board: 10 trin (med billeder)
Laser Harp Synthesizer på Zybo Board: 10 trin (med billeder)

Video: Laser Harp Synthesizer på Zybo Board: 10 trin (med billeder)

Video: Laser Harp Synthesizer på Zybo Board: 10 trin (med billeder)
Video: Crokett's Theme / Harp Laser Performance by Arkonis 2024, Juli
Anonim
Laser Harp Synthesizer på Zybo Board
Laser Harp Synthesizer på Zybo Board

I denne vejledning vil vi oprette en fuldt funktionel laserharpe ved hjælp af IR -sensorer med et serielt interface, der gør det muligt for brugeren at ændre tuning og tone på instrumentet. Denne harpe bliver det 21. århundredes nyindspilning af det ældgamle instrument. Systemet blev oprettet ved hjælp af et Xilinx Zybo udviklingsbord sammen med Vivado Design Suites. Hvad skal du bruge for at fuldføre projektet:

  • 12 IR -sensorer og emittere (mere eller mindre kan bruges afhængigt af antallet af strenge)
  • Zybo Zynq-7000 udviklingstavle
  • Gratis RTOS
  • Vivado Design Suite
  • Wire (til tilslutning af sensorerne til kortet)
  • 3 stykker PVC -rør ((2) 18 tommer og (1) 8 tommer)
  • 2 PVC albuer

Trin 1: Få Digilents Zybo DMA Audio Demo

FPGA -siden af dette projekt er i vid udstrækning baseret på demoprojektet, der findes her. Den bruger direkte hukommelsesadgang til at sende data direkte fra hukommelse, som processoren kan skrive til over AXI Stream til en I2S -lydblok. Følgende trin hjælper dig med at få DMA -lyddemoprojektet i gang:

  1. En ny version af tavlefilen til Zybo -kortet kan være nødvendig. Følg disse instruktioner for at få nye tavlefiler til Vivado.
  2. Følg trin 1 og 2 i vejledningen på denne side for at få demoprojektet åbent i Vivado. Brug Vivado -metoden, ikke SDK -hardwareoverleveringen.
  3. Du får muligvis en besked, der siger, at nogle af dine ip -blokke skal opdateres. Vælg i så fald "Vis IP -status", og vælg derefter alle forældede IP -adresser på fanen IP -status og klik på "Opgrader valgt". Når det er færdigt, og et vindue dukker op, der spørger, om du vil generere outputprodukt, skal du gå videre og klikke på "Generer". Hvis du får en kritisk advarselsmeddelelse, skal du ignorere den.
  4. Skift fra designet til fanen kilder i Vivado for at se kildefilerne. Højreklik på blokdesignet "design_1" og vælg "Opret HDL Wrapper". Når du bliver bedt om det, skal du vælge "kopier genereret indpakning for at tillade brugerredigeringer". En wrapper -fil til projektet genereres.
  5. Nu hvor de kritiske trin, der på en eller anden måde blev udeladt i den anden vejledning, er afsluttet, kan du vende tilbage til den tidligere linkede vejledning og fortsætte fra trin 4 til slutningen og sikre, at demoprojektet kører korrekt. Hvis du ikke har mulighed for at indtaste lyd, så den kan optages, skal du bare optage med dine hovedtelefoner i og lytte efter en fuzzy lyd på 5-10 sekunder, når du trykker på afspilningsknappen. Så længe der kommer noget ud af hovedtelefonstikket, når du trykker på afspilningsknappen, fungerer det sandsynligvis korrekt.

Trin 2: Foretag nogle ændringer i Vivado

Foretag nogle ændringer i Vivado
Foretag nogle ændringer i Vivado

Så nu har du Digilents DMA -lyddemo, der fungerer, men det er slet ikke slutmålet her. Så vi skal tilbage til Vivado og foretage nogle ændringer, så vores sensorer kan tilsluttes PMOD -overskrifterne, og vi kan bruge deres værdi på softwaresiden.

  1. Åbn blokdiagrammet i Vivado
  2. Opret en GPIO-blok ved at højreklikke i det tomme rum i blokdiagrammet og vælge "Tilføj IP" i menuen. Find og vælg "AXI GPIO".
  3. Dobbeltklik på den nye IP-blok, og gå til fanen IP-konfiguration i vinduet tilpas IP igen. Vælg alle input og indstil bredden til tolv, da vi vil have 12 "strenge" på vores harpe og derfor har brug for 12 sensorer. Hvis du vil bruge færre eller flere sensorer, skal du justere dette nummer korrekt. Indstil også aktiveringsafbrydelse.
  4. Højreklik på den nye GPIO IP -blok, og vælg "Kør forbindelsesautomatisering". Marker AXI -feltet og tryk på OK. Dette skulle automatisk forbinde AXI -grænsefladen, men lade udgangene fra blokken være uden forbindelse.
  5. For at give plads til den ekstra afbrydelse skal du dobbeltklikke på xlconcat_0 IP -blokken og ændre antallet af porte fra 4 til 5. Derefter kan du slutte ip2intc_irpt -stiften fra den nye GPIO -blok til den nye ubrugte port på xlconcat -blokken.
  6. Højreklik på "GPIO" output på den nye GPIO IP blok og vælg "make external". Find, hvor linjen går til, og klik på den lille sidelæns femkant, og til venstre skal der åbnes et vindue, hvor du kan ændre navnet. Skift navnet til "SENSORER". Det er vigtigt at bruge det samme navn, hvis du vil have den begrænsningsfil, vi leverer, til at fungere, ellers bliver du nødt til at ændre navnet i begrænsningsfilen.
  7. Tilbage på fanen Kilder finder du begrænsningsfilen og erstatter den med den, vi leverer. Du kan vælge enten at erstatte filen eller bare kopiere indholdet i vores begrænsningsfil og indsætte den over indholdet i den gamle. En af de vigtige ting, vores begrænsningsfil gør, er at aktivere pullup -modstande på PMOD -overskrifterne. Dette er nødvendigt for de særlige sensorer, vi brugte, men ikke alle sensorer er ens. Hvis dine sensorer kræver nedtrapningsmodstande, kan du ændre hver forekomst af "set_property PULLUP true" med "set_property PULLDOWN true". Hvis de kræver en anden modstandsværdi end den på tavlen, kan du fjerne disse linjer og bruge eksterne modstande. Pin -navnene er i kommentarerne i begrænsningsfilen, og de svarer til etiketterne i første diagram i Zybo -skemaerne side som kan findes her. Hvis du vil bruge forskellige pmod -pins, skal du bare matche navnene i begrænsningsfilen til etiketterne i skematisk. Vi bruger PMOD header JE og JD, og bruger seks datastifter på hver, udelader ben 1 og 7. Disse oplysninger er vigtige, når du tilslutter dine sensorer. Som vist i skematikken er ben 6 og 12 på PMODS VCC, og ben 5 og 11 er formalet.
  8. Genopret HDL -indpakningen som før, og kopier og overskriv den gamle. Når det er gjort, skal du generere bitstream og eksportere hardware som før, og genstarte SDK'en. Hvis du bliver spurgt, om du vil udskifte den gamle hardwarefil, er svaret ja. Det er nok bedst at have SDK lukket, når du eksporterer hardware, så det bliver korrekt udskiftet.
  9. Start SDK.

Trin 3: Få FreeRTOS kørende

Det næste trin er at få FreeRTOS til at køre på Zybo -kortet.

  1. Hvis du ikke allerede har en kopi, skal du downloade FreeRTOS her og pakke filerne ud.
  2. Importer FreeRTOS Zynq -demoen på FreeRTOSv9.0.0 / FreeRTOS / Demo / CORTEX_A9_Zynq_ZC702 / RTOSDemo. Importprocessen er stort set den samme som for det andet demoprojekt, men fordi FreeRTOS Zynq -demoen er afhængig af andre filer i FreeRTOS -mappen, bør du ikke kopiere filerne til dit arbejdsområde. I stedet skal du placere hele FreeRTOS -mappen inde i din projektmappe.
  3. Opret en ny board supportpakke ved at gå til "file" -> "new" -> "board support package". Sørg for, at standalone er valgt, og klik på Afslut. Efter et øjeblik vil et vindue dukke op, markere afkrydsningsfeltet ud for lwip141 (dette forhindrer en af FreeRTOS -demoer i ikke at kompilere) og trykke på OK. Når det er fuldført, skal du højreklikke på RTOSdemo -projektet og gå til "egenskaber", gå til fanen "projektreferencer", og markér feltet ud for den nye bsp, du har oprettet. Forhåbentlig vil det blive genkendt, men nogle gange kan Xilinx SDK være underligt omkring den slags. Hvis du stadig får en fejl efter dette trin, som xparameters.h mangler eller lignende, så prøv at gentage dette trin og måske afslutte og genstarte SDK'en.

Trin 4: Tilføj laserharpekode

Nu hvor FreeRTOS er importeret, kan du bringe filerne fra laserharpeprojektet ind i FreeRTOS -demoen

  1. Opret en ny mappe under src -mappen i FreeRTOS -demoen, og kopier og indsæt alle de medfølgende c -filer undtagen main.c i denne mappe.
  2. Udskift RTOSDemo main.c med den medfølgende main.c.
  3. Hvis alt er udført korrekt, skal du kunne køre laserharpekoden på dette tidspunkt. Til testformål bruges den knapindgang, der blev brugt i DMA -demoprojektet, nu til at afspille lyde uden sensorer tilsluttet (en af de fire hovedknapper fungerer). Den vil spille en streng hver gang du trykker på den og gennemgå alle strengene i systemet over flere tryk. Tilslut nogle hovedtelefoner eller højttalere til hovedtelefonstikket på Zybo -kortet, og sørg for at du kan høre lyden af strengene, der kommer igennem, når du trykker på en knap.

Trin 5: Om koden

Mange af jer, der læser denne vejledning, er sandsynligvis her for at lære at opsætte lyd eller bruge DMA til at gøre noget anderledes eller til at oprette et andet musikinstrument. Af den grund er de næste par afsnit dedikeret til at beskrive, hvordan den leverede kode fungerer sammen med den hardware, der tidligere er beskrevet for at få et fungerende lydoutput ved hjælp af DMA. Hvis du forstår, hvorfor kodestykkerne er der, skal du være i stand til at justere dem til det, du vil oprette.

Afbryder

Først vil jeg nævne, hvordan afbrydelser skabes i dette projekt. Måden, vi gjorde det på, var ved først at oprette en afbrydelsesvektortabelstruktur, der holder styr på id'et, afbrydelsesbehandleren og en reference til enheden for hver afbrydelse. Afbrydelses -id'erne kommer fra xparameters.h. Afbrydelsesbehandleren er en funktion, vi skrev til DMA og GPIO, og I2C -afbrydelsen kommer fra Xlic I2C -driveren. Enhedsreferencen peger på forekomster af hver enhed, som vi initialiserer andre steder. Ved slutningen af _init_audio -funktionen går en loop gennem hvert element i afbrydelsesvektortabellen og kalder to funktioner, XScuGic_Connect () og XScuGic_Enable () for at forbinde og aktivere afbrydelserne. De refererer til xInterruptController, som er en interrupt -controller, der som standard er oprettet i FreeRTOS main.c. Så grundlæggende knytter vi hver af vores afbrydelser til denne afbrydelsescontroller, som allerede blev oprettet for os af FreeRTOS.

DMA

DMA -initialiseringskoden starter på lh_main.c. Først deklareres en statisk forekomst af en XAxiDma -struktur. Derefter bliver funktionen _init_audio () konfigureret. Først kaldes konfigurationsfunktionen fra demoprojektet, som er i dma.c. Det er ret veldokumenteret og kommer direkte fra demoen. Derefter bliver afbrydelsen forbundet og aktiveret. Til dette projekt kræves kun master-to-slave-afbrydelse, fordi alle data sendes af DMA til I2S-controlleren. Hvis du ønsker at optage lyd, skal du også bruge slave-til-master-afbrydelsen. Master-to-slave-afbrydelsen bliver kaldt, når DMA er færdig med at sende de data, du fortalte den, at sende. Denne afbrydelse er utrolig vigtig for vores projekt, fordi hver gang DMA er færdig med at sende en buffer med lydprøver, skal den straks begynde at sende den næste buffer ud, ellers ville der forekomme en hørbar forsinkelse mellem afsendelser. Inde i funktionen dma_mm2s_ISR () kan du se, hvordan vi håndterer afbrydelsen. Den vigtige del er nær slutningen, hvor vi bruger xSemaphoreGiveFromISR () og portYIELD_FROM_ISR () til at underrette _audio_task () om, at den kan starte den næste DMA -overførsel. Den måde, vi sender konstante lyddata på, er ved at skifte mellem to buffere. Når en buffer overføres til I2C -blokken, får den anden buffer beregnet og lagret sine værdier. Så når afbrydelsen kommer fra DMA'en, skifter den aktive buffer, og den nyere skrevne buffer begynder at blive overført, mens den tidligere overførte buffer begynder at blive overskrevet med nye data. Den centrale del af funktionen _audio_task er, hvor fnAudioPlay () bliver kaldt. fnAudioPlay () tager DMA -forekomsten, bufferens længde og en markør til bufferen, hvorfra data vil blive overført. Et par værdier sendes til I2S -registre for at fortælle, at der kommer flere prøver. Derefter bliver XAxiDma_SimpleTransfer () kaldet til at starte overførslen.

I2S lyd

audio.c og audio.h er, hvor I2S -initialiseringen finder sted. I2S initialiseringskode er en temmelig almindelig del af kode, der flyder rundt flere steder, du kan finde små variationer fra andre kilder, men denne burde fungere. Det er ret veldokumenteret og behøver ikke meget at blive ændret til harpeprojektet. DMA -lyddemoen, som den kom fra, har funktioner til at skifte til mikrofonen eller linjeindgange, så du kan bruge dem, hvis du har brug for den funktionalitet.

Lydsyntese

For at beskrive hvordan lydsyntesen fungerer, vil jeg liste hver af de lydmodeller, der blev brugt i udviklingen, der førte til den endelige metode, da det vil give dig en fornemmelse af, hvorfor det gøres, som det gøres.

Metode 1: En periode med sinusværdier beregnes for hver streng ved den tilsvarende frekvens for denne strengs musiknote og gemmes i et array. For eksempel vil arrayets længde være perioden for sinusbølgen i prøver, hvilket er lig med # prøver / cyklus. Hvis samplingshastigheden er 48 kHz og notefrekvensen er 100 Hz, er der 48.000 prøver/sekund og 100 cyklusser/sekund, der fører til 4800 prøver pr. Cyklus, og arraylængden vil være 4800 prøver og indeholder værdierne for en komplet sinusbølge periode. Når strengen afspilles, udfyldes lydprøvebufferen ved at tage en værdi fra sinusbølge -arrayet og lægge den i lydbufferen som en prøve, hvorefter indekset øges til sinusbølge -arrayet, så ved hjælp af vores tidligere eksempel i løbet af forløbet af 4800 prøver sættes en sinusbølgecyklus i lydbufferen. En modulo -operation bruges på array -indekset, så det altid falder mellem 0 og længden, og når array -indekset går over en bestemt tærskel (f.eks. Prøver på 2 sekunder), deaktiveres strengen. Hvis du vil spille flere strenge på samme tid, skal du holde styr på hver strings 'array -indeks separat og tilføje værdien fra hver strenges sinusbølge sammen for at få hver prøve.

Metode 2: For at skabe en mere musikalsk tone starter vi med den tidligere model og tilføjer harmoniske til hver grundfrekvens. Harmoniske frekvenser er frekvenser, der er heltalsmultipler af grundfrekvensen. I modsætning til når to ikke -relaterede frekvenser summeres sammen, hvilket resulterer i, at to forskellige lyde afspilles samtidigt, når harmoniske er lagt sammen, fortsætter det med at lyde som bare en lyd, men med en anden tone. For at opnå dette tilføjer vi hver gang vi tilføjer værdien af sinusbølgen på stedet (arrayindeks % arraylængde) til lydprøven, også (2 * arrayindeks % arraylængde) og (3 * arrayindeks % arraylængde)), og så videre for hvor mange harmonier der ønskes. Disse multiplicerede indeks vil krydse sinusbølgen ved frekvenser, der er heltalsmultipler af den oprindelige frekvens. For at give mere kontrol over tonen multipliceres hver harmoniks værdier med en variabel, der repræsenterer mængden af den harmoniske i den samlede lyd. For eksempel kan den grundlæggende sinusbølge have sine værdier alle ganget med 6 for at gøre den mere af en faktor i den samlede lyd, mens den 5. harmoniske kan have en multiplikator på 1, hvilket betyder, at dens værdier bidrager meget mindre til den samlede lyd.

Metode 3: Okay, så nu har vi en meget flot tone på noterne, men der er stadig et temmelig afgørende problem: de spiller med en fast lydstyrke i en fast varighed. For overhovedet at lyde som et rigtigt instrument, bør lydstyrken på en streng, der spilles, falde glat over tid. For at opnå dette er et array fyldt med værdierne for en eksponentielt forfaldende funktion. Når lydprøverne nu oprettes, beregnes lyden fra hver streng som i den foregående metode, men før den tilføjes til lydprøven, multipliceres den med værdien ved denne strings array -indeks i den eksponentielle henfaldsfunktions array. Dette får lyden til at sprede sig jævnt over tid. Når matrixindekset når slutningen af henfaldsarrayet, stoppes strengen.

Metode 4: Dette sidste trin er det, der virkelig giver strengelydene deres realistiske strengelyd. Før lød de behageligt, men klart syntetiseret. For at forsøge bedre at efterligne en harpestreng fra den virkelige verden tildeles hver harmonisk en anden henfaldshastighed. I rigtige strenge, når strengen først slås, er der et højt indhold af højfrekvente harmoniske, der skaber den slags plukkelyd, vi forventer af en streng. Disse højfrekvente harmoniske er meget kort hoveddelen af lyden, lyden af strengen, der bliver slået, men de henfalder meget hurtigt, når de langsommere harmoniske overtager. Der oprettes et henfaldsarray for hvert harmonisk tal, der bruges i lydsyntese, hver med sin egen henfaldshastighed. Nu kan hver harmoniske uafhængigt multipliceres med værdien dens tilhørende henfaldsarray ved strengens matrixindeks og føjes til lyden.

Generelt er lydsyntesen intuitiv, men beregningstung. At lagre hele strenglyden i hukommelsen på én gang ville tage for meget hukommelse, men beregning af sinusbølgen og den eksponentielle funktion mellem hvert billede ville tage alt for lang tid at følge med lydafspilningshastigheden. En række tricks bruges i koden for at fremskynde beregningen. Al matematik undtagen ved den indledende oprettelse af sinus- og eksponentielle henfaldstabeller udføres i et heltalformat, hvilket kræver spredning af det tilgængelige numeriske rum i 24 -bit lydoutput. For eksempel er sinustabellen i amplitude 150, så den er glat, men ikke så stor, at mange strenge, der spilles sammen, kan tilføje til at være over 24 bit. På samme måde ganges de eksponentielle tabelværdier med 80, før de afrundes til heltal og gemmes. De harmoniske vægte kan antage diskrete værdier mellem 0 og 10. Også alle prøver er faktisk fordoblet, og sinusbølgerne indekseres med 2'er, hvilket effektivt halverer samplingshastigheden. Dette begrænser den maksimale frekvens, der kan spilles, men var nødvendig for at det nuværende antal strenge og harmoniske kunne beregnes hurtigt nok.

At oprette denne lydmodel og få den til at fungere krævede en stor indsats på processorsiden, og det ville have været utroligt svært at få den til at fungere på fpga -siden fra bunden i tidsrammen for dette projekt (forestil dig at skulle genskabe bitstrømmen hver gang gang et stykke verilog blev ændret for at teste lyden). Imidlertid kan det sandsynligvis være en bedre måde at gøre det på fpga'en, muligvis eliminere problemet med ikke at kunne beregne prøver hurtigt nok og tillade flere strenge, harmoniske og endda lydeffekter eller andre opgaver, der kan køres på processorside.

Trin 6: Tilslutning af sensorerne

Tilslutning af sensorerne
Tilslutning af sensorerne

For at oprette strengene brugte vi IR break beam -sensorer, der registrerer, når strengen afspilles. Vi bestilte vores sensorer fra følgende link. Sensorerne har en strøm-, jord- og datakabel, mens udsenderne kun har en strøm- og jordledning. Vi brugte 3,3 V- og jordstiftene fra PMOD -overskrifterne til at drive både emittere og sensorer. For at drive alle sensorer og emittere er det nødvendigt at forbinde alle sensorer og emitter parallelt. Datatrådene fra sensorerne skal hver især gå til deres egen pmod -pin.

Trin 7: Konstruktion af skelettet

Konstruktion af skelettet
Konstruktion af skelettet

For at skabe harpens form bruges de tre stykker som et skelet til at placere sensorer og udsendere på. På et af de to 18 tommer stykker PVC -rør justerer sensorerne og emitterne i skiftevis rækkefølge 1,5 tommer fra hinanden og tape dem derefter ned til røret. På det andet 18 tommer PVC -rør justerer sensorerne og emitterne i skiftevis rækkefølge, men sørg for at opveje ordren (dvs. hvis det første rør havde en sensor først, skulle det andet have en emitter først og omvendt). Det vil være nødvendigt at lodde længere ledninger på data-, strøm- og jordledningerne for at sikre, at de vil kunne nå brættet.

Trin 8: Bygning af træudvendigt

Bygning af træets ydre
Bygning af træets ydre

Dette trin er valgfrit, men det kan varmt anbefales. Træets ydre får ikke kun harpen til at se pæn ud, den beskytter også sensorer og ledninger mod skader. Trærammen kan skabes af en hallow rektangulær ring af træ. Indersiden af rektanglet skal have en åbning på mindst 1-1/2 tommer for at passe til røret og sensorskelet. Når rammen er konstrueret, skal du bore to huller, der tillader ledningerne fra sensoren og udsendere for at forbinde dem med brættet.

*Bemærk: Det anbefales at tilføje adgangspunkter for at kunne fjerne og indsætte rørskelettet, hvis der skal foretages reparationer, eller der skal foretages små justeringer.

Trin 9: Læg alle stykker sammen

Sætter alle stykker sammen
Sætter alle stykker sammen

Når alle de foregående trin er færdige, er det tid til at konstruere harpen. Placer først rørskelettet inde i træets ydre. Tilslut derefter ledningerne til sensorerne og emitterne til det korrekte sted på tavlen. Åbn derefter SDK'en, og klik på fejlfindingsknappen for at programmere tavlen. Når kortet er programmeret, skal du tilslutte et par hovedtelefoner eller en højttaler. Afhængigt af hvilken sensor der ender i hvilken pmod -port, vil din harpes strenge sandsynligvis være ude af drift til at begynde med. Fordi det kan være svært at vide, hvilken ledning der går til hvilken sensor, når så mange ledninger er involveret, inkluderede vi en måde at kortlægge strengnumre for at afbryde bitpositioner i software. Find "static int sensor_map [NUM_STRINGS]", og juster værdierne i arrayet, indtil strengene spiller fra laveste til højeste i rækkefølge.

Menuen kan bruges ved at åbne en seriel terminal (f.eks. RealTerm) og indstille baudhastigheden til 115200 og displayet til ANSI. Menuen kan navigeres ved at bruge w og s tasterne til at flytte op og ned og a og d tasterne til at ændre værdierne.

Trin 10: ROCK OUT

Når harpen er fuldt funktionsdygtig. Behersk harpen og lyt til den søde lyd af din egen musik!

Anbefalede: