TFT touch screen keypad

I'm hoping someone can shine some light on this one.

I’m using a Uno with a Waveshere 2.8" TFT shield to use as a alphanumeric keypad to both enter a code to enable access to another loop deeper in the code and then to enter some parameters.

It’s kind of working, the keypad renders quite well, maybe except for the chunky looking numbers but they are perfectly readable, however the key presses are very hit and miss, it often duplicates the previous keypress when I press the next key, so clearly, I’m missing something basic.

I appreciate this is quite a long unwieldly bit of code that is still very much work in progress, but I’ve tried to add some meaningful commenting and got rid of everything else that isn’t needed.

keypad small

// keypad for entering a 4 digit access code
//   using an Arduino Uno and Waveshere 2.8" touch screen
//   the entred code is to be compared with a number stored in EEPROM (eventualy) and if matched will enter a different loop
//   the keypad will then be used to enter a number for a process that will also be stored in EEPROM

// this code almost works, the rendered image on the scren is fine but keypresses are very hit and miss


#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0
#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin

#include <SPI.h>                 // f.k. for Arduino-1.5.2
#include "Adafruit_GFX.h"        // Hardware-specific library
#include <HX8347D_kbv.h>         // display hardware library
#include <EEPROM.h>              // EEPROM library
HX8347D_kbv tft;                 // not entirely sure what this is
#include <XPT2046_Touchscreen.h> // touch library
#define XPT_CS  4                // TFT chip sellect
#define XPT_IRQ 255              //use 3 if you fix interrupts in library source code


XPT2046_Touchscreen ts(XPT_CS, XPT_IRQ);


// Assign human-readable names to some common 16-bit color values:
#define  BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

#ifndef min                                   //no idea what this is
#define min(a, b) (((a) < (b)) ? (a) : (b))   //no idea what this is
#endif                                        //no idea what this is

unsigned long previousMillis = 0;     // will store last time loop was updated
const long interval = 1000;           // timed code loop interval)
const int ledPin =  LED_BUILTIN;      // the number of the LED pin
int ledState = LOW;                   // ledState used to set the LED (for debug only)
int codeTimeout = 0;                  // this will be a delay to do something if no keys are pressed
int EEPROMdigit0 = 0;                 // Eprom stored code digit 0
int EEPROMdigit1 = 0;                 // Eprom stored code digit 1
int EEPROMdigit2 = 0;                 // Eprom stored code digit 2
int EEPROMdigit3 = 0;                 // Eprom stored code digit 3
int EEPROMdigit4 = 0;                 // Eprom stored code digit 4
int EEPROMdigit5 = 0;                 // Eprom stored code digit 5



void setup() {

  pinMode(ledPin, OUTPUT);  //for debugging

  Serial.begin(9600);       //enable serial for debugging

  tft.begin();             //Enable display
  ts.begin();              //.kbv XPT2046_Touchscreen needs to start
  tft.setRotation(2);      //set screen to prtrait


  //--------------- setup touch field -------------------------

  int X_start = 360;
  int X_finish = 3840;
  int Y_start = 270;
  int Y_finish = 3860;

  keypad(); //jump straight into keypad loop

}


void loop() {//main operation loop

  //untimed code




      // currently empty




  //------------------------------------------------
  unsigned long currentMillis = millis();           //

  if (currentMillis - previousMillis >= interval) { //    code for non blocking loop
    previousMillis = currentMillis;                 //

    //timed code
    //----------------------------------------------



      // currently empty


  }
}

//----------------------------------------------------------


void keypad() {

  tft.fillScreen(BLACK);                   //clear screen

  tft.drawRect(0, 0, 240, 320, WHITE);     //outline frame of keypad

  tft.drawRect(5, 5, 230, 40, WHITE);      //frame for "user code" and display first 4 keys pressed

  tft.setTextColor(WHITE);                 //write "user code" text into box
  tft.setCursor(10, 15);
  tft.setTextSize(2);
  tft.println("User code:");

  int codeArray[4] = {0, 0, 0, 0};  // this is where the first 4 key presses will be saved

  int keyPosX = 5;      //set left hand start point for left column of keys
  int keySpaceX = 5;    //set horizontal space between keys
  int keyPosY = 48;     //set the top most start point for the top row of keys
  int keySpaceY = -5;   //set vertical space between keys (currently not working prpperly for some reason)
  int keyWidth = 73;    //set width of keys
  int keyHieght = 63;   //set hight of keys

  int colum1 = keyPosX;                                   //human readable left start point for left column of keys
  int colum2 = keyPosX + keySpaceX + keyWidth;            //human readable left start point for second column of keys
  int colum3 = keyPosX + (keySpaceX * 2) + (keyWidth * 2);//human readable left start point for third column of keys

  int row1 = keyPosY;                                     //human readable top start point for top row of keys
  int row2 = keyPosY + keySpaceY + keyWidth;              //human readable top start point for second row of keys
  int row3 = keyPosY + (keySpaceY * 2) + (keyWidth * 2);  //human readable top start point for third row of keys
  int row4 = keyPosY + (keySpaceY * 3) + (keyWidth * 3);  //human readable top start point for fourth row of keys


  //================================== draw keys =========================================
  //-----------------------------------key 1 -----------------------------------------
  tft.drawRect(colum1, keyPosY, keyWidth, keyHieght, GREEN); //key 1    draw key
  tft.setTextColor(GREEN);
  tft.setCursor(keyPosX + 25, keyPosY + 15);
  tft.setTextSize(5);
  tft.println("1");
  //-----------------------------------key 2 ----------------------------------------

  tft.drawRect(colum2, keyPosY, keyWidth, keyHieght, GREEN); //key 2
  tft.setTextColor(GREEN);
  tft.setCursor(colum2 + 25, keyPosY + 15);
  tft.setTextSize(5);
  tft.println("2");
  //-----------------------------------key 3 -----------------------------------------

  tft.drawRect(colum3, keyPosY, keyWidth, keyHieght, GREEN); //key 3
  tft.setTextColor(GREEN);
  tft.setCursor(colum3 + 25, keyPosY + 15);
  tft.setTextSize(5);
  tft.println("3");

  //-----------------------------------key 4 --------------------------------------

  tft.drawRect(colum1, row2, keyWidth, keyHieght, GREEN); //key 4
  tft.setTextColor(GREEN);
  tft.setCursor(colum1 + 25, row2 + 15);
  tft.setTextSize(5);
  tft.println("4");

  //-----------------------------------key 5 ------------------------------------

  tft.drawRect(colum2, row2, keyWidth, keyHieght, GREEN); //key 5
  tft.setTextColor(GREEN);
  tft.setCursor(colum2 + 25, row2 + 15);
  tft.setTextSize(5);
  tft.println("5");

  //-----------------------------------key 6 -----------------------------------

  tft.drawRect(colum3, row2, keyWidth, keyHieght, GREEN); //key 6
  tft.setTextColor(GREEN);
  tft.setCursor(colum3 + 25, row2 + 15);
  tft.setTextSize(5);
  tft.println("6");

  //-----------------------------------key 7 ------------------------------------

  tft.drawRect(colum1, row3, keyWidth, keyHieght, GREEN); //key 7
  tft.setTextColor(GREEN);
  tft.setCursor(colum1 + 25, row3 + 15);
  tft.setTextSize(5);
  tft.println("7");

  //-----------------------------------key 8 ----------------------------------

  tft.drawRect(colum2, row3, keyWidth, keyHieght, GREEN); //key 8
  tft.setTextColor(GREEN);
  tft.setCursor(colum2 + 25, row3 + 15);
  tft.setTextSize(5);
  tft.println("8");

  //-----------------------------------key 9 --------------------------------

  tft.drawRect(colum3, row3, keyWidth, keyHieght, GREEN); //key 9
  tft.setTextColor(GREEN);
  tft.setCursor(colum3 + 25, row3 + 15);
  tft.setTextSize(5);
  tft.println("9");

  //-----------------------------------key C -------------------------------

  tft.drawRect(colum1, row4, keyWidth, keyHieght, GREEN); //key C
  tft.setTextColor(GREEN);
  tft.setCursor(colum1 + 25, row4 + 15);
  tft.setTextSize(5);
  tft.println("C");

  //-----------------------------------key 0 -------------------------------

  tft.drawRect(colum2, row4, keyWidth, keyHieght, GREEN); //key 0
  tft.setTextColor(GREEN);
  tft.setCursor(colum2 + 25, row4 + 15);
  tft.setTextSize(5);
  tft.println("0");

  //-----------------------------------key E -------------------------------

  tft.drawRect(colum3, row4, keyWidth, keyHieght, GREEN); //key E
  tft.setTextColor(GREEN);
  tft.setCursor(colum3 + 25, row4 + 15);
  tft.setTextSize(5);
  tft.println("E");


  //========================= key press ================================



  int keypress = 55;       //declare integer to store key pressed set at 55 so will only read if a valid number


  //  set human readable touch point limits for key detection

  int pressCol1 = 336;    // start of column 1
  int presscol2 = 1420;   //end of column 1 start of column 2
  int presscol3 = 2660;   //end of column 2 start of column 3
  int presscol4 = 3740;   //right most edge of column 3 keys

  int pressrow1 = 950;    // top start point of row 1
  int pressrow2 = 1730;   //bottom of row 1 top of row 2
  int pressrow3 = 2440;   //bottom of row 2 top of row 3
  int pressrow4 = 3190;   //bottom of row 3 start of row 4

  int keypressIndex = 0;      //array index number



  tft.fillRect(130, 10, 75, 30, BLACK); // clear keypress displayed

  //keypad key read loop

  while (1) {

    TS_Point p = ts.getPoint();
    if (ts.touched()) {

      //store pressed key number in 'keypress'

      if (p.x > pressrow1 && p.x < pressrow2 && p.y < presscol2) keypress = 1;
      if (p.x > pressrow1 && p.x < pressrow2 && p.y > presscol2 && p.y < presscol3) keypress = 2;
      if (p.x > pressrow1 && p.x < pressrow2 && p.y > presscol3 && p.y < presscol4) keypress = 3;
      if (p.x > pressrow2 && p.x < pressrow3 && p.y < presscol2) keypress = 4;
      if (p.x > pressrow2 && p.x < pressrow3 && p.y > presscol2 && p.y < presscol3) keypress = 5;
      if (p.x > pressrow2 && p.x < pressrow3 && p.y > presscol3 && p.y < presscol4) keypress = 6;
      if (p.x > pressrow3 && p.x < pressrow4 && p.y < presscol2) keypress = 7;
      if (p.x > pressrow3 && p.x < pressrow4 && p.y > presscol2 && p.y < presscol3) keypress = 8;
      if (p.x > pressrow3 && p.x < pressrow4 && p.y > presscol3 && p.y < presscol4) keypress = 9;
      if (p.x >  pressrow4 && p.y > presscol2 && p.y < presscol3) keypress = 0;
      //      if (p.x >  pressrow4 && p.y > presscol3 && p.y < presscol4) screenBuild(); //cancel key will return
      //   to main running loop

      delay (100); //delay for stability, might not be required


      //Serial.println(keypress); //serial print keypress for debugging



      if (keypress != 55) codeArray[keypressIndex] = keypress;

      //codeArray[keypressIndex] = keypress;  //store keypress in array




      //------------------------- clear code -----------------------------------------------

      if (p.x >  pressrow4 && p.y < presscol2) {// clear key
        tft.fillRect(130, 10, 100, 30, BLACK); // clear keypress displayed;
        keypressIndex = 0;
        keypress = 55;
        codeArray[0] = 0;
        codeArray[1] = 0;
        codeArray[2] = 0;
        codeArray[3] = 0;
      }


      //----------------------------- display keypress ----------------------------------------------

      //dipslays the 4 digit code on the screen

      if (keypressIndex == 0) { //display first digit


        tft.setTextColor(GREEN);
        tft.setCursor(130, 10);
        tft.setTextSize(4);
        tft.println(codeArray[0]);

      }

      if (keypressIndex == 1) { //display second digit

        tft.setTextColor(GREEN);
        tft.setCursor(155, 10);
        tft.setTextSize(4);
        tft.println(codeArray[1]);

      }

      if (keypressIndex == 2) { // display third digit

        tft.setTextColor(GREEN);
        tft.setCursor(180, 10);
        tft.setTextSize(4);
        tft.println(codeArray[2]);

      }

      if (keypressIndex == 3) { //display forth digit

        tft.setTextColor(GREEN);
        tft.setCursor(205, 10);
        tft.setTextSize(4);
        tft.println(codeArray[3]);

      }


      keypressIndex++;  //increment keypress index to store next key


      if (codeArray[0] == 1 && codeArray[1] == 9 && codeArray[2] == 8 && codeArray[3] == 0) loop(); //temporary set code

      //-------------  the below serial printed for debugging purposes --------------------------------


      //   Serial.print("x= ");   |   serial print touch co-ordinates to set up key touch areas
      //  Serial.print(p.x);      |
      //  Serial.print("  y=");   |
      //  Serial.print(p.y);      |


      Serial.print("  codeArray  ");  //      serial print first 4 numbers pressed
      Serial.print(codeArray[0]);     //
      Serial.print(codeArray[1]);     //
      Serial.print(codeArray[2]);     //
      Serial.print(codeArray[3]);     //


      Serial.print("  keypress  ");   //    serial print key pressed
      Serial.print(keypress);


      Serial.print("  keypressIndex  ");  // serial print index number
      Serial.println(keypressIndex);





      delay(300); // to prevent multiple presses
    }

  }

}

I don't know your library but shouldn't that be done the other way around like "if the screen is touched, then get the coordinates where you pressed" ??

delay (100); is a bad idea, you want the code to run as fast as possible

Swapping those around has made a huge improvement! Thankyou.

glad it helped. have fun

Try using Adafruit_GFX Button it makes life much easier.

But if you do enjoy writing everything from scratch make a single function that draws a "button" at x, y with label
And a single function that detects whether your "touch" is within that particular "button".

Seriously. It is easier to start with ready made code. When you have it working with the proven code you can re-write sections with your home-grown ideas.

David.

Thanks David, I will have a look at Adafruit_GFX Button, I've never come across it before, I also like the idea of a single function, it would make the code a lot more compact. It seems to be working quite well now so this might be the next logical step in tidying it up.
There's quite a long way to go yet as I've been tasked to build a monitor for a 6000A spot welder so the display can show the current of the weld and the number of welds before flagging an alarm to change the electrodes. It's definitely going to be a fun project!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.