Atmega8, Mittelwert berechnen (Assembler)

OP #582979
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
Gast
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...
OP
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?
Gast
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
Gast
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
Persönliche Seite
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
Gast
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
Gast
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
Gast
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
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
OP
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?
Angehängte Dateien:

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 19 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.