Sketch häng sich auf / Fehlersuche

Hallo Zusammen,

ich habe einen kleinen Sketch zusammengeschrieben. Leider bleibt er nach ein paar Sekunden hängen und ich weis nicht wie ich bei der Fehlersuche vorgehen soll. Ich vermute das, dass OLED Display den Absturz verursacht aber das ist leider nur eine Vermutung.

Wie kann ich hier Systematisch nach einem Fehler suchen? Bin über jede Hilfe dankbar...

/* Encoder Library - TwoKnobs Example
 * http://www.pjrc.com/teensy/td_libs_Encoder.html
 *
 * This example code is in the public domain.
 */

#include <Encoder.h>

// Change these pin numbers to the pins connected to your encoder.
//   Best Performance: both pins have interrupt capability
//   Good Performance: only the first pin has interrupt capability
//   Low Performance:  neither pin has interrupt capability
Encoder knobLeft(2, 3);
Encoder knobRight(18, 19);
//   avoid using pins with LEDs attached



//DISPLAY
#include <Arduino.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif


U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);


//Konstanten
const int LED_Schuss=9;                  //Überwachung Eingangsignal vom UR
const int Knopf=22;                //Eingang Schusszähler
const int Reset=24;                //Reset Schusszähler 
const int Dauerlauf=26;                //Dauerlauf
const int LED_Schuss_OUT=10;            //Ausgang Schusszähler
const int FB=11;               //Förderband


//Variable
int counter;        //Zähler
int KnopfJETZT = 0;     //Knopf aktuell
int KnopfALT = 0;     //Knopf Zustand 


void setup() {
   pinMode(9, OUTPUT);
 pinMode(10, OUTPUT);

   pinMode(22, INPUT); //Eingang Schusszähler
 pinMode(24, INPUT); //Reset Schusszähler
 pinMode(26, INPUT); //Dauerlauf

  Serial.begin(9600);
  Serial.println("TwoKnobs Encoder Test:");
  u8g2.begin(); //DISPLAY
}

long positionLeft  = -999;
long positionRight = -999;

void loop() {
  float newLeft;
  int newRight;
  newLeft = knobLeft.read();
  newRight = knobRight.read();
  if (newLeft != positionLeft || newRight != positionRight) {
    Serial.print("Left = ");
    Serial.print(newLeft);
    Serial.print(", Right = ");
    Serial.print(newRight);
    Serial.println();
    positionLeft = newLeft;
    positionRight = newRight;
  }
  // if a character is sent from the serial monitor,
  // reset both back to zero.
  if (Serial.available()) {
    Serial.read();
    Serial.println("Reset both knobs to zero");
    knobLeft.write(0);
    knobRight.write(0);
  }


//Tacktung
 KnopfJETZT = digitalRead(Knopf);
  
  if (KnopfJETZT != KnopfALT) {
    if (KnopfJETZT == HIGH) {
      counter++;
      Serial.println(counter);
      digitalWrite(LED_Schuss, HIGH);
      digitalWrite(LED_Schuss_OUT, HIGH);
  
    } else {
      digitalWrite(LED_Schuss, LOW);
      digitalWrite(LED_Schuss_OUT, LOW);
     
    }
    delay(50);
  }
  KnopfALT = KnopfJETZT;
  if(counter == newRight){
  digitalWrite(FB, HIGH);

    Serial.println("Foerderband laeuft");

    delay(newLeft*100);   
    digitalWrite(FB, LOW);

    Serial.println("Foerderband stopp");

    counter = 0;
  }
if(digitalRead(24) == HIGH){
  counter=0;

}




  
    //DISPLAY
  u8g2.clearBuffer();          // clear the internal memory
  u8g2.setFont(u8g2_font_7x14B_mf); // choose a suitable font
  u8g2.drawStr(0,16,"Schuss");  // write something to the internal memory
  u8g2.setCursor(90,16);  // write something to the internal memory
  u8g2.print(counter); // write something to the internal memory
  u8g2.drawStr(0,38,"Taktung");  // write something to the internal memory
  u8g2.setCursor(90, 38);
  u8g2.print(newRight); // write something to the internal memory
  u8g2.drawStr(0,62,"Laufzeit sec");  // write something to the internal memory
  u8g2.setCursor(90, 62);
  u8g2.print(newLeft/10,1); // write something to the internal memory
  u8g2.sendBuffer();          // transfer internal memory to the display
  delay(1);  

}

Hi

Benutze im Sketch die Namen der Pins - z.B. LedSchuss ist der Pin 9 - warum benutzt Du dann '9' in setup()?

Ich blicke durch Deinen Sketch akut nicht durch - WAS soll Da wo passieren, was passiert statt Dessen?
Auch solltest Du auf delay() verzichten lernen (Stichwort: millis() ).

Selbst, wenn das Display abschmiert, interessiert Das den Arduino herzlich wenig - Der schiebt nur stur die Daten zum Display rüber, ohne Antwort zu erwarten (mir wäre zumindest nichts Anderes bekannt).
Spicke Deinen Sketch mit seriellen Ausgaben, vll. siehst Du so, wo Er falsch abbiegt.

MfG

Erste Frage: Auf welchem Board?

schrumpfkopf:
Wie kann ich hier Systematisch nach einem Fehler suchen? Bin über jede Hilfe dankbar...

long positionLeft  = -999;

long positionRight = -999;

void loop() {
float newLeft;
 int newRight;
 newLeft = knobLeft.read();
 newRight = knobRight.read();
 if (newLeft != positionLeft || newRight != positionRight) {
   Serial.print("Left = ");
   Serial.print(newLeft);
   Serial.print(", Right = ");
   Serial.print(newRight);
   Serial.println();
   positionLeft = newLeft;
   positionRight = newRight;

Du könntest Dich als erstes entscheiden, welchen Variablentyp Du nimmst.
Mischmasch aus float, int, long... wobei float da wohl fehl am Platze ist...

Wenn Du den Seriallen Monitor dran hast, bei welcher Ausgabe bleibt der Sketch hängen? Immer an der selben Stelle?

Und warum machst du zu deinem Problem einen 2. Thread auf ?
Schneller geht es dadurch auch nicht.

Danke für die ersten Denkanstöße...

Habe versucht den Sketch etwas übersichtlicher zu gestallten. Mit milis werde ich mich noch beschäftigen. Es hängt sich nicht das OLED auf sondern der Arduino. hier bekomme ich keine Anzeige mehr weder auf den Board LED oder im seriellen Monitor.

Ich arbeite mit einem Arduino Mega 2560

Ich habe die FLOAT gewählt um den Wert später im OLED als Kommazal darzustellen z.B.: 12,5 anders hab ich das nicht hinbekommen. Nach einigen Test hab ich festgestellt das sich das Board wohl beim verarbeiten den Encodersignale aufhängt. Den Grund konnte ich aber leider noch nicht feststellen.

Die Funktion:

Es soll eine Eingangssignal gezählt werden.
Sobald ein Wert (über 1.Encoder einstellbar) erreicht ist soll ein Ausgang für eine Zeit (über 2. Encoder einstellbar in 11,1sec) auf high geschaltet werden. Ansonsten noch ein Reset für den Zähler.

neues Problem neuer Thread?

Mein leicht überarbeiteter Sketch sieht nun so aus:

#include <Encoder.h>  
#include <Arduino.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

Encoder Taktung(2, 3);//Vorwahl Taktung
Encoder Laufzeit(18, 19); //Vorwahl Laufzeit

//Konstanten
const int LED_Schuss=9;            //Überwachung Eingangsignal vom UR
const int Knopf=22;                //Eingang Schusszähler
const int Reset=24;                //Reset Schusszähler 
const int Dauerlauf=26;            //Dauerlauf
const int LED_Schuss_OUT=10;       //Ausgang Schusszähler
const int FB=11;                   //Förderband

//Variable
int counter;          //Zähler
int KnopfJETZT = 0;   //Knopf aktuell
int KnopfALT = 0;     //Knopf Zustand 


void setup() {
 pinMode(LED_Schuss, OUTPUT);     
 pinMode(LED_Schuss_OUT, OUTPUT);
 pinMode(Knopf, INPUT);           //Eingang Schusszähler
 pinMode(Reset, INPUT);           //Reset Schusszähler
 pinMode(Dauerlauf, INPUT);       //Dauerlauf

  Serial.begin(9600);
  Serial.println("TwoKnobs Encoder Test:");
  u8g2.begin(); //DISPLAY
}

int positionLeft  = -999;
int positionRight = -999;



void loop() {
  float newLeft;    //Lauzeit in Darstellung in OLED xx,x sec
  int newRight;     //Taktung
  newLeft = Taktung.read();
  newRight = Laufzeit.read();
  if (newLeft != positionLeft || newRight != positionRight) {
    Serial.print("Left = ");
    Serial.print(newLeft);
    Serial.print(", Right = ");
    Serial.print(newRight);
    Serial.println();
    positionLeft = newLeft;
    positionRight = newRight;
  }

  if (Serial.available()) {
    Serial.read();
    Serial.println("Reset both knobs to zero");
    Taktung.write(0);
    Laufzeit.write(0);
  }




//Tacktung Zähler pro Signal um 1 erhöhen, beim erreichen von newRight FB=High für Zeit newLeft
 KnopfJETZT = digitalRead(Knopf);
  
  if (KnopfJETZT != KnopfALT) {
    if (KnopfJETZT == HIGH) {
      counter++;
      Serial.println(counter);
      digitalWrite(LED_Schuss, HIGH);
      digitalWrite(LED_Schuss_OUT, HIGH);
  
    } else {
      digitalWrite(LED_Schuss, LOW);
      digitalWrite(LED_Schuss_OUT, LOW);
     
    }
    delay(50);
  }
  KnopfALT = KnopfJETZT;
  if(counter == newRight){
  digitalWrite(FB, HIGH);

    Serial.println("Foerderband laeuft");
    delay(newLeft*100);   
    digitalWrite(FB, LOW);
    Serial.println("Foerderband stopp");
    counter = 0;
  }
if(digitalRead(24) == HIGH){
  counter=0;

}


  
    //DISPLAY
  u8g2.clearBuffer();          // clear the internal memory
  u8g2.setFont(u8g2_font_7x14B_mf); // choose a suitable font
  u8g2.drawStr(0,16,"Schuss");  // write something to the internal memory
  u8g2.setCursor(90,16);  // write something to the internal memory
  u8g2.print(counter); // write something to the internal memory
  u8g2.drawStr(0,38,"Taktung");  // write something to the internal memory
  u8g2.setCursor(90, 38);
  u8g2.print(newRight); // write something to the internal memory
  u8g2.drawStr(0,62,"Laufzeit sec");  // write something to the internal memory
  u8g2.setCursor(90, 62);
  u8g2.print(newLeft/10,1); // write something to the internal memory
  u8g2.sendBuffer();          // transfer internal memory to the display
  delay(1);  

}

Wenn es tatsächlich ein anderes Problem ist ( ich sehe das nicht ), dann solltest du wenigstens auf die Antworten im anderen Sketch reagieren. Das ist so üblich und dann kann jeder sehen, das dir geholfen wurde. Auch ist es üblich die Lösung zu präsentieren. Das hilft auch anderen Mitlesern.
Das ist der Sinn des Forums.

Bisher bin ich mit dem Fehler das sich das Board aufhängt leider nicht weiter gekommen. Ich habe nun aus dem TwoKnobs Sketch begonnen denn Sketch neu aufzubauen. Somit konnte ich den Fehler auf das Display eingrenzen. Sobald das ins Spiel kommt stürzt der Arduino Mega nach einigen Sekunden ab. Hab schon die verschiedensten Dinge versucht komm aber auf keine Lösung.

Wo liegt hier der Fehler ? Hat mir jemand einen Tip?

Das Display ist dieses hier

//DISPLAY
#include <Arduino.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

//ENCODER
#include <Encoder.h>
Encoder Laufzeit(2, 3);
Encoder Taktung(18, 19);

void setup() {
  Serial.begin(9600);
  Serial.println("TwoKnobs Encoder Test:");
  u8g2.begin(); //DISPLAY
}

long positionLaufzeit  = -999;
long positionTaktung = -999;

void loop() {
  long newLaufzeit, newTaktung;
  newLaufzeit = Laufzeit.read();
  newTaktung = Taktung.read();
  if (newLaufzeit != positionLaufzeit || newTaktung != positionTaktung) {
    Serial.print("Laufzeit = ");
    Serial.print(newLaufzeit);
    Serial.print(", Taktung = ");
    Serial.print(newTaktung);
    Serial.println();
    positionLaufzeit = newLaufzeit;
    positionTaktung = newTaktung;

  
  }
  

//DISPLAY
  u8g2.clearBuffer();          // clear the internal memory
  u8g2.setFont(u8g2_font_chroma48medium8_8r); // choose a suitable font
  u8g2.drawStr(0, 16, "Schuss = "); // write something to the internal memory
  u8g2.setCursor(85, 16);
  u8g2.print("counter"); // write something to the internal memory
  u8g2.drawStr(0, 38, "Taktung = "); // write something to the internal memory
  u8g2.setCursor(85, 38);
  u8g2.print(newTaktung); // write something to the internal memory
  u8g2.drawStr(0, 62, "Laufzeit = "); // write something to the internal memory
  u8g2.setCursor(85, 62);
  u8g2.print(newLaufzeit); // write something to the internal memory
  u8g2.sendBuffer();          // transfer internal memory to the display      
  
}

Viele Grüße und schönen Abend.

schrumpfkopf:
Hat mir jemand einen Tip?

Das Display ist dieses hier

1,3 Zoll OLED Display I2C SSH1106 Chip 128 x 64 Pixel I2C Anzeigemodul

U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

Ich komm mit Deinem INIT nicht klar.

Das sieht bei Oli anders aus:

Was genau gefällt dir daran nicht? Habe die Init aus dem Demo Sketch:

Meiner
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);

von Github:

U8G2_SH1106_128X64_NONAME_F_HW_I2C(rotation, [reset [, clock, data]])
[full framebuffer, size = 1024 bytes]

Habe hier verschiedene Einstellungen versucht konnte aber den Absturz nicht verhindern. Sobald ich den Sketchteil der das Display beschreibt ausklammere funktioniert es mit der Anzeige im Seriellen Monitor problemlos...

schrumpfkopf:
Was genau gefällt dir daran nicht? Habe die Init aus dem Demo Sketch:

Meiner
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);

von Github:
U8G2_SH1106_128X64_NONAME_F_HW_I2C(rotation, [reset [, clock, data]])
[full framebuffer, size = 1024 bytes]

Moin,

mein Fehler.

Ich schoß mich darauf ein:
In the reference section below, optional pins are enclosed in "[" and "]". The "[" and "]" never appear in the constructor. Example: The "reset" pin number can be skipped if the display has its own reset circuit.

Das gilt aber offensichtlich nicht immer bei I2C.

Denn es heisst:
The hardware I2C allows pin remapping for some controller types. The optional pin numbers are listed after the reset pin: ..._HW_I2C([reset [, clock, data]]). Use U8X8_PIN_NONE if the reset input of the display is not connected.

Ich halte das bei Dir für nicht notwendig, da Du kein Pin-Mapping machst.

Neuer Versuch:
Was passiert, wenn Du den I2C-Anschluß wechselst. Der Mega R3 hat einmal Pin 20/21 und einmal oberhalb von ARef. Eigentlich sollten die beiden gleich sein. Aber manchmal ist komisch.

Und dann mach doch mal im Displayteil jede Zeile ne Ausgabe:

u8g2.clearBuffer();          // clear the internal memory
  Serial.println("u8g2 Start");
  u8g2.setFont(u8g2_font_chroma48medium8_8r); // choose a suitable font
  Serial.println("Schrift gewählt");
  u8g2.drawStr(0, 16, "Schuss = "); // write something to the internal memory
  Serial.println("Draw 1");
  u8g2.setCursor(85, 16);
  u8g2.print("counter"); // write something to the internal memory
  Serial.println("SetCursor 1");
  u8g2.drawStr(0, 38, "Taktung = "); // write something to the internal memory
  Serial.println("Draw 2");
  u8g2.setCursor(85, 38);
  u8g2.print(newTaktung); // write something to the internal memory
  Serial.println("SetCursor 2");
  u8g2.drawStr(0, 62, "Laufzeit = "); // write something to the internal memory
  Serial.println("Draw 3");
  u8g2.setCursor(85, 62);
  u8g2.print(newLaufzeit); // write something to the internal memory
  Serial.println("SetCursor 3");
  u8g2.sendBuffer();          // transfer internal memory to the display     
  Serial.println("u8g2 durchlaufen");

und schau wo und ob er immer an der selben Stelle hängen bleibt.

Habe mal die SCL & SCA getauscht von 20&21 auf die SCL & SCA über AREF getauscht aber keine Besserung.

Danke für den Display Sketch. Hab Ihn genau so eingesetzt. Jedoch auch hier keine Änderung aber ich kann sehen das das Display immer beim send.Buffer()hängen bleibt. Letzte Zeile nach Absturz im seriellen Monitor ist immer SetCursor 3.

schrumpfkopf:
Letzte Zeile nach Absturz im seriellen Monitor ist immer SetCursor 3.

Was ist denn der Wert von newTaktung und NewLaufzeit, wenn das System hängen bleibt?

Dann würde ich das weiter einkreisen.
Bei der Initialisierung des mit dem U8X8_PIN_NONE raus.

Möglicher Ansatz:
Die Encoder.h deaktivieren und die auszugebenden Variablen newTaktung und newLaufzeit fest vorgeben und sehen, obs durchläuft.

// newLaufzeit = Laufzeit.read();
// newTaktung = Taktung.read();
newLaufzeit = 1000;
newTaktung = 5000;

Habe das bei der Display Initialisierung gelöscht und die beiden Variablen fest vergeben. Nach 1- 5 Sekunden hängt sich das Board trotzdem nach wie vor auf. Denke damit können wir den Encoder.h als Fehlerquelle ausschließen.

/*Förderbandtaktung
Eingänge von zwei Encodern, Taktung und Laufzeit
Eingang Schusszähler
Eingang Reset Schusszähler 
Ausgang Frderband ein
Ausgang Schuss weitergabe
Darstellung in OLED

*/

//DISPLAY
#include <Arduino.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0);


//ENCODER
//#include <Encoder.h>
//Encoder Laufzeit(2, 3);
//Encoder Taktung(18, 19);

void setup() {
  Serial.begin(9600);
  Serial.println("TwoKnobs Encoder Test:");
  u8g2.begin(); //DISPLAY
}

long positionLaufzeit  = -999;
long positionTaktung = -999;

void loop() {
  long newLaufzeit, newTaktung;
  // newLaufzeit = Laufzeit.read();
  // newTaktung = Taktung.read();
  newLaufzeit = 1000;
  newTaktung = 5000;
  if (newLaufzeit != positionLaufzeit || newTaktung != positionTaktung) {
    Serial.print("Laufzeit = ");
    Serial.print(newLaufzeit);
    Serial.print(", Taktung = ");
    Serial.print(newTaktung);
    Serial.println();
    positionLaufzeit = newLaufzeit;
    positionTaktung = newTaktung;

  
  }
  

//DISPLAY
u8g2.clearBuffer();          // clear the internal memory
  Serial.println("u8g2 Start");
  u8g2.setFont(u8g2_font_chroma48medium8_8r); // choose a suitable font
  Serial.println("Schrift gewählt");
  u8g2.drawStr(0, 16, "Schuss = "); // write something to the internal memory
  Serial.println("Draw 1");
  u8g2.setCursor(85, 16);
  u8g2.print("counter"); // write something to the internal memory
  Serial.println("SetCursor 1");
  u8g2.drawStr(0, 38, "Taktung = "); // write something to the internal memory
  Serial.println("Draw 2");
  u8g2.setCursor(85, 38);
  u8g2.print(newTaktung); // write something to the internal memory
  Serial.println("SetCursor 2");
  u8g2.drawStr(0, 62, "Laufzeit = "); // write something to the internal memory
  Serial.println("Draw 3");
  u8g2.setCursor(85, 62);
  u8g2.print(newLaufzeit); // write something to the internal memory
  Serial.println("SetCursor 3"); //hier hängts
  u8g2.sendBuffer();          // transfer internal memory to the display    
  Serial.println("u8g2 durchlaufen");

 

/*
  u8g2.clearBuffer();          // clear the internal memory
  u8g2.setFont(u8g2_font_chroma48medium8_8r); // choose a suitable font
  u8g2.drawStr(0, 16, "Schuss = "); // write something to the internal memory
  u8g2.setCursor(85, 16);
  u8g2.print("counter"); // write something to the internal memory
  u8g2.setCursor(0, 38);
  u8g2.print("Taktung = "); // write something to the internal memory
  u8g2.setCursor(85, 38);
  u8g2.print(newTaktung); // write something to the internal memory
  u8g2.setCursor(0, 62);
  u8g2.print("Laufzeit = "); // write something to the internal memory
  u8g2.setCursor(85, 62);
  u8g2.print(newLaufzeit); // write something to the internal memory
 u8g2.sendBuffer();          // transfer internal memory to the display      

 */

}

schrumpfkopf:
Habe das bei der Display Initialisierung gelöscht und die beiden Variablen fest vergeben. Nach 1- 5 Sekunden hängt sich das Board trotzdem nach wie vor auf. Denke damit können wir den Encoder.h als Fehlerquelle ausschließen.

Richtig - Danke für den schnellen Test und die Antwort.
Dann weiter in der Fehlersuche.

Hast Du in den Voreinstellungen alle Warnungen aktiviert?
DATEI-VOREINSTELLUNGEN Haken bei Ausführliche Ausgabe während Kompilierung
Ist die Ausgabe Fehlerfrei?

Dann ändere mal Deinen long in int.

// long newLaufzeit, newTaktung;
int newLaufzeit, newTaktung;

Neu testen.

Wenn der auch nicht geht, dann musst Du von vorn anfangen:
Was passiert, wenn Du ein Beispiel aus der lib nimmst? Geht?

Ja. Dann zurück zu Deinem Sketch:
Was passiert, wenn Du einen anderen Zeichensatz nimmst?
Was passiert, wenn Du von F auf 1 umstellst? setup_tutorial · olikraus/u8g2 Wiki · GitHub

Nein. Dann in der Hardware suchen.
Möglicherweise Pullups, schei** Verbindungen

Es kann sehr lange dauern, bis Du raus hast, was da nicht funktioniert.

Das Datenblatt von az gibt nichts - aber auch gar nichts her.https://cdn.shopify.com/s/files/1/1509/1638/files/1_3_inch_OLED_Datenblatt_4bcd023d-b1d6-4297-a022-71c523c952fd.pdf

Wenn Du gar nicht mehr weiter kommst, dann mal Fotos machen, vielleicht erkennt man was, woher das Teil kommt.