3.5 inch MCUFriend not drawing???????

Hi Everyone - david_prentice

I have a McuFriend 3.5 inch tft touch screen. it has an ID of ID = 0x6814

The MCULibrary works great, along with the AdaFruit GFX library…

however i have a drawing issue i cant figure out…

Here is my test sketch

#include <SPI.h>
#include "Adafruit_GFX.h"
#include <MCUFRIEND_kbv.h>
//#include <Fonts/FreeSans9pt7b.h>
#include <TouchScreen.h>


// TOUCH SCREEN STUFF


// most mcufriend shields use these pins and Portrait mode:
#define YP  A2  // must be an analog pin, use "An" notation!
#define XM  A1  // must be an analog pin, use "An" notation!
#define YM  6   // can be a digital pin
#define XP  7   // can be a digital pin

// This is calibration data for the raw touch data to the screen coordinates
#define TS_MINX 110
#define TS_MINY 80
#define TS_MAXX 900
#define TS_MAXY 940

#define MINPRESSURE 10
#define MAXPRESSURE 1000

MCUFRIEND_kbv tft;

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

#define BUTTON_TEXTSIZE 2

#define ST7735_BLACK   0x0000
#define ST7735_WHITE   0xFFFF
#define ST7735_AQUA    0x04FF
#define ST7735_BLUE    0x001F


Adafruit_GFX_Button buttons[2];

void drawScreen()
{
	tft.setRotation(2);
//	tft.setFont(&FreeSans9pt7b);

	tft.fillScreen(ST7735_BLACK);

	// reset the font
	tft.setFont();

	buttons[0].initButtonUL(&tft, 50, 100, 150, 50, ST7735_WHITE, ST7735_BLUE, ST7735_WHITE, "Test 1", BUTTON_TEXTSIZE);
	buttons[0].drawButton();

	buttons[1].initButtonUL(&tft, 50, 170, 150, 50, ST7735_WHITE, ST7735_BLUE, ST7735_WHITE, "Test 2", BUTTON_TEXTSIZE);
	buttons[1].drawButton();
}

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

	//tft.begin(HX8357D);
	uint16_t ID = tft.readID(); //
	Serial.print("ID = 0x");
	Serial.println(ID, HEX);
	if (ID == 0xD3D3) ID = 0x9481; // write-only shield
	tft.begin(ID);

	drawScreen();
}

void loop(void)
{
	// Retrieve a point  
	TSPoint p = ts.getPoint();

	// we have some minimum pressure we consider 'valid'
	// pressure of 0 means no pressing!
	if (p.z < MINPRESSURE || p.z > MAXPRESSURE) {
		return;
	}

	// For McuFriend
	p.x = map(p.x, TS_MINX, TS_MAXX, tft.width(), 0);
	p.y = map(p.y, TS_MINY, TS_MAXY, tft.height(), 0);

	// go thru all the buttons, checking if they were pressed
	for (uint8_t b = 0; b<2; b++)
	{
		if (buttons[b].contains(p.x, p.y))
		{
			{
				buttons[b].press(true);  // tell the button it is pressed
				Serial.print("Pressing "); 
				Serial.println(buttons[b].Id());
				tft.fillRect(50, 250, 150, 50, ST7735_AQUA);
				buttons[b].drawButton(true);
			}
		}
		else
		{
			{
				Serial.print("Released ");
				buttons[b].press(false);  // tell the button it is pressed
				buttons[b].drawButton();
			}
		}
	}
}

What it should do is draw the button inverted when its being pressed, and normal when its been released…

and to help test, i want it to draw a rect when i am pressing.

It seems to totally ignore any draw commands within the loop() function, so that it will not draw the buttons inverted.

What am i doing wrong ?

int pixel_x, pixel_y;     //Touch_getXY() updates global vars
bool Touch_getXY(void)
{
    TSPoint p = ts.getPoint();
    pinMode(YP, OUTPUT);      //restore shared pins
    pinMode(XM, OUTPUT);
    digitalWrite(YP, HIGH);   //because TFT control pins
    digitalWrite(XM, HIGH);
    bool pressed = (p.z > MINPRESSURE && p.z < MAXPRESSURE);
    if (pressed) {
        pixel_x = map(p.x, TS_LEFT, TS_RT, 0, tft.width()); //.kbv makes sense to me
        pixel_y = map(p.y, TS_TOP, TS_BOT, 0, tft.height());
    }
    return pressed;
}

Seriously, if people give feedback about the examples they could be improved.

As far as I know, all my examples and most Adafruit examples clearly point out that you have to restore XM, YP pins to Digital OUTPUT after TouchScreen.h has used them as Analog INPUT.
XM, YP share Touch panel with the TFT control pins.

If you omit the digitalWrite() calls, the TFT will die as soon as the CPU finishes the first Touch call.

David.

I was using this and adapting it,

which does not mention that you have to restore the XM and TP pins.

I wasn't aware of it, please accept my apologies for not understanding.

I tried running the TouchScreen_Calibr_native sketch but it would not allow me to proceed by touching the screen. I did get this in the serial monitor...

TouchScreen.h GFX Calibration
Making all control and bus pins INPUT_PULLUP
Typical 30k Analog pullup with corresponding pin
would read low when digital is written LOW
e.g. reads ~25 for 300R X direction
e.g. reads ~30 for 500R Y direction

Testing : (A1, D7) = 21
Testing : (A2, D6) = 33
Diagnosing as:-
XM,XP: (A1, D7) = 21
YP,YM: (A2, D6) = 33
ID = 0x6814

The updated library sketch worked, and this is the diagnostics from it

TouchScreen.h GFX Calibration
Making all control and bus pins INPUT_PULLUP
Typical 30k Analog pullup with corresponding pin
would read low when digital is written LOW
e.g. reads ~25 for 300R X direction
e.g. reads ~30 for 500R Y direction

Testing : (A1, D7) = 21
Testing : (A2, D6) = 32
Diagnosing as:-
XM,XP: (A1, D7) = 21
YP,YM: (A2, D6) = 32
ID = 0x6814

cx=257 cy=318 cz=137 LEFT, TOP, Pressure
cx=194 cy=522 cz=549 LEFT, MIDH, Pressure
cx=194 cy=906 cz=275 LEFT, BOT, Pressure
cx=504 cy=161 cz=686 MIDW, TOP, Pressure
cx=523 cy=912 cz=501 MIDW, BOT, Pressure
cx=863 cy=155 cz=742 RT, TOP, Pressure
cx=872 cy=530 cz=618 RT, MIDH, Pressure
cx=877 cy=927 cz=533 RT, BOT, Pressure
MCUFRIEND_kbv ID=0x6814 320 x 480

const int XP=7,XM=A1,YP=A2,YM=6; //320x480 ID=0x6814
const int TS_LEFT=193,TS_RT=891,TS_TOP=195,TS_BOT=930;
PORTRAIT CALIBRATION 320 x 480
x = map(p.x, LEFT=193, RT=891, 0, 320)
y = map(p.y, TOP=195, BOT=930, 0, 480)
Touch Pin Wiring XP=7 XM=A1 YP=A2 YM=6
LANDSCAPE CALIBRATION 480 x 320
x = map(p.y, LEFT=195, RT=930, 0, 480)
y = map(p.x, TOP=891, BOT=193, 0, 320)

Yes, it gives you a lot of diagnostic output. You only need to paste:

const int XP=7,XM=A1,YP=A2,YM=6; //320x480 ID=0x6814
const int TS_LEFT=193,TS_RT=891,TS_TOP=195,TS_BOT=930;

I built your sketch (with my calibration) and for Portrait.
There is no Id() method in my Adafruit_GFX_Button() class.

The sketch "works" but has a mind of its own. Probably down to continuous Touch reading.

I will massage it to my style. And see how it looks.

David.

Thank you.

I appreciate it.

I think the reason i was in such a pickle is that i built it on an adafruit shield first wired using SPI - for this there were no shared pins. I wasn't aware the McuFriend shared its pins...

At the moment i'm struggling to find an outlet that sells the mcufriend :frowning:

Here is a modified version of your program:

#include <MCUFRIEND_kbv.h>
#include <TouchScreen.h>

// TOUCH SCREEN STUFF
const int XP = 7, XM = A1, YP = A2, YM = 6; //320x480 ID=0x9488
const int TS_LEFT = 918, TS_RT = 125, TS_TOP = 951, TS_BOT = 121;

#define MINPRESSURE 200
#define MAXPRESSURE 1000

MCUFRIEND_kbv tft;

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

#define BUTTON_TEXTSIZE 2

#define ST7735_BLACK   0x0000
#define ST7735_WHITE   0xFFFF
#define ST7735_AQUA    0x04FF
#define ST7735_BLUE    0x001F


Adafruit_GFX_Button buttons[2];

void drawScreen()
{
    tft.setRotation(0);
    //  tft.setFont(&FreeSans9pt7b);

    tft.fillScreen(ST7735_BLACK);

    // reset the font
    tft.setFont();

    buttons[0].initButtonUL(&tft, 50, 100, 150, 50, ST7735_WHITE, ST7735_BLUE, ST7735_WHITE, "Test 1", BUTTON_TEXTSIZE);
    buttons[0].drawButton();

    buttons[1].initButtonUL(&tft, 50, 170, 150, 50, ST7735_WHITE, ST7735_BLUE, ST7735_WHITE, "Test 2", BUTTON_TEXTSIZE);
    buttons[1].drawButton();
}

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

    //tft.begin(HX8357D);
    uint16_t ID = tft.readID(); //
    Serial.print("ID = 0x");
    Serial.println(ID, HEX);
    if (ID == 0xD3D3) ID = 0x9481; // write-only shield
    tft.begin(ID);

    drawScreen();
}

void loop(void)
{
    int pixel_x, pixel_y;
    // Retrieve a point
    TSPoint p = ts.getPoint();
    pinMode(YP, OUTPUT);      //restore shared pins
    pinMode(XM, OUTPUT);
    digitalWrite(YP, HIGH);   //because TFT control pins
    digitalWrite(XM, HIGH);
    bool pressed = (p.z > MINPRESSURE && p.z < MAXPRESSURE);
    if (pressed) {
        pixel_x = map(p.x, TS_LEFT, TS_RT, 0, tft.width()); //.kbv makes sense to me
        pixel_y = map(p.y, TS_TOP, TS_BOT, 0, tft.height());
    }

    // go thru all the buttons, checking if they were pressed
    for (uint8_t b = 0; b < 2; b++)
    {
        bool state = pressed && buttons[b].contains(pixel_x, pixel_y);
        buttons[b].press(state);  // update this button
        if (buttons[b].justPressed())
        {
            Serial.print("Pressing ");
            Serial.println(b + 1);
            uint16_t color = (b == 0) ? ST7735_AQUA : ST7735_BLACK;
            tft.fillRect(50, 250, 150, 50, color);
            buttons[b].drawButton(state);
        }
        if (buttons[b].justReleased())
        {
            Serial.print("Released ");
            Serial.println(b + 1);
            buttons[b].drawButton(state);
        }
    }
}
  1. restore XM, YP to OUTPUT after a Touch call e.g. ts.getPoint()
  2. only calculate X, Y position if there is a “touch”
  3. X, Y, Z values are not exact. it is worth taking multiple readings and using median or average.
  4. most TouchScreen libraries can look after this “best reading” procedure
  5. update the state of each button e.g. is it down AND does it contain x, y
  6. register this state with button.press(state)
  7. subsequent logic determines how you want your project to behave e.g. drawButton(state)
  8. you use justPressed(), justReleased(), isPressed(), …
  9. you only need to draw a button when its state has changed (and only if you want)

From a human point of view, draw your screen on cardboard. Mark LEFT, RIGHT, TOP, BOT.
Any Calibration is going to be relative to this fixed layout.

Rotate the cardboard and the Touch “LEFT” refers to different X or Y pixels.
Use the map() function to convert the Touch readings into Pixel Coordinates.

Note that any Touch panel might give occasional stray readings. That is why it is worth processing to get a “best” result.

David.

The new library version has some new examples. I would appreciate feedback.
It is better to make improvements to the examples. No one will find your thread in two days time !!

Thank you for your help with this David.

I was going to ask you a question about a atmega1284p however after I updated to the latest version of your library everything is good.

I don’t know why it was not on the latest version.

If you have a question, ask it.

well, not being a native embedded c coder, after i installed the mightyCore to give me the option to build with an 1284p, but i was getting alot of sstuff undefined in both the TouchScreen.h and your library.

I got worried, stressed, then left it for a while. when i came back i searched for simular errors and discovered that the adafruit library i was using ( which contained touchScreen.h ) was out of date, and then the version of your library was also out of date ( as you answered and added port mappings to the *special.h file ) so i eventually managed to figure it out for myself.

but thank you anyway.

Explain what you want to do.
Explain what you have done.

Explain what you expected.
Explain what you actually got and how it differed.

Ask your question.

The MCUFRIEND_kbv library will work with Uno Shields plugged into standard Arduino headers on commercially available boards. e.g.
Uno
Leonardo
Zero
Mega2560
Due
STM32 Nucleo
IteadMaple
Teensy 3.x with SparkFun Adapter
TTGO D1 R32 (ESP32) with minor hardware mod

I have no idea what "MightyCore" is. Apparently the "Bobuino" is a publicly available pcb design but I don't think you can buy it in the shops.

If you can't "plug and go" with a Uno Shield, you have to use a SPECIAL of some kind.

If you have a commercially available target board with Arduino headers I am happy to add plug and play support.

David.

Greetings from Peru, Mr. david_prentice, the problem that you detect is that, using the libraries #include <Fonts / FreeSans12pt7b.h> and #include FreeDefaultFonts.h>, in the example attached to the MCUFRI packageEND_kbv, “Touch_shield_new”, to change the font, using the instruction tft.setFont (& FreeSans12pt7b); the output of the text is lost, since it is rewritten over the previous one, and once overlapped, the coordinate figure is no longer identified. I’m not an expert in programming, but that breaks down in my work that I intend to do with my tft 3.97 ", the ID is 0x9486.
The link to advance my work is in YouTube video:

Please, provide me with help in this regard, and excuse’me for my very bad english ( only translator :’( ).

I want to add that using the font function as follows:

tft.setFont (NULL);

What I want is corrected, although not in the way I want, but it is a temporary solution.

@trebor,

The FreeFonts look very nice but only print transparently.
You must repaint the background before you print new text / numbers.

/* life is much simpler with the 7x5 System Font
 * tft.setTextColor(FOREGROUND, BACKGROUND);
 * char buf[12];    //for formatted result
 * tft.setCursor(x, y);
 * tft.print(dtostr(floatnum, wid, prec, buf));
 */

Here is a program that shows how to right-justify a proportional font:

#include <Adafruit_GFX.h>    // Core graphics library
#include <MCUFRIEND_kbv.h>   // Hardware-specific library
MCUFRIEND_kbv tft;

#if defined(ARDUINO_ARCH_SAMD)   // for Zero and M0
#include <avr/dtostrf.h>
#endif

#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeSans12pt7b.h>
#include <Fonts/FreeSerif12pt7b.h>

#include <FreeDefaultFonts.h>

#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

uint16_t bgcolor = YELLOW;   //change this to BLACK

void setup(void)
{
    Serial.begin(9600);
    uint16_t ID = tft.readID();
    if (ID == 0xD3D3) ID = 0x9481;
    tft.begin(ID);
    tft.setRotation(1);
    tft.fillScreen(BLACK);
    tft.setTextColor(RED);
    show_prec(0.0);   //shows problem with ST Core
    delay(5000);
    show_prec(1650.45);  //round down
    delay(5000);
    show_prec(1650.55);  //round up
    delay(5000);
}

void loop(void)
{
    float num = random(-1999, 1999);
    show_prec(num);
    delay(1000);
}

void show_prec(double num)
{
    int x = 18, y;
    tft.setFont(NULL);
    tft.setTextSize(1);
    tft.setCursor(x, y);
    tft.print("7x5 system font");
    rightjustify(x, y + 10, 0.01 * num, 6, 2);
    y = 20;
    tft.setFont(NULL);
    tft.setTextSize(2);
    tft.setCursor(x, y);
    tft.print("7x5 system font");
    rightjustify(x, y + 20, 0.01 * num, 6, 2);
    y = 80;
    tft.setFont(&FreeBigFont);
    tft.setTextSize(1);
    tft.setCursor(x, y);
    tft.print("FreeBigFont");
    rightjustify(x, y + 20, 0.01 * num, 6, 2);
    y = 120;
    tft.setFont(&FreeSans12pt7b);
    tft.setTextSize(1);
    tft.setCursor(x, y);
    tft.print("FreeSans12pt7b");
    rightjustify(x, y + 20, 0.01 * num, 6, 2);
    y = 180;
    tft.setCursor(x, y);
    tft.print("FreeSevenSegNumFont");
    tft.setFont(&FreeSevenSegNumFont);
    tft.setTextSize(1);
    //SevenSeg Font does not have period or minus.  Show integer.
    rightjustify(x, y + 60, fabs(num), 4, 0);
}

/* life is much simpler with the 7x5 System Font
 * tft.setTextColor(FOREGROUND, BACKGROUND);
 * char buf[12];    //for formatted result
 * tft.setCursor(x, y);
 * tft.print(dtostr(floatnum, wid, prec, buf));
 */

/* this should work for all Fonts
 * note that FreeFonts treat x,y with y as baseline
 */
int rightjustify(int x, int y, double num, int wid, int prec)
{
    //calculate background every time
    char buf[12];
    int16_t x1, y1;
    uint16_t w, h;
    memset(buf, '0', wid);    //"0000000"
    buf[wid] = '\0';
    tft.getTextBounds(buf, x, y, &x1, &y1, &w, &h);
    //paint the background starting at x
    tft.fillRect(x, y1, w, h, bgcolor);
    //remember the full width of "0000000"
    uint16_t rt = w;
    //format the result.  works for integers too e.g. prec = 0
    //STM32 Core from ST MicroElectronics is bad format
    dtostrf(num, wid, prec, buf);
    //calculate the width of new string
    tft.getTextBounds(buf, x, y, &x1, &y1, &w, &h);
    int16_t xofs = x1 - x;
    //adjust for the correct print position
    tft.setCursor(x + rt - w - xofs, y);
    //this prints transparently on the fresh background
    tft.print(buf);
    return w;
}

In practice you often want nice proportional Fonts for text but the fixed 7x5 System font is ok for formatted Sensor readings. It looks ok in double size. Anything bigger and looks blocky.

Note that the FreeBigFont gives you the worst of both worlds. It is a fixed width font but extremely ugly.

David.