Ich habe mir einen Sketch gebastelt, um mal mit Array zu arbeiten und es besser zu verstehen.
Soweit ist mir mittlerweile auch alles klar, nur bei der linearen Interpolation steh ich etwas auf dem Schlauch.
Am Ausgang habe ich wieder eine LED angeschlossen, die beim drehen des Potis in Stufen gedimmt wird, genau so wie es auch im Serialmonitor angezeigt wird.
Ich brauche in meinem Sketch für die Formale zur interpolation also theoretisch ein "i" mit Kommastelle, nur auch gleichzeitig das "i" als nicht-Kommastelle, um die Werte zwischen die Array-Zeilen zu errechnen.
Ich habe schon mehrere Ansätze gehabt, mit z.B. float oder einen zweiten Buchstaben (j) als i-Ersatz mit Kommastelle, nur alles brachte nicht das gewünschte Ergebnis und nun sind mir die Ideen ausgegangen.
int arrayX[21] //X-Werte aus potiX/50
{
0, // 0 = 0
10, // 1 = 50
20, // 2 = 100
30, // 3 = 150
40, // 4 = 200
50, // 5 = 250
60, // 6 = 300
70, // 7 = 350
80, // 8 = 400
90, // 9 = 450
100, //10 = 500
90, //11 = 550
80, //12 = 600
70, //13 = 650
60, //14 = 700
50, //15 = 750
40, //16 = 800
30, //17 = 850
20, //18 = 900
10, //19 = 950
0, //20 = 1000
};
int i; //Platzhalter für arrayX[] (0-21)
const int potiX = A0; //Poti zum wählen von i
int wertX; //Wert von potiX, 10bit = 0-1023
const byte OUTpin = 11; //Ausgangspin
int wertOUT; //Ausgangswert, 8bit = 0-255
void setup()
{ Serial.begin(9600);}
void loop()
{ wertX = analogRead(potiX);
i = wertX/50; //Wert vom Poti wird durch 50 geteilt um auf die jeweilige arrayX[]-Zeile zu errechnen
arrayX[i] = arrayX[i-1] + (i-(i-1))*(arrayX[i]-arrayX[i-1]) / (i-(i-1)); //Formel für lineare Interpolation
wertOUT = arrayX[i]*255/100;
analogWrite(OUTpin,wertOUT);
Serial.print("arrayX[i]: "); Serial.print(arrayX[i]); Serial.print("\t");
Serial.print("i: "); Serial.print(i); Serial.print("\t");
Serial.print("potiX: "); Serial.print(wertX); Serial.print("\t");
Serial.print("wertOUT: "); Serial.println(wertOUT);}
Ja so ähnlich ist es fast, dies trifft auch bei (arrayX*-arrayX[i-1]) zu, wenn sich die Array-Zeilen jeweils nur in 1-er Schritten erhöhen, denn könnte man diesen Teil der formel weglassen.* Deswegen fehlt mir auch ein "i" mit Kommastelle bzw. ein zweiter Buchstabe, damit diese Rechnung aufgeht. Die Formel müsste also genaugenommen so aussehen: arrayX[i,?] = arrayX[i-1] + (i,?-(i-1))(arrayX-arrayX[i-1]) / (i-(i-1))* Wobei "i" auf die nächste ganze höhere Zahl aufgerundet ist und "i-1" auf die nächste ganze Zahl abgerundet. Mit Werten aus dem Array sieht es dann so aus, angenommen das Poti steht auf 625: arrayX[12.5] = arrayX[12] + (12.5-(12))*(arrayX[13]-arrayX[12]) / (13-(12)) vereinfacht heißt es dann: arrayX[12.5] = 80 + (0.5) * (10) / (1) arrayX[12.5] = 85 Das ist soweit nicht schwer, nur wie muss der Sketch dazu aussehen, das der Arduino damit rechnen kann? Ich habe schon versucht mit float-Zahlen zu rechnen, aber das funktioniert nicht.
Ohne jetzt deinen sketch im Detail geprüft zu haben:
ich hatte das mal so umgesetzt:
double _OUT;
const byte StuetzZU = 8;
const int ServoZuTab[StuetzZU][2]={ {0 , 0 }, // Kennlinie für Servo Zuluftsteuerung
{10 , 28 }, // PID_Out, Servowinkel
{20 , 38 },
{40 , 50 },
{60 , 59 },
{100 , 73 },
{170 , 93 },
{255 , 120 }};
// Aus Servo Zulufttabelle den korrekten Wert für den Winkel interpolieren
while (i < StuetzZU && _OUT > ServoZuTab[i][0]){i++;} // Passenden Eintrag in der Tabelle suchen
// den Wert zwischen den Stützstellen interpolieren
_out = (((ServoZuTab[i][1] - ServoZuTab[i-1][1]) * ( _OUT - ServoZuTab[i-1][0] ))/ (ServoZuTab[i][0] - ServoZuTab[i-1][0] )) + ServoZuTab[i-1][1];
Nachtrag: ich habe mit jetzt doch deinen Code mal angesehen.
Ich glaube, du hast da ein prinzipielles Verständnisproblem. Wenn du mit genau 20 möglichen Werten in eine Tabelle mit 21 Stützstellen reingehts, dann brauchst du nichts zu interpolieren.
Inpolieren musst du, wenn du viele mögliche Eingangswerte hast (z.B. 1024), aber nur eine Tabelle mit z.B. 16 Stützstellen anlegen willst.
Deshalb muss ein Array als Basis für eine Interpolation immer auch mindestens 2 dimensional sein.
Als Basis für die Kennlinie habe ich eine einfache quadratische Kennlinie genommen, nur um das Beispield zu verdeutlichen:
Wie du siehtst kannst du mit nur 7 (als Beispiel) Stützpunkten die Kennlinie recht gut abbilden. Das reicht für LED ansteuerung völlig.
Wenn ich das richtig verstanden habe, sollen dass deine Stützpunkte zur Interpolation sein? Der Verlauf der Werte scheint linear zu sein (erst eine steigende Gerade, dann eine identische fallende Gerade) demnach glaube ich brauchst du eigentlich nur drei dieser Werte. Und zwar:
0, // 0 = 0
100, //10 = 500
0, //20 = 1000
Mit diesen Wertepaaren solltest du jegliche Werte zwischen 0 und 20 errechnen können. Für kommerzahlen, natürlich dann ein passenden Datentypen verwenden (den Fehler hab ich vor einigen Tagen gemacht).
Wichtig!
Funktioniert nur wenn du auch wirklich eine Gerade interpolieren möchtest. Für Funktionen höheren Grades braucht man dann doch ein paar Informationen mehr wie HP/TP/WP.
guntherb:
Ich glaube, du hast da ein prinzipielles Verständnisproblem. Wenn du mit genau 20 möglichen Werten in eine Tabelle mit 21 Stützstellen reingehts, dann brauchst du nichts zu interpolieren.
Inpolieren musst du, wenn du viele mögliche Eingangswerte hast (z.B. 1024), aber nur eine Tabelle mit z.B. 16 Stützstellen anlegen willst.
Es sind doch 1024 Eingangswerte, bzw. 0-1023, die durch 50 geteilt werden, um die Zeile oder auch Stützstellen, m.M.n. die "zweite Dimension", zu ermitteln.
Zu den Stützstellen stehen die anderen Werte, was denn die erste Dimension sein dürfte.
Wenn ich das richtig sehe, habe ich genau das selbe wie du in deinem Sketch.
Ich muss den mal ausprobieren und gucken was passiert und ob die LED damit keine Sprünge macht, wie in meinem.
Oh_Ce:
Wenn ich das richtig verstanden habe, sollen dass deine Stützpunkte zur Interpolation sein? Der Verlauf der Werte scheint linear zu sein (erst eine steigende Gerade, dann eine identische fallende Gerade) demnach glaube ich brauchst du eigentlich nur drei dieser Werte. Und zwar:
0, // 0 = 0
100, //10 = 500
0, //20 = 1000
Das sind nur Beispiele, um es besseren nachvollziehen zu können, die könnten auch quer durcheinander sein.
Dazu vermute ich mal, das die LED mit nur diesen drei Zeilen, aus - an - aus sein wird.
normo:
Es sind doch 1024 Eingangswerte, bzw. 0-1023, die durch 50 geteilt werden, um die Zeile oder auch Stützstellen, m.M.n. die "zweite Dimension", zu ermitteln.
Zu den Stützstellen stehen die anderen Werte, was denn die erste Dimension sein dürfte.
Wenn du deinen Eingangswert durch 50 teilst, dann hast du keine 1023 Werte mehr, sondern nur noch 21.
Und die Information dazwischen geht dir verloren.
Lass es mich an obigem Beispiel nochmal erklären.
Ich habe diesen Graf mit den Stützstellen aus obigem Beispiel.
Und ich möchte den Y-Wert für den X-Wert "640" wissen.
Dann such zunächst das passende Wertepaar zu meiner Eingangsgrösse:
für 640 ist sind die Nachbarn { 500 , 60} und { 700 , 119}. Damit kann ich nun rechnen:
Mit der Formel
oder, anders ausgedrückt: ich ermittle die Geradengleichung zwischen den beiden Punkten und errechne mir damit den zu meinem X-Wert gehörigen Y-Wert.
Die Information, wo genau dein Eingangswert zwischen den Stützstellen liegt, verlierst du, wenn du vorher durch 50 teilst, die brauchst du aber, um die genaue Lage zwischen den Stützstellen zu kennen.
Sieh es dir auf der Grafik an, da ist es leichter zu verstehen.
Nun habe ich es verstanden wo es läuft und ich ein wenig mit den Werten rumgespielt habe.
Das einzige was mich daran noch störte, war wenn potiX auf 0 stand, leuchtete die LED und im Monitor wurde wertOUT mit -1 angezeigt.
Habe dagegen einfach
Kann es sein, dass dann der linke Wert zum Interpolieren fehlt?
Arduino, oder genauer avr-gcc, greift hemmungslos auch ausserhalb definierter Arrays zu.
Wenn das sicher zu deinem beobachteten -1 führt, ist es ja gut. Aber das ist schwer abzuschätzen.
Könntest dein arrayX bei -1 anfangen lassen oder bei 1024 aufhören lassen, und/oder die Grenz-Prüfung genau checken (was ist richtig: < <= >= > ? )
ES FUNKTIONIERT
Nun habe ich es verstanden wo es läuft und ich ein wenig mit den Werten rumgespielt habe.
GLÜCKWUNSCH, spiel ein wenig weiter und versteh noch mehr ...