ftduino: Encodermotor Synchronisation?

Hallo Kids, hier ist eine Ecke extra für euch!
Ihr könnt hier Fragen aller Art stellen, die wir euch gerne so schnell wie möglich beantworten.
Ihr dürft hier aber auch gerne eure Modelle einfach mal anderen Fischertechnikern vorstellen.
Antworten
Tukan
Beiträge: 6
Registriert: 02 Aug 2023, 16:21

ftduino: Encodermotor Synchronisation?

Beitrag von Tukan » 06 Aug 2023, 12:40

Ich habe einen ftduino und der funktioniert sehr gut. Ich habe noch nicht viel damit gebaut aber mache gerade Experimente mit den Motorausgängen und habe an M1-M4 die Encoder Motoren aus dem TXT4 Set. Ich habe einen einfachen Sketch der mir die RPM der Motoren auswertet und meldet.

Sieht ungefähr so aus

Code: Alles auswählen

#include <Ftduino.h>

const int SERIAL_BAUD_RATE = 115200; // Baudrate für die serielle Kommunikation
const int RPM_IMPULSES_PER_REVOLUTION = 63; // Impulse pro Umdrehung der Getriebeachse

unsigned long lastTime = 0;
unsigned long lastImpulseCount1 = 0;
unsigned long lastImpulseCount2 = 0;
unsigned long lastImpulseCount3 = 0;
unsigned long lastImpulseCount4 = 0;

void setup() {
  ftduino.init(); // Initialisierung der Ftduino-Bibliothek

  pinMode(LED_BUILTIN, OUTPUT);

  // Initialisiere Counter für die Encoder
  ftduino.counter_set_mode(Ftduino::C1, Ftduino::C_EDGE_RISING);
  ftduino.counter_set_mode(Ftduino::C2, Ftduino::C_EDGE_RISING);
  ftduino.counter_set_mode(Ftduino::C3, Ftduino::C_EDGE_RISING);
  ftduino.counter_set_mode(Ftduino::C4, Ftduino::C_EDGE_RISING);
  ftduino.counter_clear(Ftduino::C1);
  ftduino.counter_clear(Ftduino::C2);
  ftduino.counter_clear(Ftduino::C3);
  ftduino.counter_clear(Ftduino::C4);

  Serial.begin(SERIAL_BAUD_RATE); // Serielle Kommunikation starten mit der angegebenen Baudrate
}



// Funktion zum Zählen der Impulse und Berechnen der RPM
void calculateRPM() {
  unsigned long currentTime = millis();
  unsigned long elapsedTime = currentTime - lastTime;

  if (elapsedTime >= 1000) {
    // Impulse der Encoder zählen
    uint16_t impulseCount1 = ftduino.counter_get(Ftduino::C1);
    uint16_t impulseCount2 = ftduino.counter_get(Ftduino::C2);
    uint16_t impulseCount3 = ftduino.counter_get(Ftduino::C3);
    uint16_t impulseCount4 = ftduino.counter_get(Ftduino::C4);

    // RPM berechnen
    float rpm1 = (float)(impulseCount1 - lastImpulseCount1) * 60.0 / (elapsedTime / 1000.0) / RPM_IMPULSES_PER_REVOLUTION;
    float rpm2 = (float)(impulseCount2 - lastImpulseCount2) * 60.0 / (elapsedTime / 1000.0) / RPM_IMPULSES_PER_REVOLUTION;
    float rpm3 = (float)(impulseCount3 - lastImpulseCount3) * 60.0 / (elapsedTime / 1000.0) / RPM_IMPULSES_PER_REVOLUTION;
    float rpm4 = (float)(impulseCount4 - lastImpulseCount4) * 60.0 / (elapsedTime / 1000.0) / RPM_IMPULSES_PER_REVOLUTION;

    // Meldung nur, wenn sich RPM um mehr als 1 RPM verändert
    static float prevRpm1 = 0;
    static float prevRpm2 = 0;
    static float prevRpm3 = 0;
    static float prevRpm4 = 0;

    if (abs(rpm1 - prevRpm1) > 1 || abs(rpm2 - prevRpm2) > 1 ||
        abs(rpm3 - prevRpm3) > 1 || abs(rpm4 - prevRpm4) > 1) {
      Serial.print("RPM1: ");
      Serial.print(rpm1);
      Serial.print(", RPM2: ");
      Serial.print(rpm2);
      Serial.print(", RPM3: ");
      Serial.print(rpm3);
      Serial.print(", RPM4: ");
      Serial.println(rpm4);

      prevRpm1 = rpm1;
      prevRpm2 = rpm2;
      prevRpm3 = rpm3;
      prevRpm4 = rpm4;
    }

    lastTime = currentTime;
    lastImpulseCount1 = impulseCount1;
    lastImpulseCount2 = impulseCount2;
    lastImpulseCount3 = impulseCount3;
    lastImpulseCount4 = impulseCount4;
  }
}
Die Motoren steuere ich über die Konsole, ich habe ML(M1+M2) und MR(M3+M4), das soll ein Fahrzeug werden.

Code: Alles auswählen

// Funktion zur Motorsteuerung
void handleMotorControl() {
  if (Serial.available() > 0) {
    String msg = Serial.readStringUntil('\n');
    msg.trim();

    // Wenn die Nachricht ein gültiges Motor-Kommando enthält, setze die Motor-Geschwindigkeit
    if (msg.startsWith("ML(") && msg.endsWith(")")) {
      msg = msg.substring(3, msg.length() - 1); // Ausschneiden des Geschwindigkeitswerts für linke Motoren
      int motor_speed = msg.toInt();
      if (motor_speed >= 0 && motor_speed <= 100) {
        // Motor-Geschwindigkeit setzen (0 bis 100)
        ftduino.motor_set(Ftduino::M1, Ftduino::LEFT, motor_speed);
        ftduino.motor_set(Ftduino::M2, Ftduino::LEFT, motor_speed);
      }
    } else if (msg.startsWith("MR(") && msg.endsWith(")")) {
      msg = msg.substring(3, msg.length() - 1); // Ausschneiden des Geschwindigkeitswerts für rechte Motoren
      int motor_speed = msg.toInt();
      if (motor_speed >= 0 && motor_speed <= 100) {
        // Motor-Geschwindigkeit setzen (0 bis 100)
        ftduino.motor_set(Ftduino::M3, Ftduino::RIGHT, motor_speed);
        ftduino.motor_set(Ftduino::M4, Ftduino::RIGHT, motor_speed);
      }
    }
  }
}



void loop() {
  // Zähle die Impulse der Encoder und berechne RPM
  calculateRPM();

  // Motorsteuerung durch das Python-Skript
  handleMotorControl();


  }
}

Die Kommandos habe ich aus der Anleitung. Jetzt habe ich festgestellt, dass meine Motoren scheinbar eine große Streuung aufweisen. Geradeaus fahren wird evtl. nicht klappen. Manche meiner Motoren schaffen 150 rpm manche 170 rpm. Manche laufen ab 15rpm manche ab 50rpm Ich möchte die gerne bei Bedarf synchron laufen lassen.

Der Txt scheint da ja schon etwas an Board zu haben für einen Synchronlauf, hat der ftduino das auch? Wenn nicht, wie mach ichs am besten? PID?

Meine erste Idee war vielleicht aus der Konsole heraus direkt eine Ziel rpm anzufordern, anstatt eines motor_set speed. Dazu könnte ich Paare aus RPM und motor_set speed X experimentell bestimmen und dann "clampen". Das würde dann als Startwert dienen und PID müsste das dann feintunen, die RPM werden ja sowieso schon überwacht.

Code: Alles auswählen

//     // Wenn die Nachricht ein gültiges Motor-Kommando enthält, setze die Motor-Geschwindigkeit
    if (msg.startsWith("ML(") && msg.endsWith(")")) {
      msg = msg.substring(3, msg.length() - 1); // Ausschneiden des Geschwindigkeitswerts für linke Motoren
      int motor_speed = mapRpmToSpeed(msg.toInt());
      if (motor_speed >= 0 && motor_speed <= 100) {
        // Motor-Geschwindigkeit setzen (0 bis 100)
        ftduino.motor_set(Ftduino::M1, Ftduino::LEFT, motor_speed);
        ftduino.motor_set(Ftduino::M2, Ftduino::LEFT, motor_speed);
        Serial.print("Linken Motor auf Geschwindigkeit eingestellt: ");
        Serial.println(motor_speed);
      }
    } else if (msg.startsWith("MR(") && msg.endsWith(")")) {
      msg = msg.substring(3, msg.length() - 1); // Ausschneiden des Geschwindigkeitswerts für rechte Motoren
      int motor_speed = mapRpmToSpeed(msg.toInt());
      if (motor_speed >= 0 && motor_speed <= 100) {
        // Motor-Geschwindigkeit setzen (0 bis 100)
        ftduino.motor_set(Ftduino::M3, Ftduino::RIGHT, motor_speed);
        ftduino.motor_set(Ftduino::M4, Ftduino::RIGHT, motor_speed);
        Serial.print("Rechten Motor auf Geschwindigkeit eingestellt: ");
        Serial.println(motor_speed);
      }
    }
  }
}

Funktion zum Umrechnen der RPM in Motorgeschwindigkeit, hier müssten noch weitere Werte bestimmt werden
int mapRpmToSpeed(int rpm) {
  if (rpm <= 50) return 0;
  else if (rpm <= 80) return map(rpm, 50, 80, 10, 20);
  else if (rpm <= 120) return map(rpm, 80, 120, 20, 30);
  else if (rpm <= 138) return map(rpm, 120, 138, 30, 40);
  else return 50;
}
Aber das scheint mir eine sehr umständliche Lösung. Gehts auch irgendwie einfacher und besser? Wie macht der TXT das?

Benutzeravatar
MasterOfGizmo
Beiträge: 2725
Registriert: 30 Nov 2014, 07:44

Re: ftduino: Encodermotor Synchronisation?

Beitrag von MasterOfGizmo » 06 Aug 2023, 13:51

Zur Synchronisation der Motoren gibt es bisher m.E. nichts. Das klingt mir aber nach einer schönen Aufgabe.

Genau da unterscheidet sich ftDuino vom TXT. Beim TXT geht es ums Benutzen, aber nicht ums Verstehen. Wie der TXT die Synchronisation macht ist m.E. nicht öffentlich dokumentiert oder einsehbar.

Sobald das jemand am ftDuino löst ist es öffentlich und jeder kann es einsehen, verstehen und ggf. nachfragen.

PID klingt definitiv nach einer Möglichkeit.
Arduino für fischertechnik: ftDuino http://ftduino.de, ftDuino32 http://ftduino.de/32

atzensepp
Beiträge: 751
Registriert: 10 Jul 2012, 21:40
Wohnort: Uttenreuth

Re: ftduino: Encodermotor Synchronisation?

Beitrag von atzensepp » 06 Aug 2023, 16:25

Wenn es um Synchronisation von Geschwindigkeiten von 2 Motoren geht: https://ijsrd.com/articles/IJSRDV2I4305.pdf

Benutzeravatar
steffalk
ft:pedia-Herausgeber
Beiträge: 1869
Registriert: 01 Nov 2010, 16:41
Wohnort: Karlsruhe
Kontaktdaten:

Re: ftduino: Encodermotor Synchronisation?

Beitrag von steffalk » 06 Aug 2023, 17:42

Tach auch!

Und siehe auch l-e1 Band 1 Seite 90f von 1969 (!): https://ft-datenbank.de/ft-article/2635

Gruß,
Stefan

Benutzeravatar
fishfriend
Beiträge: 2002
Registriert: 26 Nov 2010, 11:45

Re: ftduino: Encodermotor Synchronisation?

Beitrag von fishfriend » 06 Aug 2023, 19:53

Hallo...
Ich gebe zu, ich hab es bisher vermieden das zu programmieren.
Man hat den Master(Motor) mit der Geschwindigkeit und passt nun die Geschwindigkeit des Slave(Motors) an.
Irgendwie, ob nun über PID oder über eigenes "Irgendwie".
Es ist die Umsetzung einer "Elektrischen Welle" https://de.wikipedia.org/wiki/Elektrische_Wellealso einer Regelung.
Im Bereich Arduino gibt es ein paar Lösungen. Ob nun normale DC Motoren oder Schrittmotoren ist erstmal relativ egal, da die Regelung rel. gleich ist. Nur die "Impulse" kommen aus verschiedenen Quellen.
Der TX, TXT haben soetwas drinnen. RoboPro gibt die Werte vor, aber das Interface macht das selbstständig.
Ja, es würde mich auch interessieren wie das genau geht. Es kann ja auch sein, das die alternative Firmware der ftcommunity das drin hat. Ich hab mich aber damit noch nicht beschäftigt.
Links u.a.:
https://forum.arduino.cc/t/synchronlauf ... ary/472370
Die PID-v1.h ist u.a. hier, mit mehr Infos:https://github.com/br3ttb/Arduino-PID-L ... r/PID_v1.h
Gerade im Bereich "Arduino" dürfte es noch viel mehr geben. Man kann sich ja auch mal die Bausätze anschauen, wie die das machen und evtl. Programmteile übernehmen.

Nur so als Hinweis: Wenn man Pech hat, kann der Slave nie den Master überholen, dann muss man den Master bremsen.
Mit freundlichen Grüßen
Holger
Edit Stichworte: arduino roboter geradeaus fahren
Nette Links:
https://www.boecker-systemelektronik.de ... -3-Encoder
https://www.boecker-systemelektronik.de ... -Drehungen
Ob das so (wegen der ISR)mit dem ftduino geht, keine Ahnung.
ft Riesenräder PDF: ftcommunity.de/knowhow/bauanleitungen
TX-Light: Arduino und ftduino mit RoboPro

atzensepp
Beiträge: 751
Registriert: 10 Jul 2012, 21:40
Wohnort: Uttenreuth

Re: ftduino: Encodermotor Synchronisation?

Beitrag von atzensepp » 07 Aug 2023, 18:28

Eine grobe statische Synchronisation kann man mit PID-Reglern für jeden Motor hinbekommen, indem man die Regler-Parameter fein abstimmt.
Das funktioniert gut für gleiche Motoren.

Ich habe beobachtet, dass die Motoren unterschiedlich schnell laufen, je nachdem in welche Richtung sie drehen.
Man kann das erkennen, indem man den Motor bei gleicher Spannung umpolt. Die Getriebe-Encodermotoren zeigen bei mir dieses Verhalten.
Abhilfe kann man schaffen, indem man für die Gegenrichtung einen um Faktor 2-3 höheren PWM-Wert ausgibt.

Will man genauer synchronisieren, kommt es auf die Anforderungen an:
z.B. ob man die Geschwindigkeiten der Motoren synchronisieren will (Anwendungsfall: 2-motoriges Flugzeug) oder die Stellposition (Servo) oder sogar beides.

Florian

Benutzeravatar
H.A.R.R.Y.
Beiträge: 1083
Registriert: 01 Okt 2012, 08:38
Wohnort: Westpfalz

Re: ftduino: Encodermotor Synchronisation?

Beitrag von H.A.R.R.Y. » 07 Aug 2023, 19:44

Hallo zusammen,

bei den Profis werden Kaskadenregelungen und andere Tricks angewendet um Gleichstrommaschinen zu synchronisieren.

Eine Kaskadenregelung hält zunächst den Motorstrom konstant (in dem sie dessen Versorgungsspannung kontrolliert). Dieser Regelkreis bekommt seine Sollvorgabe vom Drehzahlregler. Bei Abweichung wird so das Drehmoment über den Motorstrom kontrolliert bis die Drehzahl wieder passt. Stromabweichungen werden schnell ausgeregelt, die Drehzahländerungen sind dann nicht mehr so groß und können langsamer ausgeregelt werden.

Ein weiterer Trick ist es, den Motorstrom zu messen, den Innenwiderstand des Motors zu kennen und diese Größen vorab zur Kompensation der Motorspannung heranzuziehen. Das geht über ein Motorrechenmodell (siehe ftpedia 3/2013). Das ist einfacher als ein PID-Rgeler und funktioniert schon für sich alleine recht gut.

Die ultimative Maßnahme zur Synchronisation zweier Nicht-Drehstrom-Synchronmaschinen ist aber immer noch das Überlagerungsgetriebe. Sucht mal im Bilderpool (https://ftcommunity.de/search/) nach "Gleichlaufgetriebe".

Grüße
H.A.R.R.Y.
[42] SURVIVE - or die trying

Benutzeravatar
fishfriend
Beiträge: 2002
Registriert: 26 Nov 2010, 11:45

Re: ftduino: Encodermotor Synchronisation?

Beitrag von fishfriend » 06 Sep 2023, 19:07

Hallo...
Ich bin mir nicht 100% sicher, aber...
Ich meine unter RoboPro gibt es ein Beispiel für eine Regelung von zwei Encodermotoren.
Mit freundlichen Grüßen
Holger
ft Riesenräder PDF: ftcommunity.de/knowhow/bauanleitungen
TX-Light: Arduino und ftduino mit RoboPro

atzensepp
Beiträge: 751
Registriert: 10 Jul 2012, 21:40
Wohnort: Uttenreuth

Re: ftduino: Encodermotor Synchronisation?

Beitrag von atzensepp » 07 Sep 2023, 18:50

Hallo,

es könnte dieses RoboPro-Skript sein, das Holger meint:
https://www.ftcommunity.de/knowhow/comp ... chron_new/

Florian

Benutzeravatar
axel57
Beiträge: 74
Registriert: 22 Mai 2018, 19:52

Re: ftduino: Encodermotor Synchronisation?

Beitrag von axel57 » 07 Mär 2024, 15:10

Hallo,
unter ROBO Pro (nicht Coding) gibt es die 3 neuen Befehle:
encoder.JPG
encoder.JPG (111.75 KiB) 21138 mal betrachtet
Gruß der Axel

bücherwurm
Beiträge: 60
Registriert: 19 Okt 2019, 12:07

Re: ftduino: Encodermotor Synchronisation?

Beitrag von bücherwurm » 20 Sep 2024, 16:28

Es gibt zwei Ansätze, die nicht aus dem Ruder laufen:
1. Du läßt jeden Motor nur eine sehr kurze Strecke fahren. Sagen wir je zehn Impulse, die über IRQs erfaßt werden. Solange die zehn Impulse nicht erreicht sind, dreht der Motor weiter. Dann haben beide Motoren am Ende die gleiche Strecke zurückgelegt. Diese kurze Strecke wiederholst du so oft, bis die Gesamtstrecke gefahren wurde. Dann besteht die Ungenauigkeit aus vielen kleinen Wegstrecken. Das Modell zittert dann ein wenig, weil ein Motor immer sehr kurz dreht und einer steht.

2. Für lange Strecken mit mehr als 1.000 Impulsen werden beide Motoren mittels PWM angesteuert. Alle zehn Impulse wird geprüft, ob die Impulszahl beider Motoren gleich ist. Andernfalls wird das PWM-Signal des zu schnellen Motors etwas gestreckt, also mit größeren Pausen versehen und für den anderen Motor wird das PWM-Signal beschleunigt, so dass er aufholen kann. Auf Dauer sollte sich eine passable Regelung einstellen. Im Prinzip kann man die Erfahrung am Ende der Fahrt (PWM-Parameter) für die nächste Fahrt als gelernten Wert speichern.

Benutzeravatar
steffalk
ft:pedia-Herausgeber
Beiträge: 1869
Registriert: 01 Nov 2010, 16:41
Wohnort: Karlsruhe
Kontaktdaten:

Re: ftduino: Encodermotor Synchronisation?

Beitrag von steffalk » 20 Sep 2024, 18:05

Tach auch!

Wie wär's mit einem Gleichlaufgetriebe? Viele Beispiele finden sich bei der Suche nach "gleichlauf" auf https://ftcommunity.de/search/

Gruß,
Stefan

Benutzeravatar
Defiant
Beiträge: 364
Registriert: 31 Okt 2010, 21:42
Wohnort: Narn Homeworld
Kontaktdaten:

Re: ftduino: Encodermotor Synchronisation?

Beitrag von Defiant » 23 Sep 2024, 09:52

Ich halte Ansätze wie Gleichlaufbetriebe und ähnliche Abstimmungen für nicht zielführend, da schon minimal unterschiedliche Raddurchmesser und Schlupf der mit diesen Lösungen nicht aufgefangen wird nicht kompensiert wird.

In der Robotik ist die Standardlösung mMn. wie oben schon besprochen die Geschwindigkeit jeden Motors einzeln zu Regeln, ua. mit einem PID. Schlupf und andere externe Einflüsse werden mit einer externen Positionsquelle dann abgefangen.
"Propaganda does not deceive people; it merely helps them to deceive themselves."
E Hoffer

Antworten