Forum: Mikrocontroller und Digitale Elektronik AVR: Vcc gegen interne Referenz messen möglich?


von Wolf (Gast)


Lesenswert?

Hi,

ich glaube, hier mal gelesen zu haben, dass man die Versorgungsspannung 
vom AVR quasi ohne externe Beschaltung messen kann, mithilfe der 
internen Referenz.

Wo steht, wie das geht?

von D. W. (dave) Benutzerseite


Lesenswert?

Nen Spannungsteiler nehmen? Oder meinst du ohne Spannungsteiler?

von Johannes M. (johnny-m)


Lesenswert?

Wolf wrote:
> Wo steht, wie das geht?
Im Abschnitt "Analog to Digital Converter" im Datenblatt Deines AVR. 
Geht mit der internen Bandgap-Referenz.

von Andreas K. (a-k)


Lesenswert?

ADC-Referenz auf Vcc und den ADC-Muxer auf die Bandgap-Referenz 
einstellen, dann messen. Wenn die Bandgap-Referenz hinreichend genau 
bekannt ist, lässt sich Vcc daraus ableiten.

von Johannes M. (johnny-m)


Lesenswert?

Genau. Musst nur umgekehrt denken. Du misst dann die Bandgap-Referenz 
mit AVCC als Referenzspannung. Um AVCC zu ermitteln musste dann eben 
umrechnen.

von Wolf (Gast)


Lesenswert?

Danke für den Hinweis.

Rezept:

- Den Pin AVCC auf Vcc legen.

In ADMUX

- AVCC als Voltage Reference

- 1.18V (VBG) als Input Channel


Bei z.B. 4.72V Vcc wird dann 256*(1.18V/4.72) = 64 gemessen..

von Wolf (Gast)


Lesenswert?

(Antwort auf 16:18..)

von Johannes M. (johnny-m)


Lesenswert?

Richtig!

von Wolf (Gast)


Lesenswert?

256
Vcc = ----- * Vref
       ADC

von Wolf (Gast)


Lesenswert?

.
       256
Vcc = ----- * Vref
       ADC

von Johannes M. (johnny-m)


Lesenswert?

Misst Du nur mit 8 Bit? Wenn ja, dann ist es richtig...

von Andreas K. (a-k)


Lesenswert?

> - Den Pin AVCC auf Vcc legen.

Das ist immer nötig, ob der ADC nun gebraucht wird oder nicht!!!!

von Andreas K. (a-k)


Lesenswert?

Ach ja: Die Herstellungstoleranz der internen Referenz beachten. Wenn 
man es genauer braucht, sollte man pro Controller-Exemplar mal 
nachmessen (= bekanntes Vcc) und entsprechend einpflegen (EEPROM).

von Bastler (Gast)


Lesenswert?

Hallo!

Ich sehe gerade in diesem Beitrag dass die interne Referenz mit der VCC 
benutzt wird. Ich habe ein ähnliches Problem. ich möchte bei meinem 
ATtiny 24V eine Batterieüberwachung ausführen. Habe dafür eine 3 V 
Lithium Knopfzelle. Es soll eine Lampe angehen wenn die Spannung auf 2,4 
V abgesunken ist.
Wie programmiere ich das am einfachsten. Im ADMUX muss dann 0010.0001 
stehen. Wenn ich praktisch 2,4 V VCC erreicht habe muss ich 2,4 V 
geteilt durch 1024 rechnen. Dann könnte ich wiederrum sagen wieviele 
Stufen sind dann 1,1 V. Nur wie sage ich das. If-Schleife. 1,1 V wären 
bei VCC 2,4 V ca. 469d Stufen.

Gruß
Thomas

von Stefan E. (sternst)


Lesenswert?

Du hast doch schon einen eigenen länglichen Thread mit kompetenten 
Helfern zu deinem Thema. Wozu holst du jetzt zusätzlich noch einen alten 
fremden Thread aus der Mottenkiste?

von Karl H. (kbuchegg)


Lesenswert?

Weiter oben steht doch die Formel.
Bei dir dann eben 1024 anstelle von 256

Du rechnest   1024 * Vbg / ADC_Wert

Jetzt kommt es drauf an, wieviele Nachkommastellen du haben willst.
Sagen wir einfach mal 1 reicht aus.

Dein ADC_Wert sei 470 gewesen. Vbg (also die Bandgapspannung) sei 1.1V

   1024 * 11 / 470 =

   11264 / 470  = 23

Deine Versorgunsspannung wäre demnach 2.3 Volt
Genau genommen ist sie aber 2.39V. Da aber nicht gerundet wird, kommt 
2.3 raus.

Beachte: Da die Bandgapspannung konstant 1.1V ist und sich bei einem 
Tiny nicht mehr verändert, ist der Ausdruck 1024 * 11 konstant. Du 
kannst ihn also bereits zur Compiletime ausrechnen und zur Laufzeit nur 
noch durch den ADC_Wert dividieren.


Das ist doch simples Dreisatzrechnen:
Eine Apfel wiegt 30 Gramm. Wenn der Inhalt einer Kiste Äpfel 2 Kilo 50 
wiegt, wieviele Äpfel sind dann in der Kiste.
Oder so (Hab jetzt nicht kontrolliert ob die Berechnung in diesem 
Dreisatz dem obigen entspricht)

Und ja: Man kann Formeln nach den Regeln der Mathematik auch so 
umstellen, dass man möglichst viel schon konstant ausgerechnet hat, ehe 
die Division davon was wegschmeisst.
Und nein: Wenn man denkt, dass man zum Berechnen von Geldbeträgen in 
Euro Gleitkomma benötigt, der hat einfach nicht bedacht, dass man 
anstelle von Euros auch in Cent rechnen kann. Aus 2 Euro 58  (also 2.58) 
werden so 258 Cent (also eine ganze Zahl)

von Bastler (Gast)


Lesenswert?

Ja ich dachte nur das geht genau in meine Richtung. Ich mein ich möchte 
ja die VCC messen mit Hilfe meiner internen Referenz. Ich komme da noch 
nicht so ganz weiter.

von Bastler (Gast)


Lesenswert?

Ja aber mein Hauptproblem ist ja wie kann ich ausdrücken dass er was 
machen soll wenn die interne Referenz genau 470 Stufen beträgt. Wie kann 
man das programmieren. Ich komme nur auf eine IF Abfrage nur habe ich 
keine Ahnung wie man das dann abfragt. Ich gehe ja mal davon aus dass 
immer wieder der Hex Wert von meinen 1,1 V in ADC geschrieben wird.
Müßte also ungefähr dann so lauten:

ADMUX = 0x21h;                     // 0010.0001 b
if (ADC == 470)                   // 470 entspricht 1,1 V
   {
      PORTB |= (0<<PB1);         // PB1 auf 0 damit LED leuchtet
    }

von Karl H. (kbuchegg)


Lesenswert?

Bastler schrieb:

> Ja aber mein Hauptproblem ist ja wie kann ich ausdrücken dass er
> was machen soll wenn die interne Referenz genau 470 Stufen beträgt.
>

Na wie macht man denn in C eine Unterscheidung, so dass etwas passieert, 
wenn eine bestimmte Bedingung vorliegt.
Mit einem if. Genau das ist sein Verwendungszweck.

Kann es sein, dass du auch noch massive C-Probleme (unabhängig vom µC 
Programmieren) hast?

> genau 470 Stufen
vergiss die Idee mit genau gleich wieder. Dein ADC wird eher selten 
exakt 470 ausspucken. Das kann mal 471 sein oder auch 469.
Defensiv programmieren!

  if( .... > 471 )

Das wird immer dann wahr, wenn .... den Wert 470 oder größer ergibt.
Du willst ja deinen µC auch dann schlafen legen, wenn die Batterie nach 
dem Einschalten schon leer ist (also weniger als die ominösen 2.4V hat).


> Müßte also ungefähr dann so lauten:
>
> ADMUX = 0x21h;                     // 0010.0001 b
> if (ADC == 470)                   // 470 entspricht 1,1 V
>    {
>       PORTB |= (0<<PB1);         // PB1 auf 0 damit LED leuchtet
>     }

Nein.
Noch nicht mal ungefähr (das if ist schon richtig. aber das davor ist 
Unsinn).


> meinen Hex Wert

Vergiss in diesem Zusammenhang Hex. Du hast eine Zahl. Die muss einer 
bestimmten Bedingung genügen. Ob du das jetzt alles in Hex Schreibweise 
notierst, oder dezimal oder zur Basis 19 ist Jacke wie Hose. Für dich 
als Mensch ist dezimal am leichtesten zu lesen. Also benutz auch 
dezimal.


Es wird Zeit das Tutorial zu studieren, wie man den ADC abfrägt.

von Peter D. (peda)


Lesenswert?

Bastler schrieb:
> Müßte also ungefähr dann so lauten:
>
> ADMUX = 0x21h;                     // 0010.0001 b
> if (ADC == 470)                   // 470 entspricht 1,1 V

Der Kandidat erhält 10 Strafpunkte, gehe zurück über Los:

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Der_interne_ADC_im_AVR

Du solltest erstmal mit ner Blink-LED anfangen, dann Taste usw.

Nen 2. Thread aufzumachen gibt auch keine Pluspunkte.


Peter

von Bastler (Gast)


Lesenswert?

Ich habe da nichts neues aufgemacht sondern meine Frage bei einem 
ähnlichen Thema reingeschrieben. Ich habe für meinen Sensor schon die 
gleiche IF-Abfrage. Darum dachte ich das muss auch dieses Mal so gehen 
dass wenn ein bestimmter Wert im ADC steht ich meine LED zum leuchten 
bringe. Und das mit dem ADMUX habe ich so geschrieben weil es davor drin 
stand. Sprich ich benutze schon VCC als Referenz aber die 1,1 V als 
festen Wert. Darum verstehe ich jetzt auch nicht warum das so falsch 
ist. Dass es nicht funktioniert sehe ich selber auch gerade. Jetzt 
funktioniert die AD-Wandlung vom Sensor nämlich auch nicht mehr obwohl 
ich danach das ADMUX Register wieder umschreibe auf ADMUX = 0x00h. Dass 
man bitweise programmieren kann weiss ich schon aber in dem Fall müßte 
es ja so auch funktionieren.

von Karl H. (kbuchegg)


Lesenswert?

Bastler schrieb:

> ich danach das ADMUX Register wieder umschreibe auf ADMUX = 0x00h.

Als erstes änderst du jetzt mal deine Schreibweise.
Anstatt das da alles in eine Hex-Zahl zusammenzufassen, benutzt du die 
(1<<BIT_NAME) Schreibweise (so wie man sie auch im Tutorial sieht). Hier 
hat nämlich keiner Lust, Zahlen in Bits aufzudröseln um dann im 
Datenblatt nachzusehen, was du da eingestellt hast.

Und dann postest du bitte vollständigen Code und nicht nur 3 Zeilen.

von Helmut Artmeier (Gast)


Lesenswert?

Ein Besipiel für destruktive Kommunikation.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.