Section of Code Breaks Serial Output

Hey everyone,

Project I'm Working On: Creating a RFID reader-based login system that adjusts multiple systems to the set preferences of the user who logs in.

Section that I'm having the problem on: One specific RFID tag is designated to be the administrator. When the administrator logs in, it starts the adminRoutine function which begins accepting serial input. Using this serial input/output, the administrator can add and remove users.

What is the problem: The problem occurs in the code for the admin choosing the second option to remove a user. It first prints out the list of available users to remove, then takes the number and makes sure it's in the range using converted ASCII values (e.g. for 5 users, makes sure it's in slots 1, 2, 3, 4, because 0 is for admin). It uses that number to call the removeUser function. Right now, removeUser does nothing but return, so that's not the problem. Everything compiles fine. Here is the section of code with the issue:

 nextByte = Serial.read(); //Read incoming byte
if ((nextByte >= 49) && (nextByte <= (49 + NUMBER_USERS - 2))) { //If number is within range (converted ASCII values)
                //THIS LINE!!!!!!!
                if ((users[nextByte - 48].removeUser())) { //If a user exists at requested slot, remove them
                   users[nextByte - 48].removeUser();
                   validInput = true; //Received valid input
                   Serial.println("User removed successfully.\n");
                }

I determined the problem lies here by isolating smaller parts using comments. If this section is commented out, the program runs and will print "Start" which signifies that it entered void loop(). If it isn't commented out, it will print nothing and the reader will not function, meaning it did not even enter the void loop(). Very interesting and frustrating problem. Here's the whole adminRoutine() function. It has been doing some other weird things lately. I just tried running it again without ever calling the adminRoutine function in void loop() and the serial started spitting out Serial.print() lines from the adminRoutine() function. I'm pretty perplexed. Let me know if you need any other code.

void adminRoutine() { //Administrator routine
  Serial.println("Started Admin Routine!");
  users[0].login(keyboard); //Log administrator into computer

  char logout = 0; //Turns 1 if system wants to logout
  byte incomingByte; //Store incoming byte
  char startCommand[5]; //Command to start user management routine

  while (logout == 0) { //Loop until admin logs out
    Serial.println("Waiting for Start command.");
    if (Serial.available() > 0) { //If data is available to be read
      char dataRead = 0; //0 if no data was read, 1 if it was read

      int i = 0; //Iterator variable
      for (incomingByte = Serial.read(); i < 5; ++i) { //Read each byte as it arrives
        startCommand[i] = incomingByte; //Store each byte

        char timeoutCount = 0; //Counter for timeout
        while(Serial.available() <= 0) { //Wait until data is read or timeout if no data received
          if(timeoutCount == DATA_TIMEOUT) { //Timeout, no data has been sent
            dataRead = 1;
            break;
          }
          delay(1); //Delay 1 millisecond
          ++timeoutCount; //Increment count
        }
      }

      Serial.flush(); //Flush any remaining serial data

      if(dataRead && (startCommand == "start")) { //If data has been read and the command entered was start
        Serial.println("Start Command Received.");
        char stopAdmin = 0; //If set to 1, stop administrative tasks

        //******TURN OFF LOGOUT BUTTON ON SCREEN HERE***********

        Serial.println("Welcome Administrator."); //Print welcome message

        while (!stopAdmin) { //While stop isn't triggered
          //Start printing of options
          Serial.println("\nPlease select one of the following options by entering its number:");
          Serial.println("1. Add User");
          Serial.println("2. Remove User");
          Serial.println("3. List Users");
          Serial.println("4. Exit");

          while (Serial.available()) {
          }; //Wait for serial input to be available
          incomingByte = Serial.read();

          if(incomingByte == '1') { //If administrator wants to add a user
            Serial.flush();
            char username[MAX_USERNAME_LENGTH + 1]; //To store username (+1 for NULL)
            char password[MAX_PASSWORD_LENGTH + 1]; //To store password (+1 for NULL)
            char RFIDTag[TAG_LENGTH]; //To store a tag

            Serial.println("Option 1: Add User"); //Echo option chosen
            Serial.println("\nScan the SmartCard of the user to be added."); //Prompt admin to scan user's RFID tag

            /***Get RFID Information***/
            enableRFID();
            while(1) { //Infinite loop to wait for tag scan
              if(getRFIDTag(RFIDTag) && tagValid(RFIDTag)) { //If RFID is available and is a valid tag
                disableRFID();
                break; //Break out of infinite loop
              }
            }

            getUsernameAdmin(username); //Get username to add user
            getPasswordAdmin(password); //Get password to add user

            /***Add User***/
            if (newUser(RFIDTag, username, password)) //Add new users using entered credentials, if added successfully
              Serial.println("\nUser added successfully!\n");
            else //Maximum number of users reached
              Serial.println("\nUser was not added. Maximum number of users reached or SmartCard is already in use.\n");
          }

          else if (incomingByte == '2') { //If administrator wants to remove a user
            Serial.flush();
            Serial.println("Option 2: Remove User"); //Echo option chosen
            Serial.println("\nChoose the user you would like to remove by entering their number:");
            for (int i = 1; i < NUMBER_USERS; ++i) { //Loop through users, starting with 1 because 0 is admin
              Serial.print(i); //Print list of usernames
              Serial.print(". ");
              if(users[i].empty()) //If user slot is empty
                  Serial.print("EMPTY"); //Print that slot is empty
              else //If user is present
              Serial.print(users[i].username()); //Print username
              Serial.print("\n");
            }

            Serial.flush(); //Clear serial buffer

            bool validInput = false;
            while (!validInput) { //While input is not valid
              while (Serial.available() <= 0) {
              } //Wait for serial input to be available
              int nextByte = '\0';
              delay(5000);
              nextByte = Serial.read(); //Read incoming byte
              delay(1000);
              if ((nextByte >= 49) && (nextByte <= (49 + NUMBER_USERS - 2))) { //If number is within range (converted ASCII values)
                //THIS LINE!!!!!!!
                if ((users[nextByte - 48].removeUser())) { //If a user exists at requested slot, remove them
                   users[nextByte - 48].removeUser();
                   validInput = true; //Received valid input
                   Serial.println("User removed successfully.\n");
                }
                else { //If slot is empty
                  Serial.println("Requested slot is empty. Please choose another.");
                }
              }
              else //If invalid input
              Serial.println("Invalid input. Please input a valid slot number.");
            }
          }

          else if (incomingByte == '3') { //If administrator wants to list users
            Serial.flush();
            Serial.println("Option 3: List Users"); //Echo option chosen
            for (int i = 1; i < NUMBER_USERS; ++i) { //Loop through users, starting with 1 because 0 is admin
              Serial.print(i); //Print list of usernames
              Serial.print(". ");
              if(users[i].empty()) //If user slot is empty
                  Serial.print("EMPTY"); //Print that slot is empty
              else //If user is present
              Serial.print(users[i].username()); //Print username
              Serial.print("\n");
            }
          }

          else if (incomingByte == '4') { //If administrator wants to exit
            Serial.flush();
            Serial.println("Option 4: Exit"); //Echo option chosen
            delay(1000);
            stopAdmin = 1; //Trigger to stop administrative tasks
          }

          else //Command invalid
          Serial.println("\nCommand was not recognized.");
        }
      }
      else { //If command was not "start", invalid
        Serial.println("Command Invalid.");
        Serial.println("Please enter \"start\" to start administrative tasks.");
      }
    }
  }
}

If you guys can figure this one out, I'd be in your debt. It's been puzzling me for days.

And here's the two functions that adminRoutine calls.

void getUsernameAdmin(char username[]) { //Get username of user from admin
  char usernameConfirmed = false; //Is username correct?
  while (!usernameConfirmed) { //While the user has not confirmed username is right
    Serial.println("\nType the user's Windows username (letters and numbers only, MAX_USERNAME_LENGTH character maximum length):"); //Prompt user to type username

    char i = 0; //Iterator variable
    char commandBuffer[MAX_USERNAME_LENGTH + 1]; //Buffer to store command (size + 1 NULL)
    if(Serial.available()){ //If data is available to be read
      delay(50); //Delay for stability
      while( Serial.available() && i < MAX_USERNAME_LENGTH) { //Read all data entered, up to max username length
        commandBuffer[i++] = Serial.read();
      }
      commandBuffer[i++] = '\0'; //Append null character to end of username
    }

    for (i = 0; i < MAX_USERNAME_LENGTH + 1; ++i) { //Loop through commandBuffer, store data into username, stop when NULL is reached
      if (commandBuffer[i] == '\0') { //If reached a NULL character
        for (i; i < MAX_USERNAME_LENGTH + 1; ++i) { //Fill remaining slots with NULL characters
          username[i] = '\0';
        }
        break; //Exit loop
      }
      username[i] = commandBuffer[i];
    }

    Serial.print("Is this username correct (y/n): "); //Echo username to administrator
    Serial.println(username);

    byte incomingByte; //To store each byte of serial data read
    bool validInput = false;
    while (!validInput) { //While input is not valid
      while (Serial.available() <= 0) {
      } //Wait for serial input to be available
      incomingByte = Serial.read(); //Read incoming byte
      if (incomingByte == 'y') { //If admin confirms username is correct
        validInput = true; //Received valid input
        usernameConfirmed = true; //Username has been confirmed
      }
      else if (incomingByte == 'n') //If admin says username is incorrect, loop back to allow entering again
        validInput = true; //Recieved valid input
      else //Invalid input
      Serial.println("Invalid input.");
    }
  }
}

void getPasswordAdmin(char password[]) { //Get password of user from admin
  char passwordConfirmed = false; //Is password correct?
  while (!passwordConfirmed) { //While the user has not confirmed password is right
    Serial.println("\nType the user's Windows password (letters and numbers only, MAX_password_LENGTH character maximum length):"); //Prompt user to type password

    char i = 0; //Iterator variable
    char commandBuffer[MAX_PASSWORD_LENGTH + 1]; //Buffer to store command (size + 1 NULL)
    if(Serial.available()){ //If data is available to be read
      delay(50); //Delay for stability
      while( Serial.available() && i < MAX_PASSWORD_LENGTH) { //Read all data entered, up to max password length
        commandBuffer[i++] = Serial.read();
      }
      commandBuffer[i++] = '\0'; //Append null character to end of password
    }

    for (i = 0; i < MAX_PASSWORD_LENGTH + 1; ++i) { //Loop through commandBuffer, store data into password, stop when NULL is reached
      if (commandBuffer[i] == '\0') { //If reached a NULL character
        for (i; i < MAX_PASSWORD_LENGTH + 1; ++i) { //Fill remaining slots with NULL characters
          password[i] = '\0';
        }
        break; //Exit loop
      }
      password[i] = commandBuffer[i];
    }

    Serial.print("Is this password correct (y/n): "); //Echo password to administrator
    Serial.println(password);

    byte incomingByte; //To store each byte of serial data read
    bool validInput = false;
    while (!validInput) { //While input is not valid
      while (Serial.available() <= 0) {
      } //Wait for serial input to be available
      incomingByte = Serial.read(); //Read incoming byte
      if (incomingByte == 'y') { //If admin confirms password is correct
        validInput = true; //Received valid input
        passwordConfirmed = true; //Username has been confirmed
      }
      else if (incomingByte == 'n') //If admin says password is incorrect, loop back to allow entering again
        validInput = true; //Recieved valid input

    }
  }
}
 nextByte = Serial.read(); //Read incoming byte

What is going to happen if you have more than 9 users?

If nextByte is really an index, subtract '0' from the value up front. Quit trying to manipulate the index in every line of code.

                if ((users[nextByte - 48].removeUser())) { //If a user exists at requested slot, remove them
                   users[nextByte - 48].removeUser();

If you successfully removed the user, remove the user. Well, OK. I guess. I certainly wouldn't do it that way, but, I'm sure you have your reasons.