Forum: Mikrocontroller und Digitale Elektronik Problem mit ADC an mega128


von Kay B. (newbie)


Angehängte Dateien:

Lesenswert?

hallo,
bin grad beim probieren des adc vom mega128 den  gemessenen wert wird im 
terminal program ausgegeben,
wenn ich 5volt am adc0 anlege dann ist ja max=1023 sind den 5volt,
wie muss ich das jetzt umändern das er mir nicht 1023 anzeigt sondern 
5volt.

vielleicht könnte mir jemand von euch ein bischen weiterhelfen
danke
mfg kay

von Niels H. (monarch35)


Lesenswert?

Kay B. wrote:
> hallo,
> bin grad beim probieren des adc vom mega128 den  gemessenen wert wird im
> terminal program ausgegeben,
> wenn ich 5volt am adc0 anlege dann ist ja max=1023 sind den 5volt,
> wie muss ich das jetzt umändern das er mir nicht 1023 anzeigt sondern
> 5volt.

Leute, das ist aber jetzt übelst. DREISATZ!

von Alex B. (Firma: Ucore Fotografie www.ucore.de) (alex22) Benutzerseite


Lesenswert?

Meinst du einen Dreisatz?!
1023 <=> 5V
=> 1V <=> 1023 / 5

=> um einen gemessenen Wert A (z.B. 644) in eine Spannung B zu 
konvertieren rechnest du
B = A * 5 / 1023

Bei A = 644 wäre B = 3,15V.

Schöne Grüße,
Alex

von Falk B. (falk)


Lesenswert?

@ Kay B. (newbie)

>wie muss ich das jetzt umändern das er mir nicht 1023 anzeigt sondern
>5volt.

Festkommaarithmetik

MfG
Falk

P.S. Wenn du deinen Quelltest als *.asm anhängst wird es noch besser.

von Kay B. (newbie)


Lesenswert?

hallo Alex,
entschuldige vielleicht ne dumme frage, aber wie muss ich das nun in 
mein code umändern,

=> um einen gemessenen Wert A (z.B. 644) in eine Spannung B zu
konvertieren rechnest du
B = A * 5 / 1023





@Falk

Festkommaarithmetik,,, das ist in c geschrieben oder? bin der sprache C 
nicht mächtig
leider kann ich die formeln mit meinen browser nicht lesen


mfg kay

von Falk B. (falk)


Lesenswert?

@ Kay B. (newbie)

>=> um einen gemessenen Wert A (z.B. 644) in eine Spannung B zu
>konvertieren rechnest du
>B = A * 5 / 1023

Genau.

>Festkommaarithmetik,,, das ist in c geschrieben oder? bin der sprache C
>nicht mächtig

Und?  Die Rechnung ist unabhängig von der Programmiersprache.

>leider kann ich die formeln mit meinen browser nicht lesen

???

MFG
Falk

von spess53 (Gast)


Lesenswert?

Hi

An deiner Stelle würde ich die 2,56V interne Spannungsreferenz benutzen. 
Da hast du erstmal eine Auflösung von 2,5mV/Bit. Die Eingangsspannung 
must du natürlich auf die Hälfte teilen. Damit kommst du auf einen 
ADC-Wert von 1000 bei 5V. Damit wird das Rechnen wesentlich leichter.

MfG Spess

von Matthias L. (Gast)


Lesenswert?

Hm..

Nehmen wir mal an, dein ergebnis steht in ADCH:ADCL (rechtsorientiert)
Also 0..1023

Dann mache folgendes:
Addiere zu der Variablen einfach 1/4 nochmal dazu:
(pseudocode)
temp1 = r17:r16;
temp1 = ADC;
temp1 = temp1 + (temp1>>2);  (evtl runden)

jetz hast du im MSB die Spannungszahl vor dem Komma!
Also wenn ADC=1023 => temp1= 0x04FE (runden)
dieses highbyte von temp1 gibst du aus, anschließend ein Komma.
Dann nimmst du das LSB (also die unteren acht bit von temp1, hier 0xFE)
diesen multiplizerst du mit 10,
im MSB ist jetzt die erste Kommastelle, (MSB=0x09EC) => 9 ausgeben

das LSB wieder mit 10 multiplizieren, (10x 0xEC = 0x0938)
im MSB ist jetzt die zweite Kommastelle.. (MSB=09, ausgeben)
0x38 mal 10 = 0x0x0230,  2 ausgeben,
0x30 mal 10 = 0x01E0,    1 ausgeben,
0xE0 mal 10 = 0x08C0,    8 ausgeben,
0xC0 mal 10 = 0x0780,    7 ausgeben,
0x80 mal 10 = 0x0500,    5 ausgeben,
..
ergibt: 4,9921875    ( ~ 5*1023/1024, Rundung bei *1,25)

Achtung: Die Genauigkeit wird nur vorgegaukelt

das geht super der Algorithmus..

Programmieren kannst dus selbst..

von Falk B. (falk)


Lesenswert?

@  spess53 (Gast)

>ADC-Wert von 1000 bei 5V. Damit wird das Rechnen wesentlich leichter.

Ohje!!! Und das nur, weil EINE  EINZIGE Multiplikation zuviel ist.

MFG
Falk

von spess53 (Gast)


Lesenswert?

Hi

@Falk
Nicht die Multiplikation, sondern die Division durch 1023. Oder ist es 
für dich illegitim Software durch Nutzung der Hardwareressourcen zu 
vereinfachen.
Diese Referenzspannung ist genau dazu vorhanden.

MfG Spess

von Matthias L. (Gast)


Lesenswert?

>Division durch 1023

1024!

Und das ist nicht sooooooo schwer: LOW(var>>2)

Oder das ganz weglassen.... ;-)

von Falk B. (falk)


Lesenswert?

@ spess53 (Gast)

>Nicht die Multiplikation, sondern die Division durch 1023. Oder ist es

Auch DU solltest dir den Artikel Festkommaarithmetik mal in Ruhe 
zu Gemüte führen. Speziell

http://www.mikrocontroller.net/articles/Festkommaarithmetik#ADC_allgemein


MfG
Falk

P.S. Und die Referenzspannung ist selten 2,56V, die Toleranzen sind da 
bisweilen erheblich. Und wenn man kalibrieren will, muss man in der 
Software ein wenig rechnen. Tut aber nicht wirklich weh.

MFG
Falk

von Kay B. (newbie)


Angehängte Dateien:

Lesenswert?

hallo,
so habs jetzt mal probiert aber es haut nicht hin
bekomm das nicht richtig umgesetzt.
vielleicht könnte nochmal einer drübersehen.

mfg
kay

von spess53 (Gast)


Lesenswert?

Hi

Ich gehe davon aus, Kay nicht nur die 5V sondern auch mal eine andere 
Spannung mit einer Auflösung <1V messen will. Zum anderen ist die 
Messung einer Spannung=Referenzspannung sowieso nicht das Grüne vom Ei.

MfG Spess

von spess53 (Gast)


Lesenswert?

Hi

@Matthias

Kannst du dein Programm mal etwas erläutern.
Wenn ich das nachvollziehe, machst du erst eine Multiplikation mit 1,25 
und danach eine mit 5. Macht 6,25. Für ADC=1023 ergibt das 6390 ?!?!

MfG spess

P.S.  'clc/ror' lässt sich durch 'lsr' ersetzen

von Matthias L. (Gast)


Lesenswert?

@ spess53 (Gast):

Ich hab mir den Alghorithmus mal in nem Mikroprozessorpraktikum 
ausgdacht, die aufgabe war dort etwa so:
ein ADC-Wert 8bit, soll eine Spannung von 0..5V darstellen. Also wie 
hier, nur nicht 10bit, sondern 8bit.
(auf 8bit bezogen jetzt:)

Ich habe mir da überlegt, dass der maximalwert 255, der ja mit 
1/256mal5V gewichtet ist, ja nur mit fünf multipliziert (skaliert) 
werden muss, um im MSB (8-15.bit) eine Zahl zwischn 0..4 zu 
bekommen.(255*5=1020=0x04FB) somit ist das MSB die Stelle vor dem Komma: 
4,... Volt
da ja jetzt das komplette LSB wohl offensichtlich die Nachkommastelle 
(0..0,99999..V) beinhalten muss, kann ich diese doch einfach mit 
10multiplizieren, es entsteht im MSB eine Zahl 0...9. Das ist die erste 
Nachkommastelle: (10dez* 0xFB=0x09CE) MSB=9, LSB=0xCE => 4,9...V
Das 0xCE wieder mit 10mal nehmen:
(10dez* 0xCE=0x080C) MSB=8, LSB=0x0C                  => 4,98...V
...
(10dez* 0x0C=0x0078) MSB=0, LSB=0x78                  => 4,980...V
...
(10dez* 0x78=0x04B0) MSB=4, LSB=0xB0                  => 4,9804...V
..
(10dez* 0xB0=0x06E0) MSB=6, LSB=0xE0                  => 4,98046..V
...
(sollte irgendwann abgebrochen werden ,-)


PS:  5V*255/256 = 4,98046875V

Da in obigen beispiel der Wertebereich 4mal so groß war (1024statt256), 
dann halt nicht mal5, sondern mal 5/4=1,25....

Noch Fragen?

PS:
>'clc/ror' lässt sich durch 'lsr' ersetzen
lsr ist ohne beachtung des carry-flags, das will ich aber 
'rüber'schieben

>enn ich das nachvollziehe, machst du erst eine Multiplikation mit 1,25
>und danach eine mit 5. Macht 6,25. Für ADC=1023 ergibt das 6390 ?!?!

Nein, nur mit 1,25, im Programm hat sich ein Schusselfehler 
eingeschlichen:
Die Fünf ist hier Unsinn...
1
temp1H = r17
2
temp1L = r16
3
temp2H = r19
4
temp2L = r18
5
faktor = r20
6
counter = r21
7
ascii   = r22
8
9
;------- werte holen
10
mov r17, adch
11
mov r16, adcl
12
;------- temp puffer
13
movw temp2L, temp1L
14
;------- teile durch vier
15
clc                       ; clear carry flag
16
ror temp2H
17
ror temp2L
18
clc
19
ror temp2H
20
ror temp2L
21
;------- zusammenrechnen
22
add temp2L, temp1L
23
adc temp2H, temp1H        ; in temp2 steht jetzt 1,25*adc
24
;------- ausgabe highbyte
25
mov ascii, -0x30          ; ascii für null
26
subi temp2H, ascii
27
UDR = temp2H             ; über uart senden
28
UDR = ','                ; komma senden, warten auf udre einfügen
29
;------- lowbyte mal zehn,
30
ldi faktor, 10
31
ldi counter, 5          ; azahl nachkommastellen
32
loop:
33
mul temp2L, faktor
34
subi r0, ascii
35
UDR = r0                 ; über uart senden, warten auf udre einfügen
36
mov temp2L, r1
37
;------ genug stellen ausgegeben?
38
DEC counter 
39
BRNE loop;
40
;------- nu fertsch ;-)


Was haltet ihr von dem Algorithmus?

von Niels H. (monarch35)


Lesenswert?

Matthias L. wrote:

> Was haltet ihr von dem Algorithmus?

Hört sich schlüssig an. Wenn das so funktioniert, Hut ab, ziemlich 
Tricky.

von Matthias L. (Gast)


Angehängte Dateien:

Lesenswert?

Hier ist die Lösung aus besagtem Praktikum:

Siehe pdf Seite 5:
Routine "Analogwert in String umwandeln"
AN_TO_STRING:
...

Die hier gezeigte Lösung hat allerdings noch eine Vornullenunterdrückung 
(fall U<1V), sowie ein Autoranging:
U>=1V => Anzeige: 1.234V
U<1V  => Anzeige: 234mV bzw 98mV, nicht 098mV


Das Programm hier war aber für so nen 80C500 irgendwas ;-/

von Kay B. (newbie)


Lesenswert?

hallo,
erstmal danke ,
aber bei mir bekomme ich es nicht zum laufen

mfg
kay

von Niels H. (monarch35)


Lesenswert?

Kay B. wrote:
> aber bei mir bekomme ich es nicht zum laufen

Der gelieferte Code ist als unfertiges Modell zu betrachten. Dir ist 
hoffentlich klar, daß da noch etliche Sachen fehlen, wie z.B. 
Wandlerinitialisierung und das warten auf UDRE?

von Matthias L. (Gast)


Lesenswert?

Du solltest das stückweise machen:

erstmal nimmst du den adc wert (den du bisher ausgibst) und tust ihn mit 
1,25 multiplizieren, das gibst du erstmal aus.
Dann machst du schritt für schritt weiter

von spess53 (Gast)


Lesenswert?

Hi

So sieht das natürlich besser aus. Allerdings kommst du bei ADC=1023 
nicht auf 5,00.

movw temp2L, temp1L
;------- teile durch vier
adiw temp2L,5             ---->könnte helfen
clc                       ; clear carry flag
ror temp2H

MfG Spess

P.S.  clc - Löscht Carry-Flag (Cy=0)
      ror - Schiebt Register+Bit0=Cy

      lsr - Schiebt Register+Bit0=0

Wo ist da der Unterschied?

von Matthias L. (Gast)


Lesenswert?

>>llerdings kommst du bei ADC=1023 nicht auf 5,00.

Sollst du auch nicht, weil das ja dann nur 1023/1024stel von 5V sind...
der Wertebereich geht ja von 0...5V-1Ulsb

mit Ulsb = 5V/1024..

weil 0..1023 sind 1024 Stufen...

ADC=0        =>   Uadc>= 0,0000000V
ADC=1        =>   Uadc>=     4,8828125mV
ADC=1023     =>   Uadc>= 4,995117188V

von Kay B. (newbie)


Angehängte Dateien:

Lesenswert?

so hab nochmal etwas prpobiert geht aber immer noch nicht .


mfg Kay

von spess53 (Gast)


Lesenswert?

Hi

Warum soll ich nicht bei 5V auch 5V herausbekommen. Wenn das nicht geht, 
stimmt irgendwas nicht.

MfG Spess

von Matthias L. (Gast)


Lesenswert?

@ spess53 (Gast):

Nein. Dann hast du das Prinzip eines ADC nicht (komplett) verstanden:
Ich vereinfache mal:
Referenzspannung: 8V
Auflösung: 8Stufen: (3bit)
Eingangsspannung              ADC-Wert
0,00000000 - 0,9999999...     0
1,00000000 - 1,9999999...     1
2,00000000 - 2,9999999...     2
3,00000000 - 3,9999999...     3
4,00000000 - 4,9999999...     4
5,00000000 - 5,9999999...     5
6,00000000 - 6,9999999...     6
>7,00000000                   7

So arbeitet ein ADC!

Er teilt die Referenzspannung in (hier) 8gleiche Teile, diese beginnen 
IMMER bei Null und enden bei 2^(bit-auflösung)-1

beachte die MINUS EINS!!!

Somit sind die (hier 3bit) Auflösung ausgeschöpft, und mehr kann nicht 
dargestellt werden...

von Kay B. (newbie)


Angehängte Dateien:

Lesenswert?

hallo,
so jetzt geht es,aber warum wird jetzt zuviel augegeben.


vielleicht könnte mir einer nochmal kurz helfen
mfg
kay

von Matthias L. (Gast)


Lesenswert?

Was wird denn jetzt ausgegeben?

von Kay B. (newbie)


Lesenswert?

hallo,
es wird immer 1,5-2 zuviel angezeigt,

könntet ihr mir vielleicht nochmal helfen

mfg
kay

von Kay B. (newbie)


Lesenswert?

hallo,

vielleicht könnte mir nochmal einer weiterhelfen.

bei gemessenen 5Volt wird 6.15 angezeigt woran liegt das
sitze schon tage dran aber bekomme das nicht richtig hin.

mfg
kay

von Hannes L. (hannes)


Lesenswert?

Kay B. wrote:
> hallo,
>
> vielleicht könnte mir nochmal einer weiterhelfen.

Ich versuche es mal...

>
> bei gemessenen 5Volt wird 6.15 angezeigt woran liegt das
> sitze schon tage dran aber bekomme das nicht richtig hin.

Da ich keinen Mega128 habe (meine Projekte arbeiten mit kleineren AVRs, 
ich mag nicht mit Kanonen auf Spatzen schießen), kann ich es natürlich 
nicht testen. Daher keine Gewähr für die Richtigkeit.

Zuerst einige Hinweise, die nichts mit dem Fehler zu tun haben:

- Die von mir genutzten "kleinen AVRs" haben nicht nur 16 Register,
  sondern 32. Ich hoffe, das ist beim Mega128 auch so. Da die meisten
  Registerzugriffe ohne Konstanten erfolgen, lassen sich die unteren
  16 Register auch benutzen. ;-)

- Du definierst 5 Register (r23-r27), die Du gar nicht benutzt.

- Du nutzt eines der tempX-Register für die Addition von 0 mit Carry.
  Dazu reicht ein unteres Register, das man sinnvollerweise auch noch
  "null" nennt, völlig aus. Vorteil: Der Code erklärt sich selbst.

- Du sicherst Register auf Stack, die gar nicht gesichert werden müssen.

- Du nutzt (als temporär gekennzeichnete) Register (temp4, temp3, temp2)
  als globale Variablen zum Aufsummieren der 256 Messwerte. Das ist
  schlechter Stil, wenn man eine Variable "temp" nennt, dann muss sie
  auch temporär verwendbar sein. Sprechende Namen wie "adwh", "adwl"
  oder "adwn" (AD-Wert- High, Low, Nachkomma) verhindern
  Missverständnisse, die aktuell eingelesenen Messwerte jeder Runde sind
  dagegen "temporär" und können in temp-Registern Platz finden.

Den eigentlichen Fehler vermute ich hier:

- Du Summierst 256 ADC-Messungen in den Registern temp2, temp3 und
  temp4. Dabei ist temp4 das hochwertige Byte, temp3 das niederwertige
  Byte und temp2 die (nur für die Rundung berücksichtigte)
  Nachkommastelle. Dein 16-Bit-Ergebnis steht also in temp4:temp3.

- Du zerelegst in "number16:" eine 16-Bit-Zahl und schickst die
  einzelnen Ziffern über UART an den PC. Du zerlegst aber nicht (wie
  gewollt) temp4:temp3, sondern temp3:temp2. Vernünftige Registernamen
  hätten das Missverständnis verhindert. Dazu kommt noch etwas Unsinn
  beim Push und Pop der auszugebenden Register.

- Du erwartest bei 5V angelegter Messspannung Zahlenwerte von etwa 5
  oder 5,00. Ich sehe in Deinem Code aber nirgends eine Skalierung.
  Die Zahlenwerte, die Du bei Beseitigung des anderen Fehlers erwarten
  kannst, sind 00000 bis 01023.

Fazit: Das Abschreiben von Tutorial-Beispiel-Codes bringt nichts, 
solange Du sie nicht verstehst. Mein Vorschlag: Nimm zum Lernen einen 
kleinen AVR wie den Mega8, der ist übersichtlicher und wird von vielen 
Leuten hier verwendet, wodurch sich vermutlich mehr Helfer finden. 
Außerdem sind viele Teile des Tutorials für den Mega8 geschrieben. Falls 
Du ihn dieses Jahr noch brauchst, kannst Du Dir gerne einen oder zwei 
bei mir abholen. Ich hätte auch noch ein funkelniegelnagelneues 
blitzeblaues 4x40-LCD für Dich... ;-)

...

von Falk B. (falk)


Lesenswert?

@  Kay B. (newbie)

>bei gemessenen 5Volt wird 6.15 angezeigt woran liegt das
>sitze schon tage dran aber bekomme das nicht richtig hin.

Schau mal hier, ich hab das Tutorial etwas aufgebohrt.

AVR-Tutorial: ADC

MFG
Falk

von Kay B. (newbie)


Lesenswert?

hallo,

das erweiterte adc-beispiel habe ich mal ausprobiert das geht allerdings 
sende ich auf uart1.
wenn nun vielleicht andere sachen noch zuerledigen sind (dann sind ja 
nicht mehr genügend register vorhanden) zb. ausgabe auf dem lcd.




hallo hannes,

mega8 habe ich hier auch ein paar rumliegen .

mfg kay

von Hannes L. (hannes)


Lesenswert?

Kay B. wrote:
> wenn nun vielleicht andere sachen noch zuerledigen sind

Dann kommt man mit dem Stil im Tutorial nicht weit, da an allen Ecken 
und Kanten gewartet wird anstatt andere Dinge zu erledigen.

> (dann sind ja
> nicht mehr genügend register vorhanden)

Nööö, es wurde (außer zur Multiplikation r0 und r1) noch kein einziges 
unteres Register verwendet. Und RAM ist auch noch jede Menge frei. Wenn 
man das Beispiel etwas aufräumt, dann sind auch genügend Register frei.

> zb. ausgabe auf dem lcd.

Nööö, auch dazu reichen die Register noch massig.

>
>
>
>
> hallo hannes,
>
> mega8 habe ich hier auch ein paar rumliegen .

Und warum benutzt Du dann für sooo triviale Dinge Deinen Mega128? Lass 
ihn doch liegen bis Du etwas mehr Durchblick hast und mach' die 
Tutorial-Beiträge mit einem Mega8. Es wäre doch schade drum, wenn er bei 
solch trivialen Experimenten durch ein Missgeschick beschädigt würde.

>
> mfg kay

...

von Kay B. (newbie)


Lesenswert?

hallo,
erstmal danke für die hilfe von euch.
aber ich krieg das einfach nicht hin.
mfg
kay

von Falk B. (falk)


Lesenswert?

@ Kay B. (newbie)

>erstmal danke für die hilfe von euch.
>aber ich krieg das einfach nicht hin.

WAS willst du denn überhaupt machen? Dein Problem mit der ADC-Ausgabe 
ist doch scheinbar nun gelöst.

MFG
Falk

von Kay B. (newbie)


Lesenswert?

hallo,
die ausgabe auf'n rechner funktioniert ja so wie tutorial,
nun wollte ich versuchen statt die ausgabe zum pc aufs display 
zubekommen
daran haberts gewaltig.

mfg
kay

von Falk B. (falk)


Lesenswert?

@ Kay B. (newbie)

>daran haberts gewaltig.

Tja, vor den Erfolg haben die Götter den Schweiss gesetzt. Aber auch 
hierfür gibt es Tutorials.

AVR-Tutorial: LCD

Kleiner Tip. Der String ist schon fertig. Er muss nur auf das LCD statt 
den UART ausgegeben werden. Was nicht wirklich ein Problem ist.

MFG
Falk

von Hannes L. (hannes)


Lesenswert?

Ich habe die Vermutung, dass Kay Probleme hat, die Ressourcen 
eigenständig zu verteilen/verwalten.

Das Tutorial nutzt unbekümmert obere Register, wo auch untere Register 
reichen würden, nun fehlen ihm die Register für die LCD-Routinen.

Vielleicht dringt Kay ja beim "Verstehen" der Zusammenhänge nicht tief 
genug in die Materie ein?

Mein Tip an Kay: Kleiner überschaubarer AVR, kleine überschaubare 
Aufgaben, bei der Lösung der Aufgabe jedes Bit versuchen zu verstehen. 
Das Zusammenkopieren von fremden Quelltexten und Verändern dieser 
Quelltexte nach Versuch und Irrtum führt in eine Sackgasse.

...

von Falk B. (falk)


Lesenswert?

@ Hannes Lux (hannes)

>Mein Tip an Kay: Kleiner überschaubarer AVR, kleine überschaubare
>Aufgaben, bei der Lösung der Aufgabe jedes Bit versuchen zu verstehen.
>Das Zusammenkopieren von fremden Quelltexten und Verändern dieser
>Quelltexte nach Versuch und Irrtum führt in eine Sackgasse.

Amen. Das sollte man 1:1 in den noch leeren Artikel Copy&Paste 
Programmierung übernehmen. Ich bin mal so frei.

MFg
Falk

von Kay B. (newbie)


Lesenswert?

hallo,
erstmal danke für die hilfe,habs mal mit einen mega8 versucht aber da 
komm ich auch nicht weiter, den adc wert aufs dispaly darzustellen.
danke nochmals für die hilfe.

mfg
kay

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.