Forum: Mikrocontroller und Digitale Elektronik Atmega8, Mittelwert berechnen (Assembler)


von Ulrich B. (falken)


Lesenswert?

Hallo
ich habe ein kleines Problem mit einer Temperatursteuerung. Die 
Schaltung besteht aus vier Thermoelementen die an der oberen 
Temperaturgrenze 12mV abgeben. Diese werden dann jeweils mit einem 
Operationsverstärker auf 3.2V verstärkt und auf einen ADC-Eingang eines 
Atmega8 gelegt. Für den AVR habe ich ein Assembler Programm geschrieben 
das diese vier "Temperaturwerte" überwachen   und die entsprechenden 
Heizelemente schalten soll.(natürlich mit Hysterese)
Allerdings schwankt die Spannung an den ADC Eingängen wohl ziemlich 
sodass der  Wert ständig an die obere und untere Grenze der Hysterese 
kommt.
Hab es schon mit 100nF Kondensatoren am OP Eingang versucht aber das 
bringt nicht viel. Jetzt will ich versuchen den Mittelwert aus mehreren 
Messungen zu bilden. Leider hab ich noch sehr wenig Erfahrung mit dem 
Programmieren von AVR. Gibt es vielleicht schon eine Assembler-Routine 
dafür oder kann mir jemand helfen eine zu schreiben? Bin für jede Hilfe 
Dankbar!

Gruß, falken

von Doof Kopp (Gast)


Lesenswert?

Von wo hast du den Rest des Programmes her, dass du es nicht fertig 
bringst ein paar Werte zu addieren (am besten 2^n) und dann durch die 
Anzahl summierter Messungen zu teilen (bzw. nach rechts zu shiften mit 
lsr)?
In dieser Frage steckt auch schon ein Tipp...

von Ulrich B. (falken)


Lesenswert?

Das ist teilweise selbst geschrieben. Da wo es um den ADC ging hab ich 
manche Programmbeispiele aus dem myAVR Einsteigerset übernommen. Hab 
allerdings noch nix mathematisches gemacht.
Wie oft müsste man denn nach rechts schieben um zum Beispiel durch 16 zu 
teilen?

von Doof Kopp (Gast)


Lesenswert?

Gegenfrage: Wie oft muss man im Dezimalsystem nach rechts schieben um 
durch 100 zu teilen?

von spess53 (Gast)


Lesenswert?

Hi

Ungefähr 3,25 mal !! Was naturlich nicht so einfach geht. In Assembler 
benutzt man vorzugsweise 2er-Potenzen, also 2,4,8,16...1024... .
Einmal Rechtschieben entspricht einer Division durch 2. Vor dem Schieben 
sollte man den Wert 'aufrunden', in dem man z.B. vor einer Division 
durch Acht  4 addiert.

MfG Spess

von Ulrich B. (falken)


Lesenswert?

Schon mal danke für den Tip!
Aber auch wenn sichs jetzt blöd anhört versteh ich nicht ganz was das 
addieren mit dem aufrunden zu tun hat.

Gruß, falken

von spess53 (Gast)


Lesenswert?

Hi

Beispiel: Dein Wert ist 7. Wenn du 3mal nach rechts schiebst (Division 
durch 8) kommt 0 raus. Wenn du vorher 4 addierst kommt 1 raus. Das 
entspricht 7/8 mehr als 0.

MfG Spess

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

machs am besten so:
du benuzt 2 register

Du addierst auf das erste (nenen wir es R0) deinen Meßwert drauf
Du addierst auf das zweite (nenen wir es R1) das Carry also etwa so:


add r0, meßwert
adc r1, null (null = ein register was die 0 enthält)

dies wiederholst du 256 mal.

Nun hast du im R0 den Mittelwert über 256 Meßwerte.
Alle Regsiter wieder auf 0 setzen --> neue Meßreihe beginnen

von Ulrich B. (falken)


Lesenswert?

Und das ohne etwas zu verschieben?
Müsste dann ja auch mit weniger Messwerten z.B. 64 funktionieren, oder?

von spess53 (Gast)


Lesenswert?

Hi

Persönlich würde ich das allerdings über eine gleitende 
Mittelwertbildung realisieren (Ringpuffer+ Pointer). Dadurch bekommt man 
nach dem ersten Durchlauf für jeden Messwert einen Mittelwert.

MfG Spess

von Hannes L. (hannes)


Lesenswert?

Beitrag "Re: Mittelwert berechnung"

Ist zum "Beruhigen" von ADC-Werten bestens geeignet und erfordert extrem 
wenig Ressourcen.

...

von Thomas (kosmos)


Lesenswert?

OPAMP-Ausgang--------Widerstand---------ADC-Eingang
                                  |
                              Kondensator
                                  |
                                Masse

von Karl H. (kbuchegg)


Lesenswert?


von Fred (Gast)


Lesenswert?

Hallo Läubi,

mal ne Frage zur Funktion:

> add r0, meßwert
> adc r1, null (null = ein register was die 0 enthält)
> dies wiederholst du 256 mal.
> Nun hast du im R0 den Mittelwert über 256 Meßwerte.
> Alle Regsiter wieder auf 0 setzen --> neue Meßreihe beginnen

In r0 wird im Prinzip die Summe aller Messwerte erfasst, in r1 die 
Anzahl, sehe ich das soweit richtig? Dann müsste man mit r0/r1 den 
Mittelwert bekommen.
Ich habe da folgende Bedenken/Fragen:
- man kann dann nur solange Werte mitteln, solange r0 nicht überläuft, 
oder?
- warum nicht in einer Schleife r1 mit "inc r1" erhöhen?
- wie funktioniert die Teilung (wenn keine Zweierpotenz)?

Gruß

Fred

von spess53 (Gast)


Lesenswert?

Hi

Das Verfahren funktioniert nur mit 8Bit-Werten. Die Addition von 256 
Bytes bleibt innerhalb von 16Bit(2 Register). Im o.g. Fall ist r0 das 
Low-Byte und r1 das High-Byte und nicht der Zähler. Um den Übertrag von
'add r0,meßwert' zu berücksitigen wird das 'adc r1,0' (wobei 0 ein mit 0 
geladenenes Register ist). Rechtsschieben ist nicht notwendig,weil das 
High-Byte einer 16 Bit Zahl dem Ergebnis von 8 mal 16Bit Rechtsschieben 
ist.

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

Läubi Mail@laeubi.de wrote:
> machs am besten so:
> du benuzt 2 register
>
> Du addierst auf das erste (nenen wir es R0) deinen Meßwert drauf
> Du addierst auf das zweite (nenen wir es R1) das Carry also etwa so:
>
>
> add r0, meßwert
> adc r1, null (null = ein register was die 0 enthält)
>
> dies wiederholst du 256 mal.
>
> Nun hast du im R0 den Mittelwert über 256 Meßwerte.

Der Mittelwert (ohne Rundungskorrektur) ist in R1, nicht
in R0

von Ulrich B. (falken)


Angehängte Dateien:

Lesenswert?

Hi
Also ich hab es jetz mal so versucht wie im Anhang zu sehen.
Aber das Egebnis stimmt leider nicht. Wenn die Werte zwischen 180 und 
200 schwanken müsste der Mittelwert ja dawischen liegen. Er liegt aber 
nahe null.
Sieht vielleicht jemand einen Fehler im Code den ich übersehen habe?

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.