Taula de continguts:

Sintetitzador làser d'arpa al tauler Zybo: 10 passos (amb imatges)
Sintetitzador làser d'arpa al tauler Zybo: 10 passos (amb imatges)

Vídeo: Sintetitzador làser d'arpa al tauler Zybo: 10 passos (amb imatges)

Vídeo: Sintetitzador làser d'arpa al tauler Zybo: 10 passos (amb imatges)
Vídeo: The Children Are Not Allowed Inside Their Abandoned Mansion In Georgia 2024, Juny
Anonim
Sintetitzador làser d'arpa a la placa Zybo
Sintetitzador làser d'arpa a la placa Zybo

En aquest tutorial crearem una arpa làser completament funcional mitjançant sensors IR amb una interfície sèrie que permetrà a l’usuari canviar l’afinació i el to de l’instrument. Aquesta arpa serà el remake del segle XXI de l’antic instrument. El sistema es va crear mitjançant una placa de desenvolupament Xilinx Zybo juntament amb les Vivado Design Suites. Què necessitareu per completar el projecte:

  • 12 sensors i emissors IR (es poden utilitzar més o menys en funció del nombre de cadenes)
  • Tauler de desenvolupament Zybo Zynq-7000
  • RTOS gratuït
  • Vivado Design Suite
  • Cable (per connectar els sensors a la placa)
  • 3 peces de tub de PVC ((2) 18 polzades i (1) 8 polzades)
  • 2 colzes de PVC

Pas 1: Obteniu la demostració d'àudio Zybo DMA de Digilent

El costat FPGA d'aquest projecte es basa en gran mesura en el projecte de demostració que es troba aquí. Utilitza accés directe a la memòria per enviar dades directament des de la memòria a la qual el processador pot escriure sobre AXI Stream a un bloc d’àudio I2S. Els passos següents us ajudaran a posar en funcionament el projecte de demostració d'àudio DMA:

  1. Pot ser necessària una nova versió del fitxer del tauler per al tauler Zybo. Seguiu aquestes instruccions per obtenir nous fitxers de tauler per a Vivado.
  2. Seguiu els passos 1 i 2 de les instruccions d'aquesta pàgina per obrir el projecte de demostració a Vivado. Utilitzeu el mètode Vivado, no el lliurament de maquinari de l'SDK.
  3. És possible que rebeu un missatge que digui que s’han d’actualitzar alguns dels vostres blocs d’IP. Si és així, seleccioneu "Mostra l'estat de l'IP" i, a la pestanya d'estat de l'IP, seleccioneu totes les adreces IP obsoletes i feu clic a "Actualitza la selecció". Quan s'acabi i aparegui una finestra que us demana si voleu generar un producte de sortida, aneu endavant i feu clic a "Genera". Si rebeu un missatge d’advertència crític, ignoreu-lo.
  4. Canvieu del disseny a la pestanya fonts de Vivado per veure els fitxers font. Feu clic amb el botó dret al disseny de bloc "disseny_1" i seleccioneu "Crea HDL Wrapper". Quan se us demani, seleccioneu "copia l'embolcall generat per permetre les modificacions de l'usuari". Es generarà un fitxer wrapper per al projecte.
  5. Ara que s'han completat els passos crítics que d'alguna manera es van deixar de banda a l'altre tutorial, podeu tornar al tutorial anteriorment enllaçat i continuar des del pas 4 fins al final i assegurar-vos que el projecte de demostració s'executa correctament. Si no teniu cap manera d’entrar àudio perquè enregistri, només heu de gravar amb els auriculars i escoltar un so difús de 5-10 segons quan premeu el botó de reproducció. Sempre que surti alguna cosa del connector dels auriculars quan premeu el botó de reproducció, probablement funcioni correctament.

Pas 2: feu alguns canvis a Vivado

Feu alguns canvis a Vivado
Feu alguns canvis a Vivado

Per tant, ara teniu la demostració d’àudio DMA de Digilent funcionant, però aquest no és l’objectiu final aquí. Per tant, hem de tornar a Vivado i fer alguns canvis perquè els nostres sensors es puguin connectar a les capçaleres PMOD i puguem utilitzar el seu valor pel que fa al programari.

  1. Obriu el diagrama de blocs a Vivado
  2. Creeu un bloc GPIO fent clic amb el botó dret a l'espai buit del diagrama de blocs i seleccionant "Afegeix IP" al menú. Cerqueu i seleccioneu "AXI GPIO".
  3. Feu doble clic al nou bloc IP i, a la finestra de personalització de l'IP, torneu a la pestanya de configuració d'IP. Seleccioneu totes les entrades i configureu l'amplada a dotze, ja que tindrem 12 "cordes" a l'arpa i, per tant, necessitarem 12 sensors. Si voleu utilitzar menys o més sensors, ajusteu aquest nombre adequadament. Estableix també la interrupció d'activació.
  4. Feu clic amb el botó dret al nou bloc IP GPIO i seleccioneu "executa l'automatització de la connexió". Marqueu la casella AXI i premeu bé. Això hauria de connectar la interfície AXI automàticament, però deixant les sortides del bloc desconnectades.
  5. Per deixar espai a la interrupció addicional, feu doble clic al bloc IP xlconcat_0 i canvieu el nombre de ports de 4 a 5. A continuació, podeu connectar el pin ip2intc_irpt del nou bloc GPIO al nou port no utilitzat del bloc xlconcat.
  6. Feu clic amb el botó dret a la sortida "GPIO" del nou bloc IP GPIO i seleccioneu "make external". Cerqueu on va la línia i feu clic al petit pentàgon lateral i a l’esquerra s’hauria d’obrir una finestra on podeu canviar el nom. Canvieu el nom per "SENSORS". És important utilitzar el mateix nom si voleu que funcioni el fitxer de restriccions que proporcionem, en cas contrari haurà de canviar el nom al fitxer de restriccions.
  7. De nou a la pestanya Fonts, cerqueu el fitxer de restriccions i substituïu-lo pel que us proporcionem. Podeu substituir el fitxer o simplement copiar el contingut del nostre fitxer de restriccions i enganxar-lo sobre el contingut de l’antic. Una de les coses importants que fa el nostre fitxer de restriccions és habilitar les resistències de tracció a les capçaleres PMOD. Això és necessari per als sensors particulars que hem utilitzat, però no tots els sensors són iguals. Si els vostres sensors requereixen resistències desplegables, podeu canviar totes les instàncies de "set_property PULLUP true" per "set_property PULLDOWN true". Si requereixen un valor de resistència diferent al del tauler, podeu eliminar aquestes línies i utilitzar resistències externes. Els noms dels pins es troben als comentaris del fitxer de restriccions i corresponen a les etiquetes del primer diagrama de l’esquema Zybo. pàgina que es pot trobar aquí. Si voleu utilitzar diferents pins pmod, només heu de fer coincidir els noms del fitxer de restricció amb les etiquetes de l'esquema. Utilitzem les capçaleres PMOD JE i JD, i fem servir sis pins de dades en cadascun d’ells, ometent els pins 1 i 7. Aquesta informació és important a l’hora de connectar els sensors. Com es mostra a l’esquema, els pins 6 i 12 del PMODS són VCC i els pins 5 i 11 estan terra.
  8. Regenereu l’embolcall HDL com abans i copieu i sobreescriviu l’antic. Quan ho hàgiu fet, genereu flux de bits i exporteu maquinari com abans i torneu a llançar l'SDK. Si se us demana si voleu substituir el fitxer de maquinari antic, la resposta és sí. Probablement és millor que l’SDK estigui tancat quan exporteu maquinari perquè es substitueixi correctament.
  9. Inicieu l'SDK.

Pas 3: Feu funcionar FreeRTOS

El següent pas és fer funcionar FreeRTOS a la placa Zybo.

  1. Si encara no en teniu cap còpia, descarregueu FreeRTOS aquí i extreureu els fitxers.
  2. Importeu la demostració FreeRTOS Zynq ubicada a FreeRTOSv9.0.0 / FreeRTOS / Demo / CORTEX_A9_Zynq_ZC702 / RTOSDemo. El procés d’importació és pràcticament el mateix que per a l’altre projecte de demostració, però, perquè la demostració FreeRTOS Zynq depèn d’altres fitxers de la carpeta FreeRTOS, no hauríeu de copiar-los a l’espai de treball. En lloc d’això, hauríeu de col·locar tota la carpeta FreeRTOS dins de la carpeta del projecte.
  3. Creeu un nou paquet de suport de tauler anant a "fitxer" -> "nou" -> "paquet de suport de tauler". Assegureu-vos que estigui seleccionat independent i feu clic a Finalitza. Al cap d’un moment apareixerà una finestra, marqueu la casella que hi ha al costat de lwip141 (això impedeix que no es pugui compilar una de les demostracions de FreeRTOS) i premeu OK. Després d'això, feu clic amb el botó dret del ratolí al projecte RTOSdemo i aneu a "propietats", aneu a la pestanya "Referències del projecte" i marqueu la casella situada al costat del nou bsp que heu creat. Esperem que es reconegui, però de vegades l’SDK de Xilinx pot resultar estrany en aquest tipus de coses. Si després d'aquest pas encara apareix un error que falta xparameters.h o alguna cosa semblant, proveu de repetir aquest pas i potser sortiu i reinicieu l'SDK.

Pas 4: afegiu un codi d'arpa làser

Ara que s’importa FreeRTOS, podeu portar els fitxers del projecte làser arpa a la demostració FreeRTOS

  1. Creeu una carpeta nova a la carpeta src de la demostració FreeRTOS i copieu i enganxeu tots els fitxers c proporcionats, excepte main.c, en aquesta carpeta.
  2. Substituïu RTOSDemo main.c pel main.c proporcionat.
  3. Si tot es fa correctament, hauríeu de ser capaç d'executar el codi d'arpa làser en aquest moment. A efectes de proves, l'entrada de botons que es va utilitzar al projecte de demostració DMA ara s'utilitza per reproduir sons sense connectar sensors (qualsevol dels quatre botons principals funcionarà). Es reproduirà una cadena cada vegada que la premeu i recorrerà totes les cadenes del sistema amb diverses pulsacions. Connecteu alguns auriculars o altaveus a la presa per a auriculars de la placa Zybo i assegureu-vos que pugueu escoltar els sons de les cordes quan premeu un botó.

Pas 5: Quant al codi

És probable que molts de vosaltres que llegiu aquest tutorial aprenguin a configurar àudio o a utilitzar DMA per fer alguna cosa diferent o a crear un instrument musical diferent. Per aquest motiu, les següents seccions es dediquen a descriure com funciona el codi proporcionat juntament amb el maquinari descrit anteriorment per obtenir una sortida d’àudio que funcioni mitjançant DMA. Si enteneu per què hi ha les peces del codi, hauríeu de poder ajustar-les al que vulgueu crear.

Interrupcions

Primer esmentaré com es creen les interrupcions en aquest projecte. La manera com ho vam fer va ser creant primer una estructura de taula de vector d’interrupció que faci un seguiment de l’ID, el controlador d’interrupcions i una referència al dispositiu per a cada interrupció. Els identificadors d’interrupció provenen de xparameters.h. El gestor d'interrupcions és una funció que hem escrit per al DMA i el GPIO, i la interrupció I2C prové del controlador Xlic I2C. La referència del dispositiu apunta a les instàncies de cada dispositiu que inicialitzem en un altre lloc. Prop del final de la funció _init_audio, un bucle passa per cada element de la taula de vectors d'interrupció i crida a dues funcions, XScuGic_Connect () i XScuGic_Enable () per connectar-se i habilitar les interrupcions. Es refereixen a xInterruptController, que és un controlador d’interrupcions creat al FreeRTOS main.c per defecte. Per tant, bàsicament adjuntem cadascuna de les nostres interrupcions a aquest controlador d’interrupcions que ja ens ha creat FreeRTOS.

DMA

El codi d'inicialització DMA comença a lh_main.c. Primer es declara una instància estàtica d'una estructura XAxiDma. A continuació, a la funció _init_audio () es configura. Primer es crida la funció de configuració del projecte de demostració, que es troba a dma.c. Està força documentat i prové directament de la demostració. A continuació, la interrupció es connecta i s'activa. Per a aquest projecte només es requereix la interrupció mestre a esclau, perquè el DMA envia totes les dades al controlador I2S. Si voleu gravar àudio, també necessitareu la interrupció esclau a mestre. La interrupció mestre a esclau es crida quan el DMA acaba d'enviar les dades que li hàgiu enviat. Aquesta interrupció és increïblement important per al nostre projecte, perquè cada vegada que el DMA acaba d’enviar un buffer de mostres d’àudio ha de començar immediatament a enviar el buffer següent, o bé es produiria un retard audible entre els enviaments. Dins de la funció dma_mm2s_ISR () podeu veure com gestionem la interrupció. La part important és a prop del final, on fem servir xSemaphoreGiveFromISR () i portYIELD_FROM_ISR () per notificar a _audio_task () que pot iniciar la següent transferència DMA. La manera d’enviar dades d’àudio constants és alternant dos búfers. Quan es transmet una memòria intermèdia al bloc I2C, l'altra memòria intermèdia calcula i emmagatzema els seus valors. Aleshores, quan la interrupció prové del DMA, la memòria intermèdia activa canvia i la memòria intermèdia escrita més recentment comença a ser transferida mentre la memòria intermèdia transferida anteriorment comença a sobreescriure's amb dades noves. La part clau de la funció _audio_task és on es diu fnAudioPlay (). fnAudioPlay () pren la instància DMA, la longitud del buffer i un punter al buffer des del qual es transferiran les dades. S’envien uns quants valors als registres I2S per fer-li saber que arribaran més mostres. A continuació, es crida a XAxiDma_SimpleTransfer () per iniciar la transferència.

Àudio I2S

audio.c i audio.h són on té lloc la inicialització I2S. El codi d'inicialització I2S és un tros de codi força comú que flota en diversos llocs, és possible que trobeu lleugeres variacions d'altres fonts, però aquest hauria de funcionar. Està bastant ben documentat i no calia canviar gaire per al projecte d’arpa. La demostració d’àudio DMA d’on prové té funcions per canviar a les entrades de micròfon o de línia, de manera que podeu utilitzar-les si necessiteu aquesta funcionalitat.

Síntesi de so

Per descriure com funciona la síntesi de so, aniré a enumerar cadascun dels models de so utilitzats en el desenvolupament que van conduir al mètode final, ja que us donarà una idea de per què es fa de la manera que es fa.

Mètode 1: Es calcula un període de valors sinusoïdals per a cada corda a la freqüència corresponent per a la nota musical d'aquesta cadena i s'emmagatzema en una matriu. Per exemple, la longitud de la matriu serà el període de l'ona sinusoïdal a les mostres, que és igual a # de mostres / cicle. Si la freqüència de mostreig és de 48 kHz i la freqüència de la nota és de 100 Hz, hi ha 48.000 mostres / segon i 100 cicles / segon que porten a 4800 mostres per cicle, i la longitud de la matriu serà de 4800 mostres i contindrà els valors d’un complet període d'ona sinusoïdal. Quan es reprodueix la corda, la memòria intermèdia de mostra d’àudio s’omple prenent un valor de la matriu d’ones sinusoïdals i introduint-la a la memòria intermèdia d’àudio com a mostra, i després augmenta l’índex a la matriu d’ona sinusoïdal de manera que utilitzem el nostre exemple anterior al llarg del curs. de 4800 mostres es posa un cicle d'ona sinusoïdal a la memòria intermèdia d'àudio. S’utilitza una operació de mòdul a l’índex de matriu de manera que sempre cau entre 0 i la longitud, i quan l’índex de matriu supera un determinat llindar (com ara potser 2 segons de mostres), la cadena s’apaga. Per reproduir diverses cadenes al mateix temps, feu un seguiment de l'índex de matriu de cada cadena per separat i afegiu el valor de l'ona sinusoïdal de cada cadena per obtenir cada mostra.

Mètode 2: per crear un to més musical, comencem pel model anterior i afegim harmònics a cada freqüència fonamental. Les freqüències harmòniques són freqüències que són múltiples enters de la freqüència fonamental. A diferència de quan es combinen dues freqüències no relacionades, cosa que fa que es reprodueixin simultàniament dos sons diferents, quan s’afegeixen harmònics, continua sonant com un so, però amb un to diferent. Per aconseguir-ho, cada vegada que afegim el valor de l’ona sinusoïdal a la ubicació (índex de matriu% longitud de matriu) a la mostra d’àudio, també afegim (2 * índex de matriu% longitud de matriu) i (3 * índex de matriu% longitud de matriu)), i així successivament per a molts harmònics que es desitgin. Aquests índexs multiplicats travessaran l’ona sinusoïdal a freqüències que són múltiples enters de la freqüència original. Per permetre un major control del to, els valors de cada harmònic es multipliquen per una variable que representa la quantitat d'aquest harmònic en el so general. Per exemple, l’ona sinusoïdal fonamental pot tenir els seus valors multiplicats per 6 per convertir-la en un factor del so general, mentre que el cinquè harmònic pot tenir un multiplicador d’1, és a dir, els seus valors contribueixen molt menys al so general.

Mètode 3: d'acord, així que ara tenim un to molt agradable a les notes, però encara hi ha un problema bastant crucial: toquen a un volum fix durant una durada fixa. Per semblar un instrument real, el volum d'una corda que es toca hauria de decaure sense problemes amb el pas del temps. Per aconseguir-ho, s'omple una matriu amb els valors d'una funció en descomposició exponencial. Ara, quan es creen les mostres d'àudio, el so provinent de cada cadena es calcula com en el mètode anterior, però abans que s'afegeixi a la mostra d'àudio es multiplica pel valor de l'índex de matriu de les cadenes a la matriu de funcions de desintegració exponencial. Això fa que el so es dissipi sense problemes al llarg del temps. Quan l'índex de matriu arriba al final de la matriu de desintegració, la cadena s'atura.

Mètode 4: aquest darrer pas és el que realment dóna als sons de corda un so de corda realista. Abans sonaven agradables però clarament sintetitzats. Per intentar emular millor una corda d’arpa del món real, s’assigna una taxa de decadència diferent a cada harmònic. En cordes reals, quan es toca per primera vegada la corda, hi ha un alt contingut d’harmònics d’alta freqüència que crea el tipus de so de puny que esperem d’una corda. Aquests harmònics d'alta freqüència són molt breument la part principal del so, sentint-se el so de la corda, però decauen molt ràpidament a mesura que els harmònics més lents prenen el relleu. Es crea una matriu de desintegració per a cada nombre harmònic utilitzat en la síntesi de so cadascun amb la seva pròpia taxa de desintegració. Ara, cada harmònic es pot multiplicar independentment pel valor de la seva matriu de desintegració corresponent a l'índex de matriu de la corda i afegir-lo al so.

En general, la síntesi de so és intuïtiva, però el càlcul és intens. Emmagatzemar tot el so de les cordes a la memòria alhora necessitaria massa memòria, però calcular l’ona sinusoïdal i la funció exponencial entre tots els fotogrames trigaria massa a mantenir-se al dia amb la velocitat de reproducció d’àudio. S'utilitzen diversos trucs al codi per accelerar el càlcul. Totes les matemàtiques, excepte en la creació inicial de les taules de desintegració sinusoïdal i exponencial, es fan en format enter, que requereix distribuir l’espai numèric disponible a la sortida d’àudio de 24 bits. Per exemple, la taula sinusoïdal és d'amplitud 150 de manera que és suau però no tan gran que moltes cordes jugades juntes poden afegir més de 24 bits. De la mateixa manera, els valors de la taula exponencial es multipliquen per 80 abans de ser arrodonits a enters i emmagatzemats. Els pesos harmònics poden adoptar valors discrets entre 0 i 10. A més, totes les mostres es dupliquen i les ones sinusoïdals s’indiquen en 2, reduint a la meitat la taxa de mostreig. Això limita la freqüència màxima que es pot reproduir, però era necessari perquè el nombre actual de cordes i harmònics es calculés prou ràpidament.

Crear aquest model de so i fer-lo funcionar va suposar un esforç considerable en el costat del processador, i hauria estat increïblement difícil fer-lo funcionar des de zero en el costat fpga en el marc del temps d’aquest projecte (imagineu haver de recrear el flux de bits cada quan es va canviar un tros de verilog per provar el so). Tanmateix, fer-ho a l'fpga probablement podria ser una manera millor de fer-ho, eliminant possiblement el problema de no poder calcular mostres prou ràpidament i permetre executar més cadenes, harmònics i fins i tot efectes d'àudio o altres tasques al costat del processador.

Pas 6: Connexió dels sensors

Cablatge dels sensors
Cablatge dels sensors

Per crear les cordes hem utilitzat sensors de feix de trencament IR que detectaran quan es toca la corda. Vam demanar els nostres sensors des del següent enllaç. Els sensors tenen un cable d'alimentació, terra i dades, mentre que els emissors només tenen un cable d'alimentació i terra. Hem utilitzat els pins de terra de 3,3 V i de capçalera PMOD per alimentar tant els emissors com els sensors. Per alimentar tots els sensors i emissors és necessari connectar tots els sensors i l’emissor en paral·lel. Els cables de dades dels sensors hauran d’anar al seu propi pin pmod.

Pas 7: construcció de l'esquelet

Construint l’esquelet
Construint l’esquelet

Per tal de crear la forma de l’arpa, les tres peces s’utilitzen com a esquelet per col·locar-hi els sensors i els emissors. En una de les dues peces de canonada de PVC de 18 polzades, alineeu els sensors i els emissors en ordre altern de 1,5 polzades els uns dels altres i, a continuació, cinteu-los fins a la canonada. A l’altra canonada de PVC de 18 polzades, alineeu els sensors i els emissors en ordre altern, però assegureu-vos de compensar l’ordre (és a dir, si la primera canonada tenia un sensor primer, la segona hauria de tenir un emissor primer i viceversa). Caldrà soldar cables més llargs als cables de dades, alimentació i terra per assegurar-se que puguin arribar al tauler.

Pas 8: Construir l'exterior de fusta

Construint l'exterior de fusta
Construint l'exterior de fusta

Aquest pas és opcional, però és molt recomanable. L’exterior de fusta no només fa que l’arpa sembli agradable, sinó que també protegeix els sensors i els cables dels danys. El marc de fusta es pot crear mitjançant un anell rectangular de fusta. L'interior del rectangle ha de tenir una obertura d'almenys 1-1 / 2 polzades per adaptar-se a l'esquelet de la canonada i del sensor. Una vegada que es construeix el marc, practiqueu dos forats que permetran sortir els cables del sensor i dels emissors per connectar-los amb la placa.

* Nota: Es recomana afegir punts d’accés per poder treure i inserir l’esquelet de la canonada en cas que calgui fer reparacions o fer lleugers ajustos.

Pas 9: ajuntar totes les peces

Posant en comú totes les peces
Posant en comú totes les peces

Un cop acabats tots els passos anteriors, és hora de construir l'arpa. Primer, col·loqueu l’esquelet de la canonada dins de l’exterior de fusta. A continuació, connecteu els cables dels sensors i emissors a la ubicació correcta de la placa. A continuació, obriu l'SDK i feu clic al botó de depuració per programar la placa. Un cop programada la placa, connecteu uns auriculars o un altaveu. Depenent de quin sensor acabi en quin port pmod les cordes de l'arpa probablement estiguin fora de servei per començar. Com que pot ser difícil saber quin cable va a quin sensor quan hi ha tants cables, hem inclòs una manera de mapar números de cadena per interrompre les posicions de bits al programari. Cerqueu "static int sensor_map [NUM_STRINGS]" i ajusteu els valors de la matriu fins que les cadenes es reprodueixin de menor a major en ordre.

El menú es pot utilitzar obrint un terminal sèrie (per exemple, RealTerm) i estableix la velocitat de transmissió a 115200 i la pantalla a ANSI. Es pot navegar pel menú mitjançant les tecles w i s per moure amunt i avall i les tecles a i d per canviar els valors.

Pas 10: ROCK OUT

Un cop l’arpa estigui completament funcional. Domina l'arpa i escolta el dolç so de la teva pròpia música.

Recomanat: