Hallo alle zusammen,
in meinem Programm bekomme ich eine Periodenzeit mit Hilfe des 16-Bit
Timers. Ich möchte die gemessene Zeit über 11 Messungen addieren und
davon dann den Mittelwert bilden. Wie baue ich das im Programm ein?
Vielen Dank
1
//#define F_CPU 16000000
2
#include<avr/io.h>
3
#include<util/delay.h>
4
#include"lcd.h"
5
#include<avr/interrupt.h>
6
7
8
/*unsigned int read_ad(void)
9
{
10
// Funktion zum Auslesen des A/D-Wandlers
11
ADCSRA |= (1<<ADSC); // Wandler starten
12
while(!(ADCSRA & (1<<ADIF))); //warten auf Wandler
13
return ADCW;
14
}
15
*/
16
17
volatileuint16_tmessung=0;
18
volatileuint32_tperiodenzeit;
19
volatileuint16_tstart;
20
volatileuint16_tende;
21
inti;
22
23
24
25
ISR(ADC_vect)// Interrupt zum Auslesen des Wandlers
Gegenfrage: Du weisst wie man in C ein Array programmiert?
Wenn "Nein": Buch über die Programmiersprace C besorgen und
durcharbeiten.
Wenn "Ja": Array benutzen.
@ Daniel
Ich würde Dir folgendes raten:
1. Überlege wie man einen Mittelwert auf dem Papier berechnet. Schau in
einem Mathematik-Buch nach, falls Du Dich nicht mehr genau erinnerst,
wie das geht.
2. Denke Dir ein paar zufällige Zahlen aus und rechne das einfach mal
von Hand bzw. mit dem Taschenrechner.
3. Nimm auch ein paar Zahlen, bei denen Du am Ergebnis sofort siehst,
dass die Rechnung richtig verlaufen sein muss! Etwa nur gleiche Zahlen.
Oder Zahlen die, der Grösse nach geordnet, immer die gleiche Differenz
zu dem Vorgänger und Nachfolger haben.
4. Versuche die wesentlich wichtigen Schritte, bei dieser Berechnung
aufzuschreiben. Vielleicht ein einer Liste von nacheinander
abzuarbeitenden Punkten.
5. Überlege Dir, wie Du das Papierverfahren in der Programmiersprache
ausdrückst. Dabei sind folgende Fragen von entscheidender Bedeutung: A)
Wie und wo werden die Werte abgespeichert. B) Gibt es bestimmte
Gegebenheiten, die vor dem Beginn der Berechnung vorhanden sein müssen?
C) Lassen sich, bestimmte Schritte als Wiederholungen formulieren? D)
Wovon hängt die Anzahl dieser Wiederholungen ab?
Stephan schrieb:> Warum ausgerechnet 11 Werte ?> 1,2,4,8,16 usw. macht die DIV einfacher...schieben.
genau
1
#define READS 5 // vielfache von 2^X READS 5 nimmt den Mittelwert aus 32 Messwerten
2
uint16_tlese_analog(uint8_t_port)
3
{uint16_t_adc=0;
4
for(i=0;i<(1<<READS);i++)
5
_adc+=analogRead(_port);// read the input pin
6
_adc>>=READS;
7
#ifndef SCHNAUZE
8
DEBUG_PRINT(F("_adc: "));DEBUG_PRINTLN(_adc);
9
// Serial.println();
10
delay(500);
11
#endif
12
return_adc;
13
}
noch besser wirds wenn man obere und untere Extremwerte nicht nimmt, ein
Array + Sortalgorythmus und erste und letzte ausserhalb der Toleranz
verwerfen
Also ein Array bräuchte ich nicht. Die einzelnen Werte will ja nachher
keiner mehr wissen. Einfach die Summe in einer Variablen speichern.
Dabei ein wenig aufpassen, dass die Variable genug Platz für die
größtmögliche Zahl bietet.
Und natürlich darauf achten, dass es auch 11 Werte sind, die da
aufaddiert werden.
Damit reduziert sich das Problem auf ein Teilen durch 11.
Wenn Du dann weißt wie, kannst Du Dich an einem Median-Wert der 11
Messungen versuchen. Der bügelt Ausreisser durch Messfehler besser aus.
Und ab da kommen dann doch wieder die Arrays ins Spiel.
fop schrieb:> Also ein Array bräuchte ich nicht
bist du der TO unter Doppelnamen?
Der TO stellt eine Frage und du antwortest brauche ich nicht?
fop schrieb:> Die einzelnen Werte will ja nachher> keiner mehr wissen
stimmt auch kann man wenn ausserhalb der Toleranz auch gleich vor dem
Aufaddieren verwerfen, nur darf man dann nicht mehr durch die Anzahl der
Durchläufe teilen!
fop schrieb:> nd natürlich darauf achten, dass es auch 11 Werte sind, die da> aufaddiert werden.> Damit reduziert sich das Problem auf ein Teilen durch 11.
was unheimlich viel Zeit braucht u.U. übermäßig viel mehr als man hat
gegenüber einem einfachen RECHTS Shift!
aber jeder wie er mag.
Joachim B. schrieb:> was unheimlich viel Zeit braucht> ....> aber jeder wie er mag.
Wenn ich nicht auf jeden Takt schauen muss, ist dieses mein Arbeitsesel
für solcherart Probleme.
Ist natürlich im Arduino Style, aber der Kern sollte sich auf C
übertragen lassen.
1
2
template<typenameDatenType>
3
classGleitenderMittelwert// eher ein Tiefpassfilter
Joachim B. schrieb:> fop schrieb:>> Also ein Array bräuchte ich nicht>> bist du der TO unter Doppelnamen?> Der TO stellt eine Frage und du antwortest brauche ich nicht?
Wenn ich fop wäre würde ich dir antworten, dass das "bräuchte" eben im
Konjunktiv steht, um anzudeuten, dass er es ohne Array machen würde,
wenn er es machen würde oder der TO wäre.
Und nein ich bin nicht fop unter anderem Namen.
Arduino F. schrieb:> class GleitenderMittelwert // eher ein Tiefpassfilter
Wenn es allerdings wirklich ein gleitender Mittelwert werden soll, käme
man um ein Array, am einfachsten verwaltet als Ringpuffer, nicht
drumrum.
Wolfgang schrieb:> äme> man um ein Array, am einfachsten verwaltet als Ringpuffer, nicht> drumrum.
Natürlich nicht. Wieso überhaupt diese panische Angst vor einem Array?
Selbst der popeligste Arduino wird doch noch Platz für 11 Messwerte
haben.
Georg
georg schrieb:> Natürlich nicht. Wieso überhaupt diese panische Angst vor einem Array?> Selbst der popeligste Arduino wird doch noch Platz für 11 Messwerte> haben.
sogar für 64/32 Messwerte wo man nur 32/16 sammelt die innerhalb der
Toleranz für einen Mittelwert liegen um wieder statt teilen shiften
kann..
georg schrieb:> Selbst der popeligste Arduino wird doch noch Platz für 11 Messwerte
Ab wann wird es denn knapp?
Ab 1000 Integers?
georg schrieb:> Wieso überhaupt diese panische Angst vor einem Array?
Wie immer:
Man wähle ein, der Aufgabe angemessenes, Verfahren.
Was soll das mit Angst zu tun haben?
Arduino F. schrieb:> Ab wann wird es denn knapp?> Ab 1000 Integers?
bein UNO oder nano 328p ja, der mega2560 kommt etwas weiter, der mighty
mini 1284p hat SRAM über alles was man brauchen wird, den habe ich noch
nie überlastet, den nano schon öfter da kratzen meine
Programmiermöglichkeiten an dessen Grenzen.
Arduino F. schrieb:> Ab wann wird es denn knapp?> Ab 1000 Integers?
Da wird es dann Zeit, auf einen anderen Arduino mit besserer
RAM-Ausstattung zurückzugreifen, z.B. einen Arduino Due.
Ob solch eine hohe Zeitauflösung bei einem gleitenden Mittelwert
sinnvoll erscheint, ist ein anderes Thema. Wenn die Daten derart
verrauscht sind, das so ein Filter erforderlich ist, kann man meist auch
erstmal einen kürzeres FIR davor schalten und für den gleitenden
Mittelwert mit niedrigerer Abtastrate weiterrechnen.
Aber sicher nicht fuer einen duemmlichen Mittelwert. Ich wuerde zu einem
exponentiellen Mittelwert greifen, der genau nur eine einzelne
Speicherstelle benoetigt. Dazu siehe :
https://www.ibrtses.com/embedded/exponential.html
Da ist die Mittelungskonstante, dh Zeitkonstante, auch nur genau ein
Wert.
Eine der für mich wichtigsten Lektionen an der Uni war die
Unterscheidung zwischen:
"Building the right thing vs. building the thing right"
Es gibt viele schöne Lösungen für verschiedene Probleme.
Aktuell ist noch völlig unklar was er wirklich braucht/will.
Beispielsweise ist völlig unklar ob er einen Mittelwert alle 11 Zyklen
will (Summe bilden + Division, dann erneut von vorn beginnen) oder ob es
ein gleitender Mittelwert mit 11 Zyklen rückblickend werden soll (in
jedem Zyklus immer die aktuell letzten 11 Zyklen auswerten).
Carsten R. schrieb:> oder ob es> ein gleitender Mittelwert mit 11 Zyklen rückblickend werden soll (in> jedem Zyklus immer die aktuell letzten 11 Zyklen auswerten).
sowas hatte ich mal bei einer DFC77 Auswertung gemacht für die 1/0
Erkennung
je nach Länge vom Kabel waren die Impulse verschliffen und durch
Erwärmung verschob sich das auch noch.
Also die 1/0 Schwelle(100ms/200ms) sowie die Sekundenpause 800ms/1900ms
immer über die Zeit nachjustiert, klappte ganz gut.
(war auch nötig um im Interrupt keine µs Störer zur Auswertung zu
bringen)