Problem of displaying image from SD card without tinyFAT library

Hello all, I am new to arduino and I am trying to build a image viewer from SD card first.
However, due to some reasons, I cannot use tinyFAT library. And I found one solution from internet.
The code I found and modified is as following:

// Arduino SD image viewer

// This program requires the UTFT library.
//

#include <UTFT.h>
#include <SD.h>

// Declare which fonts we will be using
extern uint8_t SmallFont[];
extern uint8_t BigFont[];


// for Arduino Mega
UTFT myGLCD(HX8357B,38,39,40,41);   // Remember to change the model parameter to suit your display module!

#define SD_PIN 53

File root;

#define SCREEN_WIDTH 480
#define SCREEN_HEIGHT 320


void LoadImage(File& file)
{
    for (int y = 0; y < SCREEN_HEIGHT && file.available(); y++) {
        uint16_t buf[SCREEN_WIDTH];
        for (int x = SCREEN_WIDTH - 1; x >= 0; x--) {
            byte l = file.read();
            byte h = file.read();
            buf[x] = ((uint16_t)h << 8) | l;
        }
        myGLCD.drawPixelLine(0, y, SCREEN_WIDTH, buf);
    }
}

void WalkDirectory(File dir)
{
    for (;;) {
        File entry =  dir.openNextFile();
        if (! entry) {
            // no more files
            break;
        }
        if (entry.isDirectory()) {
            WalkDirectory(entry);
        } else {
       
            LoadImage(entry);
        }
        entry.close();
        // delay for a while between each image
        delay(2000);
    }
}

void setup()
{
    // Setup the LCD
    myGLCD.InitLCD();
    myGLCD.setFont(SmallFont);
    myGLCD.fillScr(255, 255, 255);

    pinMode(SD_PIN, OUTPUT);
    if (!SD.begin(SD_PIN)) {
        ShowMessage("SD not ready");
        return;
    }
    delay(1000);
    


}

void loop(){
  root = SD.open("/PICTURE");
    WalkDirectory(root);
}

This works well but the problem is that it loads images too slowly. Is there any other way to load image from SD card or any improvement can be made to fasten it?

Thanks a lot!

Hi penthrite,

Welcome to the forums! :grin:

Yes, I had a similar idea and was somewhat astounded that it took approximately 20 seconds to draw a 320*240 image using a Mega2560 done similarly to what you did!

Since then I wrote a SdFatlib version of UTFT_tinyFAT, and since then further improved it to offer other functions not included in in UTFT_tinyFAT.

My library is now called UTFT_SdRaw and is compatible with both MEGA and DUE and works using SdFatlib which is a better more supported and updated version of the included SD library. You can get SdFat from here.

You can get UTFT_SdRaw from here.

ftp://ghlawrence.myftp.org:2121/ Please add Karma if you like it :slight_smile:

The real benefit of that library comes when used with a DUE, but significant gains over other methods can still be achieved with a Mega.

Any questions, just ask.

Oh, just to mention, you do need to convert your images to .raw using the tools included with UTFT library!

Regards,

Graham

Hi Graham,

How can i utilize ur library UTFT_SdRaw for the following program:

#include <SdFat.h>
#include <UTFT_tinyFAT.h>
#include <UTFT.h>
#include <UTouch.h>

UTFT myGLCD(CTE70CPLD, 25,26,27,28);
UTouch myTouch(6, 5, 4, 3, 2);
UTFT_tinyFAT myFiles(&myGLCD);

// SD chip select pin
const uint8_t chipSelect = 53;

// file system
SdFat sd;

void screenHome() // draw main home screen showing overview info
{
myGLCD.clrScr(); // clear the screen
myGLCD.setColor(255, 255, 255);
myGLCD.drawLine(0, 360, 800, 360); // draw line above dock
int mytime = millis();
myFiles.loadBitmap(0, 0, 800, 480, "Demo.raw");
Serial.println(millis() - mytime);
}

void setup() {
myGLCD.InitLCD();
myTouch.InitTouch();

if (!sd.begin(chipSelect, SPI_FULL_SPEED)) sd.initErrorHalt();
Serial.begin(9600);
Serial.println("card initialized.");
// display home screen
screenHome();
}

void loop()
{
}

Regards,
Tanu

Hi Tanu,

You could start by deleting UTFT_tinyFAT. It is no longer required.

#include <SdFat.h>
#include <UTFT_SdRaw.h>
#include <UTFT.h>
#include <UTouch.h>

UTFT myGLCD(CTE70CPLD, 25, 26, 27, 28);
UTouch  myTouch(6, 5, 4, 3, 2);
UTFT_SdRaw myFiles(&myGLCD);

// SD chip select pin
const uint8_t chipSelect = 53;

// file system
SdFat sd;

void screenHome()  // draw main home screen showing overview info
{
  myGLCD.clrScr(); // clear the screen
  myGLCD.setColor(255, 255, 255);
  myGLCD.drawLine(0, 360, 800, 360); // draw line above dock
  int mytime = millis();
  myFiles.load(0, 0, 800, 480, "demo.raw", 16);
  Serial.println(millis() - mytime);
}

void setup() {
  myGLCD.InitLCD();
  myTouch.InitTouch();

  if (!sd.begin(chipSelect, SPI_FULL_SPEED)) sd.initErrorHalt();
  Serial.begin(9600);
  Serial.println("card initialized.");
  // display home screen
  screenHome();
}

void loop()
{
}

This line can be changed if you have smaller images...

myFiles.load(0, 0, 800, 480, "demo.raw", x, y);

x= buffer multiplier, bigger is better, but too high will cause corruption.
y= inverted colour, if you have any images which you think 'look wrong' try 1 for this. (Any .raw images made with Henning's tools do not need this)

Regards,

Graham

Hi Graham,

I made the changes u told, and I guess my lcd module is not reading any datas from the SD card (I don't think there's a problem with the lcd module because it was working fine with Mega2560).

And my image resolution is exactly 800*480 so i guess it's not necessary to change this line:

myFiles.load(0, 0, 800, 480, "demo.raw", x, y);

Regards,
Tanu

Hi Tanu,

Replace, the ScreenHome function with this :-

void screenHome()  // draw main home screen showing overview info
{
  myGLCD.clrScr(); // clear the screen
  myGLCD.setColor(255, 255, 255);
  myGLCD.drawLine(0, 360, 800, 360); // draw line above dock
  int mytime = millis();
  int ret=myFiles.load(0, 0, 800, 480, "demo.raw", 16);
  
  Serial.println(millis() - mytime);
  Serial.println(ret);
}

Open serial monitor and tell me what you see?

card initialized.
834
0

This is my serial monitor output.

Regards,

Graham

Bro, where to check the serial monitor output (sorry I'm pretty much dumb). And how u'v declared ret in the above code?

Hi Tanu,

The serial monitor is the 'magnifying glass' icon in the top right corner of the arduino software.......

I have declared 'ret' because the load function returns 0 for success, or 99 for fail....

Best wishes,

Graham

But i'm getting the compilation error as : 'ret' was not declared in this scope.

:roll_eyes:

int ret=myFiles.load(0, 0, 800, 480, "demo.raw", 16);

What the hell is this then???

Graham

Now it complied but serial monitor reads nothing, it's blank :confused:

This is getting ridiculous.....

Which port are you using on the DUE........... Serial is defined as the programming port, SerialUSB is defined as the native port. Have you set the board rate on the serial monitor to match the sketch? (9600)

Graham

I'm using programming port indeed, and yes the baud rate is set to 9600.

ok, when the serial monitor window is open, press the reset button on the DUE.

Now, tell me what the serial monitor says......

You really should start at basics if your knowledge is this poor..... UTFT image drawing is really not high on your list of priorities this soon if the serial monitor seemingly is beyond you at this stage....

Regards,

Graham

There is no response in the Serial monitor when i press reset on DUE.

Btw why there is a huge difference in libraries for Mega2560 and DUE?

How did u select the pin select line for ur lcd module? Do u think i should change this line: const uint8_t chipSelect = 53; to someother value?

Regards,
Tanu

#include <SdFat.h>
#include <UTFT_SdRaw.h>
#include <UTFT.h>
#include <UTouch.h>

UTFT myGLCD(CTE70CPLD, 25, 26, 27, 28);
UTouch  myTouch(6, 5, 4, 3, 2);
UTFT_SdRaw myFiles(&myGLCD);

// SD chip select pin
const uint8_t chipSelect = 53;

// file system
SdFat sd;

void screenHome()  // draw main home screen showing overview info
{
  myGLCD.clrScr(); // clear the screen
  myGLCD.setColor(255, 255, 255);
  myGLCD.drawLine(0, 360, 800, 360); // draw line above dock
  int mytime = millis();
  int ret = myFiles.load(0, 0, 800, 480, "demo.raw", 16);
  Serial.println(millis() - mytime);
  Serial.println(ret);
}

void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for DUE & Leonardo only
  }
  Serial.println(F("Initialising SD card..."));
  bool mysd = 0;
  // see if the card is present and can be initialized:
  while (!mysd)
  {
    if (!sd.begin(chipSelect, SPI_FULL_SPEED)) {
      Serial.println(F("Card failed, or not present"));
      Serial.println(F("Retrying...."));
    }
    else
    {
      mysd = 1;
      Serial.println(F("Card initialised."));
    }
  }
  Serial.println(F("Initialising LCD."));
  myGLCD.InitLCD();
  myGLCD.clrScr();
  Serial.println(F("LCD initialised."));
  screenHome();
}

void loop()
{
}

Replace your entire sketch with that..........tell me what you see in serial monitor.

Regards,
Graham

CUTThanu:
Btw why there is a huge difference in libraries for Mega2560 and DUE?

Because the MEGA runs on Diesel, and the DUE runs on Petrol :wink: :stuck_out_tongue:

Graham

Edit: Seriously, the MEGA is an AVR 8 bit device, the DUE is a 32 bit ARM device; they are completely different beasts.

CUTThanu:
How did u select the pin select line for ur lcd module? Do u think i should change this line: const uint8_t chipSelect = 53; to someother value?

It is not a choice, it is the chipselect line for the SD card, it either IS pin 53 or it is not. You don't just guess this....

NOTE: Stop editing the same post........ make a new post so the answers flow in an obvious sequence!!

Graham

Sorry Graham I didn't see the 2nd page, was waiting for ur reply in 1st page.

Yeah i went with ur new code, and now i'm reading messages in the Serial monitor as: Card failed, or not present
Retrying... :confused:

What shield are you using with the DUE?

Try changing SPI_FULL_SPEED to SPI_HALF_SPEED.

Regards,

Graham