Spiegazione sketch generatore di funzioni

Buona sera a tutti.
Sono uno studente all’ultimo anno del corso di elettronica e come progetto d’esame vorrei portare un generatore di funzioni utilizzando un arduino.
Il generatore di funzione prevede 4 forme d’onda ( sinusoidale, quadra, triangolare e sega).
Arduino dovrà gestire le forme d’onda generando su 8 uscite parallele sequenze binarie, che andranno convertite in seguito.
lo sketch l’ho preso dal sito http://www.instructables.com/id/Arduino-Waveform-Generator/?ALLSTEPS
e da un primo test sembra funzionare.
Non riesco a capire solo come funziona il programma non avendo mai utilizzato quei comandi e non avendo un professore competente in materia.
Chiedo quindi alla gentile comunità spiegazioni riguardo al funzionamento del programma il piu possibile precisa.
allego il file .ino con lo skatch

Grazie in anticipo

function_generator.ino (92.3 KB)

Ti invitiamo a presentarti qui: http://forum.arduino.cc/index.php?topic=113640.0 e a leggere il regolamento: http://forum.arduino.cc/index.php?topic=149082.0 - qui una serie di schede by xxxPighi per i collegamenti elettronici vari: http://forum.arduino.cc/index.php?topic=146152.0 - qui le pinout delle varie schede by xxxPighi: http://forum.arduino.cc/index.php?topic=151646.0 - qui una serie di link utili: http://forum.arduino.cc/index.php?topic=126861.0

mi scuso per non essermi presentato non avevo visto la sezione apposita

ho una conoscenza, anche se minima, dei comandi di base avendoli studiati su manuali on-line e sarei molto felice di ricevere spiegazioni anche su comandi del tipo byte sine20000[]PROGMEM=... oppure su come faccia a calcolare i valori della sinusoide o triangolare. grazie

xibisx: Non riesco a capire solo come funziona il programma non avendo mai utilizzato quei comandi e non avendo un professore competente in materia. Chiedo quindi alla gentile comunità spiegazioni riguardo al funzionamento del programma il piu possibile precisa.

Non è facile spiegare il funzionamento dello sketch se non si ha un minimo di dimestichezza con i timer. Ti consiglio, per una prima infarinatura, di scaricarti lo ZIP che trovi allegato a questo post: http://forum.arduino.cc/index.php?topic=167655.msg1303328#msg1303328

Ci sono un paio di presentazioni che ho mostrato all'incontro della comunità che si è tenuto l'anno scorso a Bassano del Grappa dove ho mostrato (a grandi linee) timer ed interrupt (trovi anche uno sketch che replica un'Atari Punk Console). Detto questo, lo sketch che hai mostrato sfrutta un timer per generare il segnale d'onda che desideri manipolando direttamente la porta logica D del microcontollore (vedi anche QUI per una spiegazione sulle porte logiche) e ricreare la forma d'onda. Perché viene usato un timer ed il corrispondente interrupt ad esso agganciato? Perché necessita lo sketch di un temporizzatore preciso, e di una funzione di generazione che venga richiamata ad intervalli estremamente precisi. Il timer è un registro interno che si incrementa continuamente con una certa frequenza (che viene impostata all'inizio) e poi chiama l'interrupt ad ogni overflow oppure al raggiungimento di un valore prefissato. A quel punto viene lanciata la routine che genera l'onda. Siccome il chip di suo è capace solo di generare onde quadre (pin on oppure pin off) per generare le onde triangolari si gioca sull'incremento decremento di una variabile a step prefissati mentre per l'onda sinusoidale (tieni conto però che non è una vera sinusoide dato che non hai 2 creste una positiva ed una negativa ma solo un'onda tutta positiva, perché i pin del chip non possono gestire tensioni negative) si usa una "mappa" dell'onda. Questa mappa, siccome è molto complessa, viene salvata in FLASH e non in RAM con l'istruzione PROGMEM, di cui chiedevi appunto più sotto:

xibisx: ho una conoscenza, anche se minima, dei comandi di base avendoli studiati su manuali on-line e sarei molto felice di ricevere spiegazioni anche su comandi del tipo byte sine20000[]PROGMEM=... oppure su come faccia a calcolare i valori della sinusoide o triangolare. grazie

Questo perché la RAM dell'Atmega328 è limitata (2K) e la occuperesti tutta creando quel vettore: tieni conto che in RAM ci stanno anche tutte le altre variabili del programma nonché lo stack, quindi la esauriresti presto. Per evitare ciò si usa PROGMEM per dire al compilatore che i dati vanno tenuti in FLASH (di default, tutte le variabili sono copiate in RAM prima di usarle) e recuperate con una funzione apposita (pgm_read_byte_near). (su PROGMEM altre info le trovi QUI e QUI).

Grazie mille, adesso riesco a capire qualcosa in più. Riassumendo: il timer genera continuamente valori ad una velocità prefissata, ad ogni incremento viene richiamato l'interrupt che a sua volta genera la funzione matematica che darà luogo all'onda. I pin di uscita vengono gestite tramite i registri che consentono una scrittura molto veloce. Per modificare la frequenza desumo che lo sckatch andrà a calcolare il valore della funzione che gestisce la forma d'onda.

xibisx:
Grazie mille, adesso riesco a capire qualcosa in più.
Riassumendo: il timer genera continuamente valori ad una velocità prefissata, ad ogni incremento viene richiamato l’interrupt che a sua volta genera la funzione matematica che darà luogo all’onda.

Un timer è semplicemente un circuito che incrementa il valore contenuto in una particolare cella di memoria ad intervalli prefissati. Quando il valore di quella cella raggiunge quello di un altro registro prefissato oppure quando va in overflow (cioè riparte da 0) viene sollevato un interrupt.
L’interrupt fa eseguire al chip una particolare routine associata che si occupa di alterare i pin in modo da ricreare l’onda desiderata.

I pin di uscita vengono gestite tramite i registri che consentono una scrittura molto veloce.

Ogni timer ha dei pin a cui è agganciato direttamente, in questo caso il timer può essere programmato affinché cambi automaticamente lo stato di questi pin. Questo è il sistem più veloce ma anche più limitato perché puoi solo generare onde quadre.
Per le altre funzioni i pin vengono pilotati in maniera diversa, direttamente da codice.

Per modificare la frequenza desumo che lo sckatch andrà a calcolare il valore della funzione che gestisce la forma d’onda.

Ci sono vari modi, puoi agire sia sulla frequenza del timer stesso sia anche da codice modificando i parametri software.
Però qui mi fermo perché non sono addentro alla generazione software di segnali audio :wink:

Grazie mille sempre molto gentile. A questo punto se riesci a dirmi, a grandi linee, come vengono formate le onde triangolari e a sega concludiamo la descrizione generale.

Mi spiace non riesco a darti altre info in merito, non sono ferrato nella generazione audio, come ti ho detto :sweat_smile: Nella pagina che hai linkato ho visto che il progetto si basa su un DAC costruito con una batteria di resistenze, mi sembra però che ad un certo punto spieghi come realizza la cosa.

A grandi linee mi sembra di capire che l'onda viene creata variando il tempo con cui il passaggio tra i vari pin del chip che sono collegati al DAC. Il DAC, poi, unisce gli impulsi digitali trasformandoli in un segnale analogico che, grazie all'amplificatore, genera il suono finale.

Da quello spiegato fino ad adesso penso che l'onda triangolare e a sega venga generata creando intervalli successivi di valori che poi il DAC decodificherà. Mi sono immaginato di inserire, su un grafico tensione/tempo, i valori della tensione che rappresentano l'onda. Arduino non farà altro che convertire questi valori, ad intervalli prefissati, in sequenze binarie.

Sì, il succo è questo. Con l'Arduino generi dei segnali digitali che fai entrare nel DAC, da cui poi escono miscelati in un unico segnale analogico. L'onda viene creata spedendo ai pin di output i segnali on/off secondo schemi precisi in modo da avere per l'onda triangolare una rampa regolare di salita e poi la caduta istantanea, per quella a dente di sega un'alternanza fra rampe in salita ed in discesa. Per quella sinusoidale c'è una mappatura di una curva codificata in memoria dove ci sono i valori per il grafico tensione/tempo a cui accennavi tu.

ok ho capito tutto (per adesso) grazie infinite per il gentile e tempestivo aiuto :)