Hallo ihr Lieben, ich habe einen wireless Gamepad an einem Arduino und möchte Servobewegungen auslösen. Mit delay im Servoprogramm führt es ab ca. 1000 Millisekunden delay im Servoprogramm zu Störungen. Unter 1000 Millisekunden funktioniert der Gamepad. Jetzt ist meine Frage, ob das Servoprogramm mit Millis anstelle delay funktioniert. Hier mein Beispielcode vom Servo: (code) #include <Servo.h> //Die Servobibliothek wird aufgerufen. Sie wird benötigt, damit die Ansteuerung des Servos vereinfacht wird. Servo servoblau; //Erstellt für das Programm ein Servo mit dem Namen „servoblau“ void setup() { servoblau.attach(8); //Das Setup enthält die Information, dass das Servo an der Steuerleitung (gelb) mit Pin 8 verbunden wird. Hier ist natürlich auch ein anderer Pin möglich. } void loop() { //Im „loop“ wird über den write-Befehl „servoblau.write(Grad)“ das Servo angesteuert. Zwischen den einzelnen Positionen gibt es eine Pause, damit das Servo genug Zeit hat, die gewünschten Positionen zu erreichen. servoblau.write(0); //Position 1 ansteuern mit dem Winkel 0° delay(3000); //Das Programm stoppt für 3 Sekunden servoblau.write(90); //Position 2 ansteuern mit dem Winkel 90° delay(3000); //Das Programm stoppt für 3 Sekunden (/code)
einen Zustandsautomaten bauen, suche delay ohne Blockierung Beitrag "Arduino ohne delay und millis" https://forum.arduino.cc/t/schaltverzogerung-ohne-delay-realisieren/418457 https://forum.arduino.cc/t/wie-zeitliche-ablaufe-ohne-delay-einfach-gestalten/121407 https://starthardware.org/timer-mit-arduino-alternative-zu-delays/ https://www.az-delivery.de/blogs/azdelivery-blog-fur-arduino-und-raspberry-pi/entwurf-blink-sketch-ohne-delay
Benni B. schrieb: > Mit delay im Servoprogramm führt es ab ca. > 1000 Millisekunden delay im Servoprogramm zu Störungen. Die Funktion yield() kennst du?
Benni B. schrieb: > ich habe einen wireless Gamepad an einem Arduino und möchte > Servobewegungen auslösen. Mit delay im Servoprogramm führt es ab ca. > 1000 Millisekunden delay im Servoprogramm zu Störungen. Unter 1000 > Millisekunden funktioniert der Gamepad. Jetzt ist meine Frage, ob das > Servoprogramm mit Millis anstelle delay funktioniert. Aha, wieder mal ein Salamibrot. Ein wireless Gamepad an einem Arduino (welcher Arduino?) bedeutet einen Receiver am Arduino, welcher dann auch etwas Software benötigt um als Eingabegerät zu funktionieren. Und dieser Softwareteil wird hier nicht gezeigt, stellt aber wahrscheinlich das Problem dar. Deinen gezeigten Beispielcode hast du vermutlich so noch nie laufen lassen. Es gibt keinen Grund weshalb dieses kleine Codesegment nicht funktionieren sollte, außer daß ihm die abschliessende Klammer fehlt. Ein 'delay' macht nichts anderes als in einer Schleife die Millisekunden zu zählen, und wenn du anstelle der 'delay' Funktion selbst die Millisekunden zählst, wird das an deinem Problem nichts ändern. > Hier mein Beispielcode vom Servo: >
1 | |
2 | > void loop() |
3 | > |
4 | > { //Im „loop“ wird über den write-Befehl „servoblau.write(Grad)“ das |
5 | > Servo angesteuert. Zwischen den einzelnen Positionen gibt es eine Pause, |
6 | > damit das Servo genug Zeit hat, die gewünschten Positionen zu erreichen. |
7 | > |
8 | > servoblau.write(0); //Position 1 ansteuern mit dem Winkel 0° |
9 | > |
10 | > delay(3000); //Das Programm stoppt für 3 Sekunden |
11 | > |
12 | > servoblau.write(90); //Position 2 ansteuern mit dem Winkel 90° |
13 | > |
14 | > delay(3000); //Das Programm stoppt für 3 Sekunden |
15 | > |
Hi, Yield() kenne ich nicht. Werde ich nachlesen. Dies ist das Programm vom wireless Gamepad mit delay: (code) #include <PS2X_lib.h> //for v1.6 #include <Servo.h> //Die Servobibliothek wird aufgerufen. Sie wird benötigt, damit die Ansteuerung des Servos vereinfacht wird. Servo servoblau; //Erstellt für das Programm ein Servo mit dem Namen „servoblau“ PS2X ps2x; // create PS2 Controller Class //right now, the library does NOT support hot pluggable controllers, meaning //you must always either restart your Arduino after you conect the controller, //or call config_gamepad(pins) again after connecting the controller. int error = 0; byte type = 0; byte vibrate = 0; void setup(){ Serial.begin(57600); servoblau.attach(8); //Das Setup enthält die Information, dass das Servo an der Steuerleitung (gelb) mit Pin 8 verbunden wird. Hier ist natürlich auch ein anderer Pin möglich. //CHANGES for v1.6 HERE!!! **************PAY ATTENTION************* error = ps2x.config_gamepad(13,11,10,12, true, true); //setup pins and settings: GamePad(clock, command, attention, data, Pressures?, Rumble?) check for error if(error == 0){ Serial.println("Found Controller, configured successful"); Serial.println("Try out all the buttons, X will vibrate the controller, faster as you press harder;"); Serial.println("holding L1 or R1 will print out the analog stick values."); Serial.println("Go to www.billporter.info for updates and to report bugs."); } else if(error == 1) Serial.println("No controller found, check wiring, see readme.txt to enable debug. visit www.billporter.info for troubleshooting tips"); else if(error == 2) Serial.println("Controller found but not accepting commands. see readme.txt to enable debug. Visit www.billporter.info for troubleshooting tips"); else if(error == 3) Serial.println("Controller refusing to enter Pressures mode, may not support it. "); //Serial.print(ps2x.Analog(1), HEX); type = ps2x.readType(); switch(type) { case 0: Serial.println("Unknown Controller type"); break; case 1: Serial.println("DualShock Controller Found"); break; case 2: Serial.println("GuitarHero Controller Found"); break; } } void loop(){ /* You must Read Gamepad to get new values Read GamePad and set vibration values ps2x.read_gamepad(small motor on/off, larger motor strenght from 0-255) if you don't enable the rumble, use ps2x.read_gamepad(); with no values you should call this at least once a second */ if(error == 1) //skip loop if no controller found return; if(type == 2){ //Guitar Hero Controller ps2x.read_gamepad(); //read controller if(ps2x.ButtonPressed(GREEN_FRET)) Serial.println("Green Fret Pressed"); if(ps2x.ButtonPressed(RED_FRET)) Serial.println("Red Fret Pressed"); if(ps2x.ButtonPressed(YELLOW_FRET)) Serial.println("Yellow Fret Pressed"); if(ps2x.ButtonPressed(BLUE_FRET)) Serial.println("Blue Fret Pressed"); if(ps2x.ButtonPressed(ORANGE_FRET)) Serial.println("Orange Fret Pressed"); if(ps2x.ButtonPressed(STAR_POWER)) Serial.println("Star Power Command"); if(ps2x.Button(UP_STRUM)) //will be TRUE as long as button is pressed Serial.println("Up Strum"); if(ps2x.Button(DOWN_STRUM)) Serial.println("DOWN Strum"); if(ps2x.Button(PSB_START)) //will be TRUE as long as button is pressed Serial.println("Start is being held"); if(ps2x.Button(PSB_SELECT)) Serial.println("Select is being held"); if(ps2x.Button(ORANGE_FRET)) // print stick value IF TRUE { Serial.print("Wammy Bar Position:"); Serial.println(ps2x.Analog(WHAMMY_BAR), DEC); } } else { //DualShock Controller ps2x.read_gamepad(false, vibrate); //read controller and set large motor to spin at 'vibrate' speed if(ps2x.Button(PSB_START)) { //will be TRUE as long as button is pressed Serial.println("Start is being held"); servoblau.write(0); //Position 1 ansteuern mit dem Winkel 0° delay(500); //Das Programm stoppt für 0,5 Sekunden servoblau.write(20); //Position 2 ansteuern mit dem Winkel 20° delay(500); //Das Programm stoppt für 0,5 Sekunden } if(ps2x.Button(PSB_SELECT)) Serial.println("Select is being held"); if(ps2x.Button(PSB_SELECT)){ servoblau.write(0); //Position 1 ansteuern mit dem Winkel 0° delay(600); //Das Programm stoppt für 0,6 Sekunden servoblau.write(20); //Position 2 ansteuern mit dem Winkel 20° delay(300); //Das Programm stoppt für 0,3 Sekunden } if(ps2x.Button(PSB_PAD_UP)) { //will be TRUE as long as button is pressed Serial.print("Up held this hard: "); Serial.println(ps2x.Analog(PSAB_PAD_UP), DEC); } if(ps2x.Button(PSB_PAD_RIGHT)){ Serial.print("Right held this hard: "); Serial.println(ps2x.Analog(PSAB_PAD_RIGHT), DEC); } if(ps2x.Button(PSB_PAD_LEFT)){ Serial.print("LEFT held this hard: "); Serial.println(ps2x.Analog(PSAB_PAD_LEFT), DEC); } if(ps2x.Button(PSB_PAD_DOWN)) { //will be TRUE as long as button is pressed Serial.println("down just pressed"); servoblau.write(90); //Position 1 ansteuern mit dem Winkel 0° delay(1000); //Das Programm stoppt für 3 Sekunden servoblau.write(45); //Position 2 ansteuern mit dem Winkel 90° delay(1000); } vibrate = ps2x.Analog(PSAB_BLUE); //this will set the large motor vibrate speed based on //how hard you press the blue (X) button if (ps2x.NewButtonState()) //will be TRUE if any button changes state (on to off, or off to on) { if(ps2x.Button(PSB_L3)) Serial.println("L3 pressed"); if(ps2x.Button(PSB_R3)) Serial.println("R3 pressed"); if(ps2x.Button(PSB_L2)) Serial.println("L2 pressed"); if(ps2x.Button(PSB_R2)) Serial.println("R2 pressed"); if(ps2x.Button(PSB_GREEN)) Serial.println("Triangle pressed"); } if(ps2x.ButtonPressed(PSB_RED)) //will be TRUE if button was JUST pressed Serial.println("Circle just pressed"); if(ps2x.ButtonReleased(PSB_PINK)) //will be TRUE if button was JUST released Serial.println("Square just released"); if(ps2x.NewButtonState(PSB_BLUE)) //will be TRUE if button was JUST pressed OR released Serial.println("X just changed"); if(ps2x.Button(PSB_L1) || ps2x.Button(PSB_R1)) // print stick values if either is TRUE { Serial.print("Stick Values:"); Serial.print(ps2x.Analog(PSS_LY), DEC); //Left stick, Y axis. Other options: LX, RY, RX Serial.print(","); Serial.print(ps2x.Analog(PSS_LX), DEC); Serial.print(","); Serial.print(ps2x.Analog(PSS_RY), DEC); Serial.print(","); Serial.println(ps2x.Analog(PSS_RX), DEC); } } delay(50); } (/code)
Könntest du bitte die Code-Tags richtig benutzen? In eckigen Klammern und nicht in runden, dann würden sie auch funktionieren!
Benni B. schrieb: > Dies ist das Programm vom wireless Gamepad mit delay: So ein langer Quellcode gehört in einen Anhang, nicht in den laufenden Text. Dieses Verhalten nennt man Anstand, Rücksicht auf die Leserschaft die man erreichen will. Dies scheint heutzutage mehr und mehr nicht mehr üblich zu sein. Lies und verinnerliche: Wichtige Regeln - erst lesen, dann posten!
Benni B. schrieb: > void loop(){ > /* You must Read Gamepad to get new values > Read GamePad and set vibration values > ps2x.read_gamepad(small motor on/off, larger motor strenght from > 0-255) > if you don't enable the rumble, use ps2x.read_gamepad(); > with no values you should call this at least once a second ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Hier im Kommentar steht die Ursache und die Lösung deines Problems. Alle Programmpfade in der Schleife müssen innerhalb von 1 Sekunde beendet werden, damit ps2x.read_gamepad() rechtzeitig wieder aufgerufen wird. Sonst gibt es vermutlich eine Störung/Abbruch der Verbindung zum Controller.
Hi, also kann ich mit Gamepad keinen Roboterarm länger als eine Sekunde steuern? Gibts da eine Lösung? Sorry mit den Code Tags, kanns jetzt nicht mehr bearbeiten, aber hier im Anhang nochmal das Programm.
1 | if(ps2x.Button(PSB_PAD_DOWN)) { //will be TRUE as long as button is pressed |
2 | Serial.println("down just pressed"); |
3 | servoblau.write(90); //Position 1 ansteuern mit dem Winkel 0° |
4 | delay(1000); //Das Programm stoppt für 3 Sekunden |
5 | servoblau.write(45); //Position 2 ansteuern mit dem Winkel 90° |
6 | delay(1000); |
7 | }
|
müsstest dann so in etwa umschreiben: warte keine 1000 milliSekunden, sondern nur 10 und merke Dir, dass du dort warst und zähle einen merker um eins höher und verschwinde da wieder an den Anfang, um den PS-Controller auslesen zu können. Dann, wenn du wiederkommst, schaust du nach, ob der zähler schon auf 100 steht (10 x 100 macht ja 1000). Naja; und wenn dein zähler auf 100 oder sogar mehr als 100 steht, setzt du ihn auf null zurück und lässt den Servoblau weiterdrehen. Vorher nicht. Solange dein Zählermerkerding kleiner 100 ist, machst Du garnix, sondern kehrst brav nach oben zurück.
Hey, ich bin programmiermässig noch Anfänger. Kann vielleicht jemand den Code abändern, dass ich das Programm mal sehen kann, wenn es länger als eine Sekunde wird? Vielen Dank im Vorraus, Benni
Na genau so, wie geschrieben...
1 | if(ps2x.Button(PSB_PAD_DOWN)) { //will be TRUE as long as button is pressed |
2 | Serial.println("down just pressed"); |
3 | if (merkerdings==0) servoblau.write(90); //Position 1 ansteuern mit dem Winkel 0° |
4 | delay(10); //Das Programm stoppt für 10mSek |
5 | merkerdings++; |
6 | if(merkerdings>=100){ |
7 | merkerdings=0; |
8 | servoblau.write(45); |
9 | } //Position 2 ansteuern mit dem Winkel 90° |
10 | delay(1000); |
11 | }
|
Hat doch mit "programmieren jetzt nix zu tun. zuhören und machen. Variabelndeklaration usw. muss man noch machen. Chic ists auch nicht. Select case usw. wäre hübscher. also, so ähnlich... merkerdings müsste auf "1", dann servo auf 45 drehen und wenn fertig, merkerdings wider auf "0". sonst dreht der immerhinunher
:
Bearbeitet durch User
Hi, das Servo fährt nur in die Mittelstellung, also 90°. Was muss ich ändern, damit die zweite Position angefahren wird? Dankeschön, Benni
Benni, du überstrapazierst die Hilfsbereitschaft der Leute. Du musst deine Sachen schon selbst programmieren oder Geld anbieten. Es ist besser, für den Anfang etwas eigenes zu programmieren, als fremde Codes ändern zu wollen die man (noch) nicht versteht. Ein Tipp von mir: Achte mal darauf, dass die Kommentare im Quelltext mit dem übereinstimmen, was da wirklich passiert. Denn falsche Kommentare sind schlimmer als gar keine.
Benni B. schrieb: > yield kenne ich nicht. Wie funktioniert sie? Hast du dir die Beschreibung von yield() auf der Arduino Webseite angeschaut? Wie lauten deine konkreten Fragen dazu? Es läuft darauf hinaus, das wir nicht für dich das Lernen übernehmen können.
Benni B. schrieb: > yield Auf AVR Arduinos wird es von delay() aufgerufen. Man kann sich damit ein Kooperatives Multitasking bauen. Beispiel:
1 | /**
|
2 | * Basisprogramm:
|
3 | * Das Blink Beispiel aus der Arduino IDE
|
4 | *
|
5 | * Zusaetzliche nebenlaeufige Funktionalitaet:
|
6 | * Eine Ablaufsteuerung
|
7 | *
|
8 | * Nach betaetigen des Schalters startet die Absaugung und danach
|
9 | * die Maschine. Nach abschalten stoppt erst die Maschine und danach die
|
10 | * Absaugung
|
11 | *
|
12 | *
|
13 | * Ablaufdiagramm - Zeitdiagramm
|
14 | *
|
15 | * schalter _----------_____ Schalterstellung
|
16 | * absaugung _-------------__ Verzoegertes abschalten
|
17 | * maschine ____-------_____ Verzoegertes einschalten
|
18 | *
|
19 | * Der Schalter arbeitet invers und ist entprellt
|
20 | *
|
21 | *
|
22 | */
|
23 | |
24 | #include <CombieTimer.h> |
25 | #include <CombiePin.h> |
26 | #include <CombieTypeMangling.h> |
27 | |
28 | using namespace Combie::Pin; |
29 | using namespace Combie::Timer; |
30 | using namespace Combie::Millis; |
31 | |
32 | TasterGND<2> schalter; // zwischen Pin und GND(invertierend) |
33 | OutputPin<3> absaugung; |
34 | OutputPin<4> maschine; |
35 | |
36 | |
37 | EntprellTimer entprell { 20_ms}; // Schalter entprellen |
38 | RisingEdgeTimer ton {500_ms}; // steigende Flanke wird verzoegert |
39 | FallingEdgeTimer toff {500_ms}; // abfallende Flanke wird verzoegert |
40 | |
41 | void setup(void) |
42 | {
|
43 | schalter.initPullup(); |
44 | absaugung.init(); |
45 | maschine.init(); |
46 | pinMode(LED_BUILTIN, OUTPUT); // unveraendert aus Blink.ino |
47 | }
|
48 | |
49 | void yield(void) |
50 | {
|
51 | bool schalterMerker = entprell = schalter; |
52 | absaugung = toff = schalterMerker; |
53 | maschine = ton = schalterMerker; |
54 | }
|
55 | |
56 | void loop(void) // unveraendert aus Blink.ino |
57 | {
|
58 | digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) |
59 | delay(1000); // wait for a second |
60 | digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW |
61 | delay(1000); // wait for a second |
62 | }
|
Stefan ⛄ F. schrieb: > Hast du dir die Beschreibung von yield() auf der Arduino Webseite > angeschaut? Die gibt es nicht! Zumindest nicht für die AVR Arduinos.
>> Hast du dir die Beschreibung von yield() auf der Arduino Webseite >> angeschaut? Arduino Fanboy D. schrieb: > Die gibt es nicht! Zumindest nicht für die AVR Arduinos. https://www.arduino.cc/en/Reference/SchedulerYield Der Text ist allerdings sehr mager.
Arduino Fanboy D. schrieb: > Benni B. schrieb: >> yield > > > Auf AVR Arduinos wird es von delay() aufgerufen. Man kann sich damit ein > Kooperatives Multitasking bauen. Kann man machen, aber der TO kann das sicher nicht. Und in seinem Fall gäbe es eine wunderschöne Rekursion, da die Funktion ps2x.read_gamepad() aus der PS2X_lib, die mindestens einmal jede Sekunde aufgerufen werden soll, ebenfalls delay() benutzt.
Stefan ⛄ F. schrieb: >>> Hast du dir die Beschreibung von yield() auf der Arduino Webseite >>> angeschaut? > > Arduino Fanboy D. schrieb: >> Die gibt es nicht! Zumindest nicht für die AVR Arduinos. > > https://www.arduino.cc/en/Reference/SchedulerYield > > Der Text ist allerdings sehr mager. Glückwunsch! Du hast den https://www.arduino.cc/en/Reference/Scheduler für die ARM Arduinos gefunden. Ist nur leider eine andere Baustelle. Conny schrieb: > wunderschöne Rekursion Das sollte man schon vermeiden. evtl. ist gar das der Grund, es nicht in der Doku zu erwähnen. Im Code Kommentar steht "Für Library Entwickler" o.ä.
Benni B. schrieb: > Hey, ich bin programmiermässig noch Anfänger. Kann vielleicht jemand den > Code abändern, dass ich das Programm mal sehen kann, wenn es länger als > eine Sekunde wird? > Vielen Dank im Vorraus, > Benni Hi Benny, das ist nicht so ganz einfach. Es ist natürlich einfach, den Servo ohne delay() anzusteuern. Du merkst dir den aktuellen Zustand und den millis()-Wert zu dem dieser Zustand hergestellt wurde. Und dann prüfst du bei jedem Durchlauf durch loop() ob millis()-zustandmillis grösser als deine Wartezeit geworden ist, und wenn ja stellst du den nächsten Zustand her und merkst dir wieder millis(). Schwierig wird es, weil dann natürlich Tastendrücke auftreten können während der Servo sich bewegt, und du entscheiden musst was du dan machen willst. LG, Sebastian
Ich bräuchte einen Denkanstoss mit Millis, also was eingefügt wird und wo es eingefügt wird.
Joachim B. schrieb: > einen Zustandsautomaten bauen, suche delay ohne Blockierung > Beitrag "Arduino ohne delay und millis" > https://forum.arduino.cc/t/schaltverzogerung-ohne-delay-realisieren/418457 > https://forum.arduino.cc/t/wie-zeitliche-ablaufe-ohne-delay-einfach-gestalten/121407 > https://starthardware.org/timer-mit-arduino-alternative-zu-delays/ > https://www.az-delivery.de/blogs/azdelivery-blog-fur-arduino-und-raspberry-pi/entwurf-blink-sketch-ohne-delay
Benni B. schrieb: > Ich bräuchte einen Denkanstoss mit Millis, also was eingefügt wird > und wo es eingefügt wird. Der Denkanstoß sind die Zustandsautomaten, die dir Joachim empfohlen hat. Zu seinen Links kann ich ergänzend noch anbieten: http://stefanfrings.de/multithreading_arduino/index.html Du musst das aber selbst lesen und umsetzen.
Benni B. schrieb: > Ich bräuchte einen Denkanstoss mit Millis, also was eingefügt wird und > wo es eingefügt wird.
1 | int status_servoangle; |
2 | unsigned long status_millis; |
3 | |
4 | void setup () { |
5 | status_millis = millis(); |
6 | status_servoangle = 0; |
7 | servoblau.write(status_servoangle); |
8 | } |
9 | |
10 | void loop () { |
11 | unsigned long now_millis = millis(); |
12 | if (now_millis-status_millis>=3000) { |
13 | status_millis = now_millis; |
14 | status_servoangle = 90-status_servoangle; // 0->90->0->90->... |
15 | servoblau.write(status_servoangle); |
16 | } |
17 | } |
LG, Sebastian
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.