TFT repeating touch inputs without being touched repeatedly

Hello,

I just wrote my first TFT program/game - tic tac toe. I am using 2.8" TFT Touch Shield for Arduino with Resistive Touch Screen from Adafruit Datasheet

This is my first foray and I see some decent cleanup I could do. I plan to have 8th graders use this to backwards design their own version, hence the abundance of comments

Anyway, I seem to be getting additional inputs occurring. For example, most times I push the New Game button, the screen reloads the board multiple times. Also, many times I get a new game starting with an X or even an X and O in places pushed at the end of the game. I don't see where the code is interfering, perhaps something I am missing for purging point inputs?

Thanks!

I removed a bunch of code so it would fit here.

 void loop()
{
  // See if there's any  touch data for us
  // Don't worry about this too much, this will always be needed on this screen.
  if (ts.bufferEmpty()) {
    return;
  }

  //Retrieve a point.  This gets the coordinates of where the screen was touched.
  TS_Point p = ts.getPoint();
 
  // Scale from ~0->4000 to tft.width using the calibration #'s
  // This converts the coordinates of the touched point to between (0,0) and (240,320)
  // Don't worry about this too much, this will always be needed on this screen.
  p.x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width());
  p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());
  
  // Prints the (x,y) coordinate to the serial monitor.  The serial monitor is the magnifying glass in the top right.  It is used to help "de-bug" the program.
  Serial.print("("); 
  Serial.print(p.x); // p.x means, give me the x coordinate of the point!
  Serial.print(", "); 
  Serial.print(p.y); // p.x means, give me the x coordinate of the point!
  Serial.println(")");
  
  // This is where we will check the location of our touches against the boxes of our grid
  // Since I am a math teacher, lets use some matrices to talk about locations. [0,0] will be the first row and first column, so the top left box.  
  // Notice I used 0's not 1.  In programming, we usually use 0 indexes, which starts counting at 0 instead of 1.
  if(p.y < BOXSIZE) // Check if the player chose a box in the top row
  {
    if(p.x < BOXSIZE && cellStatus[0].cellChosen == false) // Check if a player chose the first box in row 1. Location: [0,0]
    {
      if(playerTurn)
      {
        tft.drawChar(20, 13, TIC, RED, WHITE, 8); 
        cellStatus[0].playerChose = 1;
      }
      else
      {
        tft.drawChar(20, 13, TAC, GREEN, WHITE, 8); 
        cellStatus[0].playerChose = 2;
      }
      cellStatus[0].cellChosen = true;
      playerTurn = !playerTurn;
    }
    else if(p.x > BOXSIZE && p.x < BOXSIZE*2 && cellStatus[1].cellChosen == false) // Check if a player chose the second box in row 1. Location: [0,1]
    {
     if(playerTurn)
     {
        tft.drawChar(100, 13, TIC, RED, WHITE, 8); 
        cellStatus[1].playerChose = 1;
     }
      else
      {
        tft.drawChar(100, 13, TAC, GREEN, WHITE, 8); 
        cellStatus[1].playerChose = 2;
      }
      cellStatus[1].cellChosen = true;
      playerTurn = !playerTurn;
    }
    else if(p.x > BOXSIZE*2 && p.x < BOXSIZE*3 && cellStatus[2].cellChosen == false) //  Location: [0,2]
    {
      if(playerTurn)
      {
        tft.drawChar(180, 13, TIC, RED, WHITE, 8); 
        cellStatus[2].playerChose = 1;
      }
      else
      {
        tft.drawChar(180, 13, TAC, GREEN, WHITE, 8); 
        cellStatus[2].playerChose = 2;
      }
      cellStatus[2].cellChosen = true;
      playerTurn = !playerTurn;
    }
  }
  else if(p.y > BOXSIZE && p.y < BOXSIZE*2) // else if says "if the last if, at the same level, wasnt true, check this.
  {
    if(p.x < BOXSIZE && cellStatus[3].cellChosen == false) // Location: [1,0]
    {
      if(playerTurn)
      {
        tft.drawChar(20, 93, TIC, RED, WHITE, 8); 
        cellStatus[3].playerChose = 1;
      }
      else
      {
        tft.drawChar(20, 93, TAC, GREEN, WHITE, 8); 
        cellStatus[3].playerChose = 2;
      }
      cellStatus[3].cellChosen = true;
      playerTurn = !playerTurn;
    }
    else if(p.x > BOXSIZE && p.x < BOXSIZE*2 && cellStatus[4].cellChosen == false) // Location: [1,1]
    {
      if(playerTurn)
      {
        tft.drawChar(100, 93, TIC, RED, WHITE, 8); 
        cellStatus[4].playerChose = 1;
      }
      else
      {
        tft.drawChar(100, 93, TAC, GREEN, WHITE, 8); 
        cellStatus[4].playerChose = 2;
      }
      cellStatus[4].cellChosen = true;
      playerTurn = !playerTurn;
    }
    else if(p.x > BOXSIZE*2 && p.x < BOXSIZE*3 && cellStatus[5].cellChosen == false) //  Location: [1,2]
    {
      if(playerTurn)
      {
        tft.drawChar(180, 93, TIC, RED, WHITE, 8); 
        cellStatus[5].playerChose = 1;
      }
      else
      {
        tft.drawChar(180, 93, TAC, GREEN, WHITE, 8);
        cellStatus[5].playerChose = 2; 
      }
      cellStatus[5].cellChosen = true;
      playerTurn = !playerTurn;
    }
  }
  else if(p.y > BOXSIZE*2 && p.y < BOXSIZE*3) // else if says "if the last if, at the same level, wasnt true, check this.
  {
    if(p.x < BOXSIZE && cellStatus[6].cellChosen == false) // Location: [2,0]
    {
      if(playerTurn)
      {
        tft.drawChar(20, 173, TIC, RED, WHITE, 8); 
        cellStatus[6].playerChose = 1;
      }
      else
      {
        tft.drawChar(20, 173, TAC, GREEN, WHITE, 8); 
        cellStatus[6].playerChose = 2;
      }
      cellStatus[6].cellChosen = true;
      playerTurn = !playerTurn;
    }
    else if(p.x > BOXSIZE && p.x < BOXSIZE*2 && cellStatus[7].cellChosen == false) // Location: [2,1]
    {
      if(playerTurn)
      {
        tft.drawChar(100, 173, TIC, RED, WHITE, 8); 
        cellStatus[7].playerChose = 1;
      }
      else
      {
        tft.drawChar(100, 173, TAC, GREEN, WHITE, 8); 
        cellStatus[7].playerChose = 2;
      }
      cellStatus[7].cellChosen = true;
      playerTurn = !playerTurn;
    }
    else if(p.x > BOXSIZE*2 && p.x < BOXSIZE*3 && cellStatus[8].cellChosen == false) //  Location: [2,2]
    {
      if(playerTurn)
      {
        tft.drawChar(180, 173, TIC, RED, WHITE, 8); 
        cellStatus[8].playerChose = 1;
      }
      else
      {
        tft.drawChar(180, 173, TAC, GREEN, WHITE, 8); 
        cellStatus[8].playerChose = 2;
      }
      cellStatus[8].cellChosen = true;
      playerTurn = !playerTurn;
    }
  }
  // Check to see if the New Game/Restart button was pushed
  else if(p.y > 248 && p.y < 314 && p.x > 200 && p.x < 230)
  {
    // See newGame() definition below.  This function will start a new game.
    newGame();
  }
  // See the definition below.  This function checks if there is a winner, or if the game is over without a winner.
  gameStatus();
}

void gameStatus()
{
  int boardFull = 0;
  
  for( int a = 0; a < 9; a++)
  {
    if(cellStatus[a].cellChosen == true)
    {
      boardFull+=1;
    }
  } 
  // These two check if someone won in the top row
  if(cellStatus[0].playerChose == 1 && cellStatus[1].playerChose == 1 && cellStatus[2].playerChose == 1)
    playerOneWins();
  else if(cellStatus[0].playerChose == 2 && cellStatus[1].playerChose == 2 && cellStatus[2].playerChose == 2)
    playerTwoWins();
 //…removed lots of cases here
  else if(boardFull == 9)
  {
    noWinner();
  }
}

void noWinner()
{
   //…removed
    newGame();
}

void playerOneWins()
{
    //…removed
    newGame();
}

void playerTwoWins()
{
    //…removed
    newGame();
}

void newGame()
{
  for( int a = 0; a < 9; a++)
  {
    cellStatus[a].cellChosen = false;
    cellStatus[a].playerChose = 0; 
  }
  playerTurn = true;
  blankGrid();
}

I don't see where the code is interfering, perhaps something I am missing for purging point inputs?

I don't like compound if statements when they can be avoided. I'm sure yours could use some major restructuring. For instance, all the "where did the user press the screen" stuff belongs in a function, which should return a row and column value. Who's turn it was and whether or not it was legitimate to press there has nothing to do with where they pressed.

I removed a bunch of code so it would fit here.

Don't do that. Use the Additional Options link below the Reply (not the nearly useless Quick Reply field) or new post boxes to attach the code as an attachment.

Thank you for the advice, and sorry for not attaching the file!

I will be re-working the code, honestly to get it to this point (where it works, aside from the bug causing phantom touches after the game). I am a middle school math teacher using my planning period to teach kids what little programming I know--mainly to get them interested before going to high school. Unfortunately, the powers that be decided they would not purchase screens without seeing ME program tic tac toe that I want to work on with the students. Unfortunately they literally gave me a day, ugh. Anyway, I will attach the file.

I have been doing some addition sleuthing. This should "fix" my problem:

while (! ts.bufferEmpty()) 
  {
    ts.readData( &p.x, &p.y, &p.z );
  }

However I am confused, because this is throwing an error that I will post below. Looking through the header files and such I am finding what seems to be inconsistencies. the ts point is created with all int16_t, but the readData function wants two uint16_t and one uint8_t. Havent really done much work at this level, so perhaps someone could explain why this is so, and if it is suppose to be this way, how do I use the readData(...) function?

Arduino: 1.6.0 (Mac OS X), Board: "Arduino Uno"

TicTacToeStruct.ino: In function 'void loop()':
TicTacToeStruct.ino:334:35: error: no matching function for call to 'Adafruit_STMPE610::readData(int16_t*, int16_t*, int16_t*)'
TicTacToeStruct.ino:334:35: note: candidate is:
In file included from TicTacToeStruct.ino:22:0:
/Applications/Arduino.app/Contents/Resources/Java/libraries/Adafruit_STMPE610-master/Adafruit_STMPE610.h:137:8: note: void Adafruit_STMPE610::readData(uint16_t*, uint16_t*, uint8_t*)
void readData(uint16_t x, uint16_t y, uint8_t z);
^
/Applications/Arduino.app/Contents/Resources/Java/libraries/Adafruit_STMPE610-master/Adafruit_STMPE610.h:137:8: note: no known conversion for argument 3 from 'int16_t
{aka int
}' to 'uint8_t
{aka unsigned char*}'
Error compiling.

This report would have more information with
"Show verbose output during compilation"
enabled in File > Preferences.

Adafruit_STMPE610.cpp (8.99 KB)

Adafruit_STMPE610.h (3.94 KB)

TicTacToeStruct.ino (14.9 KB)

Adafruit_STMPE610 is buggy.

readData is declared readData(uint16_t*, uint16_t*, uint16_t*) in header, but defined readData(uint16_t*, uint16_t*, uint8_t*) in cpp file... Easy !

Do that :

delete this :

while (! ts.bufferEmpty())
{
ts.readData( &p.x, &p.y, &p.z );
}

at the end of the loop,

And replace :

TS_Point p = ts.getPoint();

with :

TS_Point p=ts.getPoint();
while(ts.touched())
p= ts.getPoint();

this way, you will get the last point you touched before release. You can change your mind until you "untouch" the screen.

Otherwise If you want the touch point, start the loop with

if (ts.bufferEmpty())
return;

TS_Point p=ts.getPoint();

and write this at the end :

while(ts.touched())
ts.getPoint();

THANKS! This did it:

TS_Point p=ts.getPoint();
while(ts.touched())
 p= ts.getPoint();

It seems it may "slow" down my ability to input, but nothing I cant accept.

How do I mark this solved (sorry, first time!).

Thanks!