4x Servo + 4x Led

Hallo zusammen, habe problem 4 servos zu steuern, durch bestätigegn der taste 1,2,3 oder 4 sollen sich die entsprechenden servos bewegen.
hier mein code:

#include <Servo.h> 
 
Servo myservo1;
Servo myservo2;
Servo myservo3;
Servo myservo4;

char senden; 
int pos1=0; 
int pos2=0; 
int pos3=0; 
int pos4=0; 
 
void setup() 
{ 
  Serial.begin(9600);
  myservo1.attach(2); //Servo Schrank 1
  myservo2.attach(3); //Servo Schrank 2
  myservo3.attach(4); //Servo Schrank 3
  myservo4.attach(5); //Servo Schrank 4
  myservo1.write(pos1);
  myservo2.write(pos2);
  myservo3.write(pos3);
  myservo4.write(pos4);
  pinMode (6, OUTPUT); //LED Schrank 1
  pinMode (7, OUTPUT); //LED Schrank 2
  pinMode (8, OUTPUT); //LED Schrank 3
  pinMode (9, OUTPUT); //LED Schrank 4
} 
  
void loop() 
{  
  if (Serial.available()>=0) {
    
    senden=Serial.read(); 

    if (senden=='1'){pos1=180; digitalWrite(6, HIGH); }  
    else  {delay(10000);pos1=0; digitalWrite(6, LOW); }  
    
    if (senden=='2'){pos2=180; digitalWrite(7, HIGH); }  
    else  {delay(10000);pos2=0; digitalWrite(7, LOW); }  

    if (senden=='3'){pos3=180; digitalWrite(8, HIGH); }  
    else  {delay(10000);pos3=0; digitalWrite(8, LOW); }  
    
    if (senden=='4'){pos4=180; digitalWrite(9, HIGH); }  
    else  {delay(10000);pos4=0; digitalWrite(9, LOW); }  

    Serial.println(pos1);
    Serial.println(pos2);
    Serial.println(pos3);
    Serial.println(pos4); 
    myservo1.write(pos1);
    myservo2.write(pos2);
    myservo3.write(pos3);
    myservo4.write(pos4); 
    
       }
       
  delay(500); 
}
if (Serial.available()>=0) {
   
    senden=Serial.read();

    if (senden=='1'){pos1=180; digitalWrite(6, HIGH); } 
    else  {delay(10000);pos1=0; digitalWrite(6, LOW); } 
   
    if (senden=='2'){pos2=180; digitalWrite(7, HIGH); } 
    else  {delay(10000);pos2=0; digitalWrite(7, LOW); } 

    if (senden=='3'){pos3=180; digitalWrite(8, HIGH); } 
    else  {delay(10000);pos3=0; digitalWrite(8, LOW); } 
   
    if (senden=='4'){pos4=180; digitalWrite(9, HIGH); } 
    else  {delay(10000);pos4=0; digitalWrite(9, LOW); }

Wenn Du eine 4 sendest dann passiert mal gar nichts. Das heißt gar nichts ist nicht richtig. Der Arduino wartet 3 mal 10 Sekunden.

Wenn Du ein Zeichen verschieden von 1, 2, 3, oder 4 schickst, zB ein NL oder CR dann blockiert der Arduino für 40 Sekunden.

Lerne wie millis() funktioniert und verwende es für die Timings.

Grüße Uwe

Danke Uwe, habe es ausprobiert jedoch komme nicht ans Ziel :cry:

andele:
Danke Uwe, habe es ausprobiert jedoch komme nicht ans Ziel :cry:

Was hast Du ausprobiert? eine 4 zu senden?

Grüße Uwe

Hallo,

Vorschlag :

Versuche es erst mal mit einem Motor und einer LED und ersetze das delay durch eine Konstuktion mit millis() in der Art wie bei dem Beispiel Blink without delay.

uwefed:
Was hast Du ausprobiert? eine 4 zu senden?

Grüße Uwe

Nicht wirklich :slight_smile:

#include <Servo.h>
 
Servo myservo1;
Servo myservo2;
Servo myservo3;
Servo myservo4;

char senden;
int pos1=0;
int pos2=0;
int pos3=0;
int pos4=0;

unsigned long previousMillis = 0;
unsigned long interval = 10000;
 
void setup()
{
  Serial.begin(9600);
  myservo1.attach(2); //Servo Schrank 1
  myservo2.attach(3); //Servo Schrank 2
  myservo3.attach(4); //Servo Schrank 3
  myservo4.attach(5); //Servo Schrank 4
  myservo1.write(pos1);
  myservo2.write(pos2);
  myservo3.write(pos3);
  myservo4.write(pos4);
  pinMode (6, OUTPUT); //LED Schrank 1
  pinMode (7, OUTPUT); //LED Schrank 2
  pinMode (8, OUTPUT); //LED Schrank 3
  pinMode (9, OUTPUT); //LED Schrank 4
}
 

void loop()
{
 if (Serial.available()>=0) {
    senden=Serial.read();

   if (senden=='1')(millis() - previousMillis > interval){
   pos1=180; digitalWrite(6, HIGH);
   previousMillis = millis();
   pos1 = !pos1;
   digitalWrite(6, LOW);
   myservo1.write(pos1);
   }

   if (senden=='2')(millis() - previousMillis > interval){
   pos2=180; digitalWrite(7, HIGH);
   previousMillis = millis();
   pos2 = !pos2;
   digitalWrite(7, LOW);
   myservo2.write(pos2);
   }

   if (senden=='3')(millis() - previousMillis > interval){
   pos3=180; digitalWrite(8, HIGH);
   previousMillis = millis();
   pos3 = !pos3;
   digitalWrite(8, LOW);
   myservo3.write(pos3);
   }

   if (senden=='4')(millis() - previousMillis > interval){
   pos4=180; digitalWrite(9, HIGH);
   previousMillis = millis();
   pos4 = !pos4;
   digitalWrite(9, LOW);
   myservo4.write(pos4);
   }
 }
}

Ist denn folgendes nicht immer wahr:

if (Serial.available() >= 0) { ...

und müsste es nicht heißen:

if (Serial.available() > 0) { ...

(Aber das ist wohl nur ein Nebenschauplatz :slight_smile: )

Hallo,

was Du da gemacht hast das klappt nicht wirklich, hast Du aber ja sicher schon bemerkt. Sorry aber das war mein Fehler. Uwe hatte es richtig geschrieben , verstehe wie man millis() verwendet.

so jedenfalls nicht.

Noch ein Hinweis, es kann ja auch passieren das Du zwei Tasten hintereinander drückst während ein Motor noch fährt. Du willst den Motor doch sofort fahren lassen und nach Ablauf der Wartezeit wieder zurück , jedenfalls hatte ich das so verstanden.

Heinz

Rentner:
Hallo,

was Du da gemacht hast das klappt nicht wirklich, hast Du aber ja sicher schon bemerkt. Sorry aber das war mein Fehler. Uwe hatte es richtig geschrieben , verstehe wie man millis() verwendet.

so jedenfalls nicht.

Noch ein Hinweis, es kann ja auch passieren das Du zwei Tasten hintereinander drückst während ein Motor noch fährt. Du willst den Motor doch sofort fahren lassen und nach Ablauf der Wartezeit wieder zurück , jedenfalls hatte ich das so verstanden.

Heinz

Schon OK, hab ja VERSUCHT das Blink-Beispiel nachzumachen bzw. zu verstehn, jedoch funzt das nicht in meinem Fall sonst hätte ich auch nicht um HILFE gebeten.
Gruss

Hi

void setup(){
...myservo1.write(pos1);
...
}

void loop(){
...
pos1=180;
...
}

Also ICH sehe Da einen kleinen Unterschied - im setup sprichst Du ein Servo an, in der loop() setzt Du nur eine Variable.

MfG

PS: delay() ist wirklich unschön, da Dabei der Arduino NICHTS macht, lerne das Konzept hinter dem Beispiel 'Blink_without_delay' auf der IDE und wende Es an.
(NICHTS ist nicht ganz richtig - er reagiert halt nicht auf Dich und arbeitet auch nicht am Sketch)

postmaster-ino:
Hi

void setup(){

...myservo1.write(pos1);
...
}

void loop(){
...
pos1=180;
...
}



Also ICH sehe Da einen kleinen Unterschied - im setup sprichst Du ein Servo an, in der loop() setzt Du nur eine Variable.

MfG

PS: delay() ist wirklich unschön, da Dabei der Arduino NICHTS macht, lerne das Konzept hinter dem Beispiel 'Blink_without_delay' auf der IDE und wende Es an.
(NICHTS ist nicht ganz richtig - er reagiert halt nicht auf Dich und arbeitet auch nicht am Sketch)

Hi , das ist mir bekannt das im scketch einige fehler sind und das delay() mein arduino blockiert, mit millis() hab ich es versucht und funzt nicht, wenn ich es könnte dann hätte ich nicht nach HILFE gebeten.
Für jede Hilfestellung bin ich sehr dankbar.
Gruss

Hi

Ok - auf das 'PS' bist Du ganz gut eingegangen - was ist mit dem Unterschied, Den ich dort gesehen habe?

Und JA, Das ist eine Hilfe.

MfG

Hi , pos1 kommt 2x vor ,1x in loop umd 1x in setup, was stimmt nicht?

Ok ...

WAS machst Du in setup() in der Zeile, wo pos1 vorkommt und warum? (Bitte eine Antwort auf beide Fragen)

Ziemlich genau das Gleiche willst Du auch in loop() machen - nur ist dort die Zeile ganz anders aufgebaut. Warum?

Der Groschen jetzt gefallen?

MfG

im setup wird die startposition festgelegt im loop sollte der servo per tastenbefehl auf 180 grad drehn, warum das so aufgebaut ist ? weil das mit delay geklappt hat mit 40 sec. verzögerung und das möchte ich nicht. alle 4 servos sollen sofort auf tastenbefehl angesprochen werden.

Hallo,
ich hab dir das mal für einen Servo zusammen gebaut, erweitern kannst Du es dann selber auf 4.
Es gibt wie immer mehrere Lösungen, ich hab jetzt mal eine gewählt die sicher programmtechnisch nicht optimal ist aber eventuell leicht verständlich, meine ich jedenfalls.

Ich hab mal zwei Funktonen erstellt damit das Program übersichtlich bleibt. Eine zum einlesen und auswerten der Zeichen, eine Zweite zur Ansteuerung des Motors.

Bei den Einstellungen am Termial. unten in der Statuszeile gibt es mehrere Einstellungen. Abgeschlossen wir eine Eingabe immer mit der Enter Taste, je nach Einstellung wir diese Abschluss mit übertragen oder auch nicht. Standard ist sicher das CR+NL gesendet wird.( Wagenrücklauf+neue Zeile, die Bezeichnungen stammen noch aus der Zeit in der es Telex gab, so bis 1980 etwa ) Damit kommen also drei Zeichen an. Der Sketch zeigt den Hex Code dazu mit an.

Der Motor startet direkt nach Erkennung des Startzeichens "1" und fährt auf pos 180. nach 3 s fährt er dann wieder zurück. Ich denke das war das was Du wolltest.

Der nächste Step für Dich wird ja sein das der Motor auch langsam fahren kann. Da wird dann aber etwas komplizierter. Das geht dann nicht mehr ganz so einfach. Dazu muss man den Motor von der aktuelle Position in kleinen Schritten auf eine Endposition fahren lassen und dazwischen eine Pause machen. natürlich sinvoller Weise mit millis() und nicht mit delay. In dem Fall setzt man aber besser eine State Mashine , Ablaufsteuerung, Schrittkette ein.

Das mit den millis() ist doch eigendlich ganz einfach, man muss es halt nur verstehen. Immer dann wenn die Verzögerungszeit nicht gebraucht oder gestartet werden soll macht man.

startzeit=millis()

wenn man die Zeit dann abfragen will

if (millis()-startzeit >= delayzeit) tu was

oder

if (millis()-startzeit <= impulszeit) tu was

so jetzt aber der Sketch

//  aus den Beispielen in der IDE zusammen gebastelt
// Terminal Einstellung  NL+CR oder NL senden erfolgt nach Enter
// es müssen mehrer Zeichen eingelesen und ausgewertet werden
//
#include <Servo.h>
Servo servo1; //Objekt erstellen
String eingabe;
bool startServo1;
unsigned long startzeit1;

void setup() {
  Serial.begin(9600);
  servo1.attach(3); // Pin setzen
  servo1.write(0);  // auf Pos 0 fahren
}

void loop() {

  Eingabelesen(); // Serielle schnittstelle lesen und auswerten

  if (startServo1) runServo1(); // Servo 1 soll fahren
  else startzeit1 = millis();  //wenn nicht benötigt reset Timer
}

//=============== Funktionen ==============

void Eingabelesen() {
  //  schnittstelle lesen und auswerten Eingabe wird mit
  //  DA Hex abgeschlossen.
  // Vorlage Beispiel / SerialEven

  while (Serial.available()) {
    char zeichen = char(Serial.read());
    eingabe += zeichen; // alle Zeichen lesen
    Serial.print(zeichen, HEX); // Zeichen ausgeben
    if (zeichen == '\n') {        // enter erkannt
      Serial.println();           // neue Zeile auf Monitor

      // auswerten
      if ( eingabe.startsWith("1")) { // erstes Zeichen ist "1"
        startServo1 = true;     // Status setzten
        Serial.println("1 erkannt Servo1 fährt vor");
      }
      
      if (eingabe.startsWith("2")) {
        // hier eingabe für zweiten Servo erkennen
      }
      
      eingabe = "";// Reset Eingabe
    }
  }
}
// Function Servo 1 fahren
void runServo1() {
  servo1.write(180); // vor
  if ((millis() - startzeit1 >= 3000)) {  // Zeit abgelaufen
    servo1.write(0);        // wieder zurück
    Serial.println ("Servo 1 zurück");
    startServo1 = false;    // Status beendet
  }
}

Hi Rentner, erstmal viel viel dank, super erklärt.....das nenne ich eine hilfestellung mit kommentar, mega.....ich werde mich damit auseinander setzten und eum probieren bzw. verstehn, habe mit LED-without Delay rum gespielt jedoch kam ich nicht unbedingt zum ergebniss.......nochmals vielen dank