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.
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
@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:
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.
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 ...
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.");
}
Und da Du in activateBluetoothAction() mit delay() alles andere sowieso ausbremst, brauchst Du das gar nicht ... So kannst Du diese boolsche Variable ganz rausnehmen ...
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) {
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!
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 ...
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.