Arduino DUE: ADC

Nel datasheet della atmel di arduino due ho visto le caratteristiche dell’adc.
riporto in seguito qualche riga:

46.7.0.1 Static performance characteristics
Minimal code=0
Maximal code=4095
ADC resolution = 12 bits (4096)
In the following tables, the LSB is relative to analog scale:
• Single Ended (ex: ADVREF=3.0V),
– Gain = 1, LSB = (3.0V / 4096) = 732uV
– Gain = 2, LSB = (1.5V / 4096) = 366uV
– Gain = 4, LSB = (750mV / 4096) = 183uV
• Differential (ex: ADVREF=3.0V),
– Gain = 0.5, LSB = (6.0V / 4096) = 1465uV
– Gain = 1, LSB = (3.0V / 4096) = 732uV
– Gain = 2, LSB = (750mV / 4096) = 366uV

domande:

  1. l’arduino due può avere in ingresso segnali differenziali ? se si ? quali sono i pin per il in+ e in-
  2. l’arduino due lavora a 3.3 v quindi i gain 1,2,4 sono 3.3 , 1.650 e 825 mv ?
  3. cioè significa che io posso settare un fondo scala di lettura di 825 mv, e avere un LSB = (825mV / 4096) = 201uV ?

grazie
gcam

gcam: 1. l’arduino due può avere in ingresso segnali differenziali ? se si ? quali sono i pin per il in+ e in-

Il datasheet parla di ingressi differenziali nel cap. 44.6.8. I pin sono accoppiati secondo la tabella 44.5.

Sulle altre due domande i valori sono riferiti a 3V per cui devi fare i conti con la tensione di 3V3 dell'Arduino, per cui direi che i tuoi risultati sono corretti: (3,3/4)/4096=201uV

innanzitutto grazie.

Operativamente come faccio ad applicare un GAIN =4, cioè settare il range a 825 mV.

Facendo un esempio se io fornisco al canale analogico 830 mV dovrei ottenere come valore 4095 (count) il massimo valore misurabile. se ottengo invece circa 1030 (count) il fondo scala è ancora 3300 mV.

come si setta il GAIN o RANGE ???

gcam

gcam: .... come si setta il GAIN o RANGE ???

Capitolo 44.6.9 "Input Gain and Offset" ... sarebbe il caso che ti [u]STUDI[/u] il datasheet prima di voler usare un prodotto ... ]:D

Guglielmo

forse (sicuramente) mi sto addentrando in qualcosa che non conosco.

Con le librerie fornite con arduino si possono fare queste cose, oppure bisogna lavorare (programmare) a basso livello.

nel caso di programmazione a basso livello a cosa faccio riferimento per iniziare a capire.

Fino ad ora la mia programmazione a basso livello (se cosi si può definire) si è limitata all'uso di dispositivi esterni collegati ad arduino e comunque utilizzando le librerie fornite con il sistema arduino.

gcam

gcam: forse (sicuramente) mi sto addentrando in qualcosa che non conosco.

Con le librerie fornite con arduino si possono fare queste cose, oppure bisogna lavorare (programmare) a basso livello.

Le librerie di Arduino sono limitate, Arduino è un prodotto che segue la filosofia della semplificazione per i novizi. Se vuoi fare molte delle cose permesse da un micro devi manipolare i registri a mano.

nel caso di programmazione a basso livello a cosa faccio riferimento per iniziare a capire.

Il "cuore" di tutto sono i registri di un microcontrollore, sono quelli che permettono la manipolazione delle sue periferiche a livello base. Però per iniziare è meglio un micro più semplice, l'Atmega328 è un sistema più semplice con cui farti le ossa. Poi, capito come si fa, passi al Sam3X.

Quindi al di là della difficoltà di di gestire i registri del microcontrollore (capire quali e come modificarli), praticamente se io vorrei gestire il range dell'adc del microcontrollore, dovrei realizzare una libreria che mi consente di modificare i registri e poi utilizzarla, nei miei programmi.

Una libreria non è strettamente necessaria, in definitiva bastano fare le modifiche ai vari registri a seconda di quel che devi fare. Certo, se devi fare diverse operazioni conviene usare una lib, almeno la puoi riutilizzare nei tuoi programmi.

Per utilizzare i canali in differential mode, basta semplicemente rispettare i collegamenti specificati nella tabella 44.5. Oppure è necessario impostare il differential mode agendo da qualche parte nel registro.

Tra i pin dell'Arduino due ho visto un pin 5v. E' possibile pensare di alimentare dispositivi esterni con questo pin ed utilizzarli in modalità 3.3 v

Esempio pratico perchè non so se sono riuscito a spiegarmi completamente: posso utilizzare l'adc LTC2440, che richiede un'alimentazione a 5v ed e settare la ref in modo che fornisce valori a 3.3 v

1) Devi impostare il modo differenziale. Di default l'Arduino usa l'ADC in single mode.

2) il pin 5V serve per fornire alimentazioni a dispositivi che usano questa tensione, la corrente erogabile è quella massima della porta USB o del regolatore integrato se usi il jack. Non ho capito il discorso di dare 5V ad un componente esterno che poi deve rispondere a 3V3

Infatti come pensavo non sono riuscito a esternare correttamente il mio dubbio.

Faccio la domanda diretta: posso collegare all'arduino due attraverso l'interfaccia spi o i2c dispositivi (ADC: esempio LTC2440) che richiedono una alimentazione a 5 v.

Sicuramente non posso utilizzare il sensore di distanza della sharp che richiede 5 v è ritorna un valore proporzionale alla distanza compreso tra 0 e 5 volt. In quanto il canale analogico dell'arduino accetta valori compresi tra 0 e 3.3 v

gcam: Infatti come pensavo non sono riuscito a esternare correttamente il mio dubbio.

Faccio la domanda diretta: posso collegare all'arduino due attraverso l'interfaccia spi o i2c dispositivi (ADC: esempio LTC2440) che richiedono una alimentazione a 5 v.

No. Ti serve un traslatore di livelli o, comunque, un partitore per portare i 5V in uscita dalla scheda che lavora a queste tensioni ai 3V3 accettate dai pin della DUE.

Sicuramente non posso utilizzare il sensore di distanza della sharp che richiede 5 v è ritorna un valore proporzionale alla distanza compreso tra 0 e 5 volt. In quanto il canale analogico dell'arduino accetta valori compresi tra 0 e 3.3 v

Ma puoi riportarlo nell'intervallo 0-3V3 con un partitore. Sicuramente perdi precisione, questo è sicuro.

Come faccio a settare un diverso valore di GAIN per i canali analogici ?

Come faccio a passare al differential mode ?

eternamente grato a chi mi può fornire uno stralcio di codice.

gcam

gcam:
Come faccio a settare un diverso valore di GAIN per i canali analogici ?

Datasheet pag. 1361: prima metti a 0 il bit WPEN del registro di stato dell’ADC, poi cambi il GAIN.

Come faccio a passare al differential mode ?

Datasheet pag. 1362: prima metti a 0 il bit WPEN del registro di stato dell’ADC, poi scegli la coppia di ingressi differenziali.

eternamente grato a chi mi può fornire uno stralcio di codice.

Non ho avuto modo di spippolare con l’ADC della DUE, per cui non so se bastano queste cose:

  • per scegliere il gain:
ADC->ADC_WPMR &= ~(1<<ADC_WPMR_WPEN);
ADC->ADC_CGR = 0x0003; // es.: guadagno 4 su GAIN0

Per la modalità differenziale, sarà simile immagino:

ADC->ADC_WPMR &= ~(1<<ADC_WPMR_WPEN);
ADC->ADC_COR = 0x0300; // es.: ingressi differenziali DIFF0/DIFF1 (??)

Prendili col beneficio del dubbio :sweat_smile: :sweat_smile:

immensamente grazie.

Faccio i dovuti test e prove e posto i risultati.

domanda: ADC->ADC_CGR = 0x0003; // es.: guadagno 4 su GAIN0 significa che sto settando gain = 4 per il GAIN0 cioè per il canale analogico 0 ?

se si. Per cambiare il valore di un canale analogico diverso, oppure per cambiare il valore a due canali analogici ?

ADC->ADC_COR = 0x0300; // es.: ingressi differenziali DIFF0/DIFF1 (??) significa che sto settando la modalità differenziale per il canale analogico 0 e 1 ?

identica domanda.

gcam

Se hai visto le pagine del datasheet che ti ho linkato, avrai visto che il gain e la mod. differenziale si attivano con coppie di bit da modificare nel registro. Quelli che vedi sono appunto questi bit modificati. Nello specifico del GAIN, vedo che mettendo la coppia di bit "11" si attiva la mod. 4x. In binario, 11 equivale a 3, da cui quel valore.

Nel secondo caso ho usanto i numeri esadecimali perché scrivere 0b00000000000000110000000000000000 era un pò lunghetto :sweat_smile:

Di default (gain=1) il registro dovrebbe avere questo valore : 01010101010101010101010101010101 cioè 01 per ogni canale da A0-A15

se io voglio cambiare il gain di un canale al registro nella posizione corrispondente al canale cambio 01 con 11

Cioè se cambio il gain del A1 il valore è: 01010101010101010101010101011101 corrispondente all'esadecimale: 0x5555555D

In un t3 ho visto questa riga

ADC->ADC_CGR=0xFFFF; //setto il Gain = 4 per i canali da A0-A7

in quanto 0xFFFF corrisponde al binario: 11 11 11 11 11 11 11 11

e i valori del registro A8-A15 rimangono inalterati. Per capire partendo da destra verso sinistra vengono cambiati sono i valori specificati e gli altri rimangono inalterati

Esempio se voglio cambiare il gain del canale A1 e lasciare inalterati gli altri considero il binario 1101 corrispondente all'esadecimale D e quindi l'istruzione diventa: ADC->ADC_CGR=0x000D; //setto il Gain = 1 per il canale da A1

o bisogna settare l'intero registro: ADC->ADC_CGR=0x5555555D; //setto il Gain = 1 per il canale da A1

gcam

Non ho capito molto del tuo post, ma se vuoi cambiare solo il gain di un canale, devi usare le operazioni sui bit.
Ad esempio, se vuoi mettere ad 1 il bit in posizione 10, devi usare una formula tipo questa:

ADC->ADC_CGR |= (1 << 10);

Questa equivale anche a:

bitSet(ADC->ADC_CGR, 10);

Per metterlo a 0:

ADC->ADC_CGR &= ~(1 << 10);

che corrisponde a:

bitClear(ADC->ADC_CGR, 10);

Se devi combinare le operazioni, ad esempio mettere ad 1 i bit 10 e 11:

ADC->ADC_CGR |= ((1 << 10) | (1 << 11));

Similarmente, per spengere quei 2 bit:

ADC->ADC_CGR &= ~((1 << 10) | (1 << 11));

Ricordati che il Sam3x vuole sempre il pin WPEN del registro ADC_WPMR messo a 0 subito prima della modifica dei questi bit.

Ok. Hai azzeccato la risposta.

Quindi nel caso del Sam3x dato che i registri sono a 32 bit la posizione dell’ennesimo bit da cambiare è un numero compreso

0 <= n < 32,

qualunque sia registro da cambiare.

grazie.
gcam

Sì, giusto. La posizione va sempre da 0 a max_numero_di_bit-1, per cui se hai un registro a 32 bit, si va da 0 a 31. Se hai un registro a 16 bit, si va da 0 a 15 ecc…