PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Spannungs Test ATmega16



albi1989
16.02.2008, 16:49
Also
Ich möchte gerne die Spannung testen bei meinem ATmega16

also über den Pin (PC5/ADC5) möchte ich mit dem AD-Converter den Digitalen Wert meiner Spannung haben.

der sollte so habe ich mich informiert nicht unter <4 V sein also Digital 800 aber wie rechnet man das um?? im Datenblat habe ich eine Formel gefunden : ADC=(Vin * 1024)/Vref

Habe auf eine Interne Referenz gestellt sollte ich (warum eigentlich?)
naja aber wie komm ich nun auf einen wert von 800 im ADC
Vin ist damit doch die Betriebsspannung die gemessen wird ich nehm jetzt mal 4V
Vref ist dann die 2.56 V
kommt bei mir aber 1600 raus und nicht 800 ?
Warum und wie komm ich auf den richtigen Wert

Und hat vlt jemand ein solches Program ?

Rofo88
16.02.2008, 17:38
Da der ADC nur 10 Bit hat ist der größte Wert den er haben kann 1023.
Wenn Du die interne Refernz nimmst kannst Du keine Spannungen messen die größer als die Refernz sind. Also kannst Du deine 4V nicht direkt mesen da brauchst Du noch nen Spannungsteiler.

JonnyP
16.02.2008, 19:11
Du kannst dich nicht selbst messen. Ist deine VCC = AVCC z.B. 4Volt, so ist das 100% Referenzspannung, genau so wenn es 5 Volt sind. Du brauchst eine unabhängige Referenz, z.B. die interne Ref von 2,56Volt oder eben eine externe stabile Spannung. Bei Verwendung von 2,56V brauchst du zur Messung der Versorgungsspannung noch einen Spannungsteiler von 2:1, da die Messspannung nicht höher sein darf, als die Ref-Spannung, wie Rofo88 auch schon geschrieben hat.

albi1989
16.02.2008, 20:06
Hmmm ok warum ich die interne Referenzspannung brauche hab ich nun verstanden aber einen ? Spannungs teiler O.O wie soll ich das denn machen ?

habe mir die funktion Battery() angeguckt ist in der adc.c aber dort kann ich nicht erkennen wo dort ein Spannungsteiler ist`? ok es ist C aber es müsste doch trozdem dort anzeichen von sonem teiler geben?

Habe hier nen Code in asm gefunden wo ist da der Spannungsteiler


;ADC Enable und ADC Prescaler auf 128
ldi temp1, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS1) // adc-clk = sys-clk/64
out IO_REG(ADCSRA), temp1
;Reference Spannung auf Interne 2,56 Volt setzen und ADC5 als Input pin
ldi temp1, (1<<REFS0) | (1<<REFS1) | (1<<MUX2) | (1<<MUX0);
out IO_REG(ADMUX), temp1




;Batt test
sbi IO_REG(ADCSRA), ADSC
batt_loop:
sbic IO_REG(ADCSRA), ADSC
rjmp batt_loop
in temp1, ADCL
in INT_REG_H, ADCH
clr INT_REG_L
add INT_REG_L, temp1
adc INT_REG_H, r1
subi INT_REG_L, lo8(BATT_MIN)
sbci INT_REG_H, hi8(BATT_MIN)
brcc batt_ok
[/code]

Rofo88
16.02.2008, 20:27
Der Spannungsteiler hat nix mit Software zu tun. Den mußt Du extern aufbauen z.B. mit 2 Widerständen a 10kOhm. Damit bekommst Du deine 4V auf 2V und die kannst Du mit dem ADC auswerten.

http://de.wikipedia.org/wiki/Spannungsteiler

Gibts sicher auch noch mehr Infos hier im Forum.

albi1989
16.02.2008, 21:53
AHHH danke :D ist ja schon dran :D
Also mein problem ist gelöst aber da wäre noch so ne kleine Frage?
was passiert in diesen Zeilen
ich versteh dasmit dem carry nicht und was in r1 ist auch nicht so richtig?
also hier


in temp1, ADCL
in INT_REG_H, ADCH
clr INT_REG_L
add INT_REG_L, temp1
adc INT_REG_H, r1
subi INT_REG_L, lo8(BATT_MIN)
sbci INT_REG_H, hi8(BATT_MIN)
brcc batt_ok

JonnyP
16.02.2008, 22:38
Ohne def-tabelle kann man doch nur raten.

albi1989
17.02.2008, 08:57
Also temp1 ist r16 INT_REG_L und H sind r24 und r25
BATT_MIN sind dann jetzt 810 wegen 4.455 V mindest Spannung
r1 wird im ghanzen prog vorher nicht verwendet. In ADC also ADCL und ADCH ist der wert für die Betriebsspannung der vorher gemessen wurde

habe in den post vorher mehr von den quelltext geposted hier nur der teil den ich nicht verstehe

ich vermute das einfach die gemessene spannung - der mindest spannung und dann geguckt wird ob es >0 oder =0 aber was da mit den Carry gemacht wird das verwirrt mich total

JonnyP
17.02.2008, 11:08
So wie beim addieren das Carry Fag einen Übertrag anzeigt, so ist das gleiche Flag bei der Subtraction ein "Borrow". Wenn du also (mal dezimal gesehen) von 3 die 4 subtrahierst ist das Ergebnis = 9, aber du must von der nächst höheren Stelle eins borgen.
Wenn du vom Messwert einen Vergleichswert abziehst und carry ist nicht gesetzt, heißt das, das der Messwert höher ist.
mal sehen ob ich hier einen Teilcode hinkriege:



in INT_REG_L, ADCL ;lies lo Wert
in INT_REG_H, ADCH ;lies hi wert
subi INT_REG_L, BATT_MIN ;Subtrahiere lo Wert (oder Register)
sbci INT_REG_H, BATT_MIN ;Subtrahiere hi Wert (oder Register)
brcc batt_ok ;Messwert größer als Vergleich (kein borrow)

albi1989
17.02.2008, 16:42
Also das Carry Flag zeig dann an ob eine zahl negativ oder positiv ist
bei minus ist dann das Carry Flag gesetzt soweit ok

aber wie funzt brcc das der beide Register also INT_REG_L und INT_REG_H vergleicht ?

und warum muss man den low mit subi und den andern mit sbci subtrahieren?

Besserwessi
17.02.2008, 17:50
Für das lowbyte nimmt man SUBI, CPI oder ADD, also ohne berücksichtigung des Caarys, denn ist gibt ja keinen übertrag von noch weniger werigen bytes. Für die höherwertigen bytes braucht man den Übertrag und nimmt entsprechend SBCI,ADC, CPCi usw. um den Übertrag zu beachten.

Der brcc Befehl wertet das Carry flag aus. Nach der subtraction (oder CP..) ist das Carry flag gesetzt, wenn die Abgezogene Zahl (2 tes argument im SUBI/CP Befehl) größer was als die erste.
Etwas anders wird das noch, wenn man die Zahlen als Vorzeichenbehaftete Zahlen interpretiert (2 er Komplent), dann wird er brpl Befehr satt bcc genommen.

JonnyP
17.02.2008, 18:11
Das ist eine 16 Bit (2 x 8) Rechnung. Vor der 1. Rechnung Meswert lo - Vergleichswert lo braucht man sich nichts zu "merken" (Carry). Ergibt sich aber aus dieser Rechnung ein "borrow", so muss dass in die 2. Rechnung, Messwert hi - Verleichswert hi, mit einbezogen werden. Diese 2. Rechnung setzt / cleared erneut das Carry Flag und kann zur Auswertung benutzt werden. In meinem Beispiel wird auch nicht INT_REG_L mit INT_REG_H verglichen sondern mit einem BATT_MIN Wert, wobei ich einen Fehler gemacht habe, dahinter ein _H bzw _L zu vergessen. (Das kommt davon, wenn man abschreibt). ;-)

albi1989
17.02.2008, 19:34
Hmm also ist grad schwer zu verstehn wo der Unterschied ist ob beim Subtrahiere der zweite Wert größer oder ob das Ergebnis minus ist.
naja das kann ich notgedrungen noch so hin nehmen :D

borrow ist docjh der zustand von den Carry ? weil dann wird ja eben dieses Carry mit sbci in die zweite rechnung mit einbezogen

so mal wie ich das verstanden habe

subi register, wert ; register - wert wenn R<wert Carry="borrow"
sbci register, wert ; register - wert - Carry
Brcc jump ; springt wenn der Carry cleared ist


aber noch so am rande wieso macht der das in meine Bsp so kompliziert den Carry einzuspeichern mit ADD und adc ?

Besserwessi
17.02.2008, 20:21
Der code sieht ein bischen nach dem aus was ein Compiler so generiert. Der C Code könnte so was wie (ADCH <<8)+ADCL sein. Dann würde auch r1 wieder Sinn machen, denn r1 wird da oft als konstant 0 vorrausgesetzt. Wenn r1 undefiniert ist, macht der ganze Dode keinen Sinn.

JonnyP
18.02.2008, 08:55
Warum schreibst du nicht einfach einen 3-zeiler: Addiere / subtrahiere r16 / r17 und testest das im AVR Studio mit verschiedenen Werten, die man ja direkt in die Register schreiben kann (sogar in dezimal) und siehst dir dabei das Carry Flag an, ob eventuell ein Übertrag stattgefunden hat (carry set).
Ein paar simple Beispiele in dezimal: 7+2=9 (Carry clear (CC))
7+4=1 (Carry set (CS)) Übertrag hat stattgefunden; 9-5=4(CC) oder
9-12=3 (CS).
Wenn du, wie Besserwessi vermutet, einen Compiler verwendest, dann solltest du mal den original code hier reinstellen.

albi1989
18.02.2008, 16:13
Ahh das mit den C hat mich auf eine Vermutung gebracht
das ist schion Assambler allerdings eine .s datei also die wird über ein C prog aufgerufen daher müsst r1 als o defeniert worden sein die register r24 und r25 also INT_REG_L und H werden vorher benutzt also stellt er damit nur sicher das das carry flag wieder auf null gestellt wird bevor er subtrahiert

also wäre das eine mögliche Erklärung ?

Besserwessi
18.02.2008, 18:43
das carry flag kann man direkt setzten oder löschen, wenn man es braucht. Für die subtraktion gibt es ja den extra Befehl für die Subtraction ohne beachten des Carry Flags.
Der Code ganz am Anfang ist einfach nur umständlich und unnötig lang.