ImpulseAdventure / GUIslice

GUIslice drag & drop embedded GUI in C for touchscreen TFT on Arduino, Raspberry Pi, ARM, ESP8266 / ESP32 / M5stack using Adafruit-GFX / TFT_eSPI / UTFT / SDL
https://www.impulseadventure.com/elec/guislice-gui.html
MIT License
1.12k stars 204 forks source link

The button is pressed without touching the display #539

Closed eagl1 closed 1 month ago

eagl1 commented 1 month ago

Hi,

I'm working on a simple project to test the touch functionality, it turns out the button is pressed without touching the display.

Here's the code:

#include "project2_GSLC.h"

static int16_t DebugOut(char ch) { if (ch == (char)'\n') Serial.println(""); else Serial.write(ch); return 0; }

// Common Button callback
bool CbBtnCommon(void* pvGui,void *pvElemRef,gslc_teTouch eTouch,int16_t nX,int16_t nY)
{
  // Typecast the parameters to match the GUI and element types
  gslc_tsGui*     pGui     = (gslc_tsGui*)(pvGui);
  gslc_tsElemRef* pElemRef = (gslc_tsElemRef*)(pvElemRef);
  gslc_tsElem*    pElem    = gslc_GetElemFromRef(pGui,pElemRef);

  if ( eTouch == GSLC_TOUCH_UP_IN ) {
    // From the element's ID we can determine which button was pressed.
    switch (pElem->nId) {

      case E_ELEM_BTN1:
      static bool val = 0;
      val ^= 1;
      digitalWrite(PC13, val);
        break;

      default:
        break;
    }
  }
  return true;
}

void setup()
{
  Serial.begin(9600);

  gslc_InitDebug(&DebugOut);

  InitGUIslice_gen();
  pinMode(PC13, OUTPUT);

}

void loop()
{
  gslc_Update(&m_gui);
}
Pconti31 commented 1 month ago

@eagl1 First thing I noticed in your code is what I assume is to cause a LED flashing your pin is in an unknown state. Your setup code should set the initial state

  // initialize digital pin LED_BUILTIN as an output.
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW

Also, you should first add code with a serial print and look at the serial monitor debug output to make sure its not a hardware issue.

        // Output a message when the button is pressed
        static uint8_t val = 0;
        val ^= 1;
        val ? Serial.println("ON") : Serial.println("OFF");
        digitalWrite(13, val);    // turn the LED on/off
        break;

If this doesn't work then to help further a few hints will be required:

Device hardware

eagl1 commented 1 month ago
  1. OK, I found one main problem which is this problem happens with STM32 boards. I tested this code on maple mini, black pill and rp2040. The code works perfectly with the rp2040 board but not with the SMT32 boards.

  2. The display link:

http://www.lcdwiki.com/4.0inch_SPI_Module_ST7796

https://www.aliexpress.com/item/1005005936396391.html?spm=a2g0o.productlist.main.7.8359tc35tc354g&algo_pvid=a0aba396-b96c-43db-99de-d5dd4f7f60b9&algo_exp_id=a0aba396-b96c-43db-99de-d5dd4f7f60b9-3&pdp_npi=4%40dis%21USD%2111.99%2110.55%21%21%2111.99%2110.55%21%40211b617b17151344262051167e146c%2112000037979135867%21sea%21SA%21175575373%21&curPageLogUid=RG0nt9ELRVN1&utparam-url=scene%3Asearch%7Cquery_from%3A

  1. As there were no files for SMT32 and rp2040 on TFT_eSPI, so I copied two files for both boards:
    // STM32:
    // ------------------------------------------------------
    //#include "../configs/stm32-adagfx-mcufriend-notouch.h"
    //#include "../configs/stm32-adagfx-mcufriend-simple.h"
    #include "../configs/stm32-tftespi-default-xpt2046.h"
    // #include "../configs/rp2040-tftespi-default-xpt2046.h"

Here are my files: GUIslice.zip

Pconti31 commented 1 month ago

@eagl1 You failed to include an important config file TFT_ESPI User_Setup.h Your app won't work unless you first edit User_Setup.h and comment out TOUCH_CS By the way make sure the TFT_eSPI examples work before trying GUIslice. If they do and GUIslice api still doesn't you will need help from @ImpulseAdventure Calvin, I only support the Builder. Paul--

eagl1 commented 1 month ago
  1. I'm including the right config file TFT_ESPI in User_Setup.h
  2. Commenting out TOUCH_CS caused this error: 'class TFT_eSPI' has no member named 'getTouch'
  3. TFT_eSPI examples works fine, I did this test and it works flawlessly:
// Button widget demo, requires SPI display with touch screen

// Requires widget library here:
// https://github.com/Bodmer/TFT_eWidget

#include "Free_Fonts.h" // Include the header file attached to this sketch

#include <TFT_eSPI.h>              // Hardware-specific library
#include <TFT_eWidget.h>           // Widget library

TFT_eSPI tft = TFT_eSPI();         // Invoke custom library

#define CALIBRATION_FILE "/TouchCalData1"
#define REPEAT_CAL false

ButtonWidget btnL = ButtonWidget(&tft);
ButtonWidget btnR = ButtonWidget(&tft);

#define BUTTON_W 100
#define BUTTON_H 50

// Create an array of button instances to use in for() loops
// This is more useful where large numbers of buttons are employed
ButtonWidget* btn[] = {&btnL , &btnR};;
uint8_t buttonCount = sizeof(btn) / sizeof(btn[0]);

void btnL_pressAction(void)
{
  if (btnL.justPressed()) {
    Serial.println("Left button just pressed");
    btnL.drawSmoothButton(true);
  }
}

void btnL_releaseAction(void)
{
  static uint32_t waitTime = 1000;
  if (btnL.justReleased()) {
    Serial.println("Left button just released");
    btnL.drawSmoothButton(false);
    btnL.setReleaseTime(millis());
    waitTime = 10000;
  }
  else {
    if (millis() - btnL.getReleaseTime() >= waitTime) {
      waitTime = 1000;
      btnL.setReleaseTime(millis());
      btnL.drawSmoothButton(!btnL.getState());
    }
  }
}

void btnR_pressAction(void)
{
  if (btnR.justPressed()) {
    btnR.drawSmoothButton(!btnR.getState(), 3, TFT_BLACK, btnR.getState() ? "OFF" : "ON");
    Serial.print("Button toggled: ");
    if (btnR.getState()) Serial.println("ON");
    else  Serial.println("OFF");
    btnR.setPressTime(millis());
  }

  // if button pressed for more than 1 sec...
  if (millis() - btnR.getPressTime() >= 1000) {
    Serial.println("Stop pressing my buttton.......");
  }
  else Serial.println("Right button is being pressed");
}

void btnR_releaseAction(void)
{
  // Not action
}

void initButtons() {
  uint16_t x = (tft.width() - BUTTON_W) / 2;
  uint16_t y = tft.height() / 2 - BUTTON_H - 10;
  btnL.initButtonUL(x, y, BUTTON_W, BUTTON_H, TFT_WHITE, TFT_RED, TFT_BLACK, "Button", 1);
  btnL.setPressAction(btnL_pressAction);
  btnL.setReleaseAction(btnL_releaseAction);
  btnL.drawSmoothButton(false, 3, TFT_BLACK); // 3 is outline width, TFT_BLACK is the surrounding background colour for anti-aliasing

  y = tft.height() / 2 + 10;
  btnR.initButtonUL(x, y, BUTTON_W, BUTTON_H, TFT_WHITE, TFT_BLACK, TFT_GREEN, "OFF", 1);
  btnR.setPressAction(btnR_pressAction);
  //btnR.setReleaseAction(btnR_releaseAction);
  btnR.drawSmoothButton(false, 3, TFT_BLACK); // 3 is outline width, TFT_BLACK is the surrounding background colour for anti-aliasing
}

void setup() {
  Serial.begin(115200);
  tft.begin();
  tft.setRotation(0);
  tft.fillScreen(TFT_BLACK);
  tft.setFreeFont(FF18);

  // Calibrate the touch screen and retrieve the scaling factors
  //touch_calibrate();
  initButtons();
}

void loop() {
  static uint32_t scanTime = millis();
  uint16_t t_x = 9999, t_y = 9999; // To store the touch coordinates

  // Scan keys every 50ms at most
  if (millis() - scanTime >= 50) {
    // Pressed will be set true if there is a valid touch on the screen
    bool pressed = tft.getTouch(&t_x, &t_y);
    scanTime = millis();
    for (uint8_t b = 0; b < buttonCount; b++) {
      if (pressed) {
        if (btn[b]->contains(t_x, t_y)) {
          btn[b]->press(true);
          btn[b]->pressAction();
        }
      }
      else {
        btn[b]->press(false);
        btn[b]->releaseAction();
      }
    }
  }
}

If they do and GUIslice api still doesn't you will need help from @ImpulseAdventure Calvin, I only support the Builder. Paul--

Thank you so much for the support, but how to contact @ImpulseAdventure Calvin ?

eagl1 commented 1 month ago

``I think I found something that might be the cause of the problem with STM32 boards specifically.

I found this in GUIslice_drv_tft_espi.cpp - line: 58-76.

#if defined(DRV_TOUCH_ADA_STMPE610)
  #include <SPI.h>
  #include <Wire.h>
  #include "Adafruit_STMPE610.h"
#elif defined(DRV_TOUCH_ADA_FT6206)
  #include <Wire.h>
  #include "Adafruit_FT6206.h"
#elif defined(DRV_TOUCH_ADA_SIMPLE)
  #include <stdint.h>
  #include <TouchScreen.h>
#elif defined(DRV_TOUCH_XPT2046_STM)
  // NOTE: This file is located in the Arduino_STM32 library:
  //       Arduino_STM32/STM32F1/libraries/Serasidis_XPT2046_touch/src/XPT2046_touch.h
  #include <XPT2046_touch.h>
#elif defined(DRV_TOUCH_XPT2046_PS)
  #include <XPT2046_Touchscreen.h>
#elif defined(DRV_TOUCH_HANDLER)
  #include <GUIslice_th.h>
#endif

So this:

  // NOTE: This file is located in the Arduino_STM32 library:
  //       Arduino_STM32/STM32F1/libraries/Serasidis_XPT2046_touch/src/XPT2046_touch.h
  #include <XPT2046_touch.h>

My question now is where to find XPT2046_touch.h ?

Is it this one https://github.com/PaulStoffregen/XPT2046_Touchscreen ? but it's not the same letters count.

Pconti31 commented 1 month ago

@eagl1 you can send email to guislice@gmail.com

I don't think you want PaulStoffregen/XPT2046_Touchscreen I just followed the path given Arduino_STM32/STM32F1/libraries/Serasidis_XPT2046_touch/ and zipped it for you. No idea if it will work or not. Unzip to your Arduino/libraries folder Serasidis_XPT2046_touch.zip Paul--

Pconti31 commented 1 month ago

@eagl1 Before you try that new touch library, if you have TFT_eSPI working without it then I would keep TOUCH_CS uncommented and instead inside your GUIslice/configs/stm32-tftespi-default-xpt2046.h change to use the TFT_eSPI internal touch driver like so

  // -----------------------------------------------------------------------------
  // SECTION 1: Device Mode Selection
  // - The following defines the display and touch drivers
  //   and should not require modifications for this example config
  // -----------------------------------------------------------------------------
  #define DRV_DISP_TFT_ESPI         // bodmer/TFT_eSPI
  #define DRV_TOUCH_TFT_ESPI        // TFT_eSPI integrated XPT2046 touch driver
  #define DRV_TOUCH_IN_DISP         // Use display driver (TFT_eSPI) for touch events
// #define DRV_TOUCH_XPT2046_STM        // XPT2046 touch driver    (rogerclarkmelbourne/Arduino_STM32)
//  #define DRV_TOUCH_XPT2046_PS      // PaulStoffregen/XPT2046_Touchscreen

Paul--

eagl1 commented 1 month ago

Worked perfectly :)

Thank you so much man !