mikrocontroller.net

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


Autor: Ulrich B. (falken)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Doof Kopp (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Ulrich B. (falken)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Doof Kopp (Gast)
Datum:

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

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Ulrich B. (falken)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Ulrich B. (falken)
Datum:

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

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Beitrag "Re: Mittelwert berechnung"

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

...

Autor: Thomas O. (kosmos)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OPAMP-Ausgang--------Widerstand---------ADC-Eingang
                                  |
                              Kondensator
                                  |
                                Masse

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Fred (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Ulrich B. (falken)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.