Innholdsfortegnelse:

Laser Harp Synthesizer på Zybo Board: 10 trinn (med bilder)
Laser Harp Synthesizer på Zybo Board: 10 trinn (med bilder)

Video: Laser Harp Synthesizer på Zybo Board: 10 trinn (med bilder)

Video: Laser Harp Synthesizer på Zybo Board: 10 trinn (med bilder)
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 opplæringen vil vi lage en fullt funksjonell laserharpe ved hjelp av IR -sensorer med et serielt grensesnitt som lar brukeren endre tuning og tone på instrumentet. Denne harpen blir en nyinnspilling fra det 21. århundre av det gamle instrumentet. Systemet ble opprettet ved hjelp av et Xilinx Zybo utviklingsbord sammen med Vivado Design Suites. Hva du trenger for å fullføre prosjektet:

  • 12 IR -sensorer og sendere (mer eller mindre kan brukes avhengig av antall strenger)
  • Zybo Zynq-7000 utviklingstavle
  • Gratis RTOS
  • Vivado Design Suite
  • Wire (for tilkobling av sensorene til kortet)
  • 3 stykker PVC -rør ((2) 18 tommer og (1) 8 tommer)
  • 2 PVC -albuer

Trinn 1: Få Digilents Zybo DMA Audio Demo

FPGA -siden av dette prosjektet er i stor grad basert på demoprosjektet som finnes her. Den bruker direkte minnetilgang til å sende data direkte fra minnet som prosessoren kan skrive til AXI Stream til en I2S lydblokk. Følgende trinn vil hjelpe deg med å få DMA -lyddemoprosjektet i gang:

  1. En ny versjon av tavlefilen for Zybo -brettet kan være nødvendig. Følg disse instruksjonene for å skaffe nye brettfiler for Vivado.
  2. Følg trinn 1 og 2 i instruksjonene på denne siden for å åpne demoprosjektet i Vivado. Bruk Vivado -metoden, ikke SDK -maskinvareoverleveringen.
  3. Du kan få en melding som sier at noen av ip -blokkene dine bør oppdateres. Velg i så fall "Vis IP -status", og velg deretter utdatert IP i kategorien IP -status og klikk "Oppgrader valgt". Når det er ferdig og et vindu dukker opp som spør om du vil generere utdataprodukt, klikker du på "Generer". Hvis du får en kritisk advarsel, ignorer den.
  4. Bytt fra designet til kilden -fanen i Vivado for å se kildefilene. Høyreklikk på blokkdesignet "design_1" og velg "Create HDL Wrapper". Velg "kopier generert innpakning for å tillate brukerredigering" når du blir bedt om det. En wrapper -fil for prosjektet vil bli generert.
  5. Nå som de kritiske trinnene som på en eller annen måte ble utelatt i den andre opplæringen er fullført, kan du gå tilbake til opplæringen som tidligere er koblet til og fortsette fra trinn 4 til slutten og sørge for at demoprosjektet fungerer som det skal. Hvis du ikke har mulighet til å legge inn lyd for at den skal kunne spilles inn, er det bare å ta opp med hodetelefonene inne og lytte etter en 5-10 sekunders fuzzy lyd når du trykker på avspillingsknappen. Så lenge det kommer noe ut av hodetelefonkontakten når du trykker på avspillingsknappen, fungerer det sannsynligvis som det skal.

Trinn 2: Gjør noen endringer i Vivado

Gjør noen endringer i Vivado
Gjør noen endringer i Vivado

Så nå har du Digilents DMA -lyddemo som fungerer, men det er slett ikke sluttmålet her. Så vi må gå tilbake til Vivado og gjøre noen endringer slik at sensorene våre kan kobles til PMOD -hodene og vi kan bruke verdien på programvaresiden.

  1. Åpne blokkdiagrammet i Vivado
  2. Opprett en GPIO-blokk ved å høyreklikke i det tomme rommet i blokkdiagrammet og velge "Legg til IP" fra menyen. Finn og velg "AXI GPIO".
  3. Dobbeltklikk på den nye IP-blokken, og gå til kategorien IP-konfigurasjon i nytt tilpassede IP-vindu. Velg alle innganger og sett bredden til tolv, siden vi vil ha 12 "strenger" på harpen vår og derfor trenger 12 sensorer. Hvis du vil bruke færre eller flere sensorer, må du justere dette tallet på riktig måte. Sett også aktiver avbryt.
  4. Høyreklikk på den nye GPIO IP -blokken og velg "Kjør tilkoblingsautomatisering". Merk av i AXI -boksen og trykk OK. Dette bør koble til AXI -grensesnittet automatisk, men la utgangene til blokken være koblet til.
  5. For å få plass til det ekstra avbruddet, dobbeltklikker du på xlconcat_0 IP -blokken og endrer antall porter fra 4 til 5. Deretter kan du koble ip2intc_irpt -pinnen fra den nye GPIO -blokken til den nye ubrukte porten på xlconcat -blokken.
  6. Høyreklikk på "GPIO" -utgangen til den nye GPIO IP -blokken og velg "make external". Finn hvor linjen går til, og klikk på den lille sideveis femkant, og til venstre skal et vindu åpnes der du kan endre navnet. Endre navnet til "SENSORER". Det er viktig å bruke samme navn hvis du vil at begrensningsfilen vi gir, skal fungere, ellers må du endre navnet i begrensningsfilen.
  7. Tilbake i kilden -fanen finner du begrensningsfilen og erstatter den med den vi tilbyr. Du kan velge å enten erstatte filen eller bare kopiere innholdet i begrensningsfilen og lime den inn over innholdet i den gamle. En av de viktige tingene vår begrensningsfil gjør, er å aktivere pullup -motstandene på PMOD -hodene. Dette er nødvendig for de spesifikke sensorene vi brukte, men ikke alle sensorene er like. Hvis sensorene krever nedtrekksmotstander, kan du endre hver forekomst av "set_property PULLUP true" med "set_property PULLDOWN true". Hvis de krever en annen motstandsverdi enn den på tavlen, kan du fjerne disse linjene og bruke eksterne motstander. Pin -navnene er i kommentarene i begrensningsfilen, og de tilsvarer etikettene i første diagram i Zybo -skjemaene side som du finner her. Hvis du vil bruke forskjellige pmod -pins, må du bare matche navnene i begrensningsfilen med etikettene i skjematisk. Vi bruker PMOD -topptekst JE og JD, og bruker seks datapinner på hver, utelater pinne 1 og 7. Denne informasjonen er viktig når du kobler til sensorene dine. Som vist i skjematikken er pinnene 6 og 12 på PMODS VCC og pinnene 5 og 11 er malt.
  8. Regenerer HDL -innpakningen som før, og kopier og skriv over den gamle. Når det er gjort, generer du bitstream og eksporterer maskinvare som før, og starter SDK -en på nytt. Hvis du blir spurt om du vil erstatte den gamle maskinvarefilen, er svaret ja. Det er sannsynligvis best å ha SDK lukket når du eksporterer maskinvare, slik at den blir riktig erstattet.
  9. Start SDK.

Trinn 3: Få FreeRTOS Running

Det neste trinnet er å få FreeRTOS til å kjøre på Zybo -brettet.

  1. Hvis du ikke allerede har en kopi, kan du laste ned FreeRTOS her og pakke ut filene.
  2. Importer FreeRTOS Zynq -demoen på FreeRTOSv9.0.0 / FreeRTOS / Demo / CORTEX_A9_Zynq_ZC702 / RTOSDemo. Importprosessen er omtrent den samme som for det andre demoprosjektet, men fordi FreeRTOS Zynq -demoen er avhengig av andre filer i FreeRTOS -mappen, bør du ikke kopiere filene til arbeidsområdet. I stedet bør du plassere hele FreeRTOS -mappen inne i prosjektmappen.
  3. Lag en ny brettstøttepakke ved å gå til "fil" -> "ny" -> "brettstøttepakke". Sørg for at frittstående er valgt, og klikk på Fullfør. Etter et øyeblikk vil et vindu dukke opp, merk av i boksen ved siden av lwip141 (dette stopper en av FreeRTOS -demoer fra å mislykkes i å kompilere) og trykk OK. Etter at det er fullført, høyreklikker du på RTOSdemo -prosjektet og går til "egenskaper", går til "prosjektreferanser" -fanen og merker av i boksen ved siden av den nye bspen du opprettet. Forhåpentligvis vil det bli gjenkjent, men noen ganger kan Xilinx SDK være rart om denne typen ting. Hvis du fortsatt får en feil etter dette trinnet som xparameters.h mangler eller noe sånt, prøv å gjenta dette trinnet og kanskje avslutte og starte SDK -en på nytt.

Trinn 4: Legg til laserharpekode

Nå som FreeRTOS er importert, kan du ta med deg filene fra laserharpeprosjektet til FreeRTOS -demoen

  1. Opprett en ny mappe under src -mappen i FreeRTOS -demoen, og kopier og lim inn alle de medfølgende c -filene bortsett fra main.c i denne mappen.
  2. Erstatt RTOSDemo main.c med main.c.
  3. Hvis alt er gjort riktig, bør du kunne kjøre laserharpekoden på dette tidspunktet. For testformål brukes knappinngangen som ble brukt i DMA -demoprosjektet nå til å spille lyder uten sensorer festet (noen av de fire hovedknappene vil fungere). Den spiller en streng hver gang du trykker på den og går gjennom alle strengene i systemet over flere trykk. Koble noen hodetelefoner eller høyttalere til hodetelefonkontakten på Zybo -kortet og sørg for at du kan høre lydene fra strengene som kommer gjennom når du trykker på en knapp.

Trinn 5: Om koden

Mange av dere som leser denne opplæringen er sannsynligvis her for å lære å sette opp lyd eller bruke DMA til å gjøre noe annerledes, eller lage et annet musikkinstrument. Av den grunn er de neste seksjonene dedikert til å beskrive hvordan den oppgitte koden fungerer sammen med maskinvaren som tidligere er beskrevet for å få en fungerende lydutgang ved bruk av DMA. Hvis du forstår hvorfor kodebitene er der, bør du kunne justere dem for hva det er du vil lage.

Avbryter

Først skal jeg nevne hvordan avbrudd oppstår i dette prosjektet. Måten vi gjorde det på var ved først å lage en interrupt -vektortabellstruktur som holder oversikt over ID, interrupt -behandler og en referanse til enheten for hvert avbrudd. Avbrudds -ID -ene kommer fra xparameters.h. Avbryterbehandleren er en funksjon vi skrev for DMA og GPIO, og I2C -avbruddet kommer fra Xlic I2C -driveren. Enhetsreferansen peker på forekomster av hver enhet som vi initialiserer andre steder. Nær slutten av _init_audio -funksjonen går en sløyfe gjennom hvert element i interrupt -vektortabellen og kaller to funksjoner, XScuGic_Connect () og XScuGic_Enable () for å koble til og aktivere avbruddene. De refererer til xInterruptController, som er en interrupt -kontroller som er opprettet i FreeRTOS main.c som standard. Så i utgangspunktet knytter vi hvert avbrudd til denne avbryterkontrolleren som allerede ble opprettet for oss av FreeRTOS.

DMA

DMA -initialiseringskoden starter på lh_main.c. Først deklareres en statisk forekomst av en XAxiDma -struktur. Så i funksjonen _init_audio () blir den konfigurert. Først blir konfigurasjonsfunksjonen fra demoprosjektet kalt, som er i dma.c. Det er ganske godt dokumentert og kommer rett fra demoen. Deretter blir avbruddet koblet til og aktivert. For dette prosjektet kreves bare master-to-slave-avbrudd, fordi alle data blir sendt av DMA til I2S-kontrolleren. Hvis du ønsker å ta opp lyd, trenger du også slave-to-master-avbruddet. Master-to-slave-avbruddet blir oppringt når DMA er ferdig med å sende ut dataene du fortalte den å sende. Dette avbruddet er utrolig viktig for prosjektet vårt, fordi hver gang DMA sender ut en buffer med lydprøver må den umiddelbart begynne å sende ut den neste bufferen, ellers vil det oppstå en hørbar forsinkelse mellom sendingene. Inne i dma_mm2s_ISR () -funksjonen kan du se hvordan vi håndterer avbruddet. Den viktige delen er nær slutten hvor vi bruker xSemaphoreGiveFromISR () og portYIELD_FROM_ISR () for å varsle _audio_task () om at den kan starte neste DMA -overføring. Måten vi sender konstant lyddata på, er ved å veksle mellom to buffere. Når en buffer overføres til I2C -blokken, får den andre bufferen sine verdier beregnet og lagret. Når avbruddet kommer fra DMA, bytter den aktive bufferen, og den mer nylig skrevne bufferen begynner å bli overført mens den tidligere overførte bufferen begynner å bli overskrevet med nye data. Den viktigste delen av _audio_task -funksjonen er hvor fnAudioPlay () blir kalt. fnAudioPlay () tar inn DMA -forekomsten, lengden på bufferen og en peker til bufferen som data skal overføres fra. Noen få verdier blir sendt til I2S -registre for å gi beskjed om at flere prøver kommer. Deretter blir XAxiDma_SimpleTransfer () kalt til å starte overføringen.

I2S lyd

audio.c og audio.h er hvor I2S -initialiseringen finner sted. I2S initialiseringskode er en ganske vanlig del av koden som flyter rundt på en rekke steder, du kan finne små variasjoner fra andre kilder, men denne burde fungere. Det er ganske godt dokumentert og trenger ikke mye å bli endret for harpeprosjektet. DMA -lyddemoen som den kom fra, har funksjoner for å bytte til mikrofonen eller linjeinngangene, slik at du kan bruke dem hvis du trenger den funksjonaliteten.

Lydsyntese

For å beskrive hvordan lydsyntesen fungerer, skal jeg liste opp hver av lydmodellene som ble brukt i utviklingen som førte til den endelige metoden, da det vil gi deg en følelse av hvorfor det gjøres slik det gjøres.

Metode 1: En periode med sinusverdier beregnes for hver streng med den tilsvarende frekvensen for den strengens musikknote og lagres i en matrise. For eksempel vil lengden på matrisen være perioden for sinusbølgen i prøver, som tilsvarer antall prøver / syklus. Hvis samplingsfrekvensen er 48 kHz og notatfrekvensen er 100 Hz, er det 48 000 prøver/sekund og 100 sykluser/sekund som fører til 4800 prøver per syklus, og matriselengden vil være 4800 prøver og vil inneholde verdiene til en komplett sinusbølgetid. Når strengen spilles, fylles lydprøvebufferen ved å ta en verdi fra sinusbølgematrisen og sette den inn i lydbufferen som en prøve, og deretter øke indeksen til sinusbølgeserien slik at ved å bruke vårt tidligere eksempel i løpet av kurset av 4800 prøver settes en sinusbølgesyklus inn i lydbufferen. En modulo -operasjon brukes på matrisindeksen slik at den alltid faller mellom 0 og lengden, og når matrisindeksen går over en viss terskel (for eksempel prøver på 2 sekunder), blir strengen slått av. Hvis du vil spille flere strenger samtidig, må du holde oversikt over hver strenges matrisindeks separat og legge til verdien fra hver strenges sinusbølge for å få hver prøve.

Metode 2: For å skape en mer musikalsk tone, starter vi med den forrige modellen og legger til harmoniske til hver grunnfrekvens. Harmoniske frekvenser er frekvenser som er heltallsmultipler av grunnfrekvensen. I motsetning til når to ikke -relaterte frekvenser summeres sammen, noe som resulterer i at to forskjellige lyder spilles samtidig, når harmoniske legges sammen, fortsetter det å høres ut som bare en lyd, men med en annen tone. For å oppnå dette, hver gang vi legger til verdien av sinusbølgen på plassering (matrisindeks % arraylengde) til lydprøven, legger vi også til (2 * array index % array length) og (3 * array index % array length), og så videre for hvor mange harmonier som er ønsket. Disse multipliserte indeksene vil krysse sinusbølgen ved frekvenser som er heltallsmultipler av den opprinnelige frekvensen. For å gi mer kontroll over tonen multipliseres hver harmonikkers verdier med en variabel som representerer mengden av den harmoniske i den totale lyden. For eksempel kan den grunnleggende sinusbølgen ha sine verdier alle multiplisert med 6 for å gjøre den mer av en faktor i den totale lyden, mens den femte harmoniske kan ha en multiplikator på 1, noe som betyr at dens verdier bidrar mye mindre til den generelle lyden.

Metode 3: Ok, så nå har vi en veldig fin tone på notene, men det er fortsatt et ganske avgjørende problem: de spiller på et fast volum i en fast varighet. For i det hele tatt å lyde som et ekte instrument, bør volumet til en streng som spilles, forsvinne jevnt over tid. For å oppnå dette er en matrise fylt med verdiene til en eksponentielt forfallende funksjon. Når lydprøver blir opprettet, blir lyden fra hver streng beregnet som i den forrige metoden, men før den blir lagt til lydprøven, multipliseres den med verdien ved den strengenes matrisindeks i den eksponentielle forfallsfunksjonsgruppen. Dette gjør at lyden jevnt forsvinner over tid. Når matrisindeksen når slutten av forfallet, stoppes strengen.

Metode 4: Dette siste trinnet er det som virkelig gir strengelydene deres realistiske strengelyd. Før hørtes de hyggelige, men tydelig syntetiserte ut. For å prøve å etterligne en harpestreng i den virkelige verden, tildeles hver harmonikk en annen forfallshastighet. I reelle strenger, når strengen først blir slått, er det et høyt innhold av høyfrekvente harmoniske som skaper den slags plukkelyd vi forventer av en streng. Disse høyfrekvente harmoniske er veldig kort hoveddelen av lyden, lyden av strengen som blir slått, men de forfaller veldig raskt etter hvert som de langsommere harmonikkene tar over. Det opprettes en forfallsmatrise for hvert harmonisk nummer som brukes i lydsyntese, hver med sin egen forfallshastighet. Nå kan hver harmoniske uavhengig multipliseres med verdien den tilhørende forfallsmatrisen ved strengindeksen til strengen og legges til lyden.

Totalt sett er lydsyntesen intuitiv, men beregningstung. Å lagre hele strenglyden i minnet på en gang ville ta for mye minne, men det ville ta altfor lang tid å beregne sinusbølgen og eksponensiell funksjon mellom hver ramme for å følge med på lydavspillingen. En rekke triks brukes i koden for å øke beregningen. All matematikk, bortsett fra ved den første opprettelsen av sinus- og eksponensielle forfallstabellene, utføres i heltallformat, noe som krever at det tilgjengelige numeriske rommet spres ut i 24 -biters lydutgang. For eksempel er sinustabellen med amplitude 150 slik at den er jevn, men ikke så stor at mange strenger som spilles sammen kan legge til å være over 24 bits. På samme måte multipliseres de eksponentielle tabellverdiene med 80 før de avrundes til heltall og lagres. De harmoniske vektene kan ta på seg diskrete verdier mellom 0 og 10. Også alle prøver er faktisk doblet og sinusbølgene indeksert med 2, noe som effektivt halverer samplingshastigheten. Dette begrenser maksimal frekvens som kan spilles, men var nødvendig for at nåværende antall strenger og harmoniske kunne beregnes raskt nok.

Å lage denne lydmodellen og få den til å fungere tok betydelig innsats på prosessorsiden, og det hadde vært utrolig vanskelig å få den til å fungere på fpga -siden fra bunnen av i tidsrammen for dette prosjektet (tenk deg å måtte gjenskape bitstrømmen hver gang et stykke verilog ble endret for å teste lyden). Imidlertid kan det å gjøre det på fpga sannsynligvis være en bedre måte å gjøre det på, muligens eliminere problemet med ikke å kunne beregne prøver raskt nok og tillate at flere strenger, harmoniske og til og med lydeffekter eller andre oppgaver kjøres på prosessorsiden.

Trinn 6: Tilkobling av sensorene

Kabling av sensorene
Kabling av sensorene

For å lage strengene brukte vi IR break beam -sensorer som vil oppdage når strengen spilles. Vi bestilte sensorene våre fra følgende lenke. Sensorene har en strøm-, jord- og datakabel mens senderne bare har en strøm- og jordledning. Vi brukte 3,3 V og jordede pinner fra PMOD -hodene for å drive både sendere og sensorer. For å drive alle sensorene og senderne er det nødvendig å koble alle sensorene og senderen parallelt. Datatrådene fra sensorene må hver gå til sin egen pmod -pin.

Trinn 7: Konstruere skjelettet

Konstruere skjelettet
Konstruere skjelettet

For å skape harpens form brukes de tre stykkene som et skjelett for å plassere sensorer og sendere på. På en av de to 18 tommers stykkene av PVC -rør justerer du sensorene og emitterne i vekslende rekkefølge 1,5 tommer fra hverandre og teiper dem deretter ned til røret. På det andre 18 tommers PVC -røret justerer du sensorene og senderne i vekslende rekkefølge, men sørg for å kompensere ordren (dvs. hvis det første røret hadde en sensor først, skulle det andre ha en sender først og omvendt). Det vil være nødvendig å lodde lengre ledninger på data-, strøm- og jordledningene for å sikre at de vil kunne nå brettet.

Trinn 8: Bygg treutvendig

Bygging av treutvendig
Bygging av treutvendig

Dette trinnet er valgfritt, men det anbefales på det sterkeste. Treutvendig gjør ikke bare harpen til å se fin ut, den beskytter også sensorene og ledningene mot skade. Trerammen kan lages av en hallow rektangulær ring av tre. Innsiden av rektanglet må ha en åpning på minst 1-1/2 tommer for å passe til røret og sensorskjelettet. Når rammen er konstruert, borer du to hull som vil tillate ledningene fra sensoren og sender ut for å koble dem til brettet.

*Merk: Det anbefales å legge til tilgangspunkter for å kunne fjerne og sette inn rørskjelettet i tilfelle reparasjoner må utføres eller små justeringer må gjøres.

Trinn 9: Sett sammen alle delene

Å sette alle brikkene sammen
Å sette alle brikkene sammen

Når alle de foregående trinnene er fullført, er det på tide å konstruere harpen. Plasser først rørskjelettet inne i treutvendig. Deretter kobler du til ledningene til sensorene og senderne til riktig plassering på brettet. Åpne deretter SDK og klikk på feilsøkingsknappen for å programmere brettet. Når kortet er programmert, kobler du til et par hodetelefoner eller en høyttaler. Avhengig av hvilken sensor som havner i hvilken pmod -port vil harpens strenger sannsynligvis være ute av drift til å begynne med. Fordi det kan være vanskelig å fortelle hvilken ledning som går til hvilken sensor når så mange ledninger er involvert, inkluderte vi en måte å kartlegge strengnummer for å avbryte bitposisjoner i programvare. Finn "static int sensor_map [NUM_STRINGS]" og juster verdiene i matrisen til strengene spiller fra laveste til høyeste i rekkefølge.

Menyen kan brukes ved å åpne en seriell terminal (f.eks. RealTerm) og sette overføringshastigheten til 115200 og displayet til ANSI. Menyen kan navigeres ved å bruke w og s -tastene for å gå opp og ned og a og d -tastene for å endre verdiene.

Trinn 10: ROCK OUT

Når harpen er fullt funksjonell. Mestre harpen og lytt til den søte lyden av din egen musikk!

Anbefalt: