MEGA TFT shield used on Arduino DUE

Hi All,

I have this MEGA TFT shied:
Screen_1

It has a NT35510 controller for he screen and a 2046 controller for the Touch screen
I have used the screen on a MEGA without any issues (screen & touch)
I have also used it on a DUE. The screen works fine with the DUE, however I cannot get the touch screen to work on the DUE.

The TIRQ pin of the screen is connected to the digital pin 44 of the Arduino.
As expected the pin is HIGH when the screen is not touched and drops to LOW when the screen is touched. At least this is what I see with the MEGA.
On the DUE the pin is ALWAYS LOW.

Note: I am simply testing this using "digitalRead(44);"

I know that he MEGA uses AVR architecture and the DUE uses SAM but as far as I understand, digitalRead(44) should be reading the same pin on the 36 pins header of both arduinos.
I am expecting the digitalRead to be quite wasteful on the DUE due to the translation needed but, it still should behave in the same way.

Could it be that I always get LOW because the shield is powered by the DUE at 3.3v instead of 5v?
I cannot come up with any other explanation at this moment.
Regards
H

Please fix the title of your related post:
https://forum.arduino.cc/t/arduino-due-and-nt33510-tft-screen/1131769 to NT35510.

I don't think this is the reason.

XPT2046 will not activate the IRQ pin as long as it is not initialized, most likely.

The Arduino Due has HW SPI only on 6pin ICSP header, you would need a touch driver with SW SPI.

There seems an option for one of the most used XPT2046 library. See
https://github.com/PaulStoffregen/XPT2046_Touchscreen/commit/2ceeeb3414c8c0fd71605796a858750f8013150f

Good Luck!

Hi JM,

Once again, thanks for the fast answer.
I fixed the title of my previous post.
I had not thought about the initialization sequence failing. Great suggestion.
The library I am using is the LIKILCD library.
I had compared it to Bodmer libraru (see: https://github.com/Bodmer/TFT_Touch) that also uses bitbanging for the SPI interface (just like the WikiLCD library).
the WikiLCD library does work when used on the MEGA.
However when I compare it side by side with Bodmer lib, I notice some subtle differences in the way they act.
So I will give a go at fixing the start-up sequence and report back.
Regards
H

Good Morning All,

I did not get the time to do as much diving into the libraries code as I wanted to but I did manage to test the two "SPI bitbanging" libraries on both the MEGA and the DUE.

Both libraries do work fine on the MEGA.
This is the WikiLCD library and the Bodmer SPI library for XPT2046 (see: https://github.com/Bodmer/TFT_Touch.

But the exact same code compiled on the DUE does not run. It compiles and loads OK but the code does not work (in so far as I don't get reliable readings).

Having looked at a few posts on the comparative speed of digitalWrite on MEGA versus DUE (see: https://forum.arduino.cc/t/i-thought-the-due-would-be-faster/964522/12), especially the quote:

I get about 123kHz on an Uno, and only 78kHz on a Mega ADK (which should be the same as a Mega.) I get 113kHz on a Due

It looks as if the DUE is approximatively 1.5 times as fast as the MEGA when it comes to toggling pins using digitalWrite .

So I guess this is where the issue is.

I can see that both the libraries have delays/wait at some points in the logic to drive the pin High/Low so timing will have an impact (or people would not have added the delays).

I will now have to look into this.
If any one out there has experience of adjusting the timing on a BitBanging SPI protocol to cater for the difference in speed from the controller, any input will be grandly received.

Regards
H

Hi All,

I have done a little bit more tests. Still no success. But I am able to share the code that I run that provides the expected results when the screen is plugged into a MEGA and does not provide the result when on a DUE.

In my "setup" function I call this "TestTouch" function of mine:

void testTouch()
{
    pinMode(TFT_INT_PIN,OUTPUT);
  
    Serial.println("Touch test Started");
    while(1)
    {
          if (my_touch.Pressed()) // Note this function updates coordinates stored within library variables
          {
            Serial.print("Pressed RawX= "); Serial.print(my_touch.RawX()); // The values returned were captured when Pressed() was called!
            Serial.print("[X= "); Serial.print(my_touch.X()); // The values returned were captured when Pressed() was called!
            Serial.print("] | RawY"); Serial.print(my_touch.RawY());       // The values returned were captured when Pressed() was called!
            Serial.print("[Y= "); Serial.print(my_touch.Y()); // The values returned were captured when Pressed() was called!
            Serial.println("]");
         }
         else
         {
            Serial.println("Not pressed");         
         }
         Serial.print("     PIN 44="); Serial.println(digitalRead(TFT_INT_PIN));
         delay(1000);
    }
}

The functions that I call are based on the Bodmer Touch library

/* Detects if the touch screen is currently pressed. Returns TRUE if pressed */
boolean TFT_Touch::Pressed(void)
{
Serial.print("TFT_Touch::Pressed [");
Serial.print("_xyswap="); Serial.print(_xyswap);
Serial.print(" | _xflip="); Serial.print(_xflip);
Serial.print(" | _yflip="); Serial.print(_yflip);
Serial.print("] ==> ");

  // Get the raw contact coordinates
  _xraw = _ReadAxis(_axis);
  _yraw = _ReadAxis(!_axis);

Serial.print("_xraw="); Serial.print(_xraw);
Serial.print(" | _yraw="); Serial.print(_yraw);
Serial.print(" ==> ");


  // Now double check the touch is still near the initial contact point
  // also calculates the proper values for X & Y
 //  No issue in this part of code, the logics works
}

The issue i face is that I get meaning full readings with the MEGA and always zero with the DUE.
The works is done in these functions:

/* Reads one of the axis (XAXIS or YAXIS) raw coordinates. */
int16_t TFT_Touch::_ReadAxis(boolean Axis)
{
  int Data;
  
  digitalWrite(_CS, LOW);
  digitalWrite(_CS, LOW);  // HL CHANGE: as recommended by JM
  delayMicroseconds(MICRO_WAIT); 
  if (Axis)
  {
    _OutputData(0x90);   
  }else
  {
    _OutputData(0xD0);
  }
  
  delayMicroseconds(MICRO_WAIT);
  Data = _ReadData();
  
  digitalWrite(_CS, HIGH); 
  digitalWrite(_Din, LOW);
  
  return Data;
}

/* Reads the raw data from the touch screen */
// SPI mode 1 protocol: The base value of the clock is always 0 and data is always sent or received on the rising edge of the clock.
uint16_t TFT_Touch::_ReadData(void)
{
  uint16_t Data = 0;
  for (uint8_t index = 12; index > 0; index--)   // Read the first 12 bits
  {
    digitalWrite(_Clk, HIGH); delayMicroseconds(MICRO_WAIT); digitalWrite(_Clk, LOW); delayMicroseconds(MICRO_WAIT); //_PulseClock();
    Data += digitalRead(_Dout) << (index-1);
  }
  for (uint8_t index = 4; index > 0; index--)   // Ignore the next 4 the first 12 bits
  {
    digitalWrite(_Clk, HIGH); delayMicroseconds(MICRO_WAIT); digitalWrite(_Clk, LOW); delayMicroseconds(MICRO_WAIT); //_PulseClock();
  }
  return Data;
}  

/* Writes to the touch screen's configuration register */
void TFT_Touch::_OutputData(byte Data)
{ 
  for (uint8_t index = 8; index > 0; index--)
  {
    digitalWrite(_Din, (Data >> (index -1)) & 1);
    delayMicroseconds(MICRO_WAIT); 
    digitalWrite(_Clk, HIGH); delayMicroseconds(MICRO_WAIT); digitalWrite(_Clk, LOW); delayMicroseconds(MICRO_WAIT); //_PulseClock();
  }
}

The doubling up of the "digitalWrite(_CS, LOW)" is something I did on the advices of JM. I believe I understand the rationale (making sur that the touch screen is 100% aware of the communication being started). but this does not appear to work.
I have also pepered the code with "delayMicroseconds(MICRO_WAIT);" in case the DUE was going too fast for the Touch Screen to follow and I have tried many different values for the delay (1,3,6,20,100 micro-seconds).

None of this has worked.

With the MEGA I get these results:

###################### PROGRAM STARTED ###############
Touch test Started
TFT_Touch::Pressed [_xyswap=0 | _xflip=0 | _yflip=1] ==> _xraw=0 | _yraw=4095 ==> Not pressed
PIN 44=1
TFT_Touch::Pressed [_xyswap=0 | _xflip=0 | _yflip=1] ==> _xraw=0 | _yraw=4095 ==> Not pressed
PIN 44=1
TFT_Touch::Pressed [_xyswap=0 | _xflip=0 | _yflip=1] ==> _xraw=1518 | _yraw=2158 ==> Pressed RawX= 1518[X= 185] | RawY2158[Y= 381]
PIN 44=0
TFT_Touch::Pressed [_xyswap=0 | _xflip=0 | _yflip=1] ==> _xraw=1512 | _yraw=2158 ==> Pressed RawX= 1512[X= 185] | RawY2158[Y= 381]
PIN 44=0
TFT_Touch::Pressed [_xyswap=0 | _xflip=0 | _yflip=1] ==> _xraw=538 | _yraw=1793 ==> Pressed RawX= 538[X= 85] | RawY1793[Y= 446]
PIN 44=0
TFT_Touch::Pressed [_xyswap=0 | _xflip=0 | _yflip=1] ==> _xraw=0 | _yraw=4095 ==> Not pressed
PIN 44=1
TFT_Touch::Pressed [_xyswap=0 | _xflip=0 | _yflip=1] ==> _xraw=3191 | _yraw=1524 ==> Not pressed
PIN 44=0
TFT_Touch::Pressed [_xyswap=0 | _xflip=0 | _yflip=1] ==> _xraw=1033 | _yraw=1730 ==> Pressed RawX= 1033[X= 135] | RawY1730[Y= 458]
PIN 44=0
TFT_Touch::Pressed [_xyswap=0 | _xflip=0 | _yflip=1] ==> _xraw=0 | _yraw=4095 ==> Not pressed
PIN 44=1
TFT_Touch::Pressed [_xyswap=0 | _xflip=0 | _yflip=1] ==> _xraw=676 | _yraw=3645 ==> Pressed RawX= 676[X= 99] | RawY3645[Y= 112]
PIN 44=0
TFT_Touch::Pressed [_xyswap=0 | _xflip=0 | _yflip=1] ==> _xraw=0 | _yraw=4095 ==> Not pressed
PIN 44=1
TFT_Touch::Pressed [_xyswap=0 | _xflip=0 | _yflip=1] ==> _xraw=3061 | _yraw=624 ==> Pressed RawX= 3061[X= 343] | RawY624[Y= 658]
PIN 44=0
TFT_Touch::Pressed [_xyswap=0 | _xflip=0 | _yflip=1] ==> _xraw=2073 | _yraw=670 ==> Not pressed
PIN 44=0
TFT_Touch::Pressed [_xyswap=0 | _xflip=0 | _yflip=1] ==> _xraw=609 | _yraw=814 ==> Pressed RawX= 609[X= 92] | RawY814[Y= 623]
PIN 44=0
TFT_Touch::Pressed [_xyswap=0 | _xflip=0 | _yflip=1] ==> _xraw=0 | _yraw=4095 ==> Not pressed
PIN 44=1

And with the DUE all I get is this:

###################### PROGRAM STARTED ###############
Touch test Started
TFT_Touch::Pressed [_xyswap=0 | _xflip=0 | _yflip=1] ==> _xraw=0 | _yraw=0 ==> Not pressed
PIN 44=0
TFT_Touch::Pressed [_xyswap=0 | _xflip=0 | _yflip=1] ==> _xraw=0 | _yraw=0 ==> Not pressed
PIN 44=0
TFT_Touch::Pressed [_xyswap=0 | _xflip=0 | _yflip=1] ==> _xraw=0 | _yraw=0 ==> Not pressed
PIN 44=0
TFT_Touch::Pressed [_xyswap=0 | _xflip=0 | _yflip=1] ==> _xraw=0 | _yraw=0 ==> Not pressed
PIN 44=0
TFT_Touch::Pressed [_xyswap=0 | _xflip=0 | _yflip=1] ==> _xraw=0 | _yraw=0 ==> Not pressed
PIN 44=0

And I really dont know why.
I cannot do any more tests for now as my compiler has stopped working for the DUE.
Some internal error I cannot fathom out.
I will create another post for this.

Regards
H

I didn't want to provide nonsense, this was by accident is your misinterpretation.
I didn't pay attention to the pin used.
I was thinking of the doubling of the length of the WR pulse needed for some P16 TFTs, e.g. when using low level IO.
This is what I wrote in post
https://forum.arduino.cc/t/arduino-due-and-nt35510-tft-screen/1131769/4?u=zinggjm:

You could try to use double TCLK_LOW. That's what I use to try.

This technique can of course also be used for SPI signals, CLK and MOSI.
delayMicroseconds will lead to rather slow SPI speed.

I thank you for the mention of the TFT_Touch from Bodmer using SW SPI.
I should be able to test this in the next few days, as my identical P16 MEGA display has arrived.
-jz-

Hi JM,

Many thanks for the fast answer.
Don't worry about the advice. I thought it made sense any way to make sure that the CS signal was well set and stable before tinkering with the data pins and the clock.

Are you going to test your screen on a DUE?

I 100% agree that the delays that i have experimented with would make the SPI slow(er).
As I only use it for the touch screen (not the display), this is a price I could live with IF that managed to make things work.
But so far I have failed to make this work and I am really curious to understand why.

Regads
H

Yes. The screen works on MEGA and DUE. I did not yet test touch nor SD, neither on MEGA nor on DUE. But I intend to test both on both boards.

Great news. I trust your ability to figure this out as better than mine.

In the mean time I fill try to get my compiler sorted (https://forum.arduino.cc/t/internal-compiler-error-with-due/1137235)

I found out that there is an issue with pinMode(53, OUTPUT) on DUE.
Pin 53 gets reset to INPUT between end of setup() and begin of loop().
Pin 53 gets reset to INPUT between Touch construction and begin of loop().

It is bad practice to do initialization of IO in static object construction.
That's why every Arduino IO driver class has begin() or init() methods.

Touch works with this addition:

/* Reads one of the axis (XAXIS or YAXIS) raw coordinates. */
int16_t TFT_Touch::_ReadAxis(boolean Axis)
{
  int Data;
  
  static bool once = false;
  if (!once)
  {
    pinMode(_CS, OUTPUT); 
    pinMode(_Clk, OUTPUT); 
    pinMode(_Din, OUTPUT); 
    pinMode(_Dout, INPUT); 
    digitalWrite(_CS, HIGH);  
    digitalWrite(_Clk, LOW);
    digitalWrite(_Din, LOW);
  	once = true;
  }

But needs additional changes. The values returned are incorrect.
-jz-

Hi JM,

Thanks for the input. I am not sure I would have found that the pins were reset before the functions starts (set-up or loop).
As per your advice, I moved the pins initialisation code:

    pinMode(_CS, OUTPUT); 
    pinMode(_Clk, OUTPUT); 
    pinMode(_Din, OUTPUT); 
    pinMode(_Dout, INPUT); 
    digitalWrite(_CS, HIGH);  
    digitalWrite(_Clk, LOW);
    digitalWrite(_Din, LOW);

Into a separate "init(void)" function that I call at the start of "setup" and all is now well.
I was even able to remove my many "delay" calls as they are not needed.

Once again: Thanks for the assistance.

Regads
H

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.