Adafruit GFX library button functions

For other supported Arduino products from Adafruit: Shields, accessories, etc.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
xenodius
 
Posts: 8
Joined: Thu Jul 23, 2015 2:20 am

Adafruit GFX library button functions

Post by xenodius »

Hello smart humans, I'm trying to write a sketch that involves drawing 6 buttons on my Adafruit 2.8" capacitive TFT shield on my genuine Arduino Mega, 4 to increase/decrease 2 values, one to execute a charging protocol, and one to stop it prematurely. I have lots of experience with electronics and programming (R mostly), but only a little of it with Arduino specifically... and I'm currently stuck on a compile issue (IDE 1.8.10).

I first tried a long if..else series to check if the last touch fit in the frame of any button, and write a boolean for that button. That didn't work despite serial prints indicating the x/y values were adjusted correctly, and serial prints indicating the comparisons were also correct... but in trying to find a solution, I discovered the Adafruit GFX library already has more elegant functions for drawing buttons and detecting presses within their frames. I haven't been able to find any documentation on these functions, just some examples, in particular the arduin-o-phone: https://learn.adafruit.com/arduin-o-pho ... one-sketch

Lacking another reference to the button function usage in the GFX library, I followed the arduin-o-phone example with few changes and rewrote my sketch to draw my 6 buttons. Except, when I try to compile I get "'b' was not declared in this scope", for each of my "if (b == 'num') {}" statements to execute my button functions, though clearly the arduin-o-phone uses these comparisons without issue... I thought b was defined by buttons. Defining it as any variety of terms in setup will prevent the compile error, but always results in no buttons being drawn on my TFT. Any ideas what I could be missing? I've been stumped for a while but I'd prefer to fix this using the GFX library functions, as it will be much easier to improve/modify this display in the future.

Sketch:

Code: Select all

#include "Adafruit_BusIO_Register.h"
#include "Adafruit_I2CDevice.h"
#include "Adafruit_I2CRegister.h"
#include "Adafruit_SPIDevice.h"
#include "Adafruit_INA260.h"
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
#include "Adafruit_FT6206.h"
#include "Wire.h"

#define Xcv 0//X-position of target voltage text
#define Ycv 0
#define Xcc 0// X-position of target current text
#define Ycc 24

#define BUTTON_X 0
#define BUTTON_Y 60
#define BUTTON_W 90
#define BUTTON_H 30
#define BUTTON_SPACEX 120
#define BUTTON_SPACEY 35
#define BUTTON_TXTSIZE 3
char buttonlabels[6][3] = {"V Up", "C Up", "V Down", "C Down", "Charge", "Stop"};
uint16_t buttoncolors[6] = {ILI9341_BLUE, ILI9341_BLUE, ILI9341_BLUE, ILI9341_BLUE, ILI9341_GREEN, ILI9341_RED};
Adafruit_GFX_Button buttons[6];
int x,y;

#define TFT_DC 9
#define TFT_CS 10
Adafruit_INA260 ina260 = Adafruit_INA260();
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
Adafruit_FT6206 ts = Adafruit_FT6206();

//If not using breakout, change TFT pins above as desired

// Display Start button, CV/CC values with buttons to increase/decrease setpoint, and INA260 current, voltage, power, CV/CC values.

// Wait until Start is pressed to run (sets ChargeState to 1, then;

int Charge; // 0 = off, 1 = CC, 2 = CV
float CV; // Max Charge voltage
float CC; // Max Charge current
float Vraw; //mV from
float V;
int INASamples = 128;

void DrawButt() {
  for (uint8_t row = 0; row < 3; row++) {
    for (uint8_t col = 0; col < 2; col++) {
      buttons[col + row * 2].initButton(&tft, BUTTON_X + col * (BUTTON_W + BUTTON_SPACEX),
                                        BUTTON_Y + row * (BUTTON_H + BUTTON_SPACEY),
                                        BUTTON_W, BUTTON_H, ILI9341_WHITE, buttoncolors[col + row * 2], ILI9341_WHITE,
                                        buttonlabels[col + row * 2], BUTTON_TXTSIZE);
      buttons[col + row * 2].drawButton();
    }
  }
}

void CC_CV_Display() {
  tft.setCursor(Xcv, Ycv);
  tft.setTextSize(3); // 3*(5x8) = 15x24 per char
  tft.setTextColor(ILI9341_WHITE);
  tft.print("MaxV:");
  tft.println(CV);

  tft.setCursor(Xcc, Ycc);
  tft.print("MaxA:");
  tft.println(CC);
}

void ButtDetective() {
  TS_Point p;
  if (ts.touched() > 0) {
    p = ts.getPoint();
  } else {
    p.x = p.y = p.z = -1;
  }
  if (p.z != -1) {
    int y = 320 - p.y;
    int x = 240 - p.x;
    Serial.print("X");
    Serial.print(x);
    Serial.print("y");
    Serial.println(y);
  }
  for (uint8_t b = 0; b < 6; b++) {
    if (buttons[b].contains(x, y)) {
      buttons[b].press(true);
      Serial.println("Touch me harder daddy!");
    } else {
      buttons[b].press(false);
    }
  }
}

void ButtAction() {
  if (b == 0) {
    float CV = (CV + 0.10);
    Serial.println("CV up!");
  }
  if (b == 1) {
    float CC = (CC + 0.5);
    Serial.println("CC up!");
  }
  if (b == 2) {
    float CV = (CV - 0.10);
    Serial.println("CV down!");
  }
  if (b == 3) {
    float CC = (CC - 0.5);
    Serial.println("CC down!");
  }
  if (b == 4) {
    int Charge = 1;
    Serial.println("Charging!");
  }
  if (b == 5) {
    int Charge = 0;
    Serial.println("Orisa online... HALT!");
  }
}

void BeginCharge() {
  // Code to close NPN to short HSP750-48 REMOTE ON/OFF pins and PV (program voltage) pins,
  // and open NPN to open PC pin, close NPN to drive PC pin-- scale slowly up from 2V minimum until current >= CC setting

  // When voltage > or ~= CV, set ChargeState = 2, enabling code to close NPN to short meanwell PC pin, open NPN for PV pin short and open NPN to drive PV with values from some kind of lookup array. I think "char PVlookup[x] = [y]" up with defines?
  // When current <50mA, return ChargeState to 0 (disconnecting Meanwell REMOTE) and trigger buzzer for 1 sec. Add code to loop to check INA260 power periodically, at end of charge display total energy added in charge cycle above SV/SC, below buttons.
}

void setup() {
  Serial.begin(115200);
  Serial.println("Mmm, my input is so turned on right now!");

  tft.begin();
  ts.begin(); // Start touchscreen
  tft.fillScreen(ILI9341_BLACK);

  Wire.begin();
  pinMode(A0, OUTPUT);
  pinMode(A1, OUTPUT);

  digitalWrite (A0, HIGH); // Close NPN for to set HSP-750-48's REMOTE ON/OFF to OFF
}

void loop() {
  CC_CV_Display();
  ButtDetective();
  ButtAction();
  delay(50);
}

User avatar
xenodius
 
Posts: 8
Joined: Thu Jul 23, 2015 2:20 am

Re: Adafruit GFX library button functions

Post by xenodius »

Dunno if this is helpful to anyone else, but I gave up on the arduin-o-phone approach that I did not understand and rewrote my whole sketch using if...else comparisons and drawing each button as simple textfields with black backgrounds (to overwrite the old values). Not terribly fast, though.

Oddly the values always print at 0.000 until modified despite being defined as 84 (volts) or 17 (amps) in setup, if anyone sees why I'd appreciate a comment.

With INA260 sense functions, some transistors switches, and scaled outputs by a calibrated nonlinear array I'll have a an inexpensive yet time-consuming programmable 1500W charger so I can reduce wear on my custom 24kw/ 3.2kwhr ebike battery.

Code: Select all

#include "Adafruit_BusIO_Register.h"
#include "Adafruit_I2CDevice.h"
#include "Adafruit_I2CRegister.h"
#include "Adafruit_SPIDevice.h"
#include "Adafruit_INA260.h"
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
#include "Adafruit_FT6206.h"
#include "Wire.h"

#define TFT_DC 9
#define TFT_CS 10
Adafruit_INA260 ina260 = Adafruit_INA260();
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
Adafruit_FT6206 ts = Adafruit_FT6206();
TS_Point p;
int x, y;

int ChargeState; // 0 = off, 1 = CC, 2 = CV
int CVCounter = 840;
int CCCounter = 170;
float CV;   // Max Charge voltage
float CC;   // Max Charge current
long Vraw; //mV from INA260
long Craw;
long SV;   //Converted supply voltage
long SC;
int INASamples = 128;

#define TXTSize 3 // Variables for button X/Y, width, height used for text cursor and touch detection
#define TXTHeight (8*TXTSize)
#define CV_X 0
#define CV_Y 0
#define CV_W 135

#define CC_X 0
#define CC_Y 24
#define CC_W CV_W

#define CVUp_X    0
#define CVUp_Y    60
#define CVUp_W    90
#define CVDown_X  0
#define CVDown_Y  100
#define CVDown_W  CVUp_W

#define CCUp_X    120
#define CCUp_Y    60
#define CCUp_W    90
#define CCDown_X  120
#define CCDown_Y  100
#define CCDown_W  CCUp_W

#define Charge_X  0
#define Charge_Y  140
#define Charge_W  90
#define Stop_X    120
#define Stop_Y    140
#define Stop_W    Charge_W

#define SV_X 0
#define SV_Y 180
#define SV_W 90
#define SC_X 0
#define SC_Y 210
#define SC_W SV_W

void DrawVal(){ //Draw voltage and current limits, as well as INA260 supply voltage and current.
  tft.setCursor(CV_X, CV_Y);
  tft.setTextSize(3); // 3*(5x8) = 15x24 per char
  tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
  tft.print("MaxV:");
  tft.println(CV, 4);

  tft.setCursor(CC_X, CC_Y);
  tft.print("MaxA:");
  tft.println(CC, 4);

  tft.setCursor(SV_X, SV_Y);
  tft.print("SupV:");
  tft.println(SV, 5);

  tft.setCursor(SC_X, SC_Y);
  tft.print("SupA:");
  tft.println(SC, 5);
}

void DrawButt() { // Draw each button
  tft.setCursor(CVUp_X, CVUp_Y);
  tft.setTextSize(TXTSize);
  tft.setTextColor(ILI9341_WHITE, ILI9341_BLUE);
  tft.print("V   Up");

  tft.setCursor(CVDown_X, CVDown_Y);
  tft.setTextSize(3);
  tft.setTextColor(ILI9341_WHITE, ILI9341_BLUE);
  tft.print("V Down");

  tft.setCursor(CCUp_X, CCUp_Y);
  tft.setTextSize(3);
  tft.setTextColor(ILI9341_WHITE, ILI9341_BLUE);
  tft.print("C   Up");

  tft.setCursor(CCDown_X, CCDown_Y);
  tft.setTextSize(3);
  tft.setTextColor(ILI9341_WHITE, ILI9341_BLUE);
  tft.print("C Down");

  tft.setCursor(Charge_X, Charge_Y);
  tft.setTextSize(3);
  tft.setTextColor(ILI9341_WHITE, ILI9341_GREEN);
  tft.print("Charge");

  tft.setCursor(Stop_X, Stop_Y);
  tft.setTextSize(3);
  tft.setTextColor(ILI9341_WHITE, ILI9341_RED);
  tft.print(" Stop ");
}

void ButtMap() { //Check if touched; if touched, retrieve coordinates and invert for rotation = 0 portrait orientation, compare with button coordinates and execute button function if matched
  TS_Point p;
  if (ts.touched() > 0) {
    p = ts.getPoint();
    x = map(p.x, 0, 240, 240, 0);
    y = map(p.y, 0, 320, 320, 0);
  } else {
    p.x = p.y = p.z = -1;
  }
  if (p.z != -1) {
    Serial.print("X:");
    Serial.println(x);
    Serial.print("Y:");
    Serial.println(y);
    
    if ((CVUp_X <= x) && (x <= (CVUp_X + CVUp_W)) && (CVUp_Y <= y) && (y <= (CVUp_Y + TXTHeight))) {
      CVUpButt();
      Serial.println(CV, 1);
      Serial.println(CVCounter);
    }
    else if ((CVDown_X <= x) && (x <= (CVDown_X + CVDown_W)) && (CVDown_Y <= y) && (y <= (CVDown_Y + TXTHeight))) {
      CVDownButt();
      Serial.println(CV, 1);
      Serial.println(CVCounter);
    } 
    else if ((CCUp_X <= x) && (x <= (CCUp_X + CCUp_W)) && (CCUp_Y <= y) && (y <= (CCUp_Y + TXTHeight))) {
      CCUpButt();
      Serial.println(CC, 4);
    }
    else if ((CCDown_X <= x) && (x <= (CCDown_X + CCDown_W)) && (CCDown_Y <= y) && (y <= (CCDown_Y + TXTHeight))) {
      CCDownButt();
      Serial.println(CC, 4);
    }
    else if ((Charge_X <= x) && (x <= (Charge_X + Charge_W)) && (Charge_Y <= y) && (y <= (Charge_Y + TXTHeight))) {
      ChargeButt();
      Serial.println(ChargeState);
    }
    else if ((Stop_X <= x) && (x <= (Stop_X + Stop_W)) && (Stop_Y <= y) && (y <= (Stop_Y + TXTHeight))) {
      StopButt();
      Serial.println(ChargeState);
    }
  }
}

void CVUpButt() {
  CVCounter = ++CVCounter;
  CV = (0.1*CVCounter);
  Serial.print("CVUp Executed");
}
void CVDownButt() {
  CVCounter = --CVCounter;
  CV = (0.1*CVCounter);
  Serial.print("CVDown Executed");
}
void CCUpButt() {
  CCCounter = ++CCCounter;
  CC = (0.1*CCCounter);
  Serial.print("CCUp Executed");
}
void CCDownButt() {
  CCCounter = --CCCounter;
  CC = (0.1*CCCounter);
  Serial.print("CCDown Executed");
}
void ChargeButt() {
  ChargeState = 1;
  Serial.print("Charge Executed");
}
void StopButt() {
  ChargeState = 0;
  Serial.print("Stop Executed");
}

void BeginCharge() {
  // Code to close NPN to short RSP-750-48 REMOTE ON/OFF pins and PV (program voltage) pins,
  // and open NPN to open PC pin, close NPN to drive PC pin-- scale slowly up from 2V minimum until current >= CC setting, if greater, decrement slightly.

  // When supply voltage >= CV, set ChargeState = 2, enabling code to close NPN to short meanwell PC pin, open NPN for PV pin short and close NPN to drive PV with values from some kind of lookup array, if linear 'map' is inaccurate
  // When current <50mA, return ChargeState to 0 (disconnecting Meanwell REMOTE) and trigger buzzer for 1 sec. Add code to loop to check INA260 power periodically and add to array, at end of charge display total Watt-hours added in charge cycle above SV/SC/SP, below buttons, and clear array.
}

void setup() {
  Serial.begin(115200);
  Serial.println("On");

  tft.begin();
  ts.begin(); // Start touchscreen
  tft.fillScreen(ILI9341_BLACK);
  DrawVal();
  DrawButt();
}

void loop() {
  ButtMap();
DrawVal();
}

User avatar
mikkosanz
 
Posts: 1
Joined: Sun Nov 03, 2019 11:51 pm

Re: Adafruit GFX library button functions

Post by mikkosanz »

What is the voltage output when i press the screen in the 2.8" TFT Touch Shield for Arduino w/Capacitive Touch? Can you help me to determine it?
Or is it just a fixed value ? becuase I read " IRQ- this is the captouch interrupt pin. when a touch is detected, this pin goes low"

Locked
Please be positive and constructive with your questions and comments.

Return to “Other Arduino products from Adafruit”