Pages: [1]   Go Down
Author Topic: DAC e Ripple  (Read 2007 times)
0 Members and 1 Guest are viewing this topic.
Parma
Offline Offline
Edison Member
*
Karma: 21
Posts: 2388
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao a tutti,
Ho realizzato qualche tempo fa un DAC (Digital-Analog-Converter) ad 8 bit basato sulla rete R-2R http://en.wikipedia.org/wiki/Resistor_ladder, con l'arrivo dell'oscilloscopio ho provato a verificare quali prestazioni poteva offrirmi.
All'uscita ho inserito un amplificatore operazionale LM358 in configurazione inseguitore di tensione http://it.wikipedia.org/wiki/Inseguitore_di_tensione e questo ha limitato diciamo l'escursione massima a 3.88 volt al posto dei 5 canonici, risolvibile alimentando con una tensione superiore l'integrato o utilizzando un op-amp equivalente rail-to-rail.

Ho notato generando una sinusoide (codice sperimentale in allegato) però che il segnale che ottengo è abbastanza "sporco", presenta dei picchi anche elevati che si attenuano al calare della frequenza, ecco la schermata dell'oscilloscopio (sinusoide a 73 Hz):



Cos'è secondo voi? una sorta di limite dovuto alle resistenze che ho scelto (9K e 18K) o all'op-amp o qualcos'altro?

La misura del ripple sull'alimentazione dell'op-amp:



Risulta relativamente elevata con un Vrms di 7 mV, è troppo?



Ecco infine la schedina:




Ciao e grazie a tutti

* DAC.ino (1.92 KB - downloaded 15 times.)
Logged

Rome
Offline Offline
God Member
*****
Karma: 1
Posts: 643
La mia prima bromografata!!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao a tutti,
Ho realizzato qualche tempo fa un DAC (Digital-Analog-Converter) ad 8 bit basato sulla rete R-2R http://en.wikipedia.org/wiki/Resistor_ladder, con l'arrivo dell'oscilloscopio ho provato a verificare quali prestazioni poteva offrirmi.
All'uscita ho inserito un amplificatore operazionale LM358 in configurazione inseguitore di tensione http://it.wikipedia.org/wiki/Inseguitore_di_tensione e questo ha limitato diciamo l'escursione massima a 3.88 volt al posto dei 5 canonici, risolvibile alimentando con una tensione superiore l'integrato o utilizzando un op-amp equivalente rail-to-rail.

Ho notato generando una sinusoide (codice sperimentale in allegato) però che il segnale che ottengo è abbastanza "sporco", presenta dei picchi anche elevati che si attenuano al calare della frequenza, ecco la schermata dell'oscilloscopio (sinusoide a 73 Hz):



Cos'è secondo voi? una sorta di limite dovuto alle resistenze che ho scelto (9K e 18K) o all'op-amp o qualcos'altro?

La misura del ripple sull'alimentazione dell'op-amp:



Risulta relativamente elevata con un Vrms di 7 mV, è troppo?



Ecco infine la schedina:




Ciao e grazie a tutti
Purtroppo non so aiutarti, però...che saldature..
Logged

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 129
Posts: 9515
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ho notato generando una sinusoide (codice sperimentale in allegato) però che il segnale che ottengo è abbastanza "sporco", presenta dei picchi anche elevati che si attenuano al calare della frequenza, ecco la schermata dell'oscilloscopio (sinusoide a 73 Hz):

Il problema è dovuto alla lentezza della digitalWrite, circa 2 us per ogni operazione, tu cambi i singoli bit (pin) tramite otto digitalWrite e questo ti porta ad avere otto valori diversi nel tempo durante il cambio dello stato dei pin, va da se che a seconda del valore binario ottieni diversi valori analogici e questo crea i picchi che osservi.
Anche se i picchi sono di breve durata, pochi us, il DSO te li visualizza sotto forma di glitch amplificandone la durata apparente a seconda della time base in modo da evidenziare il fatto.
Devi modificare tutti bit nello stesso istante, ovvero non devi usare la digitalWrite ma scrivere direttamente su i registri dei port interessati, l'ideale è utilizzare gli otto bit di un solo port, su Arduino è possibile solo con PORTD, pin da 0 a 7, non dovresti avere problemi ad utilizzare la seriale per programmare Arduino perché i PIN sono settati come OUT e non c'è nessun carico su Tx e Rx.
Logged

Parma
Offline Offline
Edison Member
*
Karma: 21
Posts: 2388
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Grazie astrobeed,
Avevo pensato anche a questo ma non è che poi non riesco più a riprogrammare Arduino se inizio a scrivere sulla seriale?
Logged

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 129
Posts: 9515
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ma non è che poi non riesco più a riprogrammare Arduino se inizio a scrivere sulla seriale?

No perché i due pin Tx e Rx (0 e 1) li usi come out, il problema si presenta se li usi come input dove hai un segnale esterno che prevale su quello del convertitore USB-UART (è collegato ai pin tramite due resistenze da 1k) o colleghi un dispositivo seriale esterno.
Tieni presente che quando resetti Arduino, manualmente o autoreset che sia, entra il funzione il bootloader che scavalca qualunque setup che fai dal tuo software, pertanto fino a che non scade il timeout prestabilito, pochi decimi di secondo, il tuo sketch non viene avviato e il bootloader può utilizzare la seriale a suo uso esclusivo.




Logged

Offline Offline
Sr. Member
****
Karma: 0
Posts: 361
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Puoi anche usare un shift register esterno. (quindi solo due pin a tua scelta dell' Arduino)

Io comunque preferirei PORTD.
Logged

Parma
Offline Offline
Edison Member
*
Karma: 21
Posts: 2388
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Scusa, non ho capito come potrei usare uno shift register per cambiare in un colpo solo tutti i pin, se devo passare da una configurazione 01010101 ad una del tipo 11111111 con lo shift register ci riuscirei in un colpo solo? Come soluzione mi viene in mente solamente disabilitare l'output, impostare il valore tramite tante cicli dove butto dentro allo shift register degli 1 e poi riabilitare l'output ma il tutto diventa estremamente lento.. PORTD sembra molto più efficente.

Ciao
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 332
Posts: 22817
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Gli shift register hanno un registro interno che viene caricato bit per bit. Una volta che hai impostato il valore, dai l'impulso sul latch ed il registro spedisce contemporaneamente il valore del registro interno sui piedini esterni.

Sicuramente manipolare la porta del micro ti fa perdere meno tempo.
Logged


Parma
Offline Offline
Edison Member
*
Karma: 21
Posts: 2388
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sono tornato a casa e ho provato le migliorie:
- Usando PORTD (ed eliminando il rescaling tramite moltiplicazione) sono riuscito ad ottenere una frequenza massima di 2604 Hz ed un output molto pulito, senza nessun glitch. Per un DAC a 8 bit mi sembra abbastanza buono, tramite la FFT la frequenza generata ha +2 Db e le altre sono molto attenuate (non mi ricordo quanto ma abbastanza)

- Ho scoperto che con
  cli();  // disable global interrupts, millis timer, and serial communication will be affected by disabling interrupts 
la frequenza generata è più stabile, altrimenti varia un pochino (di qualche Hz).

Mi ritengo molto soddisfatto per il momento.
Ringrazio tutti per i suggerimenti che mi avete dato.
Logged

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 129
Posts: 9515
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

- Usando PORTD (ed eliminando il rescaling tramite moltiplicazione) sono riuscito ad ottenere una frequenza massima di 2604 Hz ed un output molto pulito, senza nessun glitch. Per un DAC a 8 bit mi sembra abbastanza buono,

Tenuto conto che ad ogni sinusoide completa devi effettuare 256 cambi di stato del DAC in realtà esegui ben 2604*256 = 666624 cicli ad ogni secondo, un buon risultato per una piccola mcu che va a solo 16 MHz  smiley
Sicuramente ottimizzando al massimo puoi salire sensibilmente di frequenza, però tocca lavorarci molto sopra e usare vari "trucchi" di programmazione per risparmiare cicli macchina.
Logged

Parma
Offline Offline
Edison Member
*
Karma: 21
Posts: 2388
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Non mi interessa andare oltre queste frequenze con Arduino per il momento, più avanti farò un piccolo generatore di segnali in HW con una CPLD e sarà sicuramente molto più veloce smiley

Più che altro ci tenevo a dire che per risolvere il problema della saturazione dell'op-amp ho fatto così: in pratica tenendo sempre a GND il pin 7 del DAC ed eseguendo uno shift sul dato da scrivere (es. PORTD = data >> 1) trasformo per l'evenienza il DAC in un 7 bit che non fa saturare l'op-amp smiley
Logged

Parma
Offline Offline
Edison Member
*
Karma: 21
Posts: 2388
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Senza stare li a perdere tempo per ottimizzare al massimo il codice di Arduino, ho implementato in Hardware invece che in software su CPLD (http://www.electroit.tk/index.php?topic=175.0) un DDS che manda i bit al DAC, ogni ciclo di sinusoide è composto da 16 step, a 50 MHz ho quindi generato una sinusoide a 3MHz circa:

Onda e FFT


Dettaglio sull'onda:


L'onda appare con un'ampiezza di 800mV nonostante VCC sia 3.3V.. ma va bene lo stesso

Ciao
« Last Edit: May 25, 2012, 03:26:03 am by flz47655 » Logged

Pages: [1]   Go Up
Jump to: