Go Down

Topic: Abbruch des Sketches (Read 963 times) previous topic - next topic

Tommy56

Nach meinem Verständnis ist das Trennen von GND bei Servos keine gute Idee.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

michael_x

Quote
Das Problem ist, dass die for schleife nicht nach 146,2s verlassen werden soll. Wie kann ich das lösen?
einfach ganz ohne for-Schleife.

Eigentlich ist dein Sketch am einfachsten, wenn du die eine Schleife, die das Arduino-System dir vorgibt, und die ewig läuft,

Code: [Select]
// globale Zustandsmerker ...
void loop() {
// Erfasse den aktuellen Zustand
// Mach was jetzt zu tun ist
}

sinnvoll nutzt.

Johannes81

Hmmm, also ihr meint, dass es am sinnvollsten ist den kompletten Sketch nochmal neu aufzurollen ohne for schleifen und dafür mit sinnvollen Merkern?

Dann muss ich mir mal überlegen wie ich es angehen könnte. Hat jemand so einen prinzipiellen Tipp dafür für mich? Ich möchte keinen vorgekauten fertigen Sketch, weil das tüfteln ja dazu gehört und ich was lernen möchte. Aber wie könnte ich das Problem von mir konzeptionell angehen?

Und eine Frage noch. Warum gibt es eine zeitliche Beschränkung bei meinen for schleifen? Weil die normale Loop Schleife sollte doch theoretisch auch ewig laufen...

Tommy56

Der normale Loop sollte so schnell wie möglich laufen, um mehrere Sachen scheinbar gleichzeitig erledigen zu können.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

agmue

Hmmm, also ihr meint, dass es am sinnvollsten ist den kompletten Sketch nochmal neu aufzurollen ohne for schleifen und dafür mit sinnvollen Merkern?
Ja.

Hat jemand so einen prinzipiellen Tipp dafür für mich?
Code: [Select]
byte hpos = 5; //Variable in der die Position des Servos Horizontal gespeichert wird
byte vpos = 5; //Variable in der die Position des Servos Vertikal gespeichert wird
uint32_t aktMillis, pausenMillis;
const uint32_t pausezeit = 100; //Pausezeit nach einer Bewegung

void setup() {
  Serial.begin(9600);
}

void loop() {
  aktMillis = millis();
  if (aktMillis - pausenMillis >= pausezeit) {
    pausenMillis = aktMillis;
    Serial.print("hpos: ");
    Serial.print(hpos);
    Serial.print("\tvpos: ");
    Serial.println(vpos);
    hpos += 10;
    if (hpos >= 175) {
      hpos = 5;
      vpos += 10;
      if (vpos >= 175) {
        vpos = 5;
      }
    }
  }
}

Wenn Du etwas lesen möchtest, suche im Forum nach "agmue anleitung". Da findest Du auch einen Link zur beliebten Nachtwächtererklärung.
Wahnsinn und Verstand trennt nur eine dünne Wand. (Daniel Düsentrieb)

michael_x

#20
Mar 08, 2018, 09:13 pm Last Edit: Mar 08, 2018, 09:14 pm by michael_x
Quote
Und eine Frage noch. Warum gibt es eine zeitliche Beschränkung bei meinen for schleifen?
Der Sinn einer for Schleife ist eigentlich, dass sie eine bestimmte Anzahl mal läuft oder eine Kollektion von Elementen eins nach dem andern abarbeitet. Wenn das nicht gewollt ist, gibt es auch andere Konstruktionen ( while ) Da du in jedem Schleifendurchlauf ein delay drin hast, ergibt sich bei dir indirekt die Laufzeit.

Genereller Tip:
Vergiss, dass ein "Programm" ein Anfang und ein Ende hat.

Hier gilt: Initialisieren, dann ewig laufen.
Auch wenn die meiste Zeit das "Programm" nur darin besteht, zu prüfen ob der Taster betätigt wurde.

Vielleicht soll irgendwann der Taster ja auch während der Servo-Fahrerei einen Sinn haben.
Dann wäre es praktisch, wenn loop statt 2 Minuten nur 0 Sekunden dauert.

Den Taster ignorieren, wenn er im aktuellen Zustand keine Funktion haben soll, kann man ja trotzdem.



dony

#21
Mar 08, 2018, 09:13 pm Last Edit: Mar 08, 2018, 09:16 pm by dony
Hallo,

Ich habe mir Deinen Code geschnappt und die start Funktion sofort auskommentiert und den Inhalt in die loop kopiert. ;) Schon der Übersicht wegen.

Ich glaube dass Du in irgendeiner Schleife hängen bleibst. Also schnelles debugging.
Im Setup hast Serial.begin() schon drinnen. In jede Mögliche Abzweigung und natürlich in jede Funktion ein

Code: [Select]
Serial.println("for Schleife 1"); // Den Text musst Du definieren.

Dann lass das ganze nochmal laufen und beobachte den Seriellen Monitor.
So kommen wir IMHO am schnellsten zur Lösung, sind vielleicht 10 Funktionen.

Grüße,
Donny
edit: Auf die Hinweise meiner Vorposter, alles in die loop, etc. solltest Du hören. Ich brauche es ja nicht nochmals zu schreiben.
Grüße, Donny

uwefed

Wow, danke für die Hilfe schon mal.
Also beim Servisugnal verwende ich einen Transistor.

Und danke für die Kommentare im Code. Werde ich heute abend gleich versuchen. Gebe selbstverständlich Rückmeldung.  :)
Bitte genauer erklähren; Schaltplan.
Grüße Uwe

Johannes81

So, ich habe jetzt mal eine Nacht drüber geschlafen, mehr oder weniger zumindest... :-)
Was meint Ihr ist es sinnvoll, wenn ich die for schleifen durch do/while ersetze?

@ dony: Habe ich auch versucht. Der Serial Monitor gibt immer genau das aus was er soll, bzw was zu erwarten ist. Danke für den Tipp, bin aber dadurch leider nicht weiter gekommen.

agmue

#24
Mar 09, 2018, 10:25 am Last Edit: Mar 09, 2018, 10:25 am by agmue
Was meint Ihr ist es sinnvoll, wenn ich die for schleifen durch do/while ersetze?
Nein.

Wenn ich mal combie aus dem Gedächtnis zitieren darf: "Ändere Dein Denken!"

Wenn es Dir hilft, dann stelle Dir loop(){} als while(1){ } vor, wobei Dein Programm in den geschweiften Klammern steht.

Der Ansatz für Dein Programm und Dein neues Denken steht in #19, das kannst Du ausbauen, ganz ohne for und while.
Wahnsinn und Verstand trennt nur eine dünne Wand. (Daniel Düsentrieb)

Johannes81

So liebe Leute,

um dem ganzen Vorgang hier vorschriftsgemäß ein Ende zubereiten, hier mein Feedback:

Ich habe den Sketch jetzt so hin bekommen, dass er läuft wie er soll und praktisch ewig im LED grün Modus bleibt wie er soll.
Meine Lösung war, dank eurer Hilfe, den kompletten Sketch nocheinmal zu Überarbeiten und so weit es geht auf FOR schleifen zu verzichten. Die einzigen im Sketch enthaltenen DELAYS diene lediglich dazu abzuwarten bis der Servo die gewünscht Position angefahren hat.

Unten habe ich meinen Sketch dazu gepostet. An die lieben Profis hier im Forum, die mir hervoragend geholfen haben: Der Sketch ist mit Sicherheit nicht optimal und ich habe auch gelesen, dass die GOTO Funktion eigentlich ungern verwendet wird, aber (und ich denke darum geht es in diesem Forum) ich habe es hin bekommen! Die Details und das elegantere Programmieren wird denke ich mit der Zeit noch kommen. Also mea culpa für manche holprige Lösung. Werde schon noch besser werden  :)

Code: [Select]
#include <Servo.h>
Servo Horizontal; //Servo mit dem Namen Horizontal
Servo Vertikal; //Servo mit dem Namen Vertikal

int pos; //Variable in der die Position des Servos Horizontal gespeichert wird
int poos; //Variable in der die Position des Servos Vertikal gespeichert wird

int startknopf = 9; // Zuweisung an welchem pin der Suchknopf angeschlossen ist
int knopfzustand = LOW; //

int fehler = 4; // Zuweisung an welchem Pin die LED Fehler (1) angeschlossen ist
int pruefen = 5; // Zuweisung an welchem Pin die LED Suchen (2) angeschlossen ist
int gefunden = 6; //Zuweisung an welchem Pin die LED Gefunden (3) angeschlossen ist

int servosignal = 10; // Zuweisung an welchem Pin die Servos hängen
bool y;
bool z;
bool g;


int sensorValue;

int pausezeit = 100; //Pausezeit nach einer Bewegung

void setup() {
  // put your setup code here, to run once:

  pinMode(fehler, OUTPUT);
  pinMode(pruefen, OUTPUT);
  pinMode(startknopf, INPUT);
  pinMode(gefunden, OUTPUT);
  pinMode(servosignal, OUTPUT);


  Horizontal.attach(3); // an welchem Pin das Servo angeschlossen ist
  Vertikal.attach(2); // an welchem Pin das Servo angeschlossen ist

  Serial.begin(9600);
  y = LOW;
  z = LOW;
  g = LOW;

}

void loop() {

  Horizontal.write(0); // definiert den Startwinkel für Suchfunktion
  Vertikal.write(0); // definiert den Startwinkel für Suchfunktion

  digitalWrite(fehler, HIGH);
  digitalWrite(pruefen, LOW);
  digitalWrite(gefunden, LOW);
  digitalWrite(servosignal, HIGH);
  sensorValue = analogRead(A1);
  Serial.println(sensorValue);
  Serial.println("abc");
  if (digitalRead(startknopf) == HIGH) {

    Serial.println("1111111111111111111111");
    y = HIGH;
    digitalWrite(fehler, LOW);
    digitalWrite(pruefen, HIGH);
    digitalWrite(gefunden, LOW);
    digitalWrite(servosignal, HIGH);
    for (pos = 10; pos <= 170; pos += 10) {
      Horizontal.write(pos);
      for (poos = 10; poos <= 170; poos += 1) {
        Vertikal.write(poos);
        sensorValue = analogRead(A1);
        Serial.println(sensorValue);
        if (sensorValue > 200) {
          digitalWrite(servosignal, LOW);
          break;
        }
        delay(15);
      }
      delay(15);
    }
  }
  if (y == HIGH && sensorValue > 200) {
    z = HIGH;

  }
  if (z == HIGH) {
ausstieg:
    digitalWrite(fehler, LOW);
    digitalWrite(pruefen, LOW);
    digitalWrite(gefunden, HIGH);
    digitalWrite(servosignal, LOW);
    g = HIGH;

    Serial.println("999999999999");
    sensorValue = analogRead(A1);
    Serial.println(sensorValue);
    //delay(2000);
    if (g == HIGH && digitalRead(startknopf) == HIGH) {
      digitalWrite(fehler, HIGH);
      digitalWrite(pruefen, HIGH);
      digitalWrite(gefunden, LOW);
      delay(20 * pausezeit);
    }
    if (sensorValue > 200) {
      goto ausstieg;
    }
  }
  if (analogRead(A1) < 100 && g == HIGH) {
    digitalWrite(fehler, HIGH);
    digitalWrite(pruefen, HIGH);
    digitalWrite(gefunden, HIGH);
    digitalWrite(servosignal, LOW);
    delay(2000);
    g = LOW;
    z = LOW;
    y = LOW;

  }


}

postmaster-ino

Hi

Du verwendest die loop() immer noch nicht, wie vom 'Hersteller erdacht'.
Du ackerst immer noch die verschachtelte FOR-Schleifen durch.
In dieser Zeit wird auf Nichts reagiert, was außerhalb der Schleifen steht.
Da stören die zwei delay() im Code dann auch nicht mehr.

Wie ich Deinen Sketch verstehe, fährst Du mit zwei Servos eine Art X/Y-System ab und suchst nach einem hellen Punkt.
Während der Suche kannst Du den Vorgang nicht beeinflussen, da Du in den FOR-Schleifen gefangen bist.
Wenn ein heller Punkt gefunden ist, wird die Versorgung der Servos abgeschaltet (?? Servosignal auf low).
Dann gehen ein paar LEDs an oder aus, Variablen mit unbekanntem Sinn bekommen Werte zugewiesen (y,g,z).
Ggf. beginnt das Spiel von Neuem - so weit bin ich nicht durchgestiegen.

Wenn Dein Sketch so funktioniert, belasse Diesen so, für's nächste Mal versuche was in der Richtung:
Pseudocode:
Code: [Select]

if (millis()-startzeit>=wartezeit){
  //Wartezeit vorbei, schaue Dir die nächste anliegende Arbeit an
  static byte status=0;
  startzeit=millis();
  switch (status){
    case 0:  //nächste Position anfahren
      if (pos<170){
        pos++;
        wartezeit=300;  //Fahrzeit bis zum nächsten Punkt ist hier sehr kurz
      }else{
      pos=0;  //wir sind an der letzten LED, weiter in der nächsten Zeile von Vorne
      if (poos<170){
        poos++;
        wartezeit=1000;  //Wartezeit ist hier etwas länger, da eine Achse komplett gefahren werden muß
      }else{
        poos=0;
        wartezeit=1500;  //längste Wartezeit, da beide Achsen komplett fahren müssen - ggf. reicht der gleiche Wert wie drüber
      }
      Horizontal.write(pos);  //Ziel-Positionen ansteuern
      Vertical.write(poos);
      status++;    // als Nächstes den Lichtpunkt prüfen
      break;
  case 1:  //Überprüfen, ob hier der Punkt hell leuchtet
      // Prüfen, LEDs setzen, Fehler anzeigen ect.pp.
      // status so setzen, daß darauf reagiert werden kann - wenn weiter gesucht werden soll, status=0
      // wenn bei Fund zuvor 'nur' 10 Sekunden gewartet werden soll, dann wartezeit=10000; und status=2, dort dann
      //nur den Status wieder auf 0 setzen und die Wartezeit auf einen sehr kleinen Wert, damit wieder zur 0 gesprungen wird
     //so kannst Du hier bis zu 255 Status (ist auch die Mehrzahl von Status) behandeln, wichtig ist, daß Du wieder 'zurück' findest
     //also irgend wie status wieder auf 0=Programmstart gesetzt bekommst, ob Du dafür auf einen Tastendruck
     //wartest oder ein Temp-Sensor 30° messen muß, kannst Du Alles in einem der Status unterbringen und eben
     //erst bei Erfüllung der Bedingung 'einen Weiter' gehen - oder zur 0 springen, oder bei Nichterfüllung den Status
     //einfach so belassen, dann wird in der nächsten Runde eben genau das Gleiche erneut geprüft
    ...

Hier hast Du in jedem loop()-Durchlauf bei status==0 nur die Versetzung auf den nächsten Punkt.
Während der Fahrt (Zeit experimentell finden) macht der Code hier gar Nichts, sondern arbeitet die Anweisungen hinter dem ganzen Anfahr-und-Prüf-Block ab, z.B., ob Jemand den NotAus gedrückt hat oder ob ein Befehl von Extern gesendet wurde (Fahre Pixel 23 oder pos=15/poos=22 an).
Durch die Nutzung von unterschiedlichen Wartezeiten verzweigt der Sketch auch nur, wenn's nötig ist.

Was Das im Endeffekt jetzt gegeben hat, ist mir nicht ganz klar - wenn's aber funktioniert: Glückwunsch und viel Spaß damit!

Ach ja: Wenn Du keine negativen Werte erwartest, nutze statt int -> unsigned int, oder, wenn Du mit Werten 0...255 zurecht kommst, byte (ist eh vorzeichenlos).

MfG

PS: Danke für Dein Feedback!
millis() und die Wartezeit-Variable sollten in unsigned long gespeichert werden, da millis() 32 bit groß ist, nicht negativ werden kann und der Compiler nicht meckert, wenn gleich große Variablen mit einander verglichen werden.

MfG
anscheinend ist Es nicht erwünscht, einen Foren-internen Link als 'Homepage' einzubinden, damit JEDER nur einen Klick von combie's Liste zum Thema State-Maschine entfernt ist.
... dann eben nicht ...

Go Up