Ich habe eine Servosteuerung mit einem Taster geschrieben. Der Taster zählt, ob 1x oder 2x gedrückt wurde und stellt dann bei erneutem gedrückt behaltenem Taster den entsprechenden Servo 1 oder Servo 2. Während 4 Sekunden kann man erneut den Taster gedrückt behalten, um den Servo zu verstellen. Nach 4 Sekunden muss man dann erneut per Tastendruck den Servo wählen.
Jetzt habe ich aber das Problem, dass wenn ich Servo 1 steuere, der "servoState" entsprechend geändert wird, damit der Servo während den 4 Sekunden entweder auf oder ab bewegt wird.
Möchte ich dann den Servo 2 bewegen, kommt es vor, dass durch den falschen Wert bei servoState keine Steuerung mehr möglich ist, bis ich den Servo 1 wieder zurück bewegt habe.
Ich sehe momentan nicht, wie ich die zwei servoState unabhängig einbringen kann, damit beide Servos unabhängig voneinander bewegt werden können, also auch wenn Servo 1 bereits bewegt wurde, den Servo 2 trotzdem bewegt werden kann ohne den Servo 1 wieder zurück bewegt werden muss.
Ich kann es nicht besser beschreiben, man muss die Steuerung sonst mal kurz testen, dann sieht man sehr schnell, dass es manchmal klemmt und man den andern Servo erst wieder bewegen kann, sobald der vorherige Servo nochmals bewegt wird.
Kann mir hier jemand helfen wie ich die Zustände ändern muss?
Nicht wirklich, da ich nicht weiß, was es tun soll.
Aber du scheinst mir ein Freund von verschachtelten Schleifen, IF-Konstrukten und komplizierten Bedingungen zu sein.
Nicht, dass das unbedingt falsch ist, aber eben sehr unübersichtlich, ja, quasi verworren.
So komplex, dass du dich darin scheinbar selber verirrt hast.
Ich rate dir davon ab.
Ich rate zu flachen Programmen.
Verschachtelte IF Funktionen nicht, ich habe nur aufgrund der Abfolge und Zeitsteuerung mit ein paar IF Abfragen geschrieben. Wenn es einfacher geht, dann bin ich sehr gerne bereit dies zu versuchen.
Die Funktion nochmals versucht zu erklären:
Ich habe zwei Servos und einen Taster. Der Taster soll als Auswahl des Servos 1 oder Servos 2 dienen. Sobald dieser dann gewählt wurde, kann man mit demselben Taster den Servo auf und ab bewegen, indem man den Taster gedrückt hält. Wird innerhalb der 4 Sekunden kein Taster mehr betätigt, stellt sich der Zähler der Servowahl wieder auf 0 zurück für eine erneute Auswahl.
Das funktioniert auch soweit, bis auf wenn man einen der beiden Servos bewegt hat, und den andern Servo bewegen möchte, dann kommt es vor, dass aufgrund der Variablen servoState und der Bedingungen wenn servoState = 1 oder = 0 und die servoPos > 0 oder < 90, dass beide Bedingungen falsch sind und der vorher gewählte Servo den man bewegt hatte nochmals bewegen muss um den servoState wieder zu ändern, damit es mit dem andern Servo wieder geht.
Genau, nach 4 Sekunden geht der Counter der die Servoauswahl zählt auf null zurück. Innerhalb der 4 Sekunden und nach 500 Millisekunden wo die Auswahl erfolgen muss, kann dann der gewählte Servo mit gedrücktem Taster gestellt werden.
Hallo,
noch mal langsam zum mitdenken.
Vermutlich ist bei Deiner Logik was nicht eindeutig.
Der Taster wird 4s nicht gedrückt , damit ist der Betriebsmodus "auswählen" aktiv. Dann soll mit dem Taster der Servo ausgewählt werden. Dazu gibt es einen Status 0,1,2 . Dazu darf eine Wartezeit zwischen 2 mal drücken nicht länger als z.B 500 ms sein. Falls doch wechselt der Betrieb in den Verstellmodus, und ich denke da liegt Dein Problem
Im Verstellmodus soll mit dem Taster der aktive Servo verfahren werden solange wie der Taster gedrückt ist. Lässt man den Taster los fährt der Servo zurück in 0 Pos. Das kann man so oft mit dem aktuellen Servo machen wie man will, auch über die 4 s hinaus.
Wird der Taster länger als 4s nicht gedrückt, dann wechselt der Status zu 0 und es beginnt wieder mit 1.
Das könnte auf eine Schrittkette hinaus laufen.
Wenn Du jetzt die Teilaufgabe einzeln angehst solltest Du zu einer Lösung kommen.
Nachtrag
while ganz doof , es geht auch ohne, und das viel besser
beide Servos fahren nur im Status 0 zurück.
wie funktioniert das mit einem Taster?
schwenkt der Servo selbständig von 0 - 180 - 0 hin und her und du musst den den Taster loslassen um in der Stellung zu verharren?
Wenn nicht beschreibe den Vorgang.
Besser - Zeichne ein Diagramm.
Ich habe einen Taster und zwei Servos die am Arduino angeschlossen sind. Taster mit GND und D4, Servos an D2 und D3, GND an GND und 5V direkt an der Stromversorgung per Trafo (5V, 10A) wo auch der Arduino angeschlossen ist.
Der Taster kann innerhalb 500ms per Tastendruck den Servo1 oder Servo2 wählen.
Wird nun mit einmaligem Drücken der Servo1 gewählt, dann kann innerhalb der nächsten 4s mit gedrücktem Taster der Servo1 in eine Richtung gestellt werden. Wird der Taster losgelassen, stoppt der Servo1 in der entsprechend gestellten Stellung. Sind die 4s noch nicht um und der Taster wird nochmals gedrückt gehalten, stellt sich Servo1 wieder zurück in Richting Ausgangsposition. Sobald hier der Taster losgelassen wird bevor der Servo in der Ausgangsposition ist, bleibt er wieder stehen in der aktuellen Stellung.
Das selbe kann mit dem Servo2 gemacht werden, wenn der Taster zu Beginn innerhalb der 500ms zweimal gedrückt wird.
Der Reset der Anzahl gedrückten Tasten für die Auswahl erfolgt dann nach den 4s.
Als endlicher Automaten müsste es per Switch/Case erfolgen, oder? Ich sehe hier aber keinen Lösungsansatz mit viel weniger IF Abfragen. Die IF innerhalb der While Schleifen bleiben trotzdem, und die erste IF Abfrage für die Tastendrücke bleibt doch auch. Dann macht es keinen grossen Unterschied mehr oder?
taste gedrückt
-> Zeit merken
taste losgelassen
-> Servo 1 ist ausgewählt
solange aktuelle Zeit - gemerkte Zeit < 500ms
taste gedrückt
taste losgelassen
Servo++
Servo > Anzahl Servos -> Servo 1 auswählen
Wenn
aktuelle Zeit - gemerkete Zeit > 500ms UND
Taste losgelassen
gehts hier weiter
Solange
aktuelle Zeit - gemerkete Zeit < 4500ms
Taste gedrückt
-> Servo Bewegung aufwärts
Taste nochmal gedrückt
-> Servo Bewegung abwärts
ggfls. auch erneut:
Taste gedrückt
-> Servo Bewegung aufwärts
Taste nochmal gedrückt
-> Servo Bewegung abwärts
aktuelle Zeit - gemerkete Zeit > 4500ms UND
Taste losgelassen
-> Fange an von vorn
Da Du nicht wiesst, wo sich die Servos befinden, musst Du die Position so wie von mir beschrieben in einer zum Servo passenden Varaiblen speichern.
Im Moment hast Du nur eine Varaiable und versuchst die für beide zu benutzen.
Das geht so nciht.
Ich habe in Post #6 versucht die beiden Variablen für den Zustand der Servostellung für Servo1 resp Servo2 zu trennen anhand des Counters mit dem ich die Tastendrücke zähle:
Irgendwie ändert er so gar keinen servoState resp. servo2State mehr. Wieso ändert sich mit diesen zwei IF Bedingungen der servoState nicht mehr? Der UAButCounter hat er da ha bereits mit 1 oder 2 anhand der Tastendrücke definiert.
Mein Ansatz - rein aus dem Stehgreif. ungetestet und ohne Hardware.
kompiliert Fehler- und Warnungsfrei.
Egentlich erklärend kommentiert.
Vielleicht findet sich ja später jemand, der Dir hilft, wenn der nicht so läuft.
Ich hab heut blos keine Zeit....
// Forensketch
// https://forum.arduino.cc/
#include <Streaming.h> // https://github.com/janelia-arduino/Streaming
#include "Servo.h"
//#define DEBUG // Wenn aktiviert, werden Zwischenwerte ausgegeben
#ifdef DEBUG
#define DBG_PRINTLN(...) Serial << __VA_ARGS__ << endl
#else
#define DBG_PRINTLN(...)
#endif
Servo servoOne;
Servo servoTwo;
constexpr byte servos {2};
Servo myServo[servos] {servoOne, servoTwo};
constexpr byte tastePin {4};
uint8_t servoAuswahl;
uint8_t servoPos[servos] = {0, 0};
bool servoRichtung = false;
bool lastRichtung = false; // Merker
uint32_t ausloesezeit;
constexpr uint32_t debounce {40};
constexpr uint32_t tasterReaktion {500};
constexpr uint32_t servoReaktion {4000};
enum class STATE {warten, auswahl, position};
STATE state = STATE::warten;
void setup()
{
Serial.begin(115200);
#if (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2650)) // https://github.com/arduino/Arduino/issues/10764
delay(300);
#endif
Serial << (F("\r\nStart...\r\n")) << endl;
DBG_PRINTLN(__FILE__);
DBG_PRINTLN( __TIMESTAMP__);
pinMode(tastePin, INPUT_PULLUP);
myServo[0].attach(2);
myServo[1].attach(3);
}
void loop()
{
switch (state)
{
case STATE::warten:
if (tasteCheck()) // Taste ausgelöst
{
ausloesezeit = millis(); // zeit merken
servoAuswahl = 0; // ersten Servo einstellen
state = STATE::auswahl; // nächster Status
}
break;
case STATE::auswahl:
if (millis() - ausloesezeit < tasterReaktion) // Innerhalb der Reaktionszeit
{
if (tasteCheck()) // Taste gedrückt
{ servoAuswahl++; } // nächsten Servo setzen
if (servoAuswahl >= servos) // Begrenzung
{ servoAuswahl = 0; } // von vorn anfangen
}
else // Zeit abgelaufen
{
if (!tasteCheck()) // Taste losgelassen -> kann evtl. entfallen
{
servoRichtung = HIGH; // Vorbelegen
lastRichtung = LOW;
ausloesezeit = millis();
state = STATE::position; // nächsten Status
}
}
break;
case STATE::position:
if (!digitalRead(tastePin)) // Taste gedrückt
{
lastRichtung = servoRichtung;
if (servoRichtung && servoPos[servoAuswahl] < 255) // Aufwärts und unter oberer Grenze
{ servoPos[servoAuswahl]++; }
else if (!servoRichtung && servoPos[servoAuswahl] > 0)
{ servoPos[servoAuswahl]--; }
}
else if (lastRichtung == servoRichtung) // Taste losgelassen UND vorher gedrückt
{
servoRichtung = !servoRichtung;
}
if (millis() - ausloesezeit > servoReaktion) // Zeit abgelaufen
{ state = STATE::warten; } // fange an von vorn
break;
}
}
bool tasteCheck()
{
bool ret = false;
static uint32_t lastPressed = 0;
static bool lastState = LOW;
if (!digitalRead(tastePin)) // Taste gedrückt
{
if (!lastState) // und vorher nicht
{
lastPressed = millis(); // Zeit merken
lastState = HIGH; // status setzen
ret = true; //
}
}
else // nciht gedrückt
{
if (lastState) // vorher aber schon
{
if (millis() - lastPressed > debounce) // Zeit abgelaufen
{
lastState = LOW; // merker löschen
}
}
}
return ret;
}
Egal wo - ich hätte irgendwo auch nur den inhalt der pwm-Variablen auf dem SerMon ausgegeben
Ich habs oben nur mit reingenommen, damit er sieht, wie das mit dem array funktioniert....