Problem mit der Servobewegung bei Mobatools

Hallo Gemeinde
Ich habe ein Problem mit den Mobatools. Wenn ich das Programm starte, habe ich gleich im setup die Zeilen:

 ServoVertikal.setSpeed(5);
  ServoHorizontal.setSpeed(5);
  ServoVertikal.write(137);
  ServoHorizontal.write(34);

Damit sollte doch eigentlich eine langsamme Fahrt (setSpeed(5):wink: auf die erste Positon erfolgen. Da der Aufbau sehr schwer ist, ist es ziehmlich zerstörerisch, wenn die Sevos da in normalen Tempo voll anreissen. Tun sie aber. Der Speed iteressiert das Programm ers bei der nächsten Fahrt. da ist dann alles gut. Was kann ich tun, dass das Programm schon bei der ersten Bewegung mit dem vorgegebenen Speed fährt??

PS: Es ist egal ob die erste Fahrt in Setup oder im Loop beginnt. mit dem eigestellten Speed bewegen sich die Servos immer erst ab der zweiten Fahrt. Das ganze ist mit einem Nano ausgeführt.

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
#include <Adafruit_ADS1X15.h> // bindet Wire.h für I2C mit ein
Adafruit_ADS1115 ads;
#define ADS_I2C_ADDR 0x48
#include <MobaTools.h>
MoToServo ServoHorizontal;
MoToServo ServoVertikal;
byte ablauf = 0;
const float multiplier = 0.125F; // ADS1115-Multiplikator bei einf. Verstärkung
const byte panel = A0;
int panelwert = 0;
float panelspannung = 0;
float ads_mv0 = 0;  // Sensor rechts
float ads_mv1 = 0;  // Sensor links
float ads_mv2 = 0;  // Sensor hinten
float ads_mv3 = 0;  // Sensor vorne
int adc0 = 0;
int adc1 = 0;
int adc2 = 0;
int adc3 = 0;
const byte Servo1 = 5;
const byte Servo2 = 6;
unsigned long sekundenablauf1 = 0; // Messabstand 1 Sekunde
const unsigned long pausezeit1 = 1000;
unsigned long sekundenablauf2 = 0; // Messabstand 10 Sekunde
const unsigned long pausezeit2 = 10000;
unsigned long aktuellzeit = 0;
void setup() {
  //----------------------------------------------------
  lcd.begin();
  lcd.backlight();
  lcd.clear();
  //----------------------------------------------------
  Serial.begin(9600);
  //----------------------------------------------------
  ads.begin(ADS_I2C_ADDR, &Wire);
  // Werte 1-fach verstärken (ESP32 liefert  max. 3,3V)
  ads.setGain(GAIN_ONE);
  //----------------------------------------------------
  lcd.setCursor (0, 0);            // Zeile 1
  lcd.print (F("Panelspannung "));
  //----------------------------------------------------
  pinMode(panel, INPUT);         // Spannung vom Panel
  //----------------------------------------------------
  ServoHorizontal.attach(Servo1);
  ServoVertikal.attach(Servo2);
  sekundenablauf1 = millis();
  sekundenablauf2 = millis();
  ServoVertikal.setSpeed(5);
  ServoHorizontal.setSpeed(5);
  ServoVertikal.write(137);
  ServoHorizontal.write(34);
}
void loop() {
  aktuellzeit = millis();
  //Jede Sekunde Spannung am Panel messen
  if (aktuellzeit - sekundenablauf1 >= pausezeit1) { // Eine Sekunde abgelaufen?
    panelwert = analogRead(panel);
    panelspannung = panelwert * 20.3 / 1024.0;
    lcd.setCursor (14, 0);            // Zeile 1
    lcd.print (panelspannung);
    sekundenablauf1 = millis();
  }
  // -----Kanal 0 Messung------------------------------
  adc0 = ads.readADC_SingleEnded(0);
  ads_mv0 = ads.computeVolts(adc0) * 1000;
  lcd.setCursor (12, 2);             // Zeile 3
  lcd.print (ads_mv0);
  // -----Kanal 1 Messung------------------------------
  adc1 = ads.readADC_SingleEnded(1);
  ads_mv1 = ads.computeVolts(adc1) * 1000;
  lcd.setCursor (0, 2);            // Zeile 3
  lcd.print (ads_mv1);
  // -----Kanal 2 Messung------------------------------
  adc2 = ads.readADC_SingleEnded(2);
  ads_mv2 = ads.computeVolts(adc2) * 1000;
  lcd.setCursor (6, 1);             // Zeile 2
  lcd.print (ads_mv2);
  // -----Kanal 3 Messung------------------------------
  adc3 = ads.readADC_SingleEnded(3);
  ads_mv3 = ads.computeVolts(adc3) * 1000;
  lcd.setCursor (6, 3);            // Zeile 4
  lcd.print (ads_mv3);
  //------------------Servos Testfahrt------------------
  if (aktuellzeit - sekundenablauf2 >= pausezeit2) { // 10 Sekunde abgelaufen?
    Serial.println(F("10_Sekunden"));
    Serial.println(ablauf);
    if (ablauf == 2) {
      ablauf = 0;
      Serial.println(F("Null"));
      Serial.println(ablauf);
    }
    //--------------------------------------------------
    if (ablauf == 1) {
      ServoVertikal.write(135);
      ServoHorizontal.write(34);
      ablauf = 2;
    }
    //----------------------------------------------------
    if (ablauf == 0) {
      ServoVertikal.write(53);
      ServoHorizontal.write(137);
      ablauf = 1;
    }
    sekundenablauf2 = millis();
  }
  //----------------------------------------------------
}

Hier ist noch ein Video dazu. Ich denke man erkennt da, dass es seeehr wichtig ist, dass die Servos nicht bei der ersten Fahrt abräumen :roll_eyes: ....weil die Platine oben sehr Kopflastig ist. :pleading_face:

PS: Ich will damit keinen Schönheitspreis gewinnen. Es ist nur eine Testkosole mit der ich Programm und Hardware für eine Panelsteuerung für die Sonnen-Nachführung machen / testen will. Die Werte am Display sind die Lichtwerte der vier Lichtempfindlichen Widerstände und die Spannung, die das Panel erzeugt. Die Bewegung ist noch nicht abhängig vom LIcht. Das kommt noch. Die Position der Lichtwerte im Display ist gleich der Pos. der Sensoren auf der Platine. Das sind die vier kleinen Roten Dinger an den Seitenrändern.

Das ist ein grundsätzliches Problem bei der langsamen Bewegung von Standardservos. Da man dem Servo selbst nicht sagen kann, dass es sich langsam bewegen soll, muss man ihm möglichst viele Zwischenpositionen zwischen Startpunkt und Endpunkt als jeweils neue Zielpositionen in einem passenden Zeitraster vorgeben. Das bedingt aber das man nicht nur die gewünschte Endposition kennt, sondern auch die Startposition. Da man die aktuelle Position bei einem Standardservo nicht auslesen kann, ist die Startposition bei der ersten Bewegung nach Programmstart prinzipbedingt nicht bekannt. Deshalb ist die erste Bewegung immer mit voller Geschwindigkeit. Erst bei den weiteren Bewegungen ist die Startposition ( = vorherige Endposition ) bekannt.
Einzige mir bekannte Lösung: Du musst dir die letzte Endposition immer im EEPROM merken, und bei einem Neustart zuerst zu dieser Position fahren. Da das Servo ja dann bereits dort steht ( wenn es nicht mechanisch verstellt wurde ) fällt die schnelle erste Bewegung dann nicht auf. Und ab da funktioniert es dann auch wieder langsam.

Heißt das, die erste Fahrt ist nicht vom Programm gesteuert? Der Servo fährt doch bei der ersten Fahrt auch auf die Pos. die ich im Programm über MobaTools anweise. Warum dann nicht mit der Geschwindigkeit die ich anweise?

  ServoVertikal.setSpeed(5);
  ServoHorizontal.setSpeed(5);
  ServoVertikal.write(137);
  ServoHorizontal.write(34);

OK, dann wäre es Sinnvoll, Potis zur Positionskontrolle dran zu bauen, und dann erst mal diese Pos. auslesen und anfahren. Oder die letzte Pos. immer speichern, wie du schon schreibst. Die Wege die ich dann fahre sind eh nur ganz kleine Schritte, weil ich ja immer nur ein paar Grad fahre, und wieder das Licht messe, dann wieder fahren, messen, .......

Danke, schönes Wochenende
Franz

Weil der Servo nix von deiner Geschwindigkeit weiß.

Eine Variante:
Reiß die eingebaute Elektronik aus dem Servo raus, und bau eine eigene daneben.
Der könntest du dann z.B. per I2C, alles sagen, was du willst.

Industrie Servos können das, Modellbau Servos eher nicht.
Und die mit Positionsrückmelder sind ehr selten und teuer.

du könntest doch auch selber eine "Rampe" programmieren und den Servo langsam starten schneller werden lassen und bzw. invers angsam enden lassen? Obs eine Rampe für Servos in den Mobatools gibt weis ich nicht. Aber scheint mir auch zu Fuß keine Hexerei zu sein.

Sonst nur ein paar Anmerkungen:

  • du hast einen Drehpunkt - tariere deine Last aus, damit möglichst wenig Unterschied zwischen "Links/Rechts" vorherrscht.
  • Das ruckelt optisch sehr. ... das hätte ich bei meinen "Slow Servos" eigentlich in der Form noch nicht gesehen.
  • wegen dem "Anfangsproblem" ... vieleicht hilft es schon relativ langsam eine Mittelposition in Setup anzufahren.

Gibts und tuts auch.
Aber das Problem ist der "zufällige" Startpunkt.

Wie stellst du dir das vor?
Ohne Positionssensor?

Ja, die Servos selber steuern ist natürlich auch keine Hexerei. Ich mache mich mal dran. Ich habe jetzt schon kapiert, dass Mobatools das erste Pos. langsam anfahren auch nicht kann, weil es dazu eine erste Ist-Position braucht, die man dem Programm gibt, um eine Ist-Position zu haben. Also das bessere wäre Servos mit Pos. Meldung.

Franz

Ja, er meint, dass die erste Strecke dann wenigstens nicht soooooo lange ist, wenn man als erstes einen Punkt anfährt, der in der Mitte zwischen den möglichen Pos. liegt. Aber das ist auch verdammt weit. Ich fahre mit dem Horizontalen Servo echte 240 Grad und mit dem Vertikalen 140 Grad. Wenn ich da öfter vollgas starte, dann reißt mir das alles kapput.

irgend einen Tod musst sterben. Entweder beim Abschalten in Mitteposition fahren, und/oder Speichern, oder Positionsmeldung, oder grob die Mechanik ändern...

Gibts eine echte Problemstellung zu lösen oder ist das nur eine Spielerei/Bastlerei mit Servos?

edit:
Zwei Servos mit Beschleunigungs/Bremswerte.
Ramp Servo auf Wokwi

edit:
Bzw. hier beschrieben auf meiner homepage:

https://werner.rothschopf.net/microcontroller/202209_millis_servo_ramping.htm

Ist aus meiner Sicht erstmal die einfachste Lösung.
Alles, was die MobaTools bereits machen nochmal selber programmieren bringt aus meiner Sicht nichts, da Du dann das gleiche Problem bekommst. Das hat ja nichts mit den MobaTools zu tun, sondern ist ein prinzipielles Servoproblem.
Eine Positionsrückmeldung in die Servos einbauen ist jedenfalls erstmal aufwändiger als die Speicherlösung. Falls das mit der Speicherung nicht so klappt wie Du dir das vorstellst, kannst Du das immer noch machen.

P.S. mit Rampen hat das Ganze auch nichts zu tun. Das Problem ist schlicht und einfach, dass der Arduino beim Start nicht weis, wo das Servo steht.

Ja, und um langsamm zu fahren muss er kleine Schritte fahren. Das geht nur wenn die Startposition bekannt ist. Hat nur ein bischen gedauert, bis bei mir das Zenerl gefallen ist. :stuck_out_tongue_winking_eye:

:+1:

Naja, im Moment erst mal eine Konsole zum Testaufbau. Und zum Programm erstellen. Aber muss ja auch funktionieren. Ich muss schauen, ob die Panal-Nachführung zur Sonne auch bei bedeckten Himmel funktioniert. Ein Bekannter schreibt, dass das bei Bedeckten Himmel nicht mehr zuverlässig funktioniert, weil dann die Lichtverhältnisse am ganzen Himmel gleich sind. Ob ich dann das ganze im kommenden Jahr als Spannungsversorgung fürs Poolhaus verwende, weiß ich noch nicht. Das ist dann nach Lust und Laune. Aber ich mag auf jeden Fall schon mal ein fuktionierendens System erstellen. Ob das dann ich, oder jemand anders nutzt, wird sich zeigen.

Bienen haben da einen Trick auf Lager!
Die haben extra Sensoren auf dem Kopf, welche die Polarisationsrichtung des Lichtes wahrnehmen können. So können sie auch bei starker Bewölkung navigieren.
(frage mich bitte nicht, wie genau die das tun, die konnten mir das nicht verraten)

Warum nicht Sonnen stand nehmen? Die Erde dreht sich auch bei bedeckten Himmel, und nach der Zeit fahren.
Du must doch Morgens dein Panel nach Osten fahren oder?

Nein.

Ja!

Lösung: Du nutzt ein Feedback Servo.

In meiner Anleitung: RC-Servo mit Istpositionsmeldung - Anfangszucken unterdrücken ist es der zweite Punkt. Geschickt, wie Du bist, kannst Du zum Testen erstmal einen Umbau machen.

Natürlich braucht es ein Programm zum Kalibrieren, Sichern der Werte im EEPROM und Verwenden im Programm. Das habe ich bei meinem Kohlekranfunktionsmodell gemacht.

Bei Fragen bitte fragen :slightly_smiling_face:

coole Idee:

Bei Adafruit ist es ausverkauft aber bei Pimoroni ist ein Micro-Servo bestellbar.
Ist die Frage ob das genug Kraft hat

Danke dir.
Die Feedback Servos habe anscheinend alle min. 6 Volt und offenbar auch nicht mehr wie 180 Grad. Und den Umbau kenne ich von dir, kann ich auch locker machen, aber will ich nicht. Ich gehe auf die Speicherlösung. Obwohl mir die Feedback-Lösung lieber wäre. Ich will nur nicht selber im Servo rumlöten.

Ja, 1,8 kg ist mir zu wenig und auch die 6 Volt sind nicht so toll. Danke dir. Ich werde wohl bei der Speicherlösung bleiben.

Franz