Serious problem with Serial.read() function please HELP

Hii, I am new to this forum. I am currently making a code for LED based snake game with all leds attached from pin 13 to pin 2 in a line, when the snake hits end and user presses button 'a' the user scores, after score 10 the snake gets faster and faster it also gets slower if user looses lives, but I wanted to create a BOT (AI_BOT in game)
which when activated will play the game on it's own. To activate the bot I have used a function AIon which takes the input which is 'A' from user by serial monitor and then it again reads a different input from user, using Serial.read() function which is stored in variable NewAI (couldn't think of any other variable name) this variable will be passed into another function AI_BOT which is the actual bot, this function checks the value of the data passed into it and if it's 'w' it activates the bot and if 's' it deactivates it. The Problem is that user is supposed to type in 'Aw' to start bot but it takes multiple 'A's to do it like atleast three time 'AAAw' if I type this then it works otherwise it won't and it goes same with when I wanna deactivate the BOT. Also it skips through the function like wait(); if i include it in AIon function, it also skipping through a Serial.println("BOT activated" ) in function AI_BOT()

PLEASE Help me I have no idea what's going with that

int led[] = {13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2};
int sval[] = {0};

int counter = 0; 
int LIVES = 5; 

int score = 0; 
int HIGHscore; 
int j;
int q = 0;  
int nm = 1;
int delaySpeed = 100;   
int Time; 

int NewAI; 
int AIval = 0;  

void setup() {
  for(int i = 0; i < 12; i++){
     pinMode(led[i], OUTPUT);
  }

  Serial.begin(9600);
}

void loop() {

                   //For the speed of delay which tells how fast should led snake move 

for(int i = 0; i < 10; i++){                     //[[[[[MAIN CONTROL WHERE ALL FUNCTIONS FOR ANIMATIONS AND DECISIONS ARE EXECUTED]]
    counter = i+3; 
                                                            
   for(j = i; j < counter; j++){
        digitalWrite(led[j], HIGH);        
    }
     task();                                 //Task() determines if the user sent 'a' when the snake hit end
     AIon();                                  //[[THIS IS WHERE I AM GETTING PROBLEM!! this reads value 
                                                  //  for the AI_BOT()
     AI_BOT(NewAI);                 //The actual bot here with argument(NewAI)
     
     delay(delaySpeed);
    for(int u = i; u < counter; u++){
          digitalWrite(led[u], LOW);
     }
      
   }

  
}
int task() {                                      //Do not name any of the functions as "main" because this name doesn't work for function choose another name instead
  if(Serial.read() == 'a'){
                                                   //task() function checks if the user pressed enter when the snakes reaches end
         if(digitalRead(led[10]) == HIGH){        //Condition where the program checks if the user pressed enter if so, then executes the following code. 
            winAnimation(1);
            score++; 
            Serial.print("LIVES LEFT = ");
            Serial.print(LIVES);
            Serial.print("        ");
            Serial.print("TIME = ");              
            Serial.print(delaySpeed);
            Serial.print("      ");
            Serial.print("SCORE = ");
            Serial.println(score);
            
            if(score > 10){
               HIGHscore = score;
               delaySpeed -= 15; 
                
            }
            delay(3);
            
            if(Serial.read() == 'b'){
               score += 20; 
            }

        
         }

         else if(digitalRead(led[10]) != HIGH){          //If user couldn't press enter at right time, then execute this code
            LIVES--;
            score--;
             
            if((score < 0)){
                //LIVES = 0;  
                score = score + (-1*score);  
            } 
            
            Serial.print("LIVES LEFT - ");
            Serial.print(LIVES);
            Serial.print("        ");
            Serial.print("TIME = ");
            Serial.print(delaySpeed);
            Serial.print("      ");
            Serial.print("SCORE = ");
            Serial.println(score);
            gameLost(4);                                                       //Function for animation
            if(score > 13){  
               while(nm == 1){
                
               
               Serial.print("                                         ");
               Serial.println("[[///PERK UNLOCKED!!!////]]");
               nm++;
               }
              delaySpeed += 30; 
            }
            if(LIVES <=  0){
               Looser(score);          
            }
         }
         }
}


int winAnimation(int val){           //blink(4) is a function inside a function named winAnimation(), winAnimation will be a common function for adding more animations  to it, so wouldn't have to 
  
  switch (val){
    case 0:
      blink(4);
      break;                               // make a new function, just add that function to this.  

    case 1:
      AIanimation();
      break;
}   
}

int gameLost(int a){ 
  int data = 0;                              //This function is for animation of the leds when player can't score
 while(data < a){
    for(int i = 6; i < 11; i++){
       digitalWrite(led[i], LOW);
    }                                        //No current use of passing arguments or data in the function 

    for(int i = 0; i < 5; i++){
       digitalWrite(led[i], HIGH);
    }

    delay(100);

    for(int i = 0; i < 5; i++){
       digitalWrite(led[i], LOW);
    }
    
    for(int i = 6; i < 11; i++){
       digitalWrite(led[i], HIGH);
    }

    delay(100);
    data++;

    
}
}


void blink(int x){
  int limit = 0; 
  
  while(limit < x){                                                            //Number of times this blink animaiton should run 
     for(int i = 0; i < 11; i++){
        digitalWrite(led[i], HIGH);
     }

     delay(100);

     for(int p = 0; p < 11; p++){
        digitalWrite(led[p], LOW);
     }

     delay(100);
     limit++; 
}
}


int LOOSER(int scoredata){                                    //LOOSER() executes when player has lost all lives, it deals with things like if player wanna restart, revive, high score, number of chances for revive
    Serial.println("[GAME LOST!!!]");
    Serial.println("");
    Serial.println("LIVES LEFT = 0");
    Serial.println("Press 'q' to exit");

    
    while(true){

        if(Serial.read() == 'q'){
          
          LIVES = 5; 
          delaySpeed = 100;
          score = 0; 
          Serial.print("[HIGH SCORE] = ");
          Serial.println(HIGHscore);
          break;               
        }
      if(q < 2){ 
        if(scoredata > 10){
           Serial.println("You have more than 10 points available");
           Serial.println();
           Serial.println("Press 't' to revive");         
           filter();

           wait();
         
           if(Serial.read() == 't'){
              q++;
              LIVES = 1;
              delaySpeed += 60; 
              break;
           }

           delay(4);
           
           if(Serial.read() == 'q'){
              LIVES = 5; 
              delaySpeed = 100; 
              score = 0; 
              Serial.print("[HIGH SCORE] = ");
              Serial.println(HIGHscore);
              break;
           }
           
           
         }  
        }

        if(q >= 2){
           Serial.println("[[Can't revive you have used up two chances]]");      
        }
    }
}


void filter(){                                          //Filters out the serial buffer
  Serial.read(); 
}

void wait(){                                          //Hangs the control loop at specific point in code 
  while(Serial.available() == 0){
    
  }
 
}
/***************************************THIS IS THE ACTUAL BOT BELOW HERE*/
int AI_BOT(char Z){

                                                   //AI BOT which plays the game, activates when player enters the command 'AAAw' and stops when PLYR enters 'AAAs'

 if(Z == 'w'){

    while(AIval < 1){
      Serial.println("[[                  ///BOT Activated\\\\          ]]");
      AIval = 2; 
    }
    if(digitalRead(led[10]) == HIGH){
        winAnimation(1);
              score++; 
              Serial.print("LIVES LEFT = ");
              Serial.print(LIVES);
              Serial.print("        ");                                                          //Need to improve system for, data sending system doesn't work.
              Serial.print("TIME = ");
              Serial.print(Optimizer(sval[0]));
              Serial.print("      ");
              Serial.print("SCORE = ");
              Serial.println(score);
            
              if(score > 10){
                HIGHscore = score;
                delaySpeed -= 15; 

                if(delaySpeed <= 0){
                   delaySpeed = delaySpeed + (-1*delaySpeed)  + 4;             //this line prevents delayspeed to get in -ve range
                }
                
            }
           }
          }   
   else if(Z == 'm'){
     
   while(AIval == 2){
    Serial.println("[[               /////Bot Deactivated\\\\\\]]");   //IT SKIPS THIS LINE AFTER 
                                                                                                    //USING TWICE OR MORE
    AIval = 0; 
    }
}
}

void AIanimation(){
    for(int i = 7; i < 11; i++){
        digitalWrite(led[i], HIGH);
    }

    delay(100);

    for(int i = 7; i < 11; i++){
      digitalWrite(led[i], LOW);
    }
}
/************************FUNCTION WHICH PASSES DATA OR VALUES TO AI_BOT*/

void AIon(){                                  //Takes the input to set value for variable responsible to turn on and turn off the AI bot. 
  if(Serial.read() == 'A'){
        Serial.println("Do you wanna activate the bot? press 'w' or 's' otherwise");
        wait();
        if(Serial.available() > 0){
          filter();
        }
        delay(3);
        NewAI = Serial.read();  
     
        Serial.print("     ");
        Serial.println(Serial.available());
        }
        
    }

What's that?

Serial.read consumes a character from the serial buffer. It isn't returned.

This array int sval[] = {0}; was for something else but it doesn't affect working of code, maybe it consumes memory etc.

1 Like

why is there a read without checking if anything is available() and what if that char isn't an 'a'?

Have you considered a button into a GPIO instead of a keyboard key? It would probably be easier on the keyboard and later on if you wanted to add a small display you wouldn't need a keyboard at all.

I didn't use Serial.available function because if data is available it will go to buffer and I can read directly from it. If data is in buffer then by reading it will still work right? If the character isn't a than it won't do anything, cuz 'a' is only supposed to be used.

where do you think the char is stored until it is read and where do you think read() gets the character from?

Yeah I thought to use a button but I dropped out the idea because I would need to debounce etc, and checks states also if I use the button too many times it might not work properly, because the button I have is not high quality one, not even normal quality I guess, also it is small, and I using keyboard is convenient for me, because I can debug with it.

i'm looking over your code and don't understand all the Serial.read()s. i can't imagine how your code works !

seems like at those points you're waiting for a specific char. but what if that's not the next char entered.

I think it is stored in Serial buffer, then you can either read it or see if it is available
Serial available tells you how many number of chars are available in buffer it also checks if chars are available but I was thinking if I am going to send a char then there's no way it can't go in buffer so then why use Serial available that's why I used serial read directly

Because once you've read it, it's gone

i don't think you understand how Serial works

that's why your think there's a " Serious problem with Serial.read() function" and need hel[p

Sorry, for badly writing the code, I understand that. I used Serial reads to read if user enter char 'a' if user doesn't type char 'a' instead types in 'b' or something then code will do nothing, This code is for snake game, everytime you enter a it checks if you entered a when led[10] was high if so then you earn a score, so that's why you don't need anything chars

If I were debugging this issue I would make a small program that does nothing but read the serial port and Print the results to the IDE monitor.

Then I would create a crude flowchart to see how to combine the serial input with the movement of the snake and how to determine if the "A" button was pressed while the snake has reached the end but still has some segments visible.

Maybe you're right, Could be that I am missing out on something about Serial
I know that Serial.read() reads in value from buffer than that value goes somewhere, and buffer then shifts another value for it to be read

char 'A' and char 'a' are two different chars the code already uses the function task() to determine if char 'a' was sent when snake reached the end it worked perfectly but problem came when my size of program grew

Exactly it's gone like deleted from buffer, but there's a strange behavior in code that I can't seem to debug.

If you see the function task() that's where it determining if snake reached the end and if user sent char 'a' at that moment, if char 'a' is sent and snake doesn't reach end that's the state if(digitalRead(led[10] != HIGH) comes in , it tells what to do then, and in this case it means you loosing scores. so it calls functions for led animaitions and reduces the value for LIVES and score which is score--; LIVES--;

You can use Serial read() and digitalRead() to combine those things. The snake actually works perfect except the BOT feature BOT works but I have to use extra char of 'A' at least three times to activate it.

Alright I think I figured out solution to my problem, so apparently I wanted to use serial read () to get input from the user, so in each statement I put serial.read() == ' some value"
because for me declaring a variable and then use it store input and then put it in if statement. It was time consuming for me, but I forgot that using it each time it calls the function that number of times, So when I would send some values to my code it would take more than twice or thrice to send it, because calling that function each time, it deletes the value from buffer each time. So instead of using so many same functions I used it one time and so it doesn't delete all inputs. Now my code is working perfectly fine.