Forum: Mikrocontroller und Digitale Elektronik ADC hat immer den gleichen Wert


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von André M. (killroymenzel)


Angehängte Dateien:

Lesenswert?

Hallo...

Ich versuche die Batterie eines RTCs mit dem ADC0 eines ATMega128A
zu messen.

Aber egal was ich an PORTF0 anschliesse, (GND, AVCC oder die BAT)
kommt immer das gleiche ergebnis raus.

Habe ich hier einen Denkfehler?
In der Initialisierung rufe ich
rcall ADC_init
auf.

Im Hauptprogramm rufe ich folgendes auf:
rcall  ADC_start
rcall  ADC_read
rcall  Bin_dec

 und ich gebe dort nun den, im SRAM abgespeicherten Wert auf ein 
Display.

ldi    zl,low(Result_copy)
ldi    zh,high(Result_copy)
rcall  LCD_string



Im Anhang mal meine ADC-Routinen.

Danke im Vorraus.

von spess53 (Gast)


Lesenswert?

Hi

>Aber egal was ich an PORTF0 anschliesse, (GND, AVCC oder die BAT)
>kommt immer das gleiche ergebnis raus.

Wundert mich nicht:

>    ldi    rawlow,ADCL
>    ldi    rawhigh,ADCH

MfG Spess

von oldmax (Gast)


Lesenswert?

Hi
Ja Assembler... versuch es mal mit "In".
Gruß oldmax

von H.Joachim S. (crazyhorse)


Lesenswert?

Und selbst das ist nicht automatisch richtig (habe jetzt nicht 
nachgeschaut, wie es beim 128er ist).
Der Adressbereich der In/Out-Befehle ist ja sehr beschränkt und reicht 
bei grösseren AVRs nicht aus, die gesamte Peripherie abzudecken. Dann 
ist man bei lds o.ä. :-)

Sowas überlass ich gerne dem Compiler, der machts schon richtig. Und ich 
brauche mich auch nicht um die böse Falle low/highbyte zu kümmern.

von André M. (killroymenzel)


Lesenswert?

Danke...!!

Der Fehler lag mal wieder zwischen den Ohren.

Ich werde es heute Abend mal testen.


André

von oldmax (Gast)


Lesenswert?

Hi
Das Datenblatt hilft, aber auch die Hilfe in Assembler vom AVR Studio.
Gruß oldmax

von André M. (killroymenzel)


Lesenswert?

@oldmax
@spess53
Danke nochmal für den Tip - jetzt funktioniert der ADC gescheit.

Das einzige Problem was ich jetzt noch habe, ist die Berechnung.

Zu messen sind 2V-3,5V
Ich benutze den internen 5V AREF, und mein Ergebnis ist ca. 5mV zu hoch.

Hat jemand eine Idee, die relativ Register arm ist?

Ich habe nur 4 Register zur Verfügung und in zweien steht schon der 
ausgelesene Wert des ADC.


André

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

>Ich benutze den internen 5V AREF, und mein Ergebnis ist ca. 5mV zu hoch.

Du hast keine interne 5V VREF. Das ist VCC mit all seinen Abweichungen.

>Hat jemand eine Idee, die relativ Register arm ist?
>Ich habe nur 4 Register zur Verfügung und in zweien steht schon der
>ausgelesene Wert des ADC.

Erläutere das mal etwas näher.

MfG Spess

von Uwe (de0508)


Lesenswert?

Guten morgen André ,

Du hast mehrere Messfehler in deiner ADC Messung.

internen 5V AREF ist nicht genau 5V und nicht als konstant an zu 
sehen, insbesondere bei Temperatur- und Laständerungen.

Der ADC eines Atmel AVRs hat noch zwei systembedingte Fehler.

a) einen offset Fehler
b) einen linearitäts Fehler

Atmel hat zum Thema ADC verschiedene Application Note heraus gebracht, 
die es zusätzlich noch zu lesen und verstehen gilt.

Hier ist eine Auswahl:

Atmel AVR120: Characterization and Calibration of the ADC on an AVR
# http://www.atmel.com/images/doc2559.pdf

Atmel AVR121: Enhancing ADC resolution by oversampling
# http://www.atmel.com/images/doc8003.pdf

Atmel AVR126: ADC of megaAVR in Single Ended Mode
# http://www.atmel.com/Images/doc8444.pdf

: Bearbeitet durch User
von oldmax (Gast)


Lesenswert?

Hi
>Ich habe nur 4 Register zur Verfügung und in zweien steht schon der
>ausgelesene Wert des ADC.

Der 128 er hat 4 KB Ram. Und das ist alles schon verbraten? Es ist doch 
wohl kein Problem, Register frei verfügbar zu halten und Werte im Ram 
abzulegen. Der Zeitverlst ist sicherlich nicht ausschlaggebend. Ein 
Befehl ca. 2 Zyklen, das ist bei 1 MHz 2 µSek. Ok, Speichern und Laden 
dann halt 4 µSek. Aber das auch nur bei 1 MHz. Vermutlich, ich hab jetzt 
das Datenblatt nicht im Kopf kann er aber mit 20 MHz getaktet werden. 
Also nutz den RAM, das Geld dafür gibts sowieso nicht zurück.
Gruß oldmax

von Karl H. (kbuchegg)


Lesenswert?

oldmax schrieb:

> Also nutz den RAM, das Geld dafür gibts sowieso nicht zurück.

:-)
Ich glaube nicht, dass der SRAM das eigentliche Problem darstellt.

von killroymenzel (Gast)


Lesenswert?

spess53 schrieb:
> Du hast keine interne 5V VREF. Das ist VCC mit all seinen Abweichungen.

Stimmt, das habe ich nicht berücksichtigt.
Vielleicht sollte ich mir eine externe AREF zulegen.

spess53 schrieb:
> Erläutere das mal etwas näher.

Das mit dem ADC ist ja nur ein kleiner Teil des Programms.
es wird hier: Beitrag "Entsorgungskalender"
"eingepflegt".

Uwe S. schrieb:
> Der ADC eines Atmel AVRs hat noch zwei systembedingte Fehler.
> a) einen offset Fehler
> b) einen linearitäts Fehler
> Atmel hat zum Thema ADC verschiedene Application Note heraus gebracht,
> die es zusätzlich noch zu lesen und verstehen gilt.

Die ANs werde ich mir mal zur Gemüte führen, Danke für die Links.

oldmax schrieb:
> Der 128 er hat 4 KB Ram. Und das ist alles schon verbraten?

Das Programm soll am Ende auf einem kleineren AVR laufen,
dies ist "nur" mein Board zum programmieren und testen.
Wenn ich je fertig werden sollte, ;-), schaue ich was ich an Hardware 
brauche und designe mir dann eine neue Platine.

Karl Heinz schrieb:
> :-)
> Ich glaube nicht, dass der SRAM das eigentliche Problem darstellt.

Das stimmt. Ich lerne halt noch und bin gerade dabei mich mit dem ADC zu 
beschäftigen.


Aber alles im allen werde ich wohl nicht ohne eine vernünftige ext. AREF 
weiterkommen.


Danke an alle....!!

von spess53 (Gast)


Lesenswert?

Hi

>Das mit dem ADC ist ja nur ein kleiner Teil des Programms.
>es wird hier: Beitrag "Entsorgungskalender"
>"eingepflegt".

Und was hat das damit zu tun, das dir angeblich die Register ausgehen?

MfG Spess

von killroymenzel (Gast)


Lesenswert?

spess53 schrieb:
> Und was hat das damit zu tun, das dir angeblich die Register ausgehen?

Klar habe ich noch register "über", oder könnte das eine oder andere 
freischaufeln.

Allerdings ist mein Bestreben,(wenn auch unnötig), so wenig recourcen 
und Takte zu verbrauchen wie möglich.

Is halt ein TIC von mir....... gerade das macht mir daran Spass.

Frei nach dem Motto:
Je mehr Recourcen man hat, desto unsauberer wird programmiert.

André

Das Motto eines Programmierers:
programmieren, programmieren, gähn, programmieren,

Einschalten - läuft... o_O

Kann nicht sein - Fehlersuche.....

von H.Joachim S. (crazyhorse)


Lesenswert?

Im Gegenteil: unsauber, fehleranfällig und schlecht wartbar wird es 
genau durch deinen Ansatz - so wenig Ressourcen zu verbrauchen wie 
möglich.
Denn das heisst dann u.a. Mehrfachnutzung von Registern/Speicherzellen. 
Was ein Compiler ganz selbstverständlich macht (lokale Variablen), 
übersteigt des Programmierers Übersicht ganz schnell, insbesonders wenn 
man die Sache mal ein paar Tage liegen lässt. Trenn dich davon, das war 
vor 20 Jahren so. Gut überdachtes Grundkonzept (dafür sollte man einige 
Zeit aufwenden, bevor auch nur eine einzige Zeile Code geschrieben wird) 
- das ist die effektivste Zeit beim Programmieren.
Einzelne, klar gegliederte Module mit dokumentierten Schnittstellen. 
Kostet ein wenig an Performance, bringt aber ne Menge.

von Cyblord -. (cyblord)


Lesenswert?

killroymenzel schrieb:

> Klar habe ich noch register "über", oder könnte das eine oder andere
> freischaufeln.
> Allerdings ist mein Bestreben,(wenn auch unnötig), so wenig recourcen
> und Takte zu verbrauchen wie möglich.

Bei dir scheint es größere Defizite der Programmierung allgemein und bei 
Spezifika wie Registern und RAM zu geben. ich würde diese erstmal 
beheben und mich dann um solche sportlichen Bestrebungen kümmern.

> Frei nach dem Motto:
> Je mehr Recourcen man hat, desto unsauberer wird programmiert.

Himmelschreiender Unsinn. Das Gegenteil ist der Fall.

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

>Klar habe ich noch register "über", oder könnte das eine oder andere
>freischaufeln.

Vielleicht solltest du mal dieses .def-Gedödel überdenken. Für 
Spielzeugprogramme ganz nett, ab einer bestimmten Programmgröße einfach 
nur hinderlich.

Ich persönlich komme glänzend ohne Defines aus.

MfG Spess

von killroymenzel (Gast)


Lesenswert?

H.Joachim Seifert schrieb:
> Einzelne, klar gegliederte Module mit dokumentierten Schnittstellen.
> Kostet ein wenig an Performance, bringt aber ne Menge.

Ich werde es mir zu Herzen nehmen.

cyblord ---- schrieb:
> Bei dir scheint es größere Defizite der Programmierung allgemein

Vielleicht.... Aber ich lerne noch...

> und bei
> Spezifika wie Registern und RAM zu geben. ich würde diese erstmal
> beheben

könntest du das näher erläutern?

spess53 schrieb:
> Vielleicht solltest du mal dieses .def-Gedödel überdenken. Für
> Spielzeugprogramme ganz nett, ab einer bestimmten Programmgröße einfach
> nur hinderlich.

Also ich finde es nützlich, da weiss man halt wofür dieses Register 
benutzt wird.

spess53 schrieb:
> Ich persönlich komme glänzend ohne Defines aus.

Respekt, hast du ein Beispiel?


@all
Sämtliche Kritik wird von mir gerne angenommen, und ich werde es auch 
versuchen umzusetzen.

Danke

von oldmax (Gast)


Lesenswert?

Hi
>Einzelne, klar gegliederte Module mit dokumentierten Schnittstellen.
>Kostet ein wenig an Performance, bringt aber ne Menge.
 In dem Punkt gebe ich h.J.S. nur bedingt recht. Ein geübter 
Programmierer, klar, der holt noch Performance, aber ein Anfänger kann 
gar nichts besseres tun, als modular arbeiten. Nicht nur, das er 
schneller zum Ergebnis findet, sondern er wird trotz umfangreichem 
Programm in der Lage sein, einen schnellen Zyklus hinzubekommen.
Beispiel:
Hauptschleife besteht nur aus Call Sub
Jede Sub prüft, ob sie etwas zu tun hat oder gibt die Programmkontrolle 
gleich wieder ab. Nachteil, es wird immer n die Subroutine gesprungen 
und das kostet Zeit. Aber wer in der Hauptschleife prüft, ob ein e Sub 
aufgerufen werden soll spart zwar Zykluszeit, aber verliert schnell den 
Überblick. Noch schlimmer, wenn auf Subroutinen weitesgehend verzichtet 
wird und die Hauptschleife ein langer Wust von Sprüngen ist. Du wirst 
relativ schnell merken, wie man mit Variablen als Schnittstellen und 
Programmflags trotz Schachtelung mit Subroutinen schnellen Code erzeugen 
kann, ohne das der Durchblick darunter leidet.
Grußß oldmax

von Karl H. (kbuchegg)


Lesenswert?

oldmax schrieb:

> wird und die Hauptschleife ein langer Wust von Sprüngen ist. Du wirst
> relativ schnell merken


Vor allen Dingen merkt man recht schnell, dass Codekomplexität mit 
steigender Programmgröße dazu tendiert, exponentiell in den Himmel zu 
schiessen.
Code wird solange komplexer, bis er die Fähigkeit des Programmierers 
übersteigt, ihn noch zu überblicken. Dieser Punkt ist bei Könnern etwas 
höher angesetzt, ist aber bei Anfängern recht schnell erreicht. 
Anfängern versuchen die Komplexität dadurch zu drücken, in dem sie den 
Code kleiner machen. Das versuchen sie (oft) durch Tricksereien zu 
erreichen. Könner haben das längst aufgegeben und gelernt, das das nicht 
funktioniert. Sie erreichen die (für sie) noch überschaubare Komplexität 
durch Modularisierung.

Dise 'Jeden Takt einsparen, koste es was es wolle' Taktik führt 
regelmässig bei größeren Programmen zum immer gleichen Ergebnis: bei 
Erweiterungen bze. Veränderungen muss man aus ökonomischen 
Gesichtspunkten alles wegwerfen und neu anfangen. Letzten Endes ist das 
billiger und geht schneller, als wenn man erst mal Wochen damit 
verbringt, alle Details und Feinheiten eines alten Codes (den mglw. wer 
anderer geschrieben hat) zu verstehen. Versteht man die nicht, dann 
ergibt sich genauso regelmässig die Situation, das das Programm 
plötzlich seltsame Effekte zeigt, die keiner versteht und deren 
Ergründung noch mehr Analysezeit nach sich zieht.

von André M. (killroymenzel)


Lesenswert?

Das mit dem Modular programmieren mache ich schon.
Ich hab eigene Dateien die I2C, Uart, LCD, oder andere Schnittstellen 
beinhalten.
Sowie auch z.B. Routinen für OneWire,  RTC usw.

Später will uch in der Main mit Flags arbeiten die in einer ISR oder SUB 
gesetzt bzw gelöscht werden.

Derzeit arbeite ich halt an ADC und SD-card dateien.

Also wenn ich später ein neues Programm schreibe brauche ich nur noch 
die Dateien zusammen würfeln und die Main neu schreiben.

So mein Plan.........

von spess53 (Gast)


Lesenswert?

Hi

>Ich hab eigene Dateien die I2C, Uart, LCD, oder andere Schnittstellen
>beinhalten.
>Sowie auch z.B. Routinen für OneWire,  RTC usw.

Und wie hast du es da mit den Registernamen gemacht?

MfG Spess

von André M. (killroymenzel)


Lesenswert?

spess53 schrieb:
> Und wie hast du es da mit den Registernamen gemacht?


Naja.....
ich habe meine "Haupt"Register.
accu    (für jegliche Daten Übergabe Übernahme)
temp    (als ausweichregister zum rechnen)
index   (Zählregister)
rawhigh (Datenüber/gabe/nahme)
rawlow  (für 16bit)
Flag    (8bit Zustandsübergabe)
ggf. Flag2 (wenn 8bit nicht reichen)

zl:zh ist immer für Datenausgabe
xl:xh ist immer für Delays

ansonsten muss ich halt schauen, was die "unter"programme noch fordern.

Die muss ich halt im Hauptprogramm definieren.
Dann ist es aber auch egal, ob z.B. das Register EE_Adr 
(EEPromAdresse)sich auf r16 oder r25 befindet.



André

von oldmax (Gast)


Lesenswert?

Hi
> xl:xh ist immer für Delays
Da stellt sich mir die Frage, bremst du dein Programm aus? Ansonsten ist 
ja nichts an deiner Vorgehensweise falsch, aber bei Delays klingelts 
immer in den Ohren. ( Weiß nicht, obs am Alter liegt ?... ) Wenn du 
Zeiten brauchst, befass dich mit den Timern und leite dir Zeittakte ab. 
Ich hinterleg die in einer Variablen Time_Flags. Die ISR setzt, die 
Bearbeitung löscht. Selbst ein Zeitflag von einer mSek. kann in der 
Regel im Programm gepollt werden., denn selten ist eine Zykluszeit bei 
den Standardprogrammen größer. Aber in Assembler läßt sich das zur Not 
auch ausrechnen.
Gruß oldmax

von André M. (killroymenzel)


Lesenswert?

oldmax schrieb:
> aber bei Delays klingelts immer in den Ohren. ( Weiß nicht, obs am Alter
> liegt ?...


Die Delays verwende ich eigentlich nur für das LCD
und ganz wichtig für OneWire,  da dieses wirklich Zeitkritisch ist 
sollte man die Interrupts während dessen deaktivieren.

Generell hast du ja recht......
Ich muss mein Programm sowieso noch mal überdenken. ... zumindest was 
die Main angeht.



Andre

: Bearbeitet durch User
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.