La conversione ADC in una tensione si basa sul valore effettivo del pin +5 V?


13

Domande:

  1. La conversione dell'ADC conta in tensione dipende dalla tensione effettiva del pin +5 V?
  2. Se sì, qual è il metodo accettato per ottenere quella tensione dalla scheda?

Background / dettaglio:

Ho un circuito in cui ho un Arduino Nano (clone) in esecuzione da un connettore USB (da un hub). Il compito dell'Arduino è misurare la tensione di una batteria che guiderà un secondo circuito acceso / spento da Nano. Per riferimento è un tester batteria.

Circuito di prova

C'è uno schermo del Nokia 5110 che mostra la tensione dal semplice schizzo qui sotto.

void setup() {
  Serial.begin(9600);
  display.begin();
  // Init done

  // You can change the contrast around to adapt the display
  // for the best viewing!
  display.setContrast(50);

  // Text display tests
  display.setTextSize(1);
  display.setTextColor(BLACK);
}


void loop() {
  display.clearDisplay();   // Clears the screen and buffer
  display.setCursor(0,0);
  display.print("Vin=");
  int rawVIN = analogRead(VIN);
  float floatVin = (rawVIN*4.75)/1023.0;
  display.println(floatVin);
  Serial.println(rawVIN);
  display.display();
  delay(1000);
}
  • Ho misurato la tensione della batteria usando un DVM ed è 4,13 V, ma il Nano riporta 4,35 V.
  • Ho un terreno comune tra la batteria e Arduino.
  • Poiché la connessione per testare la tensione può fluttuare, ho un resistore a discesa per arrestare le fluttuazioni selvagge (> 10 kΩ)

Dopo alcune indagini ho scoperto che il +5 V stava effettivamente producendo 4,75 V e ho cambiato il mio schizzo

float v = (rawVIN*5.0)/1024.0;

per

float v = (rawVIN*4.75)/1024.0;

e la lettura della tensione sull'Arduino era ora corretta. Non l'ho fatto perché ho capito cosa ho fatto, l'ho fatto perché avevo la sensazione che potesse cambiare il valore in quello corretto.


3
Per contro, dovresti dividere per 1024, non per 1023. Questo è un errore che si ripete più volte, presumibilmente derivante dall'errore negli esempi di Arduino. Fonte? Il foglio dati per l'AVR.
Tom Carpenter,

@TomCarpenter Penso che questo sia il risultato del mio armeggiare con il calcolo e la lettura di qualcosa dopo un bel po 'di tempo a sbattere la testa contro la scrivania - ho iniziato con 1024 ma come vedi è finito con 1023 - Correggerò la mia domanda .
Caribou,

Risposte:


16

L'ADC all'interno dell'Arduino non misura la tensione, ma piuttosto un rapporto di tensione . Vale a dire il rapporto tra la tensione sull'ingresso analogico e la tensione sul pin Vref.

Nella configurazione predefinita, il pin Vref è internamente legato alla linea +5 V. Puoi selezionare invece di utilizzare un riferimento interno come Vref :

analogReference(INTERNAL);

Questo riferimento è di circa 1,1 V ed è abbastanza immune alle fluttuazioni di +5 V. Il problema è che non è possibile misurare tensioni superiori al riferimento.

Per il tester della batteria, se si desidera una sorta di misurazione "assoluta", è possibile utilizzare il riferimento interno e un divisore di tensione per assicurarsi che la tensione misurata sia inferiore a 1,1 V.

Modifica : Un'altra opzione che non richiede un partitore di tensione è l'uso di Vcc come riferimento per misurare sia l'ingresso analogico sia il riferimento interno “bandgap” 1.1 V. Misurare 1.1 V contro Vcc è un modo indiretto per misurare Vcc. Questo non è supportato dalla libreria principale di Arduino, ma puoi farlo programmando direttamente i registri di controllo dell'ADC:

// Return the supply voltage in volts.
float read_vcc()
{
    const float V_BAND_GAP = 1.1;     // typical
    ADMUX  = _BV(REFS0)    // ref = Vcc
           | 14;           // channel 14 is the bandgap reference
    ADCSRA |= _BV(ADSC);   // start conversion
    loop_until_bit_is_clear(ADCSRA, ADSC);  // wait until complete
    return V_BAND_GAP * 1024 / ADC;
}

Attenzione che la prima lettura dopo l'avvio potrebbe essere fasulla.


Grazie per la pronta risposta :) ora ha perfettamente senso e spiega perché con la mia regolazione del codice (fudge) ottengo la risposta giusta. Questo combinato con la risposta enrica mi dà tutto ciò di cui ho bisogno per continuare.
Caribou,

9

Un Arduino Nano alimentato tramite USB avrà un riferimento di tensione ADC sul quale non è possibile fare affidamento, a causa della tolleranza +/- 5% della tensione USB in ingresso. Inoltre, il Nano ha un diodo Schottky MBR0520 (D1) che scenderà tra 0,1 e 0,5 V a seconda delle proprie tolleranze di fabbricazione, della sua temperatura e dell'assorbimento di corrente della scheda.

Cosa puoi fare al riguardo?

L'MCU a bordo dell'Arduino Nano è un ATmega328P. L'ADC di Nano può ridimensionare le letture della tensione analogica in base a diversi riferimenti disponibili (e puoi scegliere quello più adatto a te). Puoi farlo attraverso la analogReference (type)funzione e scegliere tra i seguenti riferimenti type:

  • DEFAULT: il riferimento analogico predefinito di 5 volt (su schede Arduino 5 V) o 3,3 volt (su schede Arduino 3.3 V)
  • INTERNO: un riferimento incorporato, pari a 1,1 volt su ATmega168 o ATmega328 e 2,56 volt su ATmega8 (non disponibile su Arduino Mega) [...]
  • ESTERNO: la tensione applicata al pin AREF (solo da 0 a 5 V) viene utilizzata come riferimento.

Fonte: analogReference

Questo è lo schema ADC per ciò che è dentro ATmega328 in modo da poter vedere cosa sta succedendo lì:

Blocco ADC ATmega328P

Fonte: scheda tecnica ATmega328

Quindi la soluzione semplice sta costruendo un divisore di tensione debole per ottenere la tensione che si desidera misurare al di sotto del riferimento INTERNO 1.1 V, e quindi configurare di analogReferenceconseguenza.

Il divisore di tensione deve essere debole (valori R elevati) in modo da non assorbire troppa corrente dalla batteria, ma non troppo debole per essere caricato dall'impedenza di ingresso ADC.

indennità

Tuttavia, se hai bisogno di un riferimento di tensione superiore al riferimento di banda interna 1.1 V interno dell'ATmega328, sei ancora sfortunato. Un'opzione sarebbe quella di utilizzare l'uscita del regolatore LDO 3.3 V dall'FT232RL di bordo, che è disponibile al pin 14 dell'intestazione, ma non credo sia affidabile. Il foglio dati FT232RL lo specifica a 3,0 - 3,6 V (nominale 3,3 V)

Quindi una soluzione universale sarebbe quella di costruire un riferimento di tensione esterno basato su un TL431 economico . Ciò potrebbe fornire un riferimento affidabile fino a 4,0 - 4,25 V con una precisione del +/- 1%.

Il circuito di riferimento della tensione esterna sarebbe qualcosa di così semplice (e TL431 è disponibile nel pacchetto TO-92 compatibile con la breadboard!):

Regolatore di tensione shunt basato su TL431


Grazie per questa risposta esaustiva e per tutte le alternative che ho potuto cogliere: probabilmente diventerò semplice e farò un divisore di tensione per ridimensionare il mio input tra 0 e 1.1. Il suggerimento sui valori di resisteor è stato prezioso per me - grazie
Caribou

3

Ho una pagina sul convertitore ADC su Atmega328P . In qualche modo nella pagina descrivo i riferimenti di tensione. È possibile utilizzare il chip TL431 per fornire tensioni di riferimento assortite, ad esempio 4 V:

Riferimento di tensione 4V

Modificando i resistori è possibile ottenere altre tensioni (sembra che si desideri intorno a 4,2 V).

La tensione di uscita non è influenzata dalla tensione di ingresso (5 V in questo caso).

La pagina collegata descrive come è possibile scegliere i valori dei resistori.


2

La conversione di adc conta in tensione dipende dalla tensione effettiva del pin + 5v?

sì e no: il modulo adc tiene a Vref, che può essere fornito tramite Vdd, internamente o esternamente.

Se sì, qual è il metodo accettato per ottenere quella tensione dalla scheda?

configurando il modulo adc. il foglio dati del dispositivo dovrebbe avere registri / bit che devono essere impostati per questo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.