Code only working with Serial.println()

Hello everyone,

I'm currently working on a project, where I have to use many functions. The problem I face is that the program should remain in gameSetup() as long as there are two conditions false/true. As you can see in the code below, there is a "Serial.println("Hi")". There is also a function which receives I2C data (Wire.h library). However as soon as I remove the "Serial.println()" the code stops working. With stops working I mean it won't response to anything I'll do since that point. Like buttons pressing, RFIDs scanning, etc..

I already tried to replace "Serial.println()" with "delay(10)" or some other code without any results

btw: receiveEvent() will get called as soon as a I2C byte is received:

In setup():
Wire.onReceive(receiveEvent); <-- Wire.h library

Thanks in advance

Regards Conestone

void gameSetup()
{
  while(GameStatus == 0 || bullet[BULLETLENGTH-1] == 0) //Stay till Game started and bullet is 
  reveived
  {
    Serial.println("Hi");
    if(GameReset == 1)
    {
      GameReset = 0;

      resetArrays(); //Resetting Bullet
      //Here will be the Reset of all Variables
    }
  }
}
void receiveEvent()
{
  Auswertung();
}

void Auswertung()
{
  byte Auslesen = Wire.read();
  switch(Auslesen)
  {
    case 0:
    GameStatus = !GameStatus; //Game is not active
    break;
    
    case 1:
    GameStatus = 0; //Game is not active
    GameReset = 1; //Resetting Mags etc. (NewGame or Dead)
    break;
    
    case 2:
    GameStatus = 1; //Game has started (exiting gameSetup())
    break;

    case 3:
    receiveBullet(); //receiving new Bullet
    break;

  } 
}

Kudos + for using code tags on your first post.
Kudos - for not posting all your code.

sry, i just thought it would be easier with just the important code

Code: #include <Wire.h>#include <SPI.h>#include <MFRC522.h>#include <IRremote.h> - Pastebin.com

Regards Conestone

Conestone:
sry, i just thought it would be easier with just the important code

Sadly, it's the compiler that decides what is important, not you.

Adding/removing serial prints (or other code in general) causing undefined behaviour usually points to memory issues. Your use of String (capital S) might be part of the problem.

PS
Most people don't want to download from pastebin and prefer the file as an attachment here.

PPS
to others: the file is about 11 kB.

No sure. But I would seriously question your choice of variable names...

bool GameStatus = 0;
bool Gamestatus = 1;

Having two different variables which differ only by case is asinine.

Also "GameStatus" is not a great choice of name, especially for a boolean.
Status of what?
What does the TRUE state indicate? Running, paused, something else?

Suggest using descriptive names like "GameRunning" or "GameActive" for booleans.

GameStatus is not marked 'volatile' so the compiler may think it doesn't change inside the loop and will only fetch it once, before the loop. Change it to "volatile bool GameStatus;" so the compiler knows it can be changed at any time.

I'm guessing that when the compiler sees Serial.println() it decides not to optimize away the re-fetch of GameStatus for some reason.

Thanks for all your suggestions, unfortunatly, none of them worked.

Edit: forgot to quote... I'll clean it up

johnwasser:
GameStatus is not marked 'volatile' so the compiler may think it doesn't change inside the loop and will only fetch it once, before the loop. Change it to "volatile bool GameStatus;" so the compiler knows it can be changed at any time.

I'm guessing that when the compiler sees Serial.println() it decides not to optimize away the re-fetch of GameStatus for some reason.

I tried like you said and it didn't worked out, seems like it didn't change anything

pcbbc:
No sure. But I would seriously question your choice of variable names...

bool GameStatus = 0;

bool Gamestatus = 1;



Having two **different** variables which differ **only** by case is asinine.

Thank you for pointing out this mistake, it seems like it happened as I combined two codes I wanted to test seperate ( They are now the same variable)

sterretje:
Adding/removing serial prints (or other code in general) causing undefined behaviour usually points to memory issues. Your use of String (capital S) might be part of the problem.

PS
Most people don't want to download from pastebin and prefer the file as an attachment here.

I'm not 100% what you meant there, first of all shouldn't it be irrelevant when I REMOVE a code of line in terms of memory? In second I don't get what you mean by "my use of String"? what should i use instead?

And it just said it was too long, I didn't knew I can attach it, but I'll do it from there on

/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino: In function 'void setup()':
/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino:64:30: warning: invalid conversion from 'void (*)()' to 'void (*)(int)' [-fpermissive]
   Wire.onReceive(receiveEvent);
                              ^
In file included from /Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino:1:0:
/Users/john/Library/Arduino15/packages/arduino/hardware/avr/1.8.2/libraries/Wire/src/Wire.h:72:10: note:   initializing argument 1 of 'void TwoWire::onReceive(void (*)(int))'
     void onReceive( void (*)(int) );
          ^~~~~~~~~

Looks like your onReceive function is supposed to take an integer argument.

/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino: In function 'void shoot()':
/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino:272:40: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   if ((lastchangetime[0] + shootdelay) < millis() && lastchangetime[0] < (millis() + DEBOUNCETIME)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino:272:72: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   if ((lastchangetime[0] + shootdelay) < millis() && lastchangetime[0] < (millis() + DEBOUNCETIME)
                                                      ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino: In function 'void burstshotreset()':
/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino:316:42: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   if ((lastchangetime[1] + DEBOUNCETIME) < millis()) // Debounce for not resetting the Burstshots too fast
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~

/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino: In function 'void muzzleFlashOut()':
/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino:362:48: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   if ((lastchangetime[0] + FLASHLIGHTBURNTIME) < millis())
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~

Variables containing millis() values (like lastchangetime[]) should be 'unsigned long' and not just 'long'.

/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino: In function 'void bulletAcceleration()':
/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino:329:65: warning: invalid conversion from 'int*' to 'const unsigned int*' [-fpermissive]
   irsend.sendRaw(bullet, sizeof(bullet) / sizeof(bullet[0]), KHZ);
                                                                 ^
In file included from /Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino:4:0:
/Users/john/Documents/Arduino/libraries/IRremote/IRremote.h:279:9: note:   initializing argument 1 of 'void IRsend::sendRaw(const unsigned int*, unsigned int, unsigned int)'
   void  sendRaw       (const unsigned int buf[],  unsigned int len,  unsigned int hz) ;
         ^~~~~~~

Similarly, bullet[] should be 'unsigned int' and not just 'int'.

/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino: In function 'void readnewMag()':
/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino:424:52: warning: statement has no effect [-Wunused-value]
       MagazinArsenal[currentListRow][UIDANDMUNI - 1];
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^

Was that line supposed to do something? It isn't doing anything.

Conestone:
I'm not 100% what you meant there, first of all shouldn't it be irrelevant when I REMOVE a code of line in terms of memory?

It can make a difference, specially in case of bugs in your code.

Conestone:
In second I don't get what you mean by "my use of String"? what should i use instead?

So-called c-strings (null terminated character arrays). The problem with String is that it can cause memory fragmentation (when you use concatenations) and as a result undefined behaviour at runtime because you ran out of memory.

Conestone:
And it just said it was too long, I didn't knew I can attach it, but I'll do it from there on

No worries.

johnwasser:

/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino: In function 'void setup()':

/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino:64:30: warning: invalid conversion from 'void ()()' to 'void ()(int)' [-fpermissive]
  Wire.onReceive(receiveEvent);
                             ^
In file included from /Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino:1:0:
/Users/john/Library/Arduino15/packages/arduino/hardware/avr/1.8.2/libraries/Wire/src/Wire.h:72:10: note:   initializing argument 1 of 'void TwoWire::onReceive(void ()(int))'
    void onReceive( void (
)(int) );
         ^~~~~~~~~



Looks like your onReceive function is supposed to take an integer argument.

yes, I looked it up in the example sketch (code below), I now got it in but didn't change anything.

#include <Wire.h>

void setup() {
  Wire.begin(8);                // join i2c bus with address #8
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);           // start serial for output
}

void loop() {
  delay(100);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
  while (1 < Wire.available()) { // loop through all but the last
    char c = Wire.read(); // receive byte as a character
    Serial.print(c);         // print the character
  }
  int x = Wire.read();    // receive byte as an integer
  Serial.println(x);         // print the integer
}

johnwasser:

/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino: In function 'void shoot()':

/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino:272:40: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  if ((lastchangetime[0] + shootdelay) < millis() && lastchangetime[0] < (millis() + DEBOUNCETIME)
      ~~~~~~~~~~~~~~~~~^~
/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino:272:72: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  if ((lastchangetime[0] + shootdelay) < millis() && lastchangetime[0] < (millis() + DEBOUNCETIME)
                                                      ^

/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino: In function 'void burstshotreset()':
/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino:316:42: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  if ((lastchangetime[1] + DEBOUNCETIME) < millis()) // Debounce for not resetting the Burstshots too fast
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~

/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino: In function 'void muzzleFlashOut()':
/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino:362:48: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  if ((lastchangetime[0] + FLASHLIGHTBURNTIME) < millis())
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~



Variables containing millis() values (like lastchangetime[]) should be 'unsigned long' and not just 'long'.






/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino: In function 'void bulletAcceleration()':
/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino:329:65: warning: invalid conversion from 'int*' to 'const unsigned int*' [-fpermissive]
  irsend.sendRaw(bullet, sizeof(bullet) / sizeof(bullet[0]), KHZ);
                                                                ^
In file included from /Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino:4:0:
/Users/john/Documents/Arduino/libraries/IRremote/IRremote.h:279:9: note:  initializing argument 1 of 'void IRsend::sendRaw(const unsigned int*, unsigned int, unsigned int)'
  void  sendRaw      (const unsigned int buf[],  unsigned int len,  unsigned int hz) ;
        ^~~~~~~



Similarly, bullet[] should be 'unsigned int' and not just 'int'.

Thanks, I changed it, but bullet[] only has 3 different values anyways: 0, 300, 550.

johnwasser:

/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino: In function 'void readnewMag()':

/Users/john/Documents/Arduino/sketch_jun07a/sketch_jun07a.ino:424:52: warning: statement has no effect [-Wunused-value]
      MagazinArsenal[currentListRow][UIDANDMUNI - 1];
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^



Was that line supposed to do something? It isn't doing anything.

seems like I forgot to remove it

Btw. here is a much shorter version of it, same problem, same code, just before I put those two codes together.

(here: code stops working as soon as I remove the lines in the --------- space)

#include <Wire.h>

#define BULLETLENGTH 16

bool GameStatus = 0;
bool GameReset = 1;

int bullet[BULLETLENGTH];
long lastchangetime = 0;

void setup() 
{
 
  Serial.begin(9600);
  
  Wire.begin(1);
  Wire.onReceive(receiveEvent);

  //Write Bullet Array
  bullet[0] = 1200;
  bullet[1] = 900;

  resetBullet();
}

void loop() 
{
  if(GameStatus != 1)
  {
    gameSetup(); //Game has ended -> new Gamesettings receiving 
  }
  
  if((lastchangetime+1000) < millis())
  {
    lastchangetime = millis();
    Serial.println(GameStatus);
    //Code der Waffe
    Serial.println("LOOP");
  }
}

void gameSetup() //Wird immer aufgerufen, wenn ein neues Spiel gestartet wird
{
  while(GameStatus == 0 || bullet[BULLETLENGTH-1] == 0) //Stay till Game started and bullet is reveived
  {
-------------------------------------------------
   if((lastchangetime+1000) < millis())
    {
      lastchangetime = millis();
      Serial.println(GameStatus);
      //Code der Waffe
      Serial.println("GameSetup");
    }
-------------------------------------------------
    if(GameReset == 1)
    {
      GameReset = 0;

      resetBullet(); //Resetting Bullet
      //Here will be the Reset of all Variables
    }
  }
}

void receiveEvent(int howMany)
{
  Auswertung();
}

void receiveBullet()
{
  String BulletString = "";
  bool OneHit = true;
  
  while(Wire.available())
  {
    String tmp = String(Wire.read(), BIN);
    while(tmp.length() < 8)
    {
      tmp = "0" + tmp;
    }
    BulletString = BulletString + tmp;
  }

  if(BulletString.length() == 16)
  {
    BulletString = BulletString.substring(2, 16);
  }

  for(int idx = 2; idx < BULLETLENGTH; idx++)
  {
    if(BulletString.charAt(idx-2) == '1')
    {
      bullet[idx] = 550;
      if(idx <= 6) //if the first 6bit is 0, the Bullet is OneHit
      {
        OneHit = false;
      }
    }
    else
    {
      bullet[idx] = 300;
    }
  }

  //Check if OneHit is active
  if(OneHit == true)
  {
    //for to write 0s in the Damage Part of the Bullet
    for(int idx = 2; idx < (BULLETLENGTH-8); idx++)
    {
      bullet[idx] = 0;
    }
  }

  bulletAusgabe();
  
}

void Auswertung()
{
  byte Auslesen = Wire.read();
  switch(Auslesen)
  {
    case 0:
    GameStatus = !GameStatus; //Game is not active
    break;
    
    case 1:
    GameStatus = 0; //Game is not active
    GameReset = 1; //Resetting Mags etc. (NewGame or Dead)
    break;
    
    case 2:
    GameStatus = 1; //Game has started (exiting gameSetup())
    break;

    case 3:
    receiveBullet(); //receiving new Bullet
    break;

    case 10: //nothing -> Enter
    break;
  } 
}

void resetBullet()
{
  //resetting bullet Array
  for(int idx = 2; idx < BULLETLENGTH; idx++)
  {
    bullet[idx] = 0;
  }
}

void bulletAusgabe()
{
  Serial.print("Bullet: ");
  for(int idx = 0; idx < BULLETLENGTH; idx++)
  {
    Serial.print(bullet[idx]);
    Serial.print(" ");
  }
  Serial.println("");
}