Is there a way to display an image on a TFT LCD within a box?

Hi there, I have recently bought a 2.8" TFT LCD display for the arduino. I want to encorporate it into a future project and I was wanting to know if there is a way to display images from a micro sd card on the TFT LCD board, but not fullscreen. I would like them to be able to be constrained within a shape, such as a square to then act as a button. eg. Gear image for a settings button. I would appreciate any help!

Thanks, Ken

Yes, it is possible to do so. There are some tutorials out there but it is a little more complex than something that I can write in a post.

Ok cool! Do you have any links for those tutorials, because I’ve looked everywhere?

Kenn13542:
constrained within a shape, such as a square to then act as a button.

Such as a square, or even a rectangle is no problem at all.

I assume you are using the UTFT libraries by Henning Karlsen? Hazardsmind makes an alternative buttons library and also an extension library to UTFT might fit your requirements. UTFT extension here GitHub - AndrewMascolo/TFT_Extension: TFT Extension and the buttons library is also on there somewhere :stuck_out_tongue:

Alternatively, you can draw your whole screen in Photoshop your favourite graphics package with fancy text and pretty buttons which you just load from SD card using my superfast UTFT_SdRaw library :wink: and then manually decode the touch events yourself?

It really is not too hard once you start experimenting a little.

Regards,

Graham

Thanks Graham, I really like the idea of doing a custom screen in a program like photoshop and then mapping the buttons. Thanks for your advice, I'll start having a go at getting it to work.

You are welcome!

I have transferred my UTFT_SdRaw library this evening to Github, new address is nowhttps://github.com/ghlawrence2000/UTFT_SdRaw

Can draw a 240240 image from SD to TFT in about 190ms 320240 not tons slower…

Then all you need to do… is something like…

void processMyTouch() 
{ 
  static volatile byte tempAD, tempTD, tempHD, tempBL;    
  static volatile float tempHeater, tempFan;                      
  static volatile byte tempL1OnHr, tempL1OnMin;               
  static volatile byte tempL1OffHr, tempL1OffMin;              
  static volatile byte tempL2OnHr, tempL2OnMin;               
  static volatile byte tempL2OffHr, tempL2OffMin;              
  myTouch.read();             
  word x = myTouch.getX();
  word y = myTouch.getY();
  switch (dispScreen) 
  { 
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //                                                Home Screen                                               //
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    case 1:                              
      if ((y >= 64) && (y < 114))
      { 
        if ((x >= 371) && ( x < 421)) // 'Secret button'  
        { 
          listActiveAlarms();                                      
        } 
      } 
      if ((y >= 117) && (y < 235))                            
      { 
        if ((x >= 59) && (x <= 134)) // Light Settings Page
        { 
          tempL1OnHr = Light.On1Hr;                             
          tempL1OnMin = Light.On1Min;                          
          tempL1OffHr = Light.Dur1Min;                          
          tempL1OffMin = Light.Dur1Sec;                         
          tempL2OnHr = Light.On2Hr;                             
          tempL2OnMin = Light.On2Min;                           
          tempL2OffHr = Light.Dur2Min;                           
          tempL2OffMin = Light.Dur2Sec;                          
          screenLights();                                                
          myGLCD.setFont(Ubuntubold);                            
          myGLCD.printNumI(tempL1OnHr, 211, 207, 2);      
          myGLCD.printNumI(tempL1OffHr, 211, 342, 2);      
          myGLCD.printNumI(tempL1OnMin, 330, 207, 2, '0');
          myGLCD.printNumI(tempL1OffMin, 330, 342, 2, '0');
          myGLCD.printNumI(tempL2OnHr, 591, 207, 2);       
          myGLCD.printNumI(tempL2OffHr, 591, 342, 2);       
          myGLCD.printNumI(tempL2OnMin, 709, 207, 2, '0'); 
          myGLCD.printNumI(tempL2OffMin, 709, 342, 2, '0'); 
        } 
        if ((x >= 175) && (x <= 240)) // Temp Settings Page 
        { 
          temptempUnits = tempUnits; 
          tempHeater = heater;  
          tempFan = fan;  
          screenTemp();  
        } 
        if ((x >= 270) && (x <= 362)) // Fogger Settings Page
        { 
          tempFog1 = Fog;           
          screenFogger();  
          if (!(Fog.Enable & 0xF0)) 
          { 
            blankFogfanTime(1);    
          } 
          if (!(Fog.Enable & 0x0F)) 
          { 
            blankFogfanTime(2); 
          } 
          ffTimePrint(tempFog1, fogScreen);
        } 
      } 
      if (( y >= 285) && (y < 411)) { 
        if ((x >= 46) && (x <= 141)) 
        { 
          tempM1 = Mist;
          tempM2 = Mist2;                              
          screenMist();                                   
          if ( mistScreen < 3) 
          { 
            MistTimePrint(tempM1, mistScreen);  
          } 
          else  
          { 
            MistTimePrint(tempM2, mistScreen); 
          } 
        } 
        if ((x >= 171) && (x <= 237)) // Fan Settings Page 
        { 
          tempFan1 = Fan;  
          screenFan();              
          if (!(Fan.Enable & 0xF0)) 
          { 
            blankFogfanTime(1); 
          } 
          if (!(Fan.Enable & 0x0F))   
          { 
            blankFogfanTime(2);
          } 
          ffTimePrint(tempFan1, fanScreen);   
        } 
        if ((x >= 270) && (x <= 370)) // Clock Page  
        { 
          screenClock(); 
          SetDatePrint();
          SetTimePrint();
        }
      } 
      if ((x >= 712) && (x <= 779) && (y >= 13) && (y <= 77)) // Screen Page                                    
      { 
        tempAD = AutoDim;  
        tempTD = TouchDelay; 
        tempHD = HomeDelay;
        tempBL = BackLight;
        screenScreen();
      }                                                                
      break;                                                            
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //                                                Lights Screen                                             //
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    case 2:
      if ((x >= 363) && (x <= 444) && (y >= 422) && (y <= 479)) // Return Home button     
      { 
        byte change = 0xFF;
        TouchRepeatDelay = tmpTouchRepeatDelay; 
        if (tempL1OnHr != Light.On1Hr) { 
          EEPROM.write(13, tempL1OnHr);
          Light.On1Hr = tempL1OnHr;      
#if debug                                         
          Serial.println(F("Light.On1Hr -> EEPROM"));
#endif                                                            
          change = 0;                                          
        } 
        if (tempL1OnMin != Light.On1Min) { 
          EEPROM.write(14, tempL1OnMin);  
          Light.On1Min = tempL1OnMin;       
#if debug                                            
          Serial.println(F("Light.On1Min -> EEPROM")); 
#endif                                                               
          change = 0;                                             
        } 
        if (tempL1OffHr != Light.Dur1Min) {
          EEPROM.write(15, tempL1OffHr);  
          Light.Dur1Min = tempL1OffHr;     
#if debug                                           
          Serial.println(F("Light.Dur1Min -> EEPROM")); 
#endif                                                                
          change = 0;                                              
        } 
        if (tempL1OffMin != Light.Dur1Sec) { 
          EEPROM.write(16, tempL1OffMin);   
          Light.Dur1Sec = tempL1OffMin;

etc…

This will NOT compile!! It is just a tiny fragment of an enormous sketch, but you should be able to see what I am trying to show you.

Regards,

Graham

That's great! I will read through your example and see how I go, but it looks really promising.

I’m trying to do this in stages so I can understand it as it goes. I wrote this and have it hooked up to my relay switches but it only runs once. It works both ways as in if the pin is HIGH it’ll toggle LOW and vice versa, however once its completed it once, it won’t then let it toggle the other way, unless its reset.

I have tried it without the ‘while’ statement but it doesn’t work at all then. Where am I going wrong? It seems to be only running it once and not relooping after it exits the ‘while’.

#include <UTFT.h>
#include <UTouch.h>
#include <Wire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <SdFat.h>
#include <UTFT_SdRaw.h>
#include <UTFT_Buttons.h>

#define imagedatatype  unsigned int     // BITMAP IMAGES
#define SD_CHIP_SELECT  53


extern uint8_t BigFont[];
extern uint8_t various_symbols[];
extern imagedatatype homeB[];

int x, y,g,menu;

int powerPin1 = 13;      // Power relay 1
int val = 0;

UTFT myGLCD(ILI9327,38,39,40,41);        //Screen initialization
UTouch myTouch(6, 5, 4, 3, 2);           //Touch initialization
UTFT_Buttons  myButtons(&myGLCD, &myTouch);
UTFT_SdRaw myFiles(&myGLCD);
                 
SdFat sd;

void setup() 
{ 
  myGLCD.InitLCD(LANDSCAPE);                   // Initialize the display
  myGLCD.clrScr();                             // Clear the screen (black)
  myTouch.InitTouch(LANDSCAPE);
  myTouch.setPrecision(PREC_MEDIUM);
  sd.begin(SD_CHIP_SELECT, SPI_QUARTER_SPEED); // Initialize the SD card
  
  myGLCD.clrScr();                            // Clear the screen (black)
  Menu1();
  menu=1;
  
  pinMode(powerPin1, OUTPUT);      // Power relay 1
}

int but1, pressed_button;


void Menu1()
{
myGLCD.clrScr(); 
  
  myGLCD.setColor(255, 255, 255);
    myGLCD.setFont(BigFont);            // --- Labels ---
      myGLCD.print("Test Statement",20,20);  
      
  but1 = myButtons.addButton(20,60,50,50, homeB, BUTTON_NO_BORDER);
  myButtons.drawButton(but1);
}

void loop() 
{
digitalWrite(powerPin1, LOW);

val = digitalRead(powerPin1);

while(1)
  {
    if (myTouch.dataAvailable() == true)
      {
        pressed_button = myButtons.checkButtons();
          if (pressed_button==but1) 
            { 
              if (val == HIGH)
              {           
                digitalWrite(powerPin1, LOW);
              }
              else
              {
                digitalWrite(powerPin1, HIGH);
              }
          }
      }
  } 
}

I know you kindly added the above code Graham but I have as much chance of perfuming brain surgery after a month of reading about it as I have understanding that code and sculpting it into something I can use. And I’m sorry I don’t understand everything you say but I have only been doing this for a month. I also know the best way is to learn it all from scratch, but, it will take years to learn the art of coding to your kind of level and from what I am told, what I need is not that complicated, I just need to figure out how it does what it does and hopefully with a shove in the right direction sometimes. Like above, I have tried to get this section to work, over and over again, and it is close, but just needs a tweak. It may not be the cleanest way of doing it, it may not be the most efficient way of doing it, but if its the easiest way and it still does the job, then that seems ok with me.

It doesn’t appear you are listening…

Maybe this will help show where your code stops behaving as you expect??

#include <UTFT.h>
#include <UTouch.h>
#include <Wire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <SdFat.h>
#include <UTFT_SdRaw.h>
#include <UTFT_Buttons.h>

#define imagedatatype  unsigned int     // BITMAP IMAGES
#define SD_CHIP_SELECT  53


extern uint8_t BigFont[];
extern uint8_t various_symbols[];
extern imagedatatype homeB[];

int x, y, g, menu;

int powerPin1 = 13;      // Power relay 1
int val = 0;

UTFT myGLCD(ILI9327, 38, 39, 40, 41);    //Screen initialization
UTouch myTouch(6, 5, 32, 3, 2);           //Touch initialization
UTFT_Buttons  myButtons(&myGLCD, &myTouch);
UTFT_SdRaw myFiles(&myGLCD);

SdFat sd;

void setup()
{
  myGLCD.InitLCD(LANDSCAPE);                   // Initialize the display
  myGLCD.clrScr();                             // Clear the screen (black)
  myTouch.InitTouch(LANDSCAPE);
  myTouch.setPrecision(PREC_MEDIUM);
  sd.begin(SD_CHIP_SELECT, SPI_QUARTER_SPEED); // Initialize the SD card
  Serial.begin(115200);  // < ==== MOST important!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  myGLCD.clrScr();                            // Clear the screen (black)
  Menu1();
  menu = 1;

  pinMode(powerPin1, OUTPUT);      // Power relay 1
}

int but1, pressed_button;


void Menu1()
{
  myGLCD.clrScr();

  myGLCD.setColor(255, 255, 255);
  myGLCD.setFont(BigFont);            // --- Labels ---
  myGLCD.print("Test Statement", 20, 20);

  but1 = myButtons.addButton(20, 60, 50, 50, homeB, BUTTON_NO_BORDER );
  myButtons.drawButton(but1);
}

void loop()
{
  digitalWrite(powerPin1, LOW);

  val = digitalRead(powerPin1);

  while (1)
  {
    if (myTouch.dataAvailable() == true)
    {
      Serial.println("Touch dataAvailable TRUE"); // As is THIS!!!!!!!!!!!
      pressed_button = myButtons.checkButtons();
      Serial.print("pressed button ="); Serial.println(pressed_button); // AND THIS!!!!!!!!!!
      if (pressed_button == but1)
      {
        Serial.println("pressed_button == but1"); // AND THIS!!!!!!!!!!
        if (val == HIGH)
        {
          Serial.println("val == HIGH""); // AND THIS!!!!!!!!!!
                         digitalWrite(powerPin1, LOW);
                       }
                         else
                       {
                         Serial.println("val != HIGH""); // AND THIS!!!!!!!!!!
          digitalWrite(powerPin1, HIGH);
        }
      }
    }
  }
}

Already told you… Serial is THE most important debugging tool for a novice like yourself!!! That is NOT meant as a put down, the ONLY put down is that you appear to have some dislike to advice and using the serial monitor!!

I won’t say it again…

Regards,

Graham

Stevelondon:
Where am I going wrong? It seems to be only running it once and not relooping after it exits the ‘while’.

WHEN exactly do you think it will exit the while loop??

If you had prolifically used Serial as I may already have mentioned more than a couple of times, and should ALWAYS be the first thing to do in these mysterious situations… you would have figured that out already… By yourself, as part of your learning process… Shall I continue? :roll_eyes: :sob:

Regards,

Graham

ghlawrence2000:
It doesn’t appear you are listening…

Maybe this will help show where your code stops behaving as you expect??

#include <UTFT.h>

#include <UTouch.h>
#include <Wire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <SdFat.h>
#include <UTFT_SdRaw.h>
#include <UTFT_Buttons.h>

#define imagedatatype  unsigned int    // BITMAP IMAGES
#define SD_CHIP_SELECT  53

extern uint8_t BigFont;
extern uint8_t various_symbols;
extern imagedatatype homeB;

int x, y, g, menu;

int powerPin1 = 13;      // Power relay 1
int val = 0;

UTFT myGLCD(ILI9327, 38, 39, 40, 41);    //Screen initialization
UTouch myTouch(6, 5, 32, 3, 2);          //Touch initialization
UTFT_Buttons  myButtons(&myGLCD, &myTouch);
UTFT_SdRaw myFiles(&myGLCD);

SdFat sd;

void setup()
{
  myGLCD.InitLCD(LANDSCAPE);                  // Initialize the display
  myGLCD.clrScr();                            // Clear the screen (black)
  myTouch.InitTouch(LANDSCAPE);
  myTouch.setPrecision(PREC_MEDIUM);
  sd.begin(SD_CHIP_SELECT, SPI_QUARTER_SPEED); // Initialize the SD card
  Serial.begin(115200);  // < ==== MOST important!!!
  myGLCD.clrScr();                            // Clear the screen (black)
  Menu1();
  menu = 1;

pinMode(powerPin1, OUTPUT);      // Power relay 1
}

int but1, pressed_button;

void Menu1()
{
  myGLCD.clrScr();

myGLCD.setColor(255, 255, 255);
  myGLCD.setFont(BigFont);            // — Labels —
  myGLCD.print(“Test Statement”, 20, 20);

but1 = myButtons.addButton(20, 60, 50, 50, homeB, BUTTON_NO_BORDER );
  myButtons.drawButton(but1);
}

void loop()
{
  digitalWrite(powerPin1, LOW);

val = digitalRead(powerPin1);

while (1)
  {
    if (myTouch.dataAvailable() == true)
    {
      Serial.println(“Touch dataAvailable TRUE”); // As is THIS!!!
      pressed_button = myButtons.checkButtons();
      Serial.print(“pressed button =”); Serial.println(pressed_button); // AND THIS!!!
      if (pressed_button == but1)
      {
        Serial.println(“pressed_button == but1”); // AND THIS!!!
        if (val == HIGH)
        {
          Serial.println(“val == HIGH”"); // AND THIS!!!
                        digitalWrite(powerPin1, LOW);
                      }
                        else
                      {
                        Serial.println(“val != HIGH”"); // AND THIS!!!
          digitalWrite(powerPin1, HIGH);
        }
      }
    }
  }
}




Already told you.............. Serial is THE most important debugging tool for a novice like yourself!!! That is NOT meant as a put down, the ONLY put down is that you appear to have some dislike to advice and using the serial monitor!!

I won't say it again.......... 

Regards,

Graham

Graham, I really don’t mean to sound rude, and I appreciate your help more than you will ever know, but the point I am getting at is… HOW AM I SUPPOSED TO WRITE A CODE INCORPORATING A FULL SERIAL MONITOR OUTPUT TO HELP FIND THE ERRORS WHEN I CAN’T EVEN WRITE THE ORIGINAL CODE TO START WITH??? I’m asking how to do A and B and you expect me to now how to write A, B and C together. I’m afraid it might all be obvious to you, like the things that I have learnt and studied over the years are to me, but if I knew how to do all of this, including writing a whole load of code including a comprehensive serial monitor debugging matrix, I wouldn’t need to ask how to code a relay to turn on and off would I.

I have figured it out now and even fixed the original issue of turning the power lights to green on power up.

Will post the code in a mo as it may help others

Not a problem, I am done, I can't force help and advice on you. Good luck with your endeavours.

Regards,

G

ghlawrence2000: Not a problem, I am done, I can't force help and advice on you. Good luck with your endeavours.

Regards,

G

Thanks for everything yo have done for me and taught me.

PS. I have just learned how to add the serial monitor outputs and use the different statements to produce differing results. It was easier than I thought but I know I'm going to get lost on anything other than an IF. By hey.