[gelöst] Hängt sich nach kurzer Zeit auf

Hallo,
ich habe ein kleines Programm für den Nano geschrieben, welches ein Schrittmotor steuert und eine "mm Angabe" auf ein Oled Display wiedergibt, dazu auf einen zweiten Oled die eingestellte Leistung in % eines Potis anzeigt.
Das Programm läuft an sich gut, aber wenn man es ca 2 Minuten nicht benutzt, hängt es sich auf. :sob:
Was mache ich falsch? (Sry ich bin Anfänger)

LG
Celleron

Sorry, aber auch als Anfänger solltest du zwingend deinen Sketch dokumentieren.
Du wirst in 2 Wochen nicht mehr wissen, was das soll. Wir evtl. jetzt schon nicht.
Dann sind deine Variablen schlecht zu verstehen. Verwende sprechende Namen.

Und in den Funktionen zu den OLEDs ist totales durcheinander.
Du schreibst in der zweiten Funktion an das erste OLED. Da kommt man nicht mehr klar.

Wie sollen wir da einen Fehler finden ?
Und poste mal ein Schaltbild, wie du alles angeschlossen hast.

Und in den Funktionen zu den OLEDs ist totales durcheinander.
Du schreibst in der zweiten Funktion an das erste OLED.

Oh da war noch der Fehlerteufel drin. natürlich sollte da nur das zweite Display angesprochen werden. :o

Sorry, aber auch als Anfänger solltest du zwingend deinen Sketch dokumentieren.
Du wirst in 2 Wochen nicht mehr wissen, was das soll. Wir evtl. jetzt schon nicht.
Dann sind deine Variablen schlecht zu verstehen. Verwende sprechende Namen.

Werde ich in Zukunft beachachten.

Und poste mal ein Schaltbild, wie du alles angeschlossen hast.

Hab ich angehangen. Leider auch etwas Chaotisch.

celleron:
Oh da war noch der Fehlerteufel drin. natürlich sollte da nur das zweite Display angesprochen werden. :o

Der ist immer noch drin.

Werde ich in Zukunft beachachten.

Schade, so tue ich mir das nicht an. Andere evtl.

Hab ich angehangen. Leider auch etwas Chaotisch.

Das Schaltbild einer Led und eines Tasters sieht aber anders aus. Das solltest du berichtigen.
Und wieso ein Taster paralle zur Led ?
Was willst du damit erreichen ?
Einen defekten Ausgangspin ?

Und wieso ein Taster paralle zur Led ?

Meine Taster haben ein eingebaute LED. Ich wollte die nur als eine Art optisches Feedback beim Drücken. So das die jeweiligen Taster beim Drücken aufleuchten.

aber wenn man es ca 2 Minuten nicht benutzt, hängt es sich auf.

Analysiere was genau passiert.
Statte deinen Sketch mit Serial Ausgaben aus und beobachte wo dein Sketch das letzte mal verweilt.
In jedes einzelne If, in jedes for.

Ich würde mit den ganzen While / do anfangen.

und was mir so aufällt

char buffer[10];

sind manchmal definiert werden aber nicht verwendet. Schalte dir in deiner IDE die Warnings ein, dann haut dir das der Compiler gleich rüber.

char buf[3];
sprintf (buf, "%d %%", LaserPowerSetting);

check mal ob das groß genug ist
ne ziffer, ein blank ein prozent sind schon 3 Zeichen, der Null-Limiter? wo geht der hin?

Ok, damit wir (ich speziell) nicht die Lust verlieren, versehe deinen Sketch mit kommentaren, wo wir erkennen können, was da passieren soll.
Dann baust du serielle Ausgaben (auf den seriellen Monitor) ein, und stellst fest, an welcher Stelle der Sketch hängen bleibt. Diese Info brauchen wir.

Dann gehts weiter.

Hallo
prüfe wie du deinen Sketch optimieren kannst.

der Sketch verwendet 22046 Bytes (68%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 1709 Bytes (83%) des dynamischen Speichers, 339 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.
Wenig Arbeitsspeicher verfügbar, es können Stabilitätsprobleme auftreten.

Globale Variablen verwenden 1709 Bytes (83%) des dynamischen Speichers, 339 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

Das ist zuwenig freier Speicher.

Du brauchst einen größeren Controller wie zB einen Arduino MAGA 2560.

 while (digitalRead(RUNTER) && !digitalRead(ENDU)) {
      delay (dec_continious);
      do {
        Runter_S();
        poscount = poscount - 1;
        drawOLED_2();
      }
      while (digitalRead(RUNTER) && !digitalRead(ENDU));
      if (bPosHold == LOW) {
        digitalWrite(ENA, HIGH); 
      }
    }

Was sollen diese WHILE Schleifen und dazu noch eine DO WHILE Schleife alle mit der gleichen Bedingung?

Grüße Uwe

Ok, da wir hier offenbar keine weiteren Infos (Kommentare im Sketch) bekommen, bin ich hier raus.

Hallo,

warum so ungeduldig? Warum den TO unter Druck setzen? Es gibt auch in diesem Lande noch Leute die ihrem Broterwerb o.ä. nachgehen.

Tut mir leid, mir war es gestern schon etwas zu spät, und ich musste heute morgen früh raus zur Arbeit.
Wie gesagt ich bin Anfänger und mache das als Hobby nebenher Abends.
Leider konnte ich den Code nicht kommentiert posten, da ich über die maximal erlaubte Zeichen hier im Forum kam. :o
Deshalb hänge ich die Datei einfach dem Post an, wenn das ok für euch ist.
LG
Celleron

celleron:
Leider konnte ich den Code nicht kommentiert posten, da ich über die maximal erlaubte Zeichen hier im Forum kam.

Der Code aus den malerischen leerzeichen befreit:

#include <U8g2lib.h>
#include <Wire.h>
#define ENA 9 // Schritmotor Treiber Enable Pin 
#define STP 3 // Schritmotor Treiber Step Pin 
#define DIR 2 // Schritmotor Treiber Direction Pin 
#define MS1 8 // Schritmotor Treiber MSI1 Pin 
#define MS2 7 // Schritmotor Treiber MSI2 Pin 
#define MS3 6 // Schritmotor Treiber MSI3 Pin 
#define HOCH 10 // Taster/LED Pin für Taste "Hoch" 
#define RUNTER 12 // Taster/LED Pin für Taste "Runter" 
#define RESET 13 // Taster/LED Pin für Taste "Reset" 
#define START 11 // Taster/LED Pin für Taste "Start" 
#define ENDU 4 // Enschalter/LED Pin für Unten
#define ENDO 5 // Enschalter/LED Pin für Oben
bool bHOCH = LOW;
bool bRUNTER = LOW;
bool bPosHold = LOW;
int poscount = 0; // Zahl für Positions Angabe
int steps_1 = 200; // nötige Wiederholungen für 1mm bewegung des Tisches
int stepperspeed_l = 500; // Schrittmotor Geschwindigkeit bei langsame fahrt
int stepperspeed_h = 250; // Schrittmotor Geschwindigkeit bei Schnelle fahrt
int dec_continious = 1000; // Zeit welche eine Taste gedrückt gehalten werden muss, bis wechsel von langsamer Einzelfahrt, auf schnelle Dauerfahrt
int LaserPowerSetting = 0; // Zahl für Poti % Angabe
U8G2_SH1106_128X64_NONAME_F_HW_I2C OLED_1(U8G2_R0, U8X8_PIN_NONE); // U8G2 OLED_1
U8G2_SH1106_128X64_NONAME_F_HW_I2C OLED_2(U8G2_R0, U8X8_PIN_NONE); // U8G2 OLED_2

void setup() {
  OLED_1.setI2CAddress(0x3C * 2); // OLED_1 mit I2C Adresse 0x3C
  OLED_2.setI2CAddress(0x3D * 2); // OLED_1 mit I2C Adresse 0x3D
  OLED_1.begin();
  OLED_2.begin();
  pinMode(ENA, OUTPUT); // Aus und Eingäge bestimmen
  pinMode(STP, OUTPUT);
  pinMode(DIR, OUTPUT);
  pinMode(MS1, OUTPUT);
  pinMode(MS2, OUTPUT);
  pinMode(MS3, OUTPUT);
  pinMode(HOCH, INPUT);
  pinMode(RUNTER, INPUT);
  pinMode(RESET, INPUT);
  pinMode(START, INPUT);
  pinMode(ENDO, INPUT);
  pinMode(ENDU, INPUT);
  digitalWrite(ENA, HIGH); // Einstellungen Schrittmotortreiber A4988
  digitalWrite(MS1, HIGH);
  digitalWrite(MS2, HIGH);
  digitalWrite(MS3, LOW);
}

void loop() {
  LaserPowerSetting = analogRead(A3); // Poti für % Angabe Angeschlossen an A3
  LaserPowerSetting = map(LaserPowerSetting, 60, 1023, 0, 100); // Poti % Angabe
  bHOCH = digitalRead(HOCH); // Var für Hoch Taster
  bRUNTER = digitalRead(RUNTER); // Var für Runter Taster
  drawOLED_1(); // Ausgabe Oled_1
  drawOLED_2(); // Ausgabe Oled_2


  if (bRUNTER == HIGH && !digitalRead(ENDU)) { // Runter Taster gedrückt und der Endschalter Unten nicht ausgelöst in mm runter fahren
    Runter(); // Schrittmotor fährt den Tisch 1mm runter
    poscount = poscount - 1; // Zahl für die Oled wird um 1 reduziert
    drawOLED_2(); // OLED_2 anzeigen
    while (digitalRead(RUNTER) && !digitalRead(ENDU)) { // Wenn immernoch Runter Taster gedrückt und der Endschalter Unten nicht ausgelöst
      delay (dec_continious); // Zeit abwarten
      do {
        Runter_S(); // 1mm den Tisch schnell runterfahren
        poscount = poscount - 1; // Zahl für die Oled wird um 1 reduziert
        drawOLED_2(); // OLED_2 anzeigen
      }
      while (digitalRead(RUNTER) && !digitalRead(ENDU)); // Wenn immernoch Runter Taster gedrückt und der Endschalter Unten nicht ausgelöst schnelle Dauerfahrt
      if (bPosHold == LOW) { // Soll Haltestrom den Schrittmotor an Position halten, wenn oben in Var eingestellt
        digitalWrite(ENA, HIGH);
      }
    }
  }

  if (bHOCH == HIGH && !digitalRead(ENDO)) { // Hoch Taster gedrückt und der Endschalter Oben nicht ausgelöst in mm hoch fahren
    Hoch(); // Schrittmotor fährt den Tisch 1mm hoch
    poscount = poscount + 1; // Zahl für die Oled wird um 1 addiert
    drawOLED_2(); // OLED_2 anzeigen

    while (digitalRead(HOCH) && !digitalRead(ENDO)) { // Wenn immernoch Hoch Taster gedrückt und der Endschalter oben nicht ausgelöst
      delay (dec_continious); // Zeit abwarten
      do {
        Hoch_S(); // 1mm den Tisch schnell hochfahren
        poscount = poscount + 1; // Zahl für die Oled wird um 1 addiertt
        drawOLED_2(); // OLED_2 anzeigen
      }
      while (digitalRead(HOCH) && !digitalRead(ENDO)); // Wenn immer noch Runter Taster gedrückt und der Endschalter Unten nicht ausgelöst schnelle Dauerfahrt
      if (bPosHold == LOW) { // Soll Haltestrom den Schrittmotor an Position halten, wenn oben in Var eingestellt
        digitalWrite(ENA, HIGH);
      }
    }
  }

  if (digitalRead(START) == HIGH) { // Wenn Start Taster gedrückt fahrt in mm Schritten auf 0
    for (int index = 0; index < poscount; poscount = poscount - 1) // bei positiver Zahle solange runter fahren bis anzeige auf 0
    {
      Runter();
      drawOLED_2();
    }
    for (int index = 0; index > poscount; poscount = poscount + 1) // bei negertiver Zahle solange hoch fahren bis anzeige auf 0
    {
      Hoch();
      drawOLED_2();
    }
    if (bPosHold == LOW) { // Soll Haltestrom den Schrittmotor an Position halten, wenn oben in Var eingestellt
      digitalWrite(ENA, HIGH);
    }
  }

  if (digitalRead(RESET) == HIGH) { // setzt Anzeige einfahc auf 0 auf aktueller Position zurück
    poscount = 0;
    drawOLED_2();
  }
}

void Hoch_S(void) { // 1 mm Hoch fahren in schnell
  digitalWrite(ENA, LOW);
  for (int index = 0; index <= steps_1; index = index + 1)
  {
    digitalWrite(DIR, LOW);
    digitalWrite(STP, HIGH);
    delayMicroseconds(stepperspeed_h);
    digitalWrite(DIR, LOW);
    digitalWrite(STP, LOW);
    delayMicroseconds(stepperspeed_h);
  }
}

void Hoch(void) { // 1 mm Hoch fahren in langsam
  digitalWrite(ENA, LOW);
  for (int index = 0; index <= steps_1; index = index + 1)
  {
    digitalWrite(DIR, LOW);
    digitalWrite(STP, HIGH);
    delayMicroseconds(stepperspeed_l);
    digitalWrite(DIR, LOW);
    digitalWrite(STP, LOW);
    delayMicroseconds(stepperspeed_l);
  }
}

void Runter_S(void) { // 1 mm Runter fahren in schnell
  digitalWrite(ENA, LOW);
  for (int index = 0; index <= steps_1; index = index + 1)
  {
    digitalWrite(DIR, HIGH);
    digitalWrite(STP, HIGH);
    delayMicroseconds(stepperspeed_h);
    digitalWrite(DIR, HIGH);
    digitalWrite(STP, LOW);
    delayMicroseconds(stepperspeed_h);
  }
}

void Runter(void) { // 1 mm Runter fahren in langsam
  digitalWrite(ENA, LOW);
  for (int index = 0; index <= steps_1; index = index + 1)
  {
    digitalWrite(DIR, HIGH);
    digitalWrite(STP, HIGH);
    delayMicroseconds(stepperspeed_l);
    digitalWrite(DIR, HIGH);
    digitalWrite(STP, LOW);
    delayMicroseconds(stepperspeed_l);
  }
}

void drawOLED_1(void) { // OLED Ausgabe
  char buf[5];
  sprintf (buf, "%d %%", LaserPowerSetting); // String % Angabe Poti
  char buffer[10];
  OLED_1.clearBuffer();
  OLED_1.setFont(u8g_font_10x20); // Schriftart
  OLED_1.drawStr(7, 15, "Laser Power"); // OLED Ausgabe oben
  OLED_1.setFont(u8g_font_ncenR24); // Schriftart
  OLED_1.drawStr(30, 55, buf); // Ausgabe String Poti % Angabe
  OLED_1.sendBuffer();
}

void drawOLED_2(void) { // OLED Ausgabe
  char buf2[6];
  sprintf (buf2, "%d mm", poscount); // String mm Angabe Tisch Position
  char buffer[10];
  OLED_2.clearBuffer();
  OLED_2.setFont(u8g_font_10x20); // Schriftart
  OLED_2.drawStr(5, 15, "Laser Tisch"); // OLED Ausgabe oben
  OLED_2.setFont(u8g_font_ncenR24); // Schriftart
  OLED_2.drawStr(10, 55, buf2); // Ausgabe String mm Angabe Tisch Position
  OLED_2.sendBuffer();
}

my_xy_projekt:
Der Code aus den malerischen leerzeichen befreit

Oh je Danke, da hätte ich ja auch selbst draufkommen können, das die Leerzeichen (die zur Ordnung beitragen sollten) das Problem ist. :confused:
Sorry, und vielen Dank.

Hallo,

habe das ein klein wenig geändert.
Die Doppelten hoch/runter Funktionen sind raus, jetzt mit Parameter. Brachte aber leider Speicher mäßig keine Punkte. Kannste aber noch um einen 2. Parameter erweitern um die Anzahl der Steps mitzugeben. Die 'steps_1' Variable.
Was mich echt wundert ist der sehr hohe Flashverbrauch.
Das scheint aber an den Fonts zu liegen. Hier könnte man sparsamere Fonts verwenden.
Den statischen RAM Verbrauch kann man schwer drücken.
Ohne 2. Display kommt man ca. um 150 Byte runter.
Du kannst, weil die Displays gleich sind, ein Objekt einsparen.
Du schaltest immer vor Benutzung mit setI2CAddress das Display um.
Dann könnte das auf dem Uno vielleicht noch etwas werden.
Das umgesetzt spart ca. 130 Bytes ein.

Was mir noch auffällt ist, dass deine while Schleifen wohl auch ein Problem darstellen könnten. Weil Semikolon am Ende und ohne Klammern. Ich glaube nicht das es so bewusst gewollt ist. Weiß ich aber nicht genau.
Du solltest sowieso dieses Abfragemonster in eine State Maschine umwandeln.
Stichtwort enum und switch case.

#include <U8g2lib.h>
#include <Wire.h>
const byte ENA {9};
const byte STP {3};
const byte DIR {2};
const byte MS1 {8};
const byte MS2 {7};
const byte MS3 {6};
const byte HOCH {10};
const byte RUNTER {12};
const byte RESET {13};
const byte START {11};
const byte ENDU {4};
const byte ENDO {5};
bool bHOCH {LOW};
bool bRUNTER {LOW};
bool bPosHold {LOW};
int poscount {0};
const int steps_1 {200};
const int stepperspeed_l {500};
const int stepperspeed_h {250};
int dec_continious {1000};
int LaserPowerSetting {0};
U8G2_SH1106_128X64_NONAME_F_HW_I2C OLED(U8G2_R0, U8X8_PIN_NONE);

void setup() {
  OLED.setI2CAddress(0x3C * 2);
  OLED.begin();
  OLED.setI2CAddress(0x3D * 2);
  OLED.begin();
  pinMode(ENA, OUTPUT);
  pinMode(STP, OUTPUT);
  pinMode(DIR, OUTPUT);
  pinMode(MS1, OUTPUT);
  pinMode(MS2, OUTPUT);
  pinMode(MS3, OUTPUT);
  pinMode(HOCH, INPUT);
  pinMode(RUNTER, INPUT);
  pinMode(RESET, INPUT);
  pinMode(START, INPUT);
  pinMode(ENDO, INPUT);
  pinMode(ENDU, INPUT);
  digitalWrite(ENA, HIGH);
  digitalWrite(MS1, HIGH);
  digitalWrite(MS2, HIGH);
  digitalWrite(MS3, LOW);
}

void loop() {
  LaserPowerSetting = analogRead(A3);
  LaserPowerSetting = map(LaserPowerSetting, 60, 1023, 0, 100);
  bHOCH = digitalRead(HOCH);
  bRUNTER = digitalRead(RUNTER);
  drawOLED_1();
  drawOLED_2();

  if (bRUNTER == HIGH && !digitalRead(ENDU)) {
    Runter(stepperspeed_l);
    poscount--;
    drawOLED_2();
    while (digitalRead(RUNTER) && !digitalRead(ENDU)) {
      delay (dec_continious);
      do {
        Runter(stepperspeed_h);
        poscount--;
        drawOLED_2();
      }
      while (digitalRead(RUNTER) && !digitalRead(ENDU));
      if (bPosHold == LOW) {
        digitalWrite(ENA, HIGH);
      }
    }
  }

  if (bHOCH == HIGH && !digitalRead(ENDO)) {
    Hoch(stepperspeed_l);
    poscount++;
    drawOLED_2();

    while (digitalRead(HOCH) && !digitalRead(ENDO)) {
      delay (dec_continious);
      do {
        Hoch(stepperspeed_h);
        poscount++;
        drawOLED_2();
      }
      while (digitalRead(HOCH) && !digitalRead(ENDO));
      if (bPosHold == LOW) {
        digitalWrite(ENA, HIGH);
      }
    }
  }

  if (digitalRead(START) == HIGH) {
    for (int index = 0; index < poscount;  poscount--)
    {
      Runter(stepperspeed_l);
      drawOLED_2();
    }
    for (int index = 0; index > poscount;  poscount++)
    {
      Hoch(stepperspeed_h);
      drawOLED_2();
    }
    if (bPosHold == LOW) {
      digitalWrite(ENA, HIGH);
    }
  }

  if (digitalRead(RESET) == HIGH) {
    poscount = 0;
    drawOLED_2();
  }
}

void Hoch(const unsigned long stepperspeed)
{
  digitalWrite(ENA, LOW);
  for (int index = 0; index <= steps_1; index++)
  {
    digitalWrite(DIR, LOW);
    digitalWrite(STP, HIGH);
    delayMicroseconds(stepperspeed);
    digitalWrite(DIR, LOW);
    digitalWrite(STP, LOW);
    delayMicroseconds(stepperspeed);
  }
}

void Runter(const unsigned long stepperspeed)
{
  digitalWrite(ENA, LOW);
  for (int index = 0; index <= steps_1; index++)
  {
    digitalWrite(DIR, HIGH);
    digitalWrite(STP, HIGH);
    delayMicroseconds(stepperspeed);
    digitalWrite(DIR, HIGH);
    digitalWrite(STP, LOW);
    delayMicroseconds(stepperspeed);
  }
}

void drawOLED_1(void) {
  OLED.setI2CAddress(0x3C * 2);
  char buf[9];
  sprintf (buf, "%d %%", LaserPowerSetting);
  OLED.clearBuffer();
  OLED.setFont(u8g_font_10x20);       // ohne 3kB weniger Flash
  OLED.drawStr(7, 15, "Laser Power");
  OLED.setFont(u8g_font_ncenR24);     // ohne 8kB weniger Flash
  OLED.drawStr(30, 55, buf);
  OLED.sendBuffer();
}

void drawOLED_2(void) {
  OLED.setI2CAddress(0x3D * 2);
  char buf[9];
  sprintf (buf, "%d mm", poscount);
  OLED.clearBuffer();
  OLED.setFont(u8g_font_10x20);
  OLED.drawStr(5, 15, "Laser Tisch");
  OLED.setFont(u8g_font_ncenR24);
  OLED.drawStr(10, 55, buf);
  OLED.sendBuffer();
}

Hallo
die Funktionen hoch() und runter() kann zusammengefügt werden in dem in der Parameterleiste auch die Richtung übergeben wird.

void HochRunter(const unsigned long stepperspeed, bool richtung)

Doc_Arduino:
Die Doppelten hoch/runter Funktionen sind raus, jetzt mit Parameter. Brachte aber leider Speicher mäßig keine Punkte.

Ach schick - dann brauch ich meinen nicht mehr zeigen...

Vielen Dank für die Änderungen, die muss ich mir gleich in Ruhe Anschauen und daraus lernen. :slight_smile:

Das Umschalten der Display versuche ich umzusetzen, genauso werde ich mich mit enum und case belesen.
Vielleicht komme ich damit wieder ein Stück weiter.

Danke nochmal, damit bin ich denke ich die nächsten Stunden gut beschäftigt. :slight_smile:

LG
Celleron

Was mir noch auffällt ist, dass deine while Schleifen wohl auch ein Problem darstellen könnten. Weil Semikolon am Ende und ohne Klammern.

Sind das nicht DO WHILE Schleifen?

https://www.arduino.cc/reference/en/language/structure/control-structure/dowhile/:
Syntax:

do {
// statement block
} while (condition);

Also richtig.
Was ich schon angemerkt habe ist die Kombination aus While und Do While die mich sehr stören und wo mal augeräumt gehört.

Grüße Uwe

uwefed:
wo mal augeräumt gehört.

Las mir Zeit :wink:

Using board 'nano' from platform in folder: [...]
Der Sketch verwendet 21250 Bytes (69%) des Programmspeicherplatzes. Das Maximum sind 30720 Bytes.
Globale Variablen verwenden 915 Bytes (44%) des dynamischen Speichers, 1133 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.