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.
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
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.
Danke...!! Der Fehler lag mal wieder zwischen den Ohren. Ich werde es heute Abend mal testen. André
@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
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
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
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
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.
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....!!
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
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.....
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.
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
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
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
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
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.
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.........
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
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é
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.