ich habe einen 10k Potti an 5 Volt und Erde hängen und lese das, was am mittleren Pin anliegt im Loop aus:
int PottiAmp1; // cable color: orange
int PottiAmp2; // cable color: orange
int PottiAmp3; // cable color: orange
int PottiGit1; // cable color: pink
int PottiGit2; // cable color: green
int PottiGit3; // cable color: blue
// Smooth Function
long int allPottis[20][6];
int average = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
// Analog States
int PottiGit3 = analogRead(A5); //blue
Serial.print("\t 6: ");
Serial.print(PottiGit3);
// smooth Analog signals
PottiGit3 = smooth(PottiGit3, 6);
Serial.print("\t 6: ");
Serial.println(PottiGit3);
int smooth(int newValue, int Potti){
//Werte eins hoch rutschen, hinten anfangen
for (int i=0; i<=19; i++){
allPottis[19-i][Potti] = allPottis[18-i][Potti];
}
//neuen Wert an den Anfang setzen
//if (newValue == allPottis[1][Potti]){
allPottis[0][Potti] = newValue;
//}
//calculate sum
int sum = 0;
for (int i = 0; i<=19; i++){
sum = sum + allPottis[i][Potti];
}
//calculate average and cast to int
double average = sum/21;
average = (int) average;
return (average);
}
Ich hoffe das ist nicht zu viel Code. Habe schon den Großteil weggelöscht. Das Problem ist nun folgendes, wenn ich den neuen Wert am Potti und den aktuellen Durchschnittswert über den seriellen Monitor ausgeben lasse:
Was hat es für einen Sinn die arrayvariable als long zu definieren, deren summe aber als int? ok wir sind noch im INT Bereich aber ein solche Codekonstruktion läßt genaue Überlegungen bezweifeln.
uwefed:
Was hat es für einen Sinn die arrayvariable als long zu definieren, deren summe aber als int? ok wir sind noch im INT Bereich aber ein solche Codekonstruktion läßt genaue Überlegungen bezweifeln.
Grüße Uwe
Es war ursprünglich int. Dachte dann, dass der Fehler daran liegen könnte, dass das array schon "voll" ist und hab es auf long int gestellt. Danke fürs aufmerskame lesen.
Hauptsächlich lässt es dich erstmal am anderen Tip ( Dem mit dem C++ Buch ) verzweifeln, bis du zum Thema Operatoren kommst:
combie ändert nämlich die Bedeutung des = Zeichens, damit wir was zum Staunen haben.
(Ist jetzt keine Zuweisung mehr, sondern die eigentliche Tiefpass-Funktion ( gleitender Mittelwert )
Hallo,
das ist das Elend bei der MittelWertBildung- die unkontrollierten Ausreißer.
Das Zauberwort heißt Median berechnen.
Nutze ich schon seid dem ohne Probleme.
Gruß und Spaß
Andreas
Hier waren wir inzwischen bei einem anderen Problem, wie man ohne Array von alten Werten eine Filter-Funktion hinkriegt. Dein Median braucht erstens ein Array und muss das auch noch sortieren.
Wenn das nicht stört, und man Probleme mit Ausreißern hat (hier nicht), ist das sicher überlegenswert.
Hier als "Ausreißer" war ein Programmierfehler zu sehen. Da ist Median sicher keine empfehlenswerte Strategie, zumindest wenn man den Fehler auch richtig entfernen kann.
SkobyMobil:
Das Zauberwort heißt Median berechnen.
Eine gute Glättung kann man auch -ganz ohne Array- mit einer einzigen Code-Zeile realisieren:
A0smooth = A0smooth + (A0 - A0smooth ) / n;
A0 ist das Rohsignal
A0smooth das geglättenes
n das Glättungsfaktor z.B. etwas zwischen 3 und 30.
Alles vorzugsweise Float.
Wenn mit unsigned Integer gearbeitet wird, bietet sich an A0 zuerst mit Faktor 64 zu multiplizieren. Das Ergebnis ist dann im Bereich 0...65540.
Das bildet ein Low-Pass filter ab, was die Elektroniker mit einem Widerstand-Kondensator-Glied zum Entstören machten.
P.S. Wenn A0 sich nur langsam ändert, bekommt man damit auch noch 1-2 Bits mehr Auflösung geschenkt.
Ist die gleiche Lösung wie combies Anfangs-Antwort. (#2) Der allerdings versucht, diese Zeile möglichst tief zu vergraben.
Wenn mit unsigned Integer gearbeitet wird, bietet sich an A0 zuerst mit Faktor 64 zu multiplizieren. Das Ergebnis ist dann im Bereich 0...65540.
Da bietet sich auch ein n = 16 oder 32 an, wobei der Compiler automatisch Division (und Multiplikation mit 64) zu shift-Operationen optimiert.
OK, macht jetzt im Zusammenhang mit Arduinos analogRead (mit ca. 100 µs delay) nicht wirklich etwas aus, aber es gibt ja auch nicht blockierendes ADC, bei dem man diese 100 µs für anderes nutzen könnte.
Das nennt combie "gleitender Mittelwert". Es ist ein Tiefpassfilter erster Ordnung (wenn dies in einem regelmäßigen Zyklus gemacht wird), der sich asymptotisch einer sprungförmigeen Änderung von value annähern würde.
warning: ISO C++ forbids comparison between pointer and integer [-fpermissive]
Auch hübsch wäre, wenn man die Anzahl der bisherigen Zyklen prüft und am Anfang einen echten Mittelwert bildet. Da kann man digital deutlich mehr machen als Tiefpässe zu simulieren.
byte n = 1;
const byte TIEFPASS = 32;
float mittel = 0.0;
void loop() {
int v = analogRead(0);
if (n < TIEFPASS) { mittel = (mittel * (n-1) + v ) / n; n++; }
else mittel = (mittel*TIEFPASS - (mittel-v)) / TIEFPASS;
Serial.print(mittel,1);
delay (100);
}