1. septembra, 2020

Ustvarjanje zvoka z Arduino DAC in upori

ha 300x80 - Ustvarjanje zvoka z Arduino DAC in upori

Nisem bil zadovoljen z zvokom pravokotnih signalov, zato sem raziskoval kako z drugimi metodami ustvariti zvočne signale z Arduino.

Kaj vse je uporabljeno v tem projektu

Hardverske komponente

  • Digilent OpenScope MZ _ 1kos
  • Arduino UNO & Genuino UNO _ 1kos
  • Zvočnik: 0.25W, 8 Ohm _ 1kos
  • Kondenzator 100 nF _ 1kos
  • Potenciometer- 10k Ohm _ 1kos
  • Digilent Pmod R2R _ 1kos
  • NPN tranzistor _ 1kos

Softverske aplikacije in spletne storitve

  • Digilent WaveForms Live

Zgodba

Arduino ima vgrajeno funkcijo za ustvarjanje tonov, na GitHubu pa je knjižnica, ki uporabnikom omogoča razširitev števila sočasnih tonov, ki jih je mogoče predvajati od enega do treh. Ker pa Arduino ne vsebuje DACa (DAC = digitalno/analogni pretvornik) za generiranje resnično analognih signalov, tako vgrajena funkcija kot knjižnice dodatkov uporabljajo pravokotne signale za ustvarjanje tonov. Kot je opisano v mojem prejšnjem članku o digitalni sintezi zvoka, imajo pravokotni signali poseben zvok, ker so sestavljeni iz lihih harmoničnih frekvenc. Fizično ni mogoče ustvariti čistega tona, sestavljenega samo iz ene frekvence s pravokotnim signalom. Zaradi tega je zvok pravokotnega signala votel in oster.

Generiranje analognega signala
Da bi lahko generiral analogni signal, sem potreboval digitalno-analogni pretvornik (DAC). V bistvu DAC vzame binarno število in ga pretvori v določeno napetost. 8-bitni DAC ima 256 (00000000 do 11111111) različnih nivojev napetosti v referenčnem območju napetosti. Obstaja več vrst DAC-ov, pri čemer vsak uporablja drugačno metodo za ustvarjanje analognih izhodov. Eden najmanj tehničnih in tisti, do katerega sem imel dostop, je implementiran v 8-bitni R2R DAC Pmod podjetja Digilent.

R2R DAC uporablja strukturo, imenovano uporovni delilnik, za ustvarjanje diskretnih izhodov napetosti, kot je prikazano na Sliki 2.

Vsak priključek s številkami od D0 do D7 je na Arduino povezan z drugim digitalnim pinom. Nivo napetosti se izbere tako, da nastavite priključke, ki predstavljajo binarno število. Ker bo največji izhod 255, kar je v primeru Arduino 5V, je vsaka vrednost pod točko 5V del le-te. Torej bo 2,5V predstavljeno s 128 (polovica od 256 nivojev: 0 do 255) ali b1000000. V Falstadu sem ustvaril 8-bitni DAC R2R, da bi lažje razumel, kako deluje. Signali so razvrščeni od D0 do D7 od spodaj navzgor.

S tem DAC-om lahko ustvarite trikotni ali sinusni signal, ki bo imel harmonično sestavo, ki se sliši bolj naravno kot pravokotni signal. V Arduino kodi sem uporabil dve for-zanki za nastavitev vrednosti 8 različnih izhodnih priključkov in zaporedoma ponavljal skozi vrednosti do 255 v eni zanki in navzdol do 0 v drugi. Ta postopek ustvari trikotni signal.

Shema na Sliki 3 prikazuje, kako povezati D2 R2R na Arduino in zvočnik. Vzorec povezave priključkov je nastavljen tako, da odraža kodo, tako da, če spremenite vezavo, ne pozabite spremeniti tudi vrstnega reda v kodi.

Težave s časi
Specifičen način, kako se sliši posamezen ton, je rezultat osnovnih frekvenc, ki ga sestavljajo. Zato bo čas, ki je potreben za ustvarjanje ene periode signala določil frekvenco, v kateri niha. Ker postopek nastavitve vsakega priključka in iteriranja skozi for-zanke traja več taktnih ciklov procesorja, je največja frekvenca, ki jo lahko ustvarite z DAC-om R2R, omejena s številom korakov v vsaki zanki. Ugotovil sem, da sem po optimizaciji kode zmogel sintetizirati signal le približno 35Hz, kar je tik nad pragom za posluh. To je neposredno povezano s časom, ki ga Arduino potrebuje za kroženje po 512 stanjih, pri čemer vsak od 8 priključkov nastavi bodisi visoko ali nizko vrednost.

Veliko časa bi lahko prihranili z zmanjšanjem števila stanj, po katerih kroži Arduino. Igrajoč se s simulacijo Falstad, sem ugotovil, da so prvi štirje biti kode odgovorni le za spreminjanje spodnjih 292mV, kar pomeni, da jih lahko pustim vse na visokem stanju in še vedno imajo več kot 4V območja signala. Komplicira se, če bi bil moj signal manj gladek, saj bi preostali 4V imel le 16 stanj (saj bi moral spremeniti le štiri najpomembnejše bite). Z izvedbo teh sprememb sem lahko ustvaril signal pri 1130 Hz, kar je precejšnje izboljšanje v primerjavi s prejšnjim, komaj slišnim signalom.

Generiranje točnih tonov

Da bi natančno ustvaril različne tone, sem izračunal čas, ki traja, da Arduino itera skozi eno perido (ena za zanko navzgor in ena navzdol) brez zamud. Izkazalo se je, da je vrednost 1100 mikrosekund. Da bi ustvaril ton na kateri koli dani frekvenci, bi moral razdeliti zakasnitev med vsemi 32 napetostnimi nivoji, vsebovanimi v enem obdobju signala. Formula za vsako zamudo (v mikrosekundah) med nivojema je bila naslednja:

Delay = (1,000,000/[desired Hz] - 1100)/32

Imel sem že Arduino skico, ki je na začetku tega članka uporabljala povezano Github knjižnico tonov. Za predvajanje melodije sta uporabljena dva niza: eden za note (frekvence) in drugi za čas trajanja note. Programiral sem prvih nekaj tonov melodije iz prvega stavka Beethovnove Moonlight sonate, zato sem uporabil iste matrike za predvajanje melodije z uporabo DAC metode in knjižnice tonov. Poleg pričakovanih razlik v glasnosti (amplituda napetosti DAC signala ni tako visoka kot toni iz knjižnice tonov), je imel zvok drugačno kakovost.

DAC zvok ni bil tako “digitalen” in je imel bolj organsko kakovost. Vendar se zdi, da nekatere note niso bile tako natančne, zato je bila melodija bolj “usklajena”, ko uporabljamo knjižnico tonov. Na primer, A4, ki velja za 440Hz, se je z DACom predvajal na 437 Hz.

Uporabil sem OpenScope in WaveForms Live, da sem si ogledal hitro Fourierjevo transformacijo (FFT) istih tonov, ki sta jih ustvarila pravokotni in trikotni signal. Jasno je postalo, da je razlika v kakovosti zvoka posledica različnih harmonikov. Na spodnjih slikah je rumena črta DAC signal, modra pa predstavlja pravokotni signal.

DAC signal je skoraj v celoti sestavljen iz primarne frekvence (440Hz), s skoraj neobstoječim tretjim harmonikom. Pravokotni signal ima veliko močnejšo liho harmonično sestavo.
S tehnične strani knjižnica tonov uporablja strojne časovnike za izvajanje PWM signala s spremenljivo frekvenco. To pomeni, da se lahko med igranjem Arduina posluša ton, dodajanje dodatnih ukazov pa ne bo vplivalo na frekvenco.

V moji kodi je vsaka dodatna vrstica prispevala za ceno zmanjšane pasovne širine, zato je na voljo manj tonov. Po izračunih, ki so potrebni za predvajanje melodije iz matrike, je najvišja frekvenca, ki jo lahko ustvari moja koda, približno 920 Hz, ali pa je le sramežljiv ton A5, medtem ko lahko knjižnica tonov dosega kar 65,535 kHz ali več kot 3-krat višje, kot človek sliši.

Za zaključek
Menim, da je za večino uporab knjižnica tonov odlična izbira. Arduino ne samo da nenehno predvaja ton, vendar lahko prek enega zvočnika predvaja do tri tone hkrati. To je veliko več, kot si upam doseči z mojo kodo. Edina prednost, ki jo ima moj postopek pred tem, je, da so toni prijetnejši za poslušanje, saj bolj kot na pravokotne signale spominjajo na naravne zvoke. Vendar je bil to še vedno zanimiv projekt, saj sem lahko videl, kako bo vsaka vrstica kode vplivala na hitrost valovanja, kar je bil izziv za optimizacijo kode.

Povzeto po: https://www.hackster.io/boris-leonov/generating-audio-with-an-arduino-and-a-resistor-ladder-dac-d5a6b1

Opomba uredništva: z nekaj asemblerskimi ukazi lahko AVR, ki ga krmilimo s 24 MHz, generira signale v sinusni, pravokotni ali trikotni obliki do 9 MHz. Več informacij najdete na: https://bit.ly/30WAkeC

Hackster Inc.
Avtorji: Boris Leonov, Sam Kristoff, Arthur Brown
2020_288_37
https://hackster.io