// IMPORTANT: Elegoo_TFTLCD LIBRARY MUST BE SPECIFICALLY // CONFIGURED FOR EITHER THE TFT SHIELD OR THE BREAKOUT BOARD. // SEE RELEVANT COMMENTS IN Elegoo_TFTLCD.h FOR SETUP. //Technical support:goodtft@163.com //NOTE: This is a patchwork from a few sources, mostly in the pre-setup portion, comments made by me will be ended with a -SFO #include // Core graphics library #include // Hardware-specific library #include #include #include // The control pins for the LCD can be assigned to any digital or // analog pins...but we'll use the analog pins as this allows us to // double up the pins with the touch screen (see the TFT paint example). #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 // When using the BREAKOUT BOARD only, use these 8 data lines to the LCD: // For the Arduino Uno, Duemilanove, Diecimila, etc.: // D0 connects to digital pin 8 (Notice these are // D1 connects to digital pin 9 NOT in order!) // D2 connects to digital pin 2 // D3 connects to digital pin 3 // D4 connects to digital pin 4 // D5 connects to digital pin 5 // D6 connects to digital pin 6 // D7 connects to digital pin 7 // For the Arduino Mega, use digital pins 22 through 29 // (on the 2-row header at the end of the board). // 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 // Color definitions #define ILI9341_BLACK 0x0000 /* 0, 0, 0 */ #define ILI9341_NAVY 0x000F /* 0, 0, 128 */ #define ILI9341_DARKGREEN 0x03E0 /* 0, 128, 0 */ #define ILI9341_DARKCYAN 0x03EF /* 0, 128, 128 */ #define ILI9341_MAROON 0x7800 /* 128, 0, 0 */ #define ILI9341_PURPLE 0x780F /* 128, 0, 128 */ #define ILI9341_OLIVE 0x7BE0 /* 128, 128, 0 */ #define ILI9341_LIGHTGREY 0xC618 /* 192, 192, 192 */ #define ILI9341_DARKGREY 0x7BEF /* 128, 128, 128 */ #define ILI9341_BLUE 0x001F /* 0, 0, 255 */ #define ILI9341_GREEN 0x07E0 /* 0, 255, 0 */ #define ILI9341_CYAN 0x07FF /* 0, 255, 255 */ #define ILI9341_RED 0xF800 /* 255, 0, 0 */ #define ILI9341_MAGENTA 0xF81F /* 255, 0, 255 */ #define ILI9341_YELLOW 0xFFE0 /* 255, 255, 0 */ #define ILI9341_WHITE 0xFFFF /* 255, 255, 255 */ #define ILI9341_ORANGE 0xFD20 /* 255, 165, 0 */ #define ILI9341_GREENYELLOW 0xAFE5 /* 173, 255, 47 */ #define ILI9341_PINK 0xF81F #define YP A3 // must be an analog pin, use "An" notation! #define XM A2 // must be an analog pin, use "An" notation! #define YM 9 // can be a digital pin #define XP 8 // can be a digital pin //Touch For New ILI9341 TP #define TS_MINX 120 #define TS_MAXX 900 #define TS_MINY 70 #define TS_MAXY 920 // We have a status line for like, is FONA working #define STATUS_X 10 #define STATUS_Y 285 Elegoo_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET); TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300); // If using the shield, all control and data lines are fixed, and // a simpler declaration can optionally be used: // Elegoo_TFTLCD tft; char dig1 = 88; // dig1 - dig4 are the numbers displayed in the textfield, 88 is ASCII for 'X' -SFO char dig2 = 88; char dig3 = 88; char dig4 = 88; int dig1Color = RED; // these four are the colors of the digits, each unentered digit is displayed as a red X -SFO int dig2Color = RED; int dig3Color = RED; int dig4Color = RED; int imp = 0; // this variable helps us place the numbers in their correct places -SFO int tot = 0; // this is used later on to determine if all four code digits have been entered -SFO int dgt1 = 0; // these four are used for math later on, to figure out if all digits have been entered and to turn four single digits into a four digit number -SFO int dgt2 = 0; int dgt3 = 0; int dgt4 = 0; word code = 0; //this is what stores the entered code for comparison to a list of 'correct' codes -SFO unsigned long day = 24; //these are placeholders for the datalogger date/time variables, will use a RTC when I get one. unsigned long month = 7; unsigned long year = 2017; unsigned long hour = 13; unsigned long minute = 10; File myFile; //defines file for datalogger unsigned long date = year * 10000 + month * 100 + day; unsigned long tme = hour * 100 + minute; int freeRam() { extern int __heap_start,*__brkval; int v; return (int)&v - (__brkval == 0 ? (int)&__heap_start : (int) __brkval); } void setup(void) { Serial.begin(9600); while (!Serial) {}; Serial.print("Initializing SD Card..."); if (!SD.begin(10, 11, 12, 13)) { Serial.println("initialization failed"); return; } Serial.println("initialization done."); Serial.println(F("TFT LCD test")); #ifdef USE_Elegoo_SHIELD_PINOUT Serial.println(F("Using Elegoo 2.8\" TFT Arduino Shield Pinout")); #else Serial.println(F("Using Elegoo 2.8\" TFT Breakout Board Pinout")); #endif Serial.print("TFT size is "); Serial.print(tft.width()); Serial.print("x"); Serial.println(tft.height()); tft.reset(); uint16_t identifier = tft.readID(); if (identifier == 0x9325) { Serial.println(F("Found ILI9325 LCD driver")); } else if (identifier == 0x9328) { Serial.println(F("Found ILI9328 LCD driver")); } else if (identifier == 0x4535) { Serial.println(F("Found LGDP4535 LCD driver")); } else if (identifier == 0x7575) { Serial.println(F("Found HX8347G LCD driver")); } else if (identifier == 0x9341) { Serial.println(F("Found ILI9341 LCD driver")); } else if (identifier == 0x8357) { Serial.println(F("Found HX8357D LCD driver")); } else if (identifier == 0x0101) { identifier = 0x9341; Serial.println(F("Found 0x9341 LCD driver")); } else { Serial.print(F("Unknown LCD driver chip: ")); Serial.println(identifier, HEX); Serial.println(F("If using the Elegoo 2.8\" TFT Arduino shield, the line:")); Serial.println(F(" #define USE_Elegoo_SHIELD_PINOUT")); Serial.println(F("should appear in the library header (Elegoo_TFT.h).")); Serial.println(F("If using the breakout board, it should NOT be #defined!")); Serial.println(F("Also if using the breakout, double-check that all wiring")); Serial.println(F("matches the tutorial.")); identifier = 0x9341; } tft.begin(identifier); //Begins the TFT coding? -SFO tft.setRotation(2); //Sets orientation -SFO tft.fillScreen(BLACK); //Sets the background color -SFO tft.fillRect(8, 100, 73, 50, ILI9341_LIGHTGREY); //Draws button 1 -SFO tft.drawRect(8, 100, 73, 50, WHITE); tft.setCursor(37, 115); tft.setTextColor(WHITE); tft.setTextSize(3); tft.print("1"); tft.fillRect(83, 100, 73, 50, ILI9341_LIGHTGREY); //Draws button 2 -SFO tft.drawRect(83, 100, 73, 50, WHITE); tft.setCursor(110, 115); tft.setTextColor(WHITE); tft.setTextSize(3); tft.print("2"); tft.fillRect(158, 100, 73, 50, ILI9341_LIGHTGREY); //Draws button 3 -SFO tft.drawRect(158, 100, 73, 50, WHITE); tft.setCursor(183, 115); tft.setTextColor(WHITE); tft.setTextSize(3); tft.print("3"); tft.fillRect(8, 152, 73, 50, ILI9341_LIGHTGREY); //Draws button 4 -SFO tft.drawRect(8, 152, 73, 50, WHITE); tft.setCursor(37, 167); tft.setTextColor(WHITE); tft.setTextSize(3); tft.print("4"); tft.fillRect(83, 152, 73, 50, ILI9341_LIGHTGREY); //Draws button 5 -SFO tft.drawRect(83, 152, 73, 50, WHITE); tft.setCursor(110, 167); tft.setTextColor(WHITE); tft.setTextSize(3); tft.print("5"); tft.fillRect(158, 152, 73, 50, ILI9341_LIGHTGREY); //Draws button 6 -SFO tft.drawRect(158, 152, 73, 50, WHITE); tft.setCursor(183, 167); tft.setTextColor(WHITE); tft.setTextSize(3); tft.print("6"); tft.fillRect(8, 204, 73, 50, ILI9341_LIGHTGREY); //Draws button 7 -SFO tft.drawRect(8, 204, 73, 50, WHITE); tft.setCursor(37, 219); tft.setTextColor(WHITE); tft.setTextSize(3); tft.print("7"); tft.fillRect(83, 204, 73, 50, ILI9341_LIGHTGREY); //Draws button 8 -SFO tft.drawRect(83, 204, 73, 50, WHITE); tft.setCursor(110, 219); tft.setTextColor(WHITE); tft.setTextSize(3); tft.print("8"); tft.fillRect(158, 204, 73, 50, ILI9341_LIGHTGREY); //Draws button 9 -SFO tft.drawRect(158, 204, 73, 50, WHITE); tft.setCursor(183, 219); tft.setTextColor(WHITE); tft.setTextSize(3); tft.print("9"); tft.fillRect(8, 256, 73, 50, RED); //Draws the CLEAR button-SFO tft.drawRect(8, 256, 73, 50, WHITE); tft.setCursor(15, 275); tft.setTextColor(WHITE); tft.setTextSize(2); tft.print("Clear"); tft.fillRect(83, 256, 73, 50, ILI9341_LIGHTGREY); //Draws button 0 -SFO tft.drawRect(83, 256, 73, 50, WHITE); tft.setCursor(110, 271); tft.setTextColor(WHITE); tft.setTextSize(3); tft.print("0"); tft.fillRect(158, 256, 73, 50, GREEN); //Draws the ENTER button -SFO tft.drawRect(158, 256, 73, 50, WHITE); tft.setCursor(165, 275); tft.setTextColor(WHITE); tft.setTextSize(2); tft.print("ENTER"); #define MINPRESSURE 50 //These define the minimum and maximum pressure to be counted as a button 'push' -SFO #define MAXPRESSURE 1000 pinMode(13, OUTPUT); } void loop() { char fileName[13]; //variable to name file, will hold date later char timeStamp[8]; //variable to put timestamp in file, will hold time later sprintf(fileName, "%08lu.txt", date); sprintf(timeStamp, "%04lu.txt", tme); tft.drawRect(10, 10, 219, 50, WHITE); //This block draws the text field, it's in the loop section because it will draw over the old entries every time the code loops to give a new code attempt -SFO tft.setCursor(75, 25); tft.setTextColor(dig1Color); tft.setTextSize(3); tft.print(dig1); tft.setCursor(100, 25); tft.setTextColor(dig2Color); tft.setTextSize(3); tft.print(dig2); tft.setCursor(125, 25); tft.setTextColor(dig3Color); tft.setTextSize(3); tft.print(dig3); tft.setCursor(150, 25); tft.setTextColor(dig4Color); tft.setTextSize(3); tft.print(dig4); digitalWrite(13, HIGH); TSPoint p = ts.getPoint(); digitalWrite(13, LOW); pinMode(XM, OUTPUT); pinMode(YP, OUTPUT); /* if (p.z > MINPRESSURE && p.z < MAXPRESSURE) { Serial.print("X = "); Serial.print(p.x); Serial.print("\tY = "); Serial.print(p.y); Serial.print("\n"); */ p.x = map(p.x, TS_MAXX, TS_MINX, 0, 320); p.y = map(p.y, TS_MAXY, TS_MINY, 0, 240); if (p.z > MINPRESSURE && p.z < MAXPRESSURE) { Serial.print("X = "); Serial.print(p.x); Serial.print("\tY = "); Serial.print(p.y); Serial.print("\n"); if (p.x > 30 && p.x < 80 && p.y > 130 && p.y < 160) //Sets up push for button 1 -SFO { /*This switch section looks at imp to decide which digit to write to, then erases the red X that was previously in the text screen and replaces with the number, 1 in this case. 1 is coded as 49 due to the ASCII character 1 having a value of 49. It then increases imp by 1, to a maximum of 4. This is the same for buttons 2,3,4,5,6,7,8,9 and 0, all which will refer here. The default case happens when imp is 4 (or more, but that shouldnt happen. and basically renders touching any button besides Clear and ENTER do nothing-SFO */ switch (imp) { case 0: tft.fillRect(75, 25, 15, 21, BLACK); dig1Color = WHITE; dig1 = 49; imp = 1; delay(250); break; case 1: tft.fillRect(100, 25, 15, 21, BLACK); dig2Color = WHITE; dig2 = 49; imp = 2; delay(250); break; case 2: tft.fillRect(125, 25, 15, 21, BLACK); dig3Color = WHITE; dig3 = 49; imp = 3; delay(250); break; case 3: tft.fillRect(150, 25, 15, 21, BLACK); dig4Color = WHITE; dig4 = 49; imp = 4; delay(250); break; default: break; } } if (p.x > 130 && p.x < 180 && p.y > 130 && p.y < 160) //Sets up push for button 2 -SFO { //Refer to comment on button 1 above. -SFO switch (imp) { case 0: tft.fillRect(75, 25, 15, 21, BLACK); dig1Color = WHITE; dig1 = 50; imp = 1; delay(250); break; case 1: tft.fillRect(100, 25, 15, 21, BLACK); dig2Color = WHITE; dig2 = 50; imp = 2; delay(250); break; case 2: tft.fillRect(125, 25, 15, 21, BLACK); dig3Color = WHITE; dig3 = 50; imp = 3; delay(250); break; case 3: tft.fillRect(150, 25, 15, 21, BLACK); dig4Color = WHITE; dig4 = 50; imp = 4; delay(250); break; default: break; } } if (p.x > 230 && p.x < 280 && p.y > 130 && p.y < 160) //Sets up push for button 3 -SFO { //Refer to comment on button 1 above. -SFO switch (imp) { case 0: tft.fillRect(75, 25, 15, 21, BLACK); dig1Color = WHITE; dig1 = 51; imp = 1; delay(250); break; case 1: tft.fillRect(100, 25, 15, 21, BLACK); dig2Color = WHITE; dig2 = 51; imp = 2; delay(250); break; case 2: tft.fillRect(125, 25, 15, 21, BLACK); dig3Color = WHITE; dig3 = 51; imp = 3; delay(250); break; case 3: tft.fillRect(150, 25, 15, 21, BLACK); dig4Color = WHITE; dig4 = 51; imp = 4; delay(250); break; default: break; } } if (p.x > 30 && p.x < 80 && p.y > 90 && p.y < 120) //Sets up push for button 4 -SFO { //Refer to comment on button 1 above. -SFO switch (imp) { case 0: tft.fillRect(75, 25, 15, 21, BLACK); dig1Color = WHITE; dig1 = 52; imp = 1; delay(250); break; case 1: tft.fillRect(100, 25, 15, 21, BLACK); dig2Color = WHITE; dig2 = 52; imp = 2; delay(250); break; case 2: tft.fillRect(125, 25, 15, 21, BLACK); dig3Color = WHITE; dig3 = 52; imp = 3; delay(250); break; case 3: tft.fillRect(150, 25, 15, 21, BLACK); dig4Color = WHITE; dig4 = 52; imp = 4; delay(250); break; default: break; } } if (p.x > 130 && p.x < 180 && p.y > 90 && p.y < 120) //Sets up push for button 5 -SFO { //Refer to comment on button 1 above. -SFO switch (imp) { case 0: tft.fillRect(75, 25, 15, 21, BLACK); dig1Color = WHITE; dig1 = 53; imp = 1; delay(250); break; case 1: tft.fillRect(100, 25, 15, 21, BLACK); dig2Color = WHITE; dig2 = 53; imp = 2; delay(250); break; case 2: tft.fillRect(125, 25, 15, 21, BLACK); dig3Color = WHITE; dig3 = 53; imp = 3; delay(250); break; case 3: tft.fillRect(150, 25, 15, 21, BLACK); dig4Color = WHITE; dig4 = 53; imp = 4; delay(250); break; default: break; } } if (p.x > 230 && p.x < 280 && p.y > 90 && p.y < 120) //Sets up push for button 6 -SFO { //Refer to comment on button 1 above. -SFO switch (imp) { case 0: tft.fillRect(75, 25, 15, 21, BLACK); dig1Color = WHITE; dig1 = 54; imp = 1; delay(250); break; case 1: tft.fillRect(100, 25, 15, 21, BLACK); dig2Color = WHITE; dig2 = 54; imp = 2; delay(250); break; case 2: tft.fillRect(125, 25, 15, 21, BLACK); dig3Color = WHITE; dig3 = 54; imp = 3; delay(250); break; case 3: tft.fillRect(150, 25, 15, 21, BLACK); dig4Color = WHITE; dig4 = 54; imp = 4; delay(250); break; default: break; } } if (p.x > 30 && p.x < 80 && p.y > 50 && p.y < 80) //Sets up push for button 7 -SFO { //Refer to comment on button 1 above. -SFO switch (imp) { case 0: tft.fillRect(75, 25, 15, 21, BLACK); dig1Color = WHITE; dig1 = 55; imp = 1; delay(250); break; case 1: tft.fillRect(100, 25, 15, 21, BLACK); dig2Color = WHITE; dig2 = 55; imp = 2; delay(250); break; case 2: tft.fillRect(125, 25, 15, 21, BLACK); dig3Color = WHITE; dig3 = 55; imp = 3; delay(250); break; case 3: tft.fillRect(150, 25, 15, 21, BLACK); dig4Color = WHITE; dig4 = 55; imp = 4; delay(250); break; default: break; } } if (p.x > 130 && p.x < 180 && p.y > 50 && p.y < 80) //Sets up push for button 8 -SFO { //Refer to comment on button 1 above. -SFO switch (imp) { case 0: tft.fillRect(75, 25, 15, 21, BLACK); dig1Color = WHITE; dig1 = 56; imp = 1; delay(250); break; case 1: tft.fillRect(100, 25, 15, 21, BLACK); dig2Color = WHITE; dig2 = 56; imp = 2; delay(250); break; case 2: tft.fillRect(125, 25, 15, 21, BLACK); dig3Color = WHITE; dig3 = 56; imp = 3; delay(250); break; case 3: tft.fillRect(150, 25, 15, 21, BLACK); dig4Color = WHITE; dig4 = 56; imp = 4; delay(250); break; default: break; } } if (p.x > 230 && p.x < 280 && p.y > 50 && p.y < 80) //Sets up push for button 9 -SFO { //Refer to comment on button 1 above. -SFO switch (imp) { case 0: tft.fillRect(75, 25, 15, 21, BLACK); dig1Color = WHITE; dig1 = 57; imp = 1; delay(250); break; case 1: tft.fillRect(100, 25, 15, 21, BLACK); dig2Color = WHITE; dig2 = 57; imp = 2; delay(250); break; case 2: tft.fillRect(125, 25, 15, 21, BLACK); dig3Color = WHITE; dig3 = 57; imp = 3; delay(250); break; case 3: tft.fillRect(150, 25, 15, 21, BLACK); dig4Color = WHITE; dig4 = 57; imp = 4; delay(250); break; default: break; } } if (p.x > 30 && p.x < 80 && p.y > 10 && p.y < 40) //Sets up push for Clear button -SFO { /*The clear button erases the previous input by drawing over it, then changes each digit back to 88, the value for X and its color back to red. -SFO */ imp = 0; tft.fillRect(10, 10, 219, 50, BLACK); dig1 = 88; dig1Color = RED; dig2 = 88; dig2Color = RED; dig3 = 88; dig3Color = RED; dig4 = 88; dig4Color = RED; } if (p.x > 130 && p.x < 180 && p.y > 10 && p.y < 40) //Sets up push for button 0 -SFO { //Refer to comment on button 1 above. -SFO switch (imp) { case 0: tft.fillRect(75, 25, 15, 21, BLACK); dig1Color = WHITE; dig1 = 48; imp = 1; delay(250); break; case 1: tft.fillRect(100, 25, 15, 21, BLACK); dig2Color = WHITE; dig2 = 48; imp = 2; delay(250); break; case 2: tft.fillRect(125, 25, 15, 21, BLACK); dig3Color = WHITE; dig3 = 48; imp = 3; delay(250); break; case 3: tft.fillRect(150, 25, 15, 21, BLACK); dig4Color = WHITE; dig4 = 48; imp = 4; delay(250); break; default: break; } } if (p.x > 230 && p.x < 280 && p.y > 10 && p.y < 40) //Sets up push for enter button -SFO { /*The first portion of this button draws over the keypad to give a 'blank slate'. The second portaion takes the ASCII value of the numbers and translates them into the actual numbers by subtracting the ASCII value of 0 from them, and then holds them in the dgt variables. The tot variable then adds them up. The third section is an if statment, the maximum value of all added digits should never be over 36 (9*4) for a four digit number, unless one digit was still an X, which has a value of 88, or 40 after the ASCII value for 0 has been subtracted. If using for a 5 digit number, you will either need to change 88 (X) to 126 (~) or 196 (-) as the new sum would be maxed at 45, and thus would be possible to go past this point with the other digits adding to less than 6. If this check passes it outputs to a red LED and throws an error message, if it fails it continues on. -SFO Each scenario (invalid entry, valid entry/valid user, valid entry/invalid user) will then light a red or green LED and holds a message for 5 seconds, then resets to the beginning of the code. Eventually each entry (valid/invalid) will be logged to the same place as the user codes. -SFO */ tft.fillRect(8, 100, 231, 306, BLACK); dgt1 = dig1 - 48; dgt2 = dig2 - 48; dgt3 = dig3 - 48; dgt4 = dig4 - 48; tot = dgt1 + dgt2 + dgt3 + dgt4; //Within the if coding, it will throw an error if the sum is over 36. if (tot > 36) { tft.setCursor(10, 100); tft.setTextColor(RED); tft.print(" INVALID INPUT"); pinMode(51, OUTPUT); digitalWrite(51, HIGH); myFile = SD.open(fileName, FILE_WRITE); Serial.println("File opened."); myFile.print("Invalid Entry - Not a full code: "); myFile.print(timeStamp); myFile.println(";"); Serial.println("Entry Written"); myFile.close(); Serial.println("File Closed"); delay(5000); digitalWrite(51, LOW); softwareReset(); } /*The else code captures any full input, outputs that it is checking the ID, delays and then converts the four numbers by a bit of multiplication and addition, the new four digit number is then checked against a held code in the if statement (this will hopefully soon be linked to an SD card database with multiple numbers. -SFO */ else { tft.setCursor(10, 100); tft.setTextColor(WHITE); tft.print("Checking ID..."); delay(1000); dgt1 = dgt1 * 1000; dgt2 = dgt2 * 100; dgt3 = dgt3 * 10; code = dgt1 + dgt2 + dgt3 + dgt4; /*After the if statement verifies the code as correct, it erases the previous 'Checking ID' output and welcomes the user, in this case 'Ben'. It then lights a green LED. */ if (code == 6581) { tft.fillRect(8, 100, 231, 306, BLACK); tft.setCursor(10, 100); tft.setTextColor(WHITE); tft.print("Welcome Ben!"); pinMode(50, OUTPUT); digitalWrite(50, HIGH); delay(5000); digitalWrite(50, LOW); softwareReset(); } /* When the entered code and the sotred code do not match, then the else statment takes care of it by throwing an error message and lighting a red LED. */ else { tft.fillRect(8, 100, 231, 306, BLACK); tft.setCursor(10, 100); tft.setTextColor(RED); tft.print("ID NOT FOUND"); pinMode(51, OUTPUT); digitalWrite(51, HIGH); delay(5000); digitalWrite(51, LOW); softwareReset(); } } } } } /*This resets back to the begining, was said to be a 'dirty' way to do this, but with such a simple code shoud have no problems.-SFO */ void softwareReset() { asm volatile (" jmp 0"); }