Function somehow impacting un-referenced variables

Hi, I'm building an augmented reality game where uses earn points by tagging an RFID reader. A strip of WS8212 LEDs serves as an information display (depicting whose turn, current score, etc.).
I'm experiencing a bug that I've narrowed down to one LED lighting function that if I comment out, disappears. Essentially, the bug is this:

All player points are kept in an int array playerScores[11]. But when I call waitingPlayerLed() on line 136 so the LEDs show the color of the player whose turn it is, somehow the value in playerScores[1] unexpectedly jumps to 255. It should remain as-is unless called by addPlayerPoint(playerTurn) on line 146.

The thing is, there's no functionality inside waitingPlayerLed() that references playerScores[]. All I can think of is something in the fastLED library that may be point to a memory location? ideas? Thanks in advance!

//1.2


//▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
//Definitions

//PN532 code ; If using the PN532 with I2C, define the pins connected to the IRQ and reset lines as well.
//You MUST ALSO CONNECT SDA & SCL with i2c Mode! (Nano pins A4/A5) -Josh
#define PN532_IRQ   (2)
#define PN532_RESET (3)


//fastLED definitions

#define LED_PIN     7
#define COLOR_ORDER GRB  // interesting...
#define CHIPSET     WS2812
#define NUM_LEDS    40
#define BASE_LED    8   // the first LEDs on the bottom to be used 
#define BRIGHTNESS  50 // up to 255
#define FRAMES_PER_SECOND 60

//▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
//LIBRARIES

//PN532
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_PN532.h>
// use this line for a breakout or shield with an I2C connection:
Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET); //

//fastLED
#include <FastLED.h> //See fastLED example file fire2012 for original code comments and explanation
CRGB leds[NUM_LEDS];


//▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
//Global Variables


//Game settings
long roundLength = 5000; //in milliseconds
byte numOfRounds = 4;
long rndExpireTime = 30000; // when set by pendingPlayer(), sets the millis time that ends the round
byte numOfPlayers = 2;

//Rfid  info
byte uid[] = { 0, 0, 0, 0, 0, 0, 0 };  // Buffer to store the returned Uid from Library
byte uidLength;                        // Length of the Uid (4 or 7 ints depending on ISO14443A card type)
byte playerColors [11][3] = {{0, 0, 0}, {255, 0, 0}, {0, 0, 255}}; //player x RGB/HSV value
byte playerIDs [11][4]; // first dimension (11) is the number of possible players; 2nd is for the 4 blocks of RFID #
// note that for a 10 player game, I've reserved 11 spaces; this is because int playerTurn
//points to the player number in the array so instead of [0][], player one's uid is at playerIDs [1]
byte p1ID[] = {60, 166, 231, 11}; //red tag I think
byte p2ID[] = {76, 132, 231, 11}; // hard coded for now
bool success = 0;


//Misc bg processes etc.
byte currentRound = 1;
bool gameOver = 0;
bool gameIsLive = 0;
int playerScores[11]; // playerScores[0] = coop group score; playerScores[1]=p1 score; can make this multi-dimensional for roundscores
//round victor calculated by comparing p
byte playerTurn = 1;
int tagDebounce = 200; //used as milliseconds between tagReads before it's recognized
unsigned long lastTagTime = 0;
byte timerPos = 0;
byte hsTimerLum = 0; // 40 or whatever. an independent array on which to do math for the timer
byte pNumJustTagged;
long currentMillis;


//▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
//SETUP
//▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
void setup(void) {
  Serial.begin(115200);


  //For PN532
  nfc.begin();
  nfc.setPassiveActivationRetries(2); //keeps code from searching for card indefinitely
  uint32_t versiondata = nfc.getFirmwareVersion();
  if (! versiondata) {
    Serial.print("Didn't find PN53x board");
    while (1); // halt
  }
  // Got ok data, print it out!
  Serial.print("Found chip PN5"); Serial.println((versiondata >> 24) & 0xFF, HEX);  Serial.print("Firmware ver. "); Serial.print((versiondata >> 16) & 0xFF, DEC);  Serial.print('.'); Serial.println((versiondata >> 8) & 0xFF, DEC);
  nfc.SAMConfig();
  Serial.println("Waiting for an ISO14443A Card ...");
  //End PN532 setup code: see pn532 example sketch included with library

  //fastLED
  FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  FastLED.setBrightness( BRIGHTNESS );

  //My Code
  assignPlayer(1, p1ID); //make sure to adjust the TotalPlayers variable
  assignPlayer(2, p2ID);


  //startAnimation();
}//end setup

//▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
//    Loop
//▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
void loop() {
  delay(1000);

  //clear tag variables
  memset(uid, 0, sizeof(uid)); // clears uid[]
  success = 0;
  pNumJustTagged = 0; //This variable holds the player number that just tagged the reader; only calculated once/loop and cleared at the begnning

  //processes
  currentMillis = millis();
  getUid(); // triggers success = 1, populates uid

  //Tag events
  if (success && currentMillis - lastTagTime > tagDebounce) { //what player # just tagged?
    pNumJustTagged = whoTagged();
    lastTagTime = currentMillis;
  }
  printInfo();

  //waiting for player to begin
  if (!gameIsLive && !gameOver) { //if it's not live or over, it must be waiting for the first player
    if (currentRound <= numOfRounds) {
      //Serial.println("currentRound <= numOfRounds");
      //don't need to check the timer
      waitingPlayer(playerTurn);
      waitingPlayerLed(); //this works but for some reason makes p1 score 255 after first round

    } else {
      gameOver = 1;
    }
  }
  // LIVE gameplay
  if (gameIsLive) {
    timerCheck();
    if (playerTurn == pNumJustTagged) {
      addPlayerPoint(playerTurn);
      //addPointAnimate();
    }
    //showPlayerScores();
    //CountDownLed();
  }

  if (gameOver) {
    //victor animation
    //LCD scores
  }


  // LED display to reflect playerTurn, time left, & all player scores
  //HS stands for High Score Game


  FastLED.show(); // display this frame
  FastLED.delay(1000 / FRAMES_PER_SECOND);
  //Serial.println("//end main loop");


} //end main loop

...continued

//▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
//    FUNCTIONS
//▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒


void waitingPlayerLed() {
  //Serial.println("waitingPlayer()");
  for (int b = 8; b <= 40; b++) {
    leds[b].r = playerColors[playerTurn][0];
    leds[b].g = playerColors[playerTurn][1];
    leds[b].b = playerColors[playerTurn][2];
    FastLED.show(); // display this frame
    FastLED.delay(20);
  }
} //end waitingPlayerLed



void addPointAnimate() {
  Serial.println("addPointAnimate() rolling");

}



byte whoTagged () {
  byte x;
  for (x = 1; x <= numOfPlayers; x++) {
    if (tagMatch(uid, playerIDs[x])) //when running for loops, make sure no conflicting local variable names are inheritted
      return x;
  }
  Serial.println("player # tagged: ");
  Serial.println(x);
}


void CountDownLed() {
  //Serial.println("countdownled()");
  long msLeft = rndExpireTime - currentMillis;
  timerPos = map (msLeft, 0, roundLength, BASE_LED, NUM_LEDS);
  leds[timerPos] = CRGB:: White;
  leds[timerPos + 1] = CRGB:: White;
  FastLED.delay(10);
  leds[timerPos].fadeToBlackBy( 64 );

}


void showPlayerScores() {
  //Serial.println("showplayerScores()");
  for (byte i = 1; i <= numOfPlayers; i++) { //starts at i=1 because player scores starts at 1
    int score = playerScores[i];
    byte color[3];
    for (byte x = 0; x < 3; x++) {
      color [x] = playerColors[i][x];
    }
    byte scorePos = map(score, 0, NUM_LEDS - BASE_LED + 1, BASE_LED, NUM_LEDS);
    leds[scorePos] = (color[0], color[1], color[2]);
  }
}

void printInfo() {
  //Serial.println("printInfo() ");

  //Serial.print("success=");
  //Serial.println(success);

  Serial.print("p1:");
  Serial.print(playerScores[1]);

  Serial.print(" p2:");
  Serial.print(playerScores[2]);


  Serial.print(" round:");
  Serial.print(currentRound);
  Serial.print("/");
  Serial.print(numOfRounds);


  Serial.print(" time:");
  Serial.print(currentMillis);
  Serial.print("/");
  Serial.print(rndExpireTime);
  Serial.print(" pTurn:");
  Serial.print(playerTurn);

  /*Serial.print("LEDS:");
    Serial.print(leds[20].r);
    Serial.print(leds[20].g);
    Serial.print(leds[20].b);
  */

  Serial.print(" gameOver:");
  Serial.print(gameOver);


  Serial.print(" gameIsLive: ");
  Serial.println(gameIsLive);
}

void timerCheck() {
  //Serial.println("timerCheck()");
  if (currentMillis > rndExpireTime) {
    gameIsLive = 0;
    nextRound();
  }
}

void nextRound() {
  if (currentRound <= numOfRounds) {
    currentRound++;
    nextPlayer();
  } else gameOver = 1;
}


byte addPlayerPoint(byte x) {
  //Serial.println("addPlayerPoint");
  playerScores[x]++;

  //Serial.println(playerScores[playerTurn]);
  //update LED here
}

void nextPlayer() {
  //Serial.println("nextPlayer()");
  playerTurn < numOfPlayers ? playerTurn++ : playerTurn = 1;
}

void assignPlayer(byte slotNum, byte Rfid[]) { //slot 0 reserved for coop game score;
  //Serial.print("assignPlayer()");
  for (byte x = 0; x < 4; x++) {
    playerIDs [slotNum][x] = Rfid[x];
  }
}

void waitingPlayer(byte x) { //x = playerTurn

  if (x == pNumJustTagged) { //5 rounds = 6 turns / 2 ps = 3 rounds of 2 ps
    rndExpireTime = currentMillis + roundLength;
    gameIsLive = 1;
    Serial.print("correct player Found! round ends at: ");
    Serial.println(rndExpireTime);

  }
}

bool isTurnTag() {
  //Serial.println("isTUrnTag");
  if (gameIsLive && tagMatch(uid, playerIDs[playerTurn])) {
    return true;
  }
}

bool tagMatch(byte array1[], byte array2[]) { //receives arrays as arguments
  //Serial.println("tagMatch()");
  for (byte i = 0; i < 4; i++) {
    if (array1[i] != array2[i]) {
      //Serial.println("no match");
      return false;
      break; // if not equal, then break out of the "for" loop
    }
    if (i == 3) { // if we made it to 4 loops for each of the array positions, then all 4 Tag Serial numbers sections are matching
      //Serial.println("matches");
      return true;
    }
  }
}

void getUid() {
  //Serial.println("getUid()");
  success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength); // searches for and populates uid[] and uidLength

}

void printUid() {
  Serial.println("printUid running");
  for (int x = 0; x < uidLength; x++) { //note uidLength = 0 every round of the loop, so uidLength = 0 until the loop where a card is detected
    Serial.print(uid[x]);
    x < uidLength - 1 ? Serial.print(", ") : Serial.println(); //add a comma and space until last digit
  }
}

[/code]

Do you think that it might be a good idea if you posted the waitingPlayerLed() function or preferably a whole program that shows the problem

A wild guess, but the symptoms sound like you are writing outside of an array somewhere in the program

Newb poster here, AKA mandatory 9000 character limit and 5-minute delay between posts.

You must have opened this before I was allowed to get the rest of the functions up :slight_smile:

#define NUM_LEDS    40
...
for (int b = 8; b <= 40; b++) {
    leds[b].r = playerColors[playerTurn][0];
    ...
}

What's wrong with this picture?

Regards,
Ray L.

a common cause (and happened to me recently) is exceeding the array length. there's nothing to prevent code from accessing index 20 of an array that's only 10 elements

RayLivingston:

#define NUM_LEDS    40

...
for (int b = 8; b <= 40; b++) {
    leds[b].r = playerColors[playerTurn][0];
    ...
}




What's wrong with this picture?

Regards,
Ray L.

Ahh yes, I thought maybe some local variables were interfering, so I hard coded it as a test and forgot to undue. Thanks for the pointer. My problem still exists however.

rooshio:
My problem still exists however.

Probably because you do it in more than one place...

for (x = 1; x <= numOfPlayers; x++) {

Regards,
Ray L.

gcjr:
a common cause (and happened to me recently) is exceeding the array length. there's nothing to prevent code from accessing index 20 of an array that's only 10 elements

That's a good point I wasn't aware of. I might have guessed the compiler wouldn't allow it. Thank you! If I'm understanding you correctly, though, don't think my problem is there because I'm accessing the array via hard-code in printInfo() where the problem reveals itself:

...
  Serial.print("p1:");
  Serial.print(playerScores[1]);
...

//returns p1:255

RayLivingston:
Probably because you do it in more than one place...

for (x = 1; x <= numOfPlayers; x++) {

I know the convention is to begin at 0; however, several arrays organize all my player data, and I have array slots 0 reserved for a "teamscore" concept while slots [1] = player 1 info, [2] = player 2, etc. So for this program when I only need to access the player information, my for loops initialize x = 1 in order to access player 1's data.