Ich finde einfach den Fehler nicht in meinem Sketch

Wo ist mein Gedankenfehler?

Ich will über die Arduino-IDE einen Nachbau eines Arduino Nano programmieren. Grundsätzlich habe ich alles korrekt angeschlossen und eingerichtet, denn der Beispiel-Sketch "Blink" lässt sich korrekt übersetzen und wird auch fehlerfrei auf den Nano übertragen - zu sehen an der gelb blinkenden LED.

Es geht um diesen Sketch:

int  shiftPin=6;          // verbunden mit SH-CP am Shift-Register (11)
int  storePin=7;          // verbunden mit ST-CP am Shift-Register (12)
int  dataPin=8;           // verbunden mit DS am Shift-Register (14)

int  AktuellAn;           // Anzahl aktuell leuchtende LEDs
int  AnzShifts=2;         // Anzahl angeschlossene Shift-Register
int  AnzLEDs=AnzShifts*8; // Anzahl ansteuerbarer LEDs
int  MaxLEDs=AnzShifts*5; // Maximale Anzahl leuchtender LEDs
int  Tab[8];              // Status-Tabelle der LEDs; 0=aus, 1=an
int  Zufall;              // Wert der zufaellig ausgewaehlten LED

void setup() {
  
  Serial.begin(9600);
  Serial.println("Setup");

  pinMode(storePin, OUTPUT);
  pinMode(shiftPin, OUTPUT);
  pinMode(dataPin, OUTPUT);

  randomSeed(analogRead(1)); 

  for (int i=0; i<AnzLEDs; i++) {
    Tab[i]=0;
    }
  AktuellAn=0;
  }

void loop() {

  delay(2000);
  Serial.println("Loop");

  Zufall=random(AnzLEDs);

  if (Tab[Zufall] == 0) {
    if (AktuellAn < MaxLEDs) {
      Tab[Zufall]=1;
      AktuellAn++;
      }
  else  {
    Tab[Zufall]=0;
    AktuellAn--;
      }
    }

  }

Wenn ich diesen Sketch übersetze und an den Nano schicke, sehe ich im seriellen Monitor alle 2 Sekunden eine neue Zeile mit dem Inhalt "Setup" - was schon seltsam genug ist, weil ja die Routine 'setup' nur 1x pro Start des Nanos ausgeführt werden sollte. Zur Routine 'loop' scheint der Nano nie zu kommen.

Aber: Wenn ich jetzt die Zeile "Serial.println("Loop");" (zweites Commando im Loop) vor die letzte schließende, geschweifte Klammer im Loop setze, kommt eine einzige wirre Ausgabe im seriellen Monitor und das war es dann. Weitere Ausgaben gibt es keine.

Und dieses Verhalten verstehe ich irgendwie nicht. Kann mir da jemand auf die Sprünge helfen? Was an meinem Code ist offensichtlich falsch?

Thanks ....

Da würde ich mal ansetzen und mir die Schleife ansehen.
AnzLEDs = 16
Tab[8]

2 Likes

Wie @Klaus_ww schon schreibt. Wenn Du ein Array für 16 LEDs brauchst, dann musst du es auch entsprechend groß initialisieren.

z.B.

constexpr byte shiftPin {6};        // verbunden mit SH-CP am Shift-Register (11)
constexpr byte storePin {7};        // verbunden mit ST-CP am Shift-Register (12)
constexpr byte dataPin {8};         // verbunden mit DS am Shift-Register (14)

constexpr int AnzShifts {2};       // Anzahl angeschlossene Shift-Register
constexpr int AnzLEDs {AnzShifts * 8}; // Anzahl ansteuerbarer LEDs
constexpr int MaxLEDs {AnzShifts * 5}; // Maximale Anzahl leuchtender LEDs
int  AktuellAn;           // Anzahl aktuell leuchtende LEDs
int Tab[AnzLEDs];         // Status-Tabelle der LEDs; 0=aus, 1=an
int  Zufall;              // Wert der zufaellig ausgewaehlten LED

Das ist das Zeichen dafür, das der immer wieder neu startet.

Der Code wirft erstmal keine Warnung oder Fehlermeldung aus.
Was mir aber auffällt:

Interessant wurde es erst, als ich das mal an meine Schreibweise angepasst habe. Da kam dann zum Vorschein:

/home/user1/arduino-1.8.19/hardware/arduino/avr/cores/arduino/main.cpp: In function 'main':
/tmp/arduino_modified_sketch_5090/sketch_aug12b.ino:22:12: warning: iteration 8 invokes undefined behavior [-Waggressive-loop-optimizations]
     Tab[i] = 0

Und ja.

Uops.

@Kai-R kannste mal den originalen Sketch kompilieren?

Das Compilieren geht (auf wokwi, ohne Fehlerausgabe), aber es gibt halt einen Speicherüberlauf....

Jupp.
Und jetzt das Ganze mit dem:

constexpr byte shiftPin {6};        // verbunden mit SH-CP am Shift-Register (11)
constexpr byte storePin {7};        // verbunden mit ST-CP am Shift-Register (12)
constexpr byte dataPin {8};         // verbunden mit DS am Shift-Register (14)

byte  AktuellAn;           // Anzahl aktuell leuchtende LEDs
constexpr byte AnzShifts {2};       // Anzahl angeschlossene Shift-Register
constexpr byte AnzLEDs {AnzShifts * 8}; // Anzahl ansteuerbarer LEDs
constexpr byte  MaxLEDs {AnzShifts * 5}; // Maximale Anzahl leuchtender LEDs
bool  Tab[8];              // Status-Tabelle der LEDs; 0=aus, 1=an
byte  Zufall;              // Wert der zufaellig ausgewaehlten LED

void setup()
{
  Serial.begin(9600);
  Serial.println("Setup");
  pinMode(storePin, OUTPUT);
  pinMode(shiftPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  randomSeed(analogRead(1));
  for (byte i = 0; i < AnzLEDs; i++)
  {
    Tab[i] = 0;
  }
  AktuellAn = 0;
}

void loop()
{
  delay(2000);
  Serial.println("Loop");
  Zufall = random(AnzLEDs);
  if (Tab[Zufall] == 0)
  {
    if (AktuellAn < MaxLEDs)
    {
      Tab[Zufall] = 1;
      AktuellAn++;
    }
    else
    {
      Tab[Zufall] = 0;
      AktuellAn--;
    }
  }
}

Und ? :slight_smile:

So läuft zumindest die Ausgabe

Setup
Loop
Loop
[...]

Ich würde aber sagen .. zufällig... weil bool Tab[8] ist immer noch zu klein. Wobei bool eine bessere Wahl als int ist, würde ich sagen :wink:

Es gibt beim kompilieren keine Warnung?
Das wundert mich aber.
Denn in der Standalone-IDE geht der Originalsketch auch ganz normal durch, aber dann heisst es (nach meiner Modifikation):


/tmp/arduino_modified_sketch_134207/sketch_aug12b.ino: In function 'setup':
/tmp/arduino_modified_sketch_134207/sketch_aug12b.ino:22:12: warning: iteration 8 invokes undefined behavior [-Waggressive-loop-optimizations]
     Tab[i] = 0;
     ~~~~~~~^~~
/tmp/arduino_modified_sketch_134207/sketch_aug12b.ino:20:22: note: within this loop
   for (byte i = 0; i < AnzLEDs; i++)
                    ~~^~~~~~~~~
[...]

/tmp/arduino_modified_sketch_134207/sketch_aug12b.ino:22:12: warning: iteration 8 invokes undefined behavior [-Waggressive-loop-optimizations]
     Tab[i] = 0;
/home/user1/arduino-1.8.19/portable/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-objcopy -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 /tmp/arduino_build_453200/sketch_aug12b.ino.elf /tmp/arduino_build_453200/sketch_aug12b.ino.eep
            ^
/tmp/arduino_modified_sketch_134207/sketch_aug12b.ino:20:22: note: within this loop
   for (byte i = 0; i < AnzLEDs; i++)
                      ^

Wokwi zeigt da nix, compiliere ich es in platformIO, dann kommt die Warnung.

1 Like

Zwei Dinge die daraus gelernt:
constexpr wenns angebracht ist, dann kommt der Compiler schon und meckert.
wokwi trau ich genau keinen Millimeter (weiterhin)
:wink:
Danke fürs probieren.

Danke für die absolut hilfreichen Antworten - jetzt ärgere ich mich selber, weil DARAUF hätte ich eigentlich auch selber kommen sollen.

Aber dafür hab ich wieder was gelernt, denn dass ich mit constexpr die Größe der Tabelle bestimmen kann, hab ich bislang noch nicht herausgefunden. Genau daraus resultierte das Problem, weil zuerst wollte ich die Größe abhängig vom Ergebnis aus der Anzahl angeschlossener Shift-Register und der Anzahl der Ports pro Shift-Register machen. Und dann hab ich die Anzahl in der Tabelle vergessen anzupassen.

Es ist tatsächlich so, dass der Sketch beim Compilieren keinen Fehler bringt. Und wenn der Sketch mal am Arduino läuft, sehe ich ja auch keinen Fehler. Zumindest läuft der Sketch jetzt wie geplant. Somit kann ich den Sketch gleich mal weiter entwickeln und dann gucken, ob meine Schaltung am Steckbrett funktioniert.

Danke nochmals!

Nein, kannst Du auch nicht :slight_smile:
Du kannst aber dem Compiler mitteiler, das er da schon mal etwas genauer hinschaut.
Und durch die constante fällt Dir dann auch in der Schleife das Konstrukt auf die Füsse.
Weil dem compiler klar ist, das es nicht passt....

Ich glaube eher, dass er meint, dass folgendes Konstrukt nicht funktioniert:

int AnzLEDs {AnzShifts * 8}; // Anzahl ansteuerbarer LEDs
bool Tab[AnzLEDs];         // Status-Tabelle der LEDs; 0=aus, 1=an

Da meckert sogar wokwi :wink: .

Mit einer Konstanten geht es aber ....

Ja klar. Die Vorgabe für die Anzahl der Elemente muss ja const sein. :wink:

Ja, mir ist das inzwischen klar... dem TO aber bis dato wohl noch nicht ... :slightly_smiling_face:

Wieso sollte man das nicht können?

constexpr byte AnzShifts {3};
constexpr byte AnzLEDs {AnzShifts * 8};
bool tab[AnzLEDs];

void setup() {
  for (byte i=0;i<AnzLEDs;i++) tab[i] = 0;
}

void loop() {}

Gruß Tommy

Ich hatte das doch oben schon gezeigt.
Es gilt nur den Irrtum zu vermeiden, das constexpr die Größe bestimmt.

Wieso? Das macht es doch nach der vorgegebenen Berechnungsvorschrift.

Gruß Tommy

:smile:
Danke @Kai-R - Du hast den Nagel auf den Kopf getroffen. Ich weiß, ich tu mir schwer damit, die richtigen Begrifflichkeiten zu finden, deswegen bin ich froh, dass es doch noch Menschen gibt, die mich verstehen ... :+1:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.