ADC Code

Gast #396068
Lesenswert?

Hallo alle zusammen,

ich möchte am PIN 3 des Ports A einen analogen Wert zyklisch mit dem
AD-Wandler einlesen.
Dazu habe ich das Programm wie im Anhang geschrieben.
Da meine Hardware noch nicht vorhanden ist, Teste ich im AVR Studio.
Nun meine Frage, ist der Code prinzipiell richtig, da ich in der AVR
Simulation ja nicht wirklich das Auslesen des AD-Pins testen kann, weiß
ich nicht, ob der Code so zyklisch ausliest?
Oder habe ich einen denkfehler?

Danke für eure Antworten schon mal.
Angehängte Dateien:
Gast #396069
Lesenswert?

Sollte eigentlich funktionieren. Ich häng' Dir mal meine Funktionen
dran die funktionieren definitiv, über die Handhabung einer Addition
bei vorzeichenbehafteten Zahlen kann man anderer Meinung sein,
funktioniert hier aber. Die Funktion wird mit ADMUX-Einstellung und
Anzahl Mittelwerte aufgerufen. Jeweils einmal für single-ended und
differentielle Messung.
Angehängte Dateien:
Gast #396072
Lesenswert?

Ein Aufruf würde so aussehen:

Messergebnis = ADC_conversion (2,32);

Würde bedeuten dass ADMUX mit 2 (=> ADC2, siehe Datenblatt) und 32 für
32 Messwerte zum mitteln gesetzt würde.
Der Rückgabewert der Funktion steht dann in 'Messergebnis'
Sofern Du den GNU-Compiler (hier WinAVR) benutzt sollte es auch im
AVR-Studio funktionieren.
Gast #396074
Lesenswert?

Abgesehen davon, dass es nicht sonderlich sinnvoll ist, eine übergebene
Variable (in diesem Falle channel) in der Funktion sofort wieder zu
überschreiben, könnte das ganze funktionieren.

Kleiner Tip: Bei einer Mittelwertbildung wenn möglich immer Potenzen
von 2 als Anzahl der Messwerte nehmen. Das schon Ressourcen, da das
Programm dadurch kleiner und schneller wird, weil sich Divisionen durch
2^n durch einfache Bitschiebeoperationen ersetzen lassen. Nimm also
(vorausgesetzt, das ist möglich) lieber 4 Messwerte für den Mittelwert
anstatt 3.
#396075
Lesenswert?

OT...

Mittelwert von Messungen mache ich meist über 256 Messungen, denn dann
kann man die Division durch Byteschieben realisieren, was sehr
effizienten Code ergibt:

;====================================================================
; Routine für Mittelwert über 256 Messungen (z.B. ADC)
;--------------------------------------------------------------------
; in 'wert_h' und 'wert_l' steht der Mittelwert,
; in 'wert_n' sind die Nachkommastellen, wl und wh sind
Temp-Register
; das Register 'null' enthält immer 0

;für 16-Bit-Werte:
 in wl,adcl             ;ADC-Wert
 in wh,adch             ;einlesen
 sub wert_n,wert_l      ;1/256 vom Wert
 sbc wert_l,wert_h      ;mit Übertrag
 sbc wert_h,null        ;subtrahieren,
 add wert_n,wl          ;1/256 des neuen
 adc wert_l,wh          ;Wertes mit Übertrag
 adc wert_h,null        ;addieren
;fertig...

;für 8-Bit-Wert:
 in wl,adch             ;linksbündig justierten ADC-Wert einlesen
 sub wert_n,wert        ;1/256 vom alten Wert
 sbc wert,null          ;mit Übertrag subtrahieren
 add wert_n,wl          ;1/256 vom neuen Wert
 adc wert,null          ;mit Übertrag addieren
;fertig...

...
Gast #396076
Lesenswert?

In meiner Lösung habe ich absichtlich eine double-Variable gewählt, da
die Anzahl der Aufzusummierenden Werte sonst begrenzt (Überlauf), oder
durch mehr Rechenaufwand zu realisieren ist. Außerdem habe ich bei
bitweiser Division am Ende immer noch die 5mV-Sprünge (Uref 5V). Bei
Atmel auf de HP gibt's Beispiele für einen 'Quasi-16-Bit-ADC'.
Gast #396077
Lesenswert?

double ist auf dem AVR auch nicht größer als float. Ein 32bit-Integer
hat mehr Genauigkeit als eine float-Variable.
Und was den Rechenaufwand betrifft, so sind Fließkommaberechnungen auf
einem Prozessor ohne FPU um ein Vielfaches aufwendiger, als die
Integerberechnungen, selbst wenn man diese mit 64 bits macht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren