I've got quite a bit of time in this now and I may have bitten off more that I can chew.
I'm using an Uno R3, but it will be a bare bones 328P-AU or the 328PB, and I bought an ILI9341 with touchscreen controller. Amazon Link
I found some videos by Bytes and Bits that helped me get the screen up and running and being able to use the touch. Most tutorials for the ili9341 are using a shield that I am not using, so this has already been difficult, while this is using the adafruit 9341 library, it is using that only for the display. The touchscreen part is using the XPT2046 library, which there are not very many examples in it to learn from.
What I need... I need to be able to make a home screen where I choose from different parameters to adjust and then run the main function of the device using the chosen values. I've tried multiple things and I can't get this to work. I have never created a menu before, nor have I tried using a touch screen, so it is all new.
I can get what I want on the first page, I can then select an item on the first page and goto a second page. If I go to the first option, I can then change the value of the parameter. I can even go back to the main menu, but that is where it breaks. I get button bleed through and the values from whatever page I was on also show up on the home screen now, and you can't get back out of the home page after that.
Once I get that all sorted, I would also like to get rid of having to calibrate every time I reset or turn on the display.
Below is my code. Thanks!
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
#include "XPT2046_Touchscreen.h"
#include "Math.h"
// Define SPI pins for both display and touch
#define TFT_CS 10
#define TFT_DC 9
#define TFT_MOSI 11
#define TFT_CLK 13
#define TFT_RST 8
#define TFT_MISO 12
#define TS_CS 7
#define ROTATION 3
char currentPage;
// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC/RST
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
XPT2046_Touchscreen ts(TS_CS);
// calibration values
float xCalM = 0.0, yCalM = 0.0; // gradients
float xCalC = 0.0, yCalC = 0.0; // y axis crossing points
int8_t blockWidth = 20; // block size
int8_t blockHeight = 20;
int16_t blockX = 0, blockY = 0; // block position (pixels)
class ScreenPoint {
public:
int16_t x;
int16_t y;
// default constructor
ScreenPoint(){
}
ScreenPoint(int16_t xIn, int16_t yIn){
x = xIn;
y = yIn;
}
};
class Button {
public:
int x;
int y;
int width;
int height;
char *text;
Button(){
}
void initButtonP(int xPos, int yPos, int butWidth, int butHeight, char *butText){
x = xPos;
y = yPos;
width = butWidth;
height = butHeight;
text = butText;
renderP();
}
void initButtonM(int xPos, int yPos, int butWidth, int butHeight, char *butText){
x = xPos;
y = yPos;
width = butWidth;
height = butHeight;
text = butText;
renderM();
}
void renderP(){
tft.fillRect(x,y,width,height,ILI9341_GREEN);
tft.setCursor(x+5,y+5);
tft.setTextSize(2);
tft.setTextColor(ILI9341_WHITE);
tft.print(text);
}
void renderM(){
tft.fillRect(x,y,width,height,ILI9341_RED);
tft.setCursor(x+5,y+5);
tft.setTextSize(2);
tft.setTextColor(ILI9341_WHITE);
tft.print(text);
}
bool isClicked(ScreenPoint sp) {
if ((sp.x >= x) && (sp.x <= (x+width)) && (sp.y <= (y+height))){
return true;
}
else {
return false;
}
}
};
ScreenPoint getScreenCoords(int16_t x, int16_t y){
int16_t xCoord = round((x * xCalM) + xCalC);
int16_t yCoord = round((y * yCalM) + yCalC);
if(xCoord < 0) xCoord = 0;
if(xCoord >= tft.width()) xCoord = tft.width() - 1;
if(yCoord < 0) yCoord = 0;
if(yCoord >= tft.height()) yCoord = tft.height() - 1;
return(ScreenPoint(xCoord, yCoord));
}
void calibrateTouchScreen(){
TS_Point p;
int16_t x1,y1,x2,y2;
tft.fillScreen(ILI9341_BLACK);
// wait for no touch
while(ts.touched());
tft.drawFastHLine(10,20,20,ILI9341_RED);
tft.drawFastVLine(20,10,20,ILI9341_RED);
while(!ts.touched());
delay(50);
p = ts.getPoint();
x1 = p.x;
y1 = p.y;
tft.drawFastHLine(10,20,20,ILI9341_BLACK);
tft.drawFastVLine(20,10,20,ILI9341_BLACK);
delay(500);
while(ts.touched());
tft.drawFastHLine(tft.width() - 30,tft.height() - 20,20,ILI9341_RED);
tft.drawFastVLine(tft.width() - 20,tft.height() - 30,20,ILI9341_RED);
while(!ts.touched());
delay(50);
p = ts.getPoint();
x2 = p.x;
y2 = p.y;
tft.drawFastHLine(tft.width() - 30,tft.height() - 20,20,ILI9341_BLACK);
tft.drawFastVLine(tft.width() - 20,tft.height() - 30,20,ILI9341_BLACK);
int16_t xDist = tft.width() - 40;
int16_t yDist = tft.height() - 40;
// translate in form pos = m x val + c
// x
xCalM = (float)xDist / (float)(x2 - x1);
xCalC = 20.0 - ((float)x1 * xCalM);
// y
yCalM = (float)yDist / (float)(y2 - y1);
yCalC = 20.0 - ((float)y1 * yCalM);
Serial.print("x1 = ");Serial.print(x1);
Serial.print(", y1 = ");Serial.print(y1);
Serial.print("x2 = ");Serial.print(x2);
Serial.print(", y2 = ");Serial.println(y2);
Serial.print("xCalM = ");Serial.print(xCalM);
Serial.print(", xCalC = ");Serial.print(xCalC);
Serial.print("yCalM = ");Serial.print(yCalM);
Serial.print(", yCalC = ");Serial.println(yCalC);
}
Button btnIP;
Button btnIM;
Button btnVP;
Button btnVM;
Button btnMI;
Button btnMV;
Button btnMM;
int IV = 30;
float VV = 385.00;
void setup() {
Serial.begin(9600);
// avoid chip select contention
pinMode(TS_CS, OUTPUT);
digitalWrite(TS_CS, HIGH);
pinMode(TFT_CS, OUTPUT);
digitalWrite(TFT_CS, HIGH);
tft.begin();
tft.setRotation(ROTATION);
tft.fillScreen(ILI9341_BLACK);
ts.begin();
ts.setRotation(ROTATION);
calibrateTouchScreen();
//btnMV.initButtonP(0,50,180,25,"Discharge");
//btnMI.initButtonP(0,100,180,25,"Voltage");
//btnVP.initButtonP(175,125,20,25,"+");
//btnVM.initButtonM(175,200,80,25,"Main Menu");
currentPage = '0'; // Indicates that we are at Home Screen
Home();
}
unsigned long lastFrame = millis();
void loop(void) {
ScreenPoint sp;
// limit frame rate
while((millis() - lastFrame) < 20);
lastFrame = millis();
// Home Screen
if(currentPage=='0'){
if (ts.touched()) {
TS_Point p = ts.getPoint();
sp = getScreenCoords(p.x, p.y);
if(btnMV.isClicked(sp)){
currentPage = '1'; // Go to Discharge Current
tft.fillScreen(ILI9341_BLACK);
discharge();
}
else if(btnMI.isClicked(sp)){
currentPage = '2'; // Go to Cutoff Voltage
tft.fillScreen(ILI9341_BLACK);
cutoff();
}
}
}
// Discharge Current
if(currentPage=='1'){
tft.setCursor(225,50);
tft.print(IV);
tft.setCursor(275,50);
tft.print("A");
if (ts.touched()) {
TS_Point p = ts.getPoint();
sp = getScreenCoords(p.x, p.y);
if(btnIP.isClicked(sp)){
IV++;
tft.fillRect(200,50,125,50,ILI9341_BLACK);
delay(50);
}
else if (btnIM.isClicked(sp)){
IV--;
tft.fillRect(200,50,125,50,ILI9341_BLACK);
delay(50);
}
else if (btnMM.isClicked(sp)){
currentPage=='0';
Home();
}
}
}
// Cutoff Voltage
if(currentPage=='2'){
tft.setCursor(205,50);
tft.print(VV/100);
tft.setCursor(275,50);
tft.print("V");
if (ts.touched()) {
TS_Point p = ts.getPoint();
sp = getScreenCoords(p.x, p.y);
if(btnIP.isClicked(sp)){
VV++;
tft.fillRect(205,50,60,50,ILI9341_BLACK);
delay(50);
}
else if (btnIM.isClicked(sp)){
VV--;
tft.fillRect(205,50,60,50,ILI9341_BLACK);
delay(50);
}
else if (btnMM.isClicked(sp)){
currentPage=='0';
Home();
}
}
}
}
void Home(){
tft.fillScreen(ILI9341_BLACK);
btnMV.initButtonP(0,50,180,25,"Discharge");
btnMI.initButtonP(0,100,180,25,"Voltage");
}
void discharge(){
btnIP.initButtonP(175,50,20,25,"+");
btnIM.initButtonM(175,75,20,25,"-");
btnMM.initButtonM(100,200,140,25,"Main Menu");
tft.setCursor(0,50);
tft.setTextSize(3);
tft.setTextColor(ILI9341_YELLOW);
tft.print("Discharge");
tft.setCursor(0,75);
tft.print("Current");
tft.setCursor(225,50);
tft.print(IV);
tft.setCursor(275,50);
tft.print("A");
}
void cutoff(){
btnIP.initButtonP(135,50,20,25,"+");
btnIM.initButtonM(135,75,20,25,"-");
btnMM.initButtonM(100,200,140,25,"Main Menu");
tft.setCursor(0,50);
tft.setTextSize(3);
tft.setTextColor(ILI9341_BLUE);
tft.print("Voltage");
tft.setCursor(0,75);
tft.print("Cutoff");
}