3.5inch_Arduino_ILI9486_V1.3

in this sketch , the original bmp file is working , a new bmp picture ( i tried irfan , paint and gmp ) give only vertical lines .

  1. ShowBMP.ino = original sketch
  2. ShowBMP_zonder_loop_2.ino = my adapted sketch
  3. 02.bmp = original bmp picture
  4. rotator_good_100dpi.bmp = my bmp.picture

I adapted the sketch for my needs as far and good as I understand Arduino ( there is stell a lot in the sketch , I don't understand )

Question , what's wrong with my picture or what to change in the code to accept my picture ?

Marco

Ooops , the bmp-files were not accepted ? Looking for an other way to do it .

ShowBMP_zonder__loop_2.ino (3.5 KB)

ShowBMP.ino (5.65 KB)

Ooops the bitmaps are not accepted , looking for an other way to do it . :o

Put your .BMP files inside a ZIP
Add your original artwork as JPG or PNG to the ZIP too.

Then attach the Zip file to your message.

Most Forums accept .ZIP and .TXT but may be fussy about other file extensions.

David.

Good Morning , David ,
Please find herewith the zip files .
In a next post I'll atteche the jpg files
Marco

02 - kopie.zip (385 KB)

rotator_good_100dpi.zip (77.4 KB)

Just add the JPG to the ZIP. Edit your message to replace the attached file with your newer Zip.

attached the jpg and png files

02 - jpg.zip (31.6 KB)

rotator_good_100dpi_jpg.zip (22.6 KB)

02 - png.zip (266 KB)

rotator_good_100dpi_png.zip (69 KB)

Life would have been a lot simpler if you had put all the files into a single ZIP.

Anyway, both the Chinese Girl and the Rotator image get rendered from the microSD.

Obviously the Girl is Portrait and the Rotator is Landscape.

What is your question?

David.

Sorry for that , Mea culpa , mea culpa mea maxima culpa .......

When I change the name in :

char bmp_name[FILENAME_LEN] = {"02.bmp",};

into the name of my bmp-file I get some lines and colors on the display ( 3.5" MCU on a Arduino-UNO ) insteat a readable picture .

The 02.bmp original bmp is working fine .

Than I did following test . I loaded 02.bmp in IRFAN and saved the file right again as bmp. That IRFAN-bmp don't work in the sketch . So my idea was that something in the original picture was differend from mine .

When I check out the metadata of both pictures , for me they are the same .

So therefore my question: what's wrong with my picture or what to change in the code to make accept my picture ?

Marco

I provide you with a BMP display program that will accept several different .BMP formats.

If you are only using the 24-bit colour format, I could strip out all the other code.
Or you could do it as a "user exercise".

There are many examples on the Internet that can render a BMP24 file. (only BMP24)

You appear to have made a half-hearted attempt to do your own thing.
I could debug it for you but this will defeat the "user exercise".

Please note that you do not need enormous buffers. I tend to use a Uno which has limited SRAM.
If you want readers to assist you, it is worth making your code "buildable" by forum members.

David.

I know my knowledge of Arduino or C++ is limited but using some code ( sketch ) without understanding is something I don't like to do .

I like you bmp program but as I don't understand all of it I'm not capable to strip out all the things I don't need for my project .

I tried to do it but was blocked several times . Thanks to that I learned a lot about cases , SD-cards commands and other functions . So for me it was not a lost of time .

What I like to do :

  1. using a MEGA
  2. monitoring one ( 1 ) bitmap om a 3.5" tft screen .
  3. No code in the loop

If you will strip your code monitoring one bitmap ( my rotator ) please do that.

After all I will study your code again and do some "reverce engeneering" .

Marco

Here is a minimal sketch. You would normally use the return value from showBMP24()

showBMP24_F8VOA.ino

#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
#include <SD.h>

#define SD_CS 10
#define RESTORE_SPI_GPIO()   //empty for parallel TFT

void setup()
{
    uint16_t ID;
    Serial.begin(9600);
    Serial.print("Show BMP files on TFT with ID:0x");
    ID = tft.readID();
    Serial.println(ID, HEX);
    tft.begin(ID);
    bool good = SD.begin(SD_CS);
    if (!good) {
        Serial.print(F("cannot start SD"));
        while (1) yield();
    }
}

void loop()
{
    tft.setRotation(1);     //LANDSCAPE
    tft.fillScreen(TFT_BLUE);
    uint8_t ret = showBMP24("/rotato~1.bmp", 0, 0);
    delay(5000);
}

// These read 16- and 32-bit types from the SD card file.
// BMP data is stored little-endian, Arduino is little-endian too.
// May need to reverse subscript order if porting elsewhere.

uint16_t read16(File &f) {
    uint16_t result;
    f.read(&result, sizeof(result));
    return result;
}

uint32_t read32(File &f) {
    uint32_t result;
    f.read(&result, sizeof(result));
    return result;
}

// This function opens a Windows Bitmap (BMP) file and
// displays it at the given coordinates.  It's sped up
// by reading many pixels worth of data at a time
// (rather than pixel by pixel).  Increasing the buffer
// size takes more of the Arduino's precious RAM but
// makes loading a little faster.  20 pixels seems a
// good balance.

#define BMPIMAGEOFFSET 54
#define BUFFPIXEL 20

uint8_t showBMP24(char *nm, int x, int y)
{
    File bmpFile;
    int bmpWidth, bmpHeight;    // W+H in pixels
    uint8_t bmpDepth;           // Bit depth (currently must be 24, 16, 8, 4, 1)
    uint32_t bmpImageoffset;    // Start of image data in file
    uint32_t rowSize;           // Not always = bmpWidth; may have padding
    uint8_t sdbuffer[3 * BUFFPIXEL];    // pixel in buffer (R+G+B per pixel)
    uint16_t lcdbuffer[BUFFPIXEL];
    boolean flip = true;        // BMP is stored bottom-to-top
    int w, h, row, col, lcdbufsiz = BUFFPIXEL, buffidx;
    uint32_t pos;               // seek position

    uint16_t bmpID;
    uint16_t n;                 // blocks read
    uint8_t ret;

    if ((x >= tft.width()) || (y >= tft.height()))
        return 1;               // off screen

    bmpFile = SD.open(nm);      // Parse BMP header
    bmpID = read16(bmpFile);    // BMP signature
    (void) read32(bmpFile);     // Read & ignore file size
    (void) read32(bmpFile);     // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile);       // Start of image data
    (void) read32(bmpFile);     // Read & ignore DIB header size
    bmpWidth = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    n = read16(bmpFile);        // # planes -- must be '1'
    bmpDepth = read16(bmpFile); // bits per pixel
    pos = read32(bmpFile);      // format
    if (bmpID != 0x4D42) ret = 2; // bad ID
    else if (bmpDepth != 24) ret = 4;   // unsupported format
    else {
        bool first = true;
        // BMP rows are padded (if needed) to 4-byte boundary
        rowSize = (bmpWidth * bmpDepth / 8 + 3) & ~3;
        if (bmpHeight < 0) {              // If negative, image is in top-down order.
            bmpHeight = -bmpHeight;
            flip = false;
        }

        w = bmpWidth;
        h = bmpHeight;
        RESTORE_SPI_GPIO();
        //        tft.setRotation(w > h ? 1 : 0);   //PORTRAIT or LANDSCAPE
        if ((x + w) >= tft.width())       // Crop area to be loaded
            w = tft.width() - x;
        if ((y + h) >= tft.height())      //
            h = tft.height() - y;

        RESTORE_SPI_GPIO();
        // Set TFT address window to clipped image bounds
        tft.setAddrWindow(x, y, x + w - 1, y + h - 1);
        for (row = 0; row < h; row++) { // For each scanline...
            // Seek to start of scan line.  It might seem labor-
            // intensive to be doing this on every line, but this
            // method covers a lot of gritty details like cropping
            // and scanline padding.  Also, the seek only takes
            // place if the file position actually needs to change
            // (avoids a lot of cluster math in SD library).
            uint8_t r, g, b, *sdptr;
            int lcdidx, lcdleft;
            if (flip)   // Bitmap is stored bottom-to-top order (normal BMP)
                pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
            else        // Bitmap is stored top-to-bottom
                pos = bmpImageoffset + row * rowSize;
            if (bmpFile.position() != pos) { // Need seek?
                bmpFile.seek(pos);
                buffidx = sizeof(sdbuffer); // Force buffer reload
            }

            for (col = 0; col < w; ) {  //pixels in row
                lcdleft = w - col;
                if (lcdleft > lcdbufsiz) lcdleft = lcdbufsiz;
                for (lcdidx = 0; lcdidx < lcdleft; lcdidx++) { // buffer at a time
                    uint16_t color;
                    // Time to read more pixel data?
                    if (buffidx >= sizeof(sdbuffer)) { // Indeed
                        bmpFile.read(sdbuffer, sizeof(sdbuffer));
                        buffidx = 0; // Set index to beginning
                    }
                    b = sdbuffer[buffidx++];
                    g = sdbuffer[buffidx++];
                    r = sdbuffer[buffidx++];
                    color = tft.color565(r, g, b);
                    lcdbuffer[lcdidx] = color;

                }
                RESTORE_SPI_GPIO();
                tft.pushColors(lcdbuffer, lcdidx, first);
                first = false;
                col += lcdidx;
            }           // end cols
        }               // end rows
        tft.setAddrWindow(0, 0, tft.width() - 1, tft.height() - 1); //restore full screen
        ret = 0;        // good render
    }
    bmpFile.close();
    RESTORE_SPI_GPIO();
    return (ret);
}

You could always pre-process the BMP24 file into a RAW file with known dimensions.
This is much simpler to display.

David.

Thanks David and a very good morning ,

I'll try it out.
Any way , I'll try it also by myself ( learning process )

I'm not familiar with RAW , never used that in radio or electronics.
I'l try to play with that also.

You are an early bird .... like me .

We have a predicate : " Morning time will give you gold in the mouth ".

thank you , Marco

#define USE_SDFAT
#include <SdFat.h> // Use the SdFat library
SdFatSoftSpi<12, 11, 13> SD; //Bit-Bang on the Shield pins
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
//#include <SD.h>
#define SD_CS 10
#define RESTORE_SPI_GPIO() //empty for parallel TFT

I had to do this to get the picture on my screen.
Working fine , thanks , it's a lot smaller then before .

Can it all be done outside of the loop ? So yes , I will try to do it by myself

Thanks for all your patience .

how to understand this line :

int w, h, row, col, lcdbufsiz = BUFFPIXEL, buffidx;

I know integers but not how to use w,h,...... ( all together )

Marco

You can call showBMP24() as a one-off in setup()
I put it in loop() so that you could see it working.

There are lots of variables. You can declare several on the same line.
There is nothing complicated. You read width, height, ... from the BMP header.
Then read each row as RGBRGBRGB... i.e. each pixel as RGB

Rows are normally stored bottom to top in th BMP file.
Sometimes they are in top to bottom order.

Preprocessing all the RGB into a raw sequence of 16-bit pixels LHLHLHLH... is what the UTFT utility does.

David.

That's crystal clear . Very simple once you know it.

It's a pitty but finding clear user manuals is very hard.

It's enough for today , I have a lot of work to do with it.

Have a nice day and thanks
Marco

Good Morning David ,

I have a small problem with the bitmap and do not find the reason .
Attached you will find the whole sketch.

I use a MEGA and the 3.5 inch screen.
The sketch is not the problem , the rotator is working fine.Some small details but that's for later.

But :
When I start the sketch from the USB power or with an extern power source , the bitmat is not on the right place on the screen . The bitmap is out of the center and more to the right side . On the left side you can see than the beginning of the picture ( a small vertical white line )

When , after starting like above , I upload the sketch again , the bitmap is in the center .

Do you have any idea why ?

Marco.

rotator_small_1.1.zip (6.27 KB)

Your code "looks" ok. I have not run it.

You can view your .BMP file on your PC.
It should look exactly the same on the TFT.

David.

OK , David
I did that before and the BMP is fine.

Problem is :
every time I restart the Mega ( shut down the power and put it back on ) the BMP move on the screen a little bit to the right. Sometimes after restarting a few times , the screen is back to normal.

The screen and the Mega are powered by 5VDC ( stab with a 7805 - like it should be ) I checked this PS , no hum , no shut down or other issues

it's bizar

Marco