Code funktioniert nicht richtig warum?

Hallo,

habe ein Projekt am laufen, bei dem ich zwei Servos mit dem Handy über Bluetooth steuern will. Wenn ich am Handy ein Signal eingebe, sollen sich die Servos um 180 Grad drehen.
Ebenso sollen sie sich um 180 Grad drehen, wenn der angeschlossene Potentiometer unter den Wert 990 fällt.
Wenn der Wert weiter unter 700 fällt und anschließend wieder über 700 steigt, dann sollen sie sich wieder zurück auf die Startposition drehen.

Allerdings habe ich das Problem, dass sich die Servos nach dem Bluetooth Signal auf die Zielposition drehen, aber dann nicht mehr auf die Startposition zurück. Sie wackeln dann nur kurz. Habe schon alles versucht kann mir bitte Verwende dieses Symbol um Code zu postenjemand helfen? Wenn ich den Code umschreibe entstehen andere Probleme.

Hier ist der Code:

  #include <Servo.h>

Servo servo1; // Servo 1 an Pin 9
Servo servo2; // Servo 2 an Pin 10

const int potPin = A0; // Potentiometer an Pin A0
int potValue;          // Aktueller Potentiometerwert
bool hasCrossed700 = false; // Flag, ob der Wert einmal unter 700 gefallen ist
bool hasCrossed990 = false; // Flag, ob der Wert einmal unter 990 war
bool isMoving = false;      // Flag, um Bewegungen zu verfolgen

void setup() {
  servo1.attach(9);   // Servo 1 an Pin 9 anschließen
  servo2.attach(10);  // Servo 2 an Pin 10 anschließen
  Serial.begin(9600); // Serielle Kommunikation starten

  // Servos in der Startposition initialisieren
  servo1.write(0);    // Servo 1 Startposition: 0 Grad
  servo2.write(180);  // Servo 2 Startposition: 180 Grad
   
 
  Serial.println("System bereit. Warte auf Bluetooth-Befehle.");
}

void loop() {
  potValue = analogRead(potPin); // Potentiometerwert lesen
  Serial.print("Aktueller Potentiometerwert: ");
  Serial.println(potValue); // Potentiometerwert ausgeben

  // Überprüfen, ob Daten über Bluetooth empfangen wurden
 if (Serial.available() > 0) {
    char receivedChar = Serial.read(); // Lese ein Zeichen vom Bluetooth-Modul
    if (receivedChar == 'T') {
      moveToTargetPosition(); // Servos zur Zielposition bewegen
      delay(2000);            // 2 Sekunden warten
      servo1.write(0);  // Servos zurück zur Startposition bewegen
      servo2.write(180);
    }
  }

  // Wenn der Potentiometerwert unter 990 fällt und die Servos nicht bewegen
   if (potValue < 990 && !isMoving) {
    moveToTargetPosition(); // Flag setzen, dass der Wert unter 990 gefallen ist
  }

  // Wenn der Potentiometerwert unter 700 fällt
    if (potValue < 700) {
    hasCrossed700 = true; // Flag setzen, dass der Wert unter 700 gefallen ist
  }

  // Wenn der Potentiometerwert über 700 steigt und wir zuvor unter 700 waren
  if (potValue > 700 && hasCrossed700) {
    moveToStartPosition(); // Beide Servos zurück zur Startposition bewegen
    hasCrossed700 = false; // Flag zurücksetzen
  }

  // Wenn der Potentiometerwert über 990 steigt, setze das isMoving-Flag zurück
   if (potValue > 990) {
    isMoving = false; // Flag zurücksetzen
  }

  delay(100); // Kleiner Delay für Stabilität
}

// Funktion zum Bewegen der Servos in die Zielposition
void moveToTargetPosition() {
  isMoving = true; // Bewegungsflag setzen
  servo1.write(180); // Servo 1 auf Zielposition: 180 Grad
  servo2.write(0);   // Servo 2 auf Zielposition: 0 Grad
  Serial.println("Servos auf Zielpositionen gedreht.");
}

// Funktion zum Bewegen der Servos in die Startposition
void moveToStartPosition() {
  isMoving = true; // Bewegungsflag setzen
  servo1.write(0);   // Servo 1 zurück auf Startposition: 0 Grad
  servo2.write(180); // Servo 2 zurück auf Startposition: 180 Grad
  Serial.println("Servos zurück auf Startpositionen gedreht.");
}

Im englischen Teil des Forum müssen die Beiträge und Diskussionen in englischer Sprache verfasst werden. Deswegen wurde diese Diskussion in den deutschen Teil des Forums verschoben.

mfg ein Moderator.

Es ist möglich, dass Serial.read() ein unsichtbares Zeichen CRLF enthält. Platzieren Sie eine zusätzliche Serial.read(), um den serial buffer zu leeren.

  // Überprüfen, ob Daten über Bluetooth empfangen wurden
 if (Serial.available() > 0) {
    char receivedChar = Serial.read(); // Lese ein Zeichen vom Bluetooth-Modul
    char abfallChar = Serial.read(); // <== CRLF vielleicht entfernen
    if (receivedChar == 'T') {

Deine viele hintereinander geschalteten ifs werden wahrscheinlich nie sauber funktionieren. Deine Aufgabenstellung schreit förmlich nach einer Statemaschiene. Lies dich dazu mal ein, wie man die erstellt.
In einer Statemaschiene brauchst du auch kein

mehr.

2 Likes

@laurinmennicken
ich bin auch der Meinung dass du das mit einer State Machine sauberer definieren kannst und dann auch die Übergänge von einem State in den anderen exakt definieren kannst.

Nur ein Anfang ... müsstest du auf Vollständigkeit noch prüfen:

1 Like

Was soll passieren, wenn
Poti unter 900 fällt, via BT 699 kommen und das Poti danach wieder auf >900 ansteigt?
Poti unter 700 fällt, via BT 901 kommen?

Wenn die beiden Steuerdinge sich gegenseitig beeinflussen dürfen, dann würde ich nur eine Varable als Merker nutzen und den Wert darin speichern.

Moin @laurinmennicken ,

ich habe Deinen Code mal zu Wokwi kopiert:

https://wokwi.com/projects/416190905277762561

In der Simulation läuft es (jedenfalls so gut, wie es die aktuelle Ausführung erlaubt).

Wie schon oben gepostet, ist die Umsetzung nicht besonders übersichtlich und damit ggf. anfällig für Fehler in der Programmlogik. Auch auf die Delays sollte man besser verzichten.

Das größte Fehlerpotential liegt bei den beiden miteinander konkurrenzierenden Ansteuerungen für die Servos; es sollte hier nur eine Stelle geben, die die Signale vom Poti und von der seriellen Schnittstelle reagiert.

Gruß
ec2021

[Edit:] Und hier ein Sketch, der eine "Mini-Statemachine" benutzt und ohne Delays auskommt. Dafür aber Kommandos ignoriert, bis eine vorgegebene Zeit SERVODELAY abgelaufen ist bzw. bis der seriell kommandierte Zyklus (mit Verzögerung SERIALDELAY ) abgelaufen ist. Kann man bestimmt auch kürzer und schöner machen ...

Siehe Wokwi: https://wokwi.com/projects/416192201811842049

Sketch
/*
   Forum: https://forum.arduino.cc/t/code-funktioniert-nicht-richtig-warum/1327820
   Wokwi: https://wokwi.com/projects/416192201811842049

  Changes by ec2021
  2024-12-02

*/


#include <Servo.h>
const boolean doOverride = true;
const boolean doTry      = false;
const unsigned long SERIALDELAY = 2000;
const unsigned long SERVODELAY  =  300;
const int potPin = A0; // Potentiometer an Pin A0

Servo servo1; // Servo 1 an Pin 9
Servo servo2; // Servo 2 an Pin 10
enum Commands {IDLE, MOVING, POT_GOSTART, POT_GOTARGET, SER_GOSTART, SER_GOTARGET};
Commands servoCmd = IDLE;
unsigned long targetBySerialStarted;
unsigned long startMoving;

void setup() {
  servo1.attach(9);   // Servo 1 an Pin 9 anschließen
  servo2.attach(10);  // Servo 2 an Pin 10 anschließen
  Serial.begin(9600); // Serielle Kommunikation starten
  // Servos in der Startposition initialisieren
  moveToStartPosition();
  Serial.println("System bereit. Warte auf serielle Befehle.");
}

void loop() {
  checkPoti();
  checkSerial();
  controlServos();
}


void setServos(Commands cmd, boolean Override) {
  if (servoCmd == IDLE || Override) {
    servoCmd = cmd;
    if (cmd == MOVING) {
      startMoving = millis();
    }
    if (cmd == SER_GOSTART) {
      targetBySerialStarted = millis();
    }
  }
}

void checkPoti() {
  static boolean wasAbove990 = false;
  static boolean wasBelow700 = false;
  int potValue = analogRead(potPin); // Potentiometerwert lesen
  boolean below990 = (potValue < 990);
  boolean below700 = (potValue < 700);

  // Hier die "Verriegelungen" lösen
  if (below700 && !wasBelow700) {
    wasBelow700 = true;
    Serial.println("was below 700");
  }
  if (!below990 && !wasAbove990) {
    wasAbove990 = true;
    Serial.println("was above 990");
  }

  // Bei Rückkehr von unterem Bereich nach oben
  if (!below700 && wasBelow700) {
    setServos(POT_GOSTART, doTry);
    wasBelow700      = false;
  }

  // Bei Rückkehr aus dem oberen Bereich nach unten
  if (below990 && wasAbove990) {
    setServos(POT_GOTARGET, doTry);
    wasAbove990 = false;
  }
}

void checkSerial() {
  if (Serial.available() > 0) {
    char receivedChar = Serial.read(); // Lese ein Zeichen von Serial
    if (receivedChar == 'T') {
      setServos(SER_GOTARGET, doTry);
    }
  }
}

void controlServos() {
  switch (servoCmd) {
    case IDLE:
      // do Nothing
      break;
    case SER_GOSTART:
      if (millis() - targetBySerialStarted < SERIALDELAY) {
        break;
      }
    case POT_GOSTART:
      moveToStartPosition();
      break;
    case SER_GOTARGET:
      moveToTargetPosition();
      setServos(SER_GOSTART, doOverride);
      break;
    case POT_GOTARGET:
      moveToTargetPosition();
      break;
    case MOVING:
      if (millis() - startMoving > SERVODELAY) {
        setServos(IDLE, doOverride);
      }
      break;
    default:
      // Do nothing
      break;
  }
}


// Funktion zum Bewegen der Servos in die Zielposition
void moveToTargetPosition() {
  setServos(MOVING, doOverride);
  servo1.write(180); // Servo 1 auf Zielposition: 180 Grad
  servo2.write(0);   // Servo 2 auf Zielposition: 0 Grad
  Serial.println("Go to TARGET");
}

// Funktion zum Bewegen der Servos in die Startposition
void moveToStartPosition() {
  setServos(MOVING, doOverride);
  servo1.write(0);   // Servo 1 zurück auf Startposition: 0 Grad
  servo2.write(180); // Servo 2 zurück auf Startposition: 180 Grad
  Serial.println("Go to START");
}
1 Like

vielen Dank für eure Hilfe, allerdings funktioniert immer noch nicht alles richtig.
Habe den Code jetzt aktualisiert. Jetzt funktioniert er an sich schon, aber die Aktion mit dem Potentiometer funktioniert nur wenn ich kein Bluetooth Signal sende. Sobald ich ein Signal sende funktioniert die Poti Aktion danach nicht mehr.
Wenn ich den Reset Knopf am Controller drücke, funktioniert die Aktion wieder solange, bis ich das Bluetooth Signal gebe.

#include <Servo.h>

// Servo-Objekte erstellen
Servo servo1;
Servo servo2;

// Potentiometer-Pin
const int potPin = A0;
int potValue; // Aktueller Potentiometerwert

// Bluetooth-Signal
char bluetoothSignal;
bool bluetoothActive = false; // Flag für Bluetooth-Steuerung

// Definition der Zustände
enum State {
  STARTPOSITION,
  ZIELPOSITION,
  UNTERSCHRITTEN_700,
  WARTEN_AUF_RESET
};

State currentState = STARTPOSITION; // Initialzustand
bool resetAllowed = false;          // Flag, ob erneuter Übergang erlaubt ist

void setup() {
  servo1.attach(9);   // Servo 1 an Pin 9
  servo2.attach(10);  // Servo 2 an Pin 10
  Serial.begin(9600); // Serielle Kommunikation starten (auch für Bluetooth)

  // Startposition
  servo1.write(0);
  servo2.write(180);
  Serial.println("System initialisiert. Servos auf Startposition.");
}

void loop() {
  // Potentiometerwert einlesen
  potValue = analogRead(potPin);

  // Bluetooth-Befehl prüfen
  if (Serial.available()) {
    bluetoothSignal = Serial.read();
    if (bluetoothSignal == 'T') {
      Serial.println("Bluetooth-Befehl 'T' empfangen. Servos bewegen sich.");
      activateBluetoothAction();
      bluetoothActive = true; // Bluetooth-Steuerung aktivieren
    }
  }

  // Zustandslogik nur ausführen, wenn Bluetooth nicht aktiv ist
  if (!bluetoothActive) {
    switch (currentState) {
      case STARTPOSITION:
        if (potValue < 990) {
          moveToTargetPosition();
          currentState = ZIELPOSITION;
          Serial.println("Wechsel zu: ZIELPOSITION");
        }
        break;

      case ZIELPOSITION:
        if (potValue < 700) {
          currentState = UNTERSCHRITTEN_700;
          Serial.println("Wechsel zu: UNTERSCHRITTEN_700");
        }
        break;

      case UNTERSCHRITTEN_700:
        if (potValue > 700) {
          moveToStartPosition();
          currentState = WARTEN_AUF_RESET;
          Serial.println("Wechsel zu: WARTEN_AUF_RESET");
          resetAllowed = false;
        }
        break;

      case WARTEN_AUF_RESET:
        if (potValue > 990) {
          resetAllowed = true;
          currentState = STARTPOSITION;
          Serial.println("Reset erlaubt. Wechsel zu: STARTPOSITION");
        }
        break;
    }
  }

  delay(50); // Kurze Verzögerung für Stabilität
}

// Funktion: Bewegung in die Zielposition
void moveToTargetPosition() {
  servo1.write(180);
  servo2.write(0);
  Serial.println("Servos bewegen sich zur Zielposition.");
}

// Funktion: Bewegung zurück in die Startposition
void moveToStartPosition() {
  servo1.write(0);
  servo2.write(180);
  Serial.println("Servos bewegen sich zurück zur Startposition.");
}

// Funktion: Bluetooth-Aktion ausführen
void activateBluetoothAction() {
  moveToTargetPosition(); // Servos zur Zielposition bewegen

  // Verzögerung von 2 Sekunden (2000 ms)
  delay(2000);

  moveToStartPosition(); // Servos zurück zur Startposition bewegen
  delay(100);

  // Nach der Aktion Bluetooth-Steuerung deaktivieren
  bluetoothActive = false; // Reset auf false, um Potentiometer-Aktionen zu ermöglichen
  Serial.println("Bluetooth-Aktion abgeschlossen. Zurück zur Potentiometer-Steuerung.");
}

Du setzt die Variable gleich nach dem Funktionsaufruf wieder auf true:

      activateBluetoothAction();
      bluetoothActive = true; // Bluetooth-Steuerung aktivieren

Und da Du in activateBluetoothAction() mit delay() alles andere sowieso ausbremst, brauchst Du das gar nicht ... So kannst Du diese boolsche Variable ganz rausnehmen ... :wink:

Edit:
Oder Du machst es so in der loop():

 // Bluetooth-Befehl prüfen
  if (Serial.available()) {
    bluetoothSignal = Serial.read();
    if (bluetoothSignal == 'T') {
      Serial.println("Bluetooth-Befehl 'T' empfangen. Servos bewegen sich.");
      bluetoothActive = true; // Bluetooth-Steuerung aktivieren
    }
  }

  // Zustandslogik nur ausführen, wenn Bluetooth nicht aktiv ist
  if (bluetoothActive){
    activateBluetoothAction();
  } else {
    switch (currentState) {
      case STARTPOSITION:
        if (potValue < 990) {
  

siehe hier: https://wokwi.com/projects/416199928123552769

Ich seh noch immer nicht, wie da was funktionieren soll.

Es gibt den POTI-Wert, der bei 1000 liegt.
Kommt der unter 990 dreht sich der Servo um 180°
Kommt der Poti unter 700 passiert erstmal nix
Steigt der jetzt über 700 dreht der Servo sich in Ausgangsposition.

Soweit verstanden.
Das wäre eine klassische State-Machine

Jetzt kommt der Wert vom BT dazu.
Und da weiss ich noch immer nicht, was da wann passieren soll.

Nehmen wir an, das Poti steht in Ausgangsposition (>900) und Du sendest mit dem BT ein 899.
Dann geht der Servo in die Stellung "ausgelöst"

Muss jetzt ein BT-Wert unter 700 kommen und dann ein Wert größer 700, damit der Servo wieder in Ausgangsstellung geht?

Was passiert, wenn der BT-Wert unter 700 geht und das Poti jetzt unter 900 fällt?
Und danach der BT-Wert auf z.B. 800 ansteigt?
Eigentlich müsste eine Sperre rein, wenn ein Kanal auslöst, dass der andere entweder den selben Wert erreichen muss oder gar nicht auslösen darf.

Da sind soviele ungeklärte Möglichkeiten drin, dass es gar keine vernünftige Lösung dafür geben kann!

Klär doch mal bitte auf, mit allen Varianten!

Moin @my_xy_projekt ,

ist einfacher, als Du denkst. Wenn das Bluetooth-Kommando kommt,

  • werden die Servos in die Target-Position geschickt,
  • für 2 s alles andere ausgebremst -> delay(2000)
  • danach geht's zwangsweise auf Start-Position
  • und nochmal für 0,1s nix ...

Danach kommt die Potentiometer-Steuerung wieder ans Ruder.

Alles was in den 2,1 s am Poti passiert, wird durch die delays natürlich ignoriert.

// Funktion: Bluetooth-Aktion ausführen
void activateBluetoothAction() {
  moveToTargetPosition(); // Servos zur Zielposition bewegen

  // Verzögerung von 2 Sekunden (2000 ms)
  delay(2000);

  moveToStartPosition(); // Servos zurück zur Startposition bewegen
  delay(100);

  // Nach der Aktion Bluetooth-Steuerung deaktivieren
  bluetoothActive = false; // Reset auf false, um Potentiometer-Aktionen zu ermöglichen
  Serial.println("Bluetooth-Aktion abgeschlossen. Zurück zur Potentiometer-Steuerung.");
}

Ob das genau so gewollt ist oder nicht, sagt uns gleich der TO ... :slight_smile:

Gruß
ec2021

1 Like

Tatsächlich war genau das der Gedanke, aber ich habe mittlerweile eine andere Lösung gefunden, aber dennoch danke für die Hilfe

Wenn man den Gedanken verstehen können soll dann müsstest du beschreiben was der Gedanke ist. Und nicht nur ein "das" schreiben.

Dann solltest du als Dankeschön diese andere Lösung als vollständigen Sketch posten.
Das Arduino-Forum ist zum Wissen teilen da.

Habe für das Projekt den Potentiometer ganz rausgenommen, da dieser für das Registrieren einer Drehung einer Achse zuständig war. Die Servos sollten dann eine Bewegung machen, die eine andere Bewegung ausgleicht, jedoch habe ich das mechanisch lösen können und brauche das ausgleichen mit Motoren nun nicht mehr.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.