Unable to decipher communication from touch LCD to ESP32

I have this touch LCD being used with an ESP32 board.

I am able to upload data to this LCD, but the touch buttons on this LCD are sending some signals in Low Byte which are then supposed to initiate some process in the microcontroller. Below is the code which is supposed to handle the incoming communication. It is not working. Where am I going wrong?

void Touch_Button_Activity()
{
  if (Serial2.available() >= 9) // Ensure there are at least 9 bytes available
  {
    for (int i = 0; i < 9; i++)
    {
      Buffer[i] = Serial2.read();
    }
    
    // Debug: Print buffer content
    Serial.print("Buffer: ");
    for (int i = 0; i < 9; i++)
    {
      Serial.print(Buffer[i], HEX);
      Serial.print(" ");
    }
    Serial.println();

    if (Buffer[0] == 0x5A)
    {
      switch (Buffer[4])
      {
        case 0x55:
          // Use the Low Byte (Buffer[8]) to determine the touch button state
          switch (Buffer[8])
          {
            case 0:
              Baseline = average;
              Serial.println("Baseline set to average");
              break;
            case 1:
              Baseline = average;
              Serial.println("Baseline set to average");
              break;
            case 2:
              Factor = average - Baseline;
              Serial.println("Factor set to average - Baseline");
              break;
            default:
              Serial.println("Unexpected value in Buffer[8]");
              break;
          }
          break;

        default:
          Serial.println("No communication received from touch screen.");
          break;
      }
    }
    else
    {
      Serial.println("Invalid start byte in Buffer");
    }
  }
}


Below are the touch button settings in the UI.

Hi @guava123456

welcome to the arduino-forum.

You deleted your two other threads on the same subject this is good.
double-posting is against forum-rules.

imagine any person trying to analyse what the problem is.
Any person
except that person that has had this special kind of faulty behaviour dozens of time

will start analysing

  • by reading your complete sketch => post your complete sketch
  • by reading the datasheet => provide the datasheet of this LCD
  • printing the received bytes to the serial monitor => post what is printed to the serial monitor as a code-section
  • uploading a demo-code that is well known for working for checking if hardware-wiring is OK

You are working on an informatic poject and what is needed most in an informatic project is information.

Hard to tell; what output do you get from your sketch on the Serial monitor if you input some data on the keypad? Do you get anything? Can you show us some examples of the output that's generated? Do you have a protocol description that you can post that shows what kind of data format is being sent by the module?

Also, I see there's two TX/RX pairs on the header of your UI module; are you using the correct pair? Have you also verified that the TTL/RS232 jumper on the PCB is correctly set for your application?

The product-page has a leave your message feature.

I would send the manufacturer a message with quoting the exact display-type as text and copy & paste the link of the website itself

that they shall send you all the documentation for exact that touch-LCD.

If you want to start yourself you can crawl through their development-guide
https://www.dwin-global.com/development-guide/

Hi,

Below is my complete code.

#include <Arduino.h>
#include <Adafruit_ADS1X15.h>
#include <cmath>


Adafruit_ADS1115 ads;  /* Use this for the 16-bit version */

const int numReadings = 100; // Number of readings to average
int readings[numReadings];  // Array to store readings
int readIndex = 0;          // Index for current reading
int total = 0;              // Running total of readings
int average = 0;            // Moving average

bool CodeRunningFirstTime = true;
unsigned long TimeSinceCodeStart;
unsigned long LastDataDisplayMillis;

double Baseline = 0.00;
double Factor = 260.00;
double Volume = 0.00;

    //DWIN Part
    const byte rxPin = 16;
    const byte txPin = 17;
    #define some_value_add 0x50
    unsigned char HMI_some_value[8] = {0x5A, 0xA5, 0x05, 0x82, some_value_add, 0x00, 0x00, 0x00};
    unsigned char Buffer[9];


            




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

  if (!ads.begin())
  {
    Serial.println("Failed to initialize ADS.");
    while (1);
  }
  else
  {
    Serial.println("ADS Initialised");
  }

  // Initialize the readings array
  for (int i = 0; i < numReadings; i++)
  {
    readings[i] = 0;
  }
  

      //DWIN Part
      Serial2.begin(115200, SERIAL_8N1, rxPin, txPin); // Initialize Serial2 on pins 16 and 17

            

   TimeSinceCodeStart = millis();
   LastDataDisplayMillis = millis();
}


void loop()
{
  
  int16_t adc0;
  adc0 = ads.readADC_SingleEnded(0);

  // Update the total by subtracting the oldest reading and adding the new reading
  total = total - readings[readIndex] + adc0;
  // Store the new reading in the array
  readings[readIndex] = adc0;
  // Move to the next index
  readIndex = (readIndex + 1) % numReadings;
  // Calculate the moving average
  average = total / numReadings;

  //Serial.println(average);
  
  if((millis()-TimeSinceCodeStart) > 2000)
  {
     if(CodeRunningFirstTime == true)
    {
      Baseline = average;
      CodeRunningFirstTime = false;
    } 
  }

  Volume = (average - Baseline)/Factor;
  
  
  Data_Display();
  Touch_Button_Activity();

}

void Data_Display() 
{
  if((millis()-LastDataDisplayMillis) >= 0)
  {
    int t_int = Volume * 100; // Convert float to int to preserve two decimal places
  
    HMI_some_value[6] = highByte(t_int);
    HMI_some_value[7] = lowByte(t_int);
    
    Serial2.write(HMI_some_value, 8); // Use Serial2 instead of SoftwareSerial

    LastDataDisplayMillis = millis();
  }
  
  
  
}

void Touch_Button_Activity()
{
  if (Serial2.available() >= 9) // Ensure there are at least 9 bytes available
  {
    for (int i = 0; i < 9; i++)
    {
      Buffer[i] = Serial2.read();
    }
    
    // Debug: Print buffer content
    Serial.print("Buffer: ");
    for (int i = 0; i < 9; i++)
    {
      Serial.print(Buffer[i], HEX);
      Serial.print(" ");
    }
    Serial.println();

    if (Buffer[0] == 0x5A)
    {
      switch (Buffer[4])
      {
        case 0x55:
          // Use the Low Byte (Buffer[8]) to determine the touch button state
          switch (Buffer[8])
          {
            case 0:
              Baseline = average;
              Serial.println("Baseline set to average");
              break;
            case 1:
              Baseline = average;
              Serial.println("Baseline set to average");
              break;
            case 2:
              Factor = average - Baseline;
              Serial.println("Factor set to average - Baseline");
              break;
            default:
              Serial.println("Unexpected value in Buffer[8]");
              break;
          }
          break;

        default:
          Serial.println("No communication received from touch screen.");
          break;
      }
    }
    else
    {
      Serial.println("Invalid start byte in Buffer");
    }
  }
}

I am able to send data to the LCD but not from the LCD to the board.

Ok, I just discovered through debugging that when this below line (Lets call it "Line A") is not commented out....

...this below "if condition" (Lets Call it "Condition A") is not fulfilled.

But when "Line A" is commented out, "Condition A" is fullfilled.

Which means if the variable "Volume" is anything more than 0.00, serial2 becomes unavailable to touch button activity. Why?

I don't understand what you want to say with that.

Which is the "first line commented out?"

  • first line of your complete sketch?
  • the line
void Touch_Button_Activity()

?
any other line?

analyse at my writing-style:
I do not write about a whatever "first" line
I repeatedly write the line explicitly
So there is no room for interpretation.

If you comment out the line

void Touch_Button_Activity()

this means you remove the function "Touch_Button_Activity()"

You can solve your problems two ways:

way 1: always quickly posting a short description just for having posted quickly

way2: taking the time to post a complete sketch each and every time
including what gets printed to the serial monitor
writing not with words like "this", "it", 2the second" etc.
but explcitly naming everything by its clearly identifiable and unique name.

Which in the end will be faster than quick postings.
Quick but less informative postings just cause asking back or not answering at all.
=> result delayed solving of problems.

What you've found out is that it really helps to whittle down your sketch to the bare minimum required to demonstrate the problem. So I'd recommend to make a new sketch that only reads input from the LCD/keypad module, and outputs it back to the Serial monitor so you can see what's going on - nothing else. That will allow you to learn to interface with the keypad module properly. Then start dressing it back up and add functionality.

What's biting you currently is a form of interactive complexity; i.e. your system exhibits behavior due to unintended interactions between parts (in this case of your own software) that you did not foresee. The oversight is due to the complexity surpassing your ability to comprehend what's going on. So the fundamental way to deal with this is to break down the whole thing into smaller chunks that you do understand, so that their behavior once again becomes linear and predictable.

Feel free to ignore the second, theoretical paragraph and just remember what the Romans also knew very well: "divide and conquer".

Ok, I'll try a simpler sketch and get back with the results.

@StefanL38 I have tried to make my last post better understandable. Hope that helps.

This is contradictionary.
Your are calling the line

if (Serial2.available() >= 9)

Line A

you could make this clear by writing

DIRECTLY WRITING

if (Serial2.available() >= 9) // <== line A

Now you write

commenting out line a means

DIRECTLY WRITING the line of code

// if (Serial2.available() >= 9) // <== line A

and this means the same as if you would have deleted the line

if (Serial2.available() >= 9) // <== line A

So your writing of

is simply wrong. There is no more condition when you have commented out the line

if (Serial2.available() >= 9) // <== line A

Simply post both versions of your complete sketch
the version with whatever lines active

the version with whatever commented out

first three lines of your code

#include <Arduino.h>
#include <Adafruit_ADS1X15.h>
#include <cmath>

Are you sure that the line

#include <cmath>

compiles for you?

usually these files are named

#include <cmath. h >

Your line has no ".h"

#include <cmath> // should be #include <cmath.h>

yes it compiles. I wouldn't expect it too, but it does.

What exact type of microcontroller are you using?

esp32 development board.

Here is your code with additional debug-printing to the serial monitor that makes visible what is going on.

This is the usual way to analyse and narrow down such problems
I have written above what kind of information you should provide.

// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *
// a detailed explanation how these macros work is given in this tutorial
// https://forum.arduino.cc/t/comfortable-serial-debug-output-short-to-write-fixed-text-name-and-content-of-any-variable-code-example/888298

#define dbg(myFixedText, variableName) \
  Serial.print( F(#myFixedText " "  #variableName"=") ); \
  Serial.println(variableName);

#define dbgi(myFixedText, variableName,timeInterval) \
  { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " "  #variableName"=") ); \
      Serial.println(variableName); \
    } \
  }

#define dbgc(myFixedText, variableName) \
  { \
    static long lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }

#define dbgcf(myFixedText, variableName) \
  { \
    static float lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *


#include <Arduino.h>
#include <Adafruit_ADS1X15.h>
#include <cmath>


Adafruit_ADS1115 ads;  /* Use this for the 16-bit version */

const int numReadings = 100; // Number of readings to average
int readings[numReadings];  // Array to store readings
int readIndex = 0;          // Index for current reading
int total = 0;              // Running total of readings
int average = 0;            // Moving average

bool CodeRunningFirstTime = true;
unsigned long TimeSinceCodeStart;
unsigned long LastDataDisplayMillis;

double Baseline = 0.00;
double Factor = 260.00;
double Volume = 0.00;

//DWIN Part
const byte rxPin = 16;
const byte txPin = 17;
#define some_value_add 0x50
unsigned char HMI_some_value[8] = {0x5A, 0xA5, 0x05, 0x82, some_value_add, 0x00, 0x00, 0x00};
unsigned char Buffer[9];


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

  if (!ads.begin()){
    Serial.println("Failed to initialize ADS.");
    while (1);
  }
  else{
    Serial.println("ADS Initialised");
  }

  // Initialize the readings array
  for (int i = 0; i < numReadings; i++){
    readings[i] = 0;
  }

  //DWIN Part
  Serial2.begin(115200, SERIAL_8N1, rxPin, txPin); // Initialize Serial2 on pins 16 and 17

  TimeSinceCodeStart = millis();
  LastDataDisplayMillis = millis();
}


void loop() {

  int16_t adc0;
  adc0 = ads.readADC_SingleEnded(0);

  // Update the total by subtracting the oldest reading and adding the new reading
  total = total - readings[readIndex] + adc0;
  // Store the new reading in the array
  readings[readIndex] = adc0;
  // Move to the next index
  readIndex = (readIndex + 1) % numReadings;
  // Calculate the moving average
  average = total / numReadings;

  //Serial.println(average);

  if ((millis() - TimeSinceCodeStart) > 2000) {
    if (CodeRunningFirstTime == true) {
      Baseline = average;
      CodeRunningFirstTime = false;
    }
  }

  Volume = (average - Baseline) / Factor;

  Data_Display();
  Touch_Button_Activity();
}

void Data_Display() {
  if ((millis() - LastDataDisplayMillis) >= 0) {
    int t_int = Volume * 100; // Convert float to int to preserve two decimal places

    HMI_some_value[6] = highByte(t_int);
    HMI_some_value[7] = lowByte(t_int);

    Serial2.write(HMI_some_value, 8); // Use Serial2 instead of SoftwareSerial

    LastDataDisplayMillis = millis();
  }
}


void Touch_Button_Activity() {

  dbgc("TBA",Serial2.available() ); // whenever number Serial2.available() has a different number print once
  if (Serial2.available() >= 9) { // Ensure there are at least 9 bytes available
  
    for (int i = 0; i < 9; i++) {
      Buffer[i] = Serial2.read();
    }

    // Debug: Print buffer content
    Serial.print("Buffer: ");
    for (int i = 0; i < 9; i++) {
      Serial.print(Buffer[i], HEX);
      Serial.print(" ");
    }
    Serial.println();

    dbgc("buf",Buffer[0]); // whenever Buffer[0]has a different value print once
    if (Buffer[0] == 0x5A) {
      
      switch (Buffer[4]) {
        case 0x55:
          // Use the Low Byte (Buffer[8]) to determine the touch button state
          switch (Buffer[8]) {
            case 0:
              Baseline = average;
              Serial.println("case 0 Baseline set to average");
              break;
              
            case 1:
              Baseline = average;
              Serial.println("case 1 Baseline set to average");
              break;
              
            case 2:
              Factor = average - Baseline;
              Serial.println("case 2 Factor set to average - Baseline");
              break;
              
            default:
              Serial.print("Unexpected value in Buffer[8] value is");
              Serial.println(Buffer[8]);
              break;
          }
          break;

        default:
          Serial.print("default: Buffer[4] has value ");
          Serial.println(Buffer[4]);
          break;
      }
    }
    else {
      Serial.print("Invalid byte in Buffer[0] value is ");
      Serial.println(Buffer[0]);
    }
  }
}

C++ libraries do not end in ".h". Other examples:

#include "vector"
#include "map"
#include "memory"

However, the above won't compile for an AVR processor.

1 Like

Ok, I have tried a simpler sketch and I am confused.

What I did.

  1. I connected an LED to the ESP32 board to debug.
  2. I tested the LED connections by trying to light the LED by putting the relevant code line in the Loop function.
  3. After the LED was successfully lit, I put the LED lighting code line in the Touch function under if statement, and called the Touch function in the Loop function.
  4. The LED did not light up.
  5. Then, without powering up the LCD, I connected the LCD RX pin to the Tx pin of the ESP32 board, and the Tx pin of of the LCD to the Rx pin of the ESP32 board, using Dupont Jumper cables.
  6. The LCD end of the jumper cables were then cut and soldered to the LCD points, to make sure that the connection was good. The ESP32 board side of the jumper cable is still the dupont jumper type.
  7. The moment the jumper cables touched the relevant pins on the ESP32 came in touch with the Jumper cables, the LED lighted up.
  8. I was surprised how this could happen as the LCD was not powered.
  9. With the jumper cables still connected, I removed the data cable connecting the ESP32 board to he computer, and then reconnected it to the computer. Now the LED did not light up.
  10. Now with the ESP32board connected to he computer and the LED not lit, I removed he jumper cables on the RX Tx pins of the ESP32 board, and reconnected them. Istantly the LED lighted up again.

So apparrently, somehow the if(Serial2.available) condition is fulfiled when the Jumper cables are connected to the unpowered LCD.

What is happening?

Below is my code.

const int ledPin = 18;

const byte rxPin = 16;
const byte txPin = 17;



void setup() {
  // setup pin 5 as a digital output pin
  pinMode (ledPin, OUTPUT);

  Serial2.begin(115200, SERIAL_8N1, rxPin, txPin); // Initialize Serial2 on pins 16 and 17
  Serial.begin(115200);
}

void loop() {

  Touch();
  //digitalWrite (ledPin, HIGH);
  
}

void Touch()
{
  if (Serial2.available()) 
  {   
    Serial.println("Howdy");
    digitalWrite (ledPin, HIGH);    // turn on the LED 
  }
}

Interestingly, I just noticed, the LED also lights up when I switch up my soldering iron. Am I having EMI issues?

Post a picture of your ESP32, the wiring and the LCD

What power-supply are you using to supply the ESP32?

Here is your code with aditional debug-out that will tell you more what is going on.

// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *
// a detailed explanation how these macros work is given in this tutorial
// https://forum.arduino.cc/t/comfortable-serial-debug-output-short-to-write-fixed-text-name-and-content-of-any-variable-code-example/888298

#define dbg(myFixedText, variableName) \
  Serial.print( F(#myFixedText " "  #variableName"=") ); \
  Serial.println(variableName);

#define dbgi(myFixedText, variableName,timeInterval) \
  { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " "  #variableName"=") ); \
      Serial.println(variableName); \
    } \
  }

#define dbgc(myFixedText, variableName) \
  { \
    static long lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }

#define dbgcf(myFixedText, variableName) \
  { \
    static float lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *

unsigned long MyTestTimer = 0;                   // Timer-variables MUST be of type unsigned long

unsigned long shortWait = 200;
unsigned long longWait = 1000;

unsigned long waitInterval;

const byte ledPin = 18;

const byte rxPin = 16;
const byte txPin = 17;


void setup() {
  // setup pin 5 as a digital output pin
  pinMode (ledPin, OUTPUT);

  Serial2.begin(115200, SERIAL_8N1, rxPin, txPin); // Initialize Serial2 on pins 16 and 17
  Serial.begin(115200);
}

void loop() {
  Touch();
  //digitalWrite (ledPin, HIGH);  
}


void Touch() {
  // only in case the value of Serial2.available() changes
  // print once
  dbgc("T1",Serial2.available() );

  if (Serial2.available())  {   
    //Serial.println("Howdy");
    //digitalWrite (ledPin, HIGH);    // turn on the LED 
    waitInterval = shortWait; 
    dbg("avail",Serial2.read() ) ;   
  }
  else {
    waitInterval = longWait;
  }

  if (TimePeriodIsOver(MyTestTimer,waitInterval) ) {
    digitalWrite(ledPin, !digitalRead(ledPin) ); // invert state of ledpin
  }
}


// helper-functions
void PrintFileNameDateTime() {
  Serial.println( F("Code running comes from file ") );
  Serial.println( F(__FILE__) );
  Serial.print( F("  compiled ") );
  Serial.print( F(__DATE__) );
  Serial.print( F(" ") );
  Serial.println( F(__TIME__) );  
}


// easy to use helper-function for non-blocking timing
// explanation see here
// https://forum.arduino.cc/t/example-code-for-timing-based-on-millis-easier-to-understand-through-the-use-of-example-numbers-avoiding-delay/974017
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}



void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
  static unsigned long MyBlinkTimer;
  pinMode(IO_Pin, OUTPUT);
  
  if ( TimePeriodIsOver(MyBlinkTimer,BlinkPeriod) ) {
    digitalWrite(IO_Pin,!digitalRead(IO_Pin) ); 
  }
}

Please post a schematic of this experimental setup and some photos of how it's all wired up.

It sounds to me like a dangling wire or unpowered module on the ESP's Serial2 RX is simply creating noise which ends up as a random character in the UART buffer. Try printing out the characters that are received on Serial2; I bet it's just random noise.