Servoansteuerung exponentiell

Hallo,

hab das mal versucht. Halber Knüppelweg entspricht 25% Servoauslenkung.

x  	     y
   0      0
 511	 45
1023	180

Damit komme ich auf folgende Ganzzahlformel.

return ((2UL*x*x) + (3UL*x)) / 11577UL;

Das gilt aber noch für den kompletten Weg. Wenn ich den TO richtig verstehe will er zu beiden Seiten diese nicht lineare Auslenkung. Also 90° nach links und 90° nach rechts und davon wiederum diese 25% Marke. Knüppelmittelstellung sollte analogRead Werte um 512-513 ausspucken.
Müßte dann so sein ....
Je 50% nach links oder rechts machen nur 25% Servoauslenkung von 90° ausgehend. Ist das so?

   x	  y
   0	  0
 255	 68
 512	 90
 513	 90
 768	112
1023	180

Hallo,

beim halben Knüppelweg komme ich auf ein Polynom mit Subtraktion, dass erzeugt mit Ganzzahlrechnung im niedrigen Wertebereich sporadische Überläufe.

y = (0.0003 * x * x) - (0.0025 * x) = (3UL * x * x) - (25UL * x) 

Im Grunde hatte Michael mit dem einfachen quadrieren schon das Auge dafür. Das passt dafür und erspart komplizierte Rechnungen. Mit obiger Annahme wie es der TO sucht komme ich auf folgendes ...

void setup()
{
  Serial.begin(115200);

  for (unsigned long x = 0; x < 1024; x++)
  {
    unsigned long y {0};
    byte servoWinkel {90};
    
    if (x < 512) {
      y = calcServoWinkel(512-x);
      servoWinkel = 90-y;
    }

    if (x > 512) {
      y = calcServoWinkel(x-512);
      servoWinkel = 90+y;
    }
    
    Serial.print(x);
    Serial.print('\t');
    Serial.print(y);
    Serial.print('\t');
    Serial.println(servoWinkel);
  }
}

void loop()
{

}

unsigned long calcServoWinkel(const unsigned long x)
{
  return (x*x*90/262144);
}

Das mit Excel und Polynom war dennoch Lehrreich.

Hallo,
ja ich denke so solllte das sein. Dann kommst Du aber nicht mehr mit einer quadratischen Funktion aus, das ist dann eine x^3. oder man müsste nur die Hälfte nehmen und das dann irgendwie spiegeln.

Nachtrag : das hat sich überschnitten mein Post bezieht sich auf #21

Heinz

Hallo,

ich rechne mit je den halben Knüppelweg und der Rest rechnet mit Differenzen.
calcServoWinkel() quadriert und rechnet in den halben Winkelwert um, damit wird weitergerechnet zum endgültigen absoluten Winke für das Servo.

Hallo,
typischer Fall : wie komme ich nach Rom ? :wink:
Wenn die Stützpunke jetzt nicht auf einer einfachen quadratische Linie liegen würden ?? Ich hab da mit der Excell Variante gute Erfahrung gemacht. Bekommt man auch mit einer ziemlich blöden SPS ganz gut hin. Klar Gleitpunkt (float) muss sie können.
Gruß Heinz

über viele Wege :wink:

Na dann ginge das natürlich nicht so einfach, sollte klar sein.

Hallo, vielen Dank euch Allen. Das funktioniert schon ect gut, und ich kann nun auch die Werte soweit anpassen, das die Steuerungscharakteristik passt. Jetzt gibt es nur ein letztes Problem, ein Servo läuft falsch herum. Wie kann ich denn die Drehrichtung ändern?

Ich verstehe nicht, warum du nicht einfach eine PROGMEM Tabelle benutzt.

Mit voller, unkomprimierter Zuordnung braucht das gerade mal 1k Flash.
Ich möchte annehmen, dass all der float Kram viel mehr Platz wegnimmt.

Vom Laufzeitunterschied will ich gar nicht reden.

const uint8_t alle1024Werte[1024] PROGMEM = { 0, };

  analogWrite(ausgabePin, pgm_read_byte(alle1024Werte + analogRead(potiPin)));

oder so ähnlich.

Die Werte könnte man dann mit den ausgefeiltesten Algorithmen generieren lassen.

Die Tabelle (oder eine weitere alternative) würde sogar in den EEPROM passen, oder?

Vielleicht so:

servoValue = 1023 - analogRead(...)

Wie sieht denn dein aktueller Sketch aus? Gar so ins Blaue raten mag ich dann doch nicht.

@ Whandall: Das ist wie immer, es gibt mehrere Möglichkeiten solange nirgends der Schuh drückt. Optimieren kann man ja auch nur dann wenn man die Möglichkeiten kennt. Danach ist Frage optimiere ich weil ich es kann, weil es Spass macht oder weil es notwendig ist ...

@Doc_Arduino die langsamste, Speicher aufwändigste Variante über 27 Antworten
zum Erfolg zu reiten hat natürlich auch seinen besonderen Charme,
wenn einem extrem langweilig ist.

6 posts were merged into an existing topic: Probleme mit internem Pullup Widerstand

Hab einige Beiträgen von hier in einen anderen Tread verschoben da diese dorhingehören.

Grüße Uwe

Hallo,

ich bin es nochmal. Ich hab nun ein weinig weiterarbeiten können, und es hat sich gezeigt, das es mit dem Code von "Rentner" zwar funktioniert, die Servos aber recht stark zitteren . Kann man das noch verbesseren?

Viele Dank

Hallo,
wie stabil ist denn der eingelesen Sollwert vom Poti. ? der wird ja auch schon etwas schwanken. Wenn das der Fall ist könnte man darüber einen gleitenden Mittelwert bilden. Das bring aber eine gewisse zeitliche Verzögerung mit sich.
Eigentlich zittern Servos immer etwas herum, letztlich hat der einen eingebauten Regler der ein wenig um den Sollwert herum wacken kann.
Wenn der Motor wirklich stehen soll kannst Du den pin über die lib abschalten. Schau dir mal dazu in die Hilfe der IDE unter Servo lib.
Heinz

Ja wenn das Servo schrott ist schon, die vernünftigen Servos verhalten sich ruhig.

Also das sind schon hochwertige Didgitalservos. Am Servotester laufen die auch ganz ruhig ohne zu zittern. Zittern ist wohl auch nicht ganz richtig, der Servoarm wackelt schon ein paar mm hin und her.
Eine leichte Zeitliche Verzögerung würde in meinem Fall nichts ausmachen.

Dann ist eindeutig das Ansteuer-Signal nicht sauber.
Das mit den schrottigen Servos habe ich auf @Rentner Aussage bezogen, Servos würden immer zucken, denn das kenne ich auch anders. das war vlt, ganz früher mal so.

Hallo,
dann lass Dir doch mal den Analogwert anzeigen . Ausgabe im Monitor mit Serial.print()
Eventuell die ungenutzten Analogeingänge mal auf 0V legen.
Was ist das eigentlich für ein microcontroller bei einem UNO ist der Pin A7 nicht pwm fähig.

servo1Value = analogRead(servo1PotPin); 
Serial.println(servo1Value);

Heinz

A7 sehe ich nicht als PWM Pin definiert. Er definiert Pin 7, also D7 als Servo-Pin. Okay auch D7 ist kein Hardware PWM-Pin.