Sending Bitmap to TFT display using coolterm

I am trying to send the bitmap from PC via serial interface to the TFT 240x240display. I am shocked that this is so complicated. I wrote this program

#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <SPI.h>

#define TFT_DC    D1     // TFT DC pin is connected to NodeMCU pin D1 (GPIO5)
#define TFT_RST   D2     // TFT RST pin is connected to NodeMCU pin D2 (GPIO4)
#define TFT_CS    D8     // TFT CS pin is connected to NodeMCU pin D8 (GPIO15)

// Initialize ST7789 TFT library with hardware SPI module
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

// Constants for bitmap dimensions
const int IMAGE_WIDTH = 240;
const int IMAGE_HEIGHT = 240;
const int PIXEL_BUFFER_SIZE = IMAGE_WIDTH; // One line of pixels

uint16_t pixelBuffer[PIXEL_BUFFER_SIZE]; // Buffer to hold one line of pixel data

void setup() {
    Serial.begin(9600);
    delay(1000);
    
    tft.init(240, 240, SPI_MODE2);  // Initialize the TFT display
    tft.setRotation(0);             // Set rotation (0, 1, 2, or 3)
    tft.fillScreen(ST77XX_BLACK);   // Clear screen
    Serial.println("Debug messages:");
}

void loop() {
    static int currentLine = 0;  // Track the current line being received
    
    // Check if there is enough data available for one line of pixels
    if (Serial.available() >= PIXEL_BUFFER_SIZE * 2) { // 2 bytes per pixel (16-bit color)
        // Read pixel data directly into the buffer
        Serial.readBytes((char*)pixelBuffer, PIXEL_BUFFER_SIZE * 2);
        
        // Display the line of pixels on the TFT
        tft.writePixels(pixelBuffer, IMAGE_WIDTH);
        
        currentLine++;  // Move to the next line
        
        // Check if all lines have been received
        if (currentLine >= IMAGE_HEIGHT) {
            // Reset for the next image
            currentLine = 0;
            tft.fillScreen(ST77XX_BLACK);  // Clear screen for the next image
        }
    }
}

I am using coolterm to send the file. I created the BMP file and then converted it to RGB565 format. To no avail. Has anyone managed to display images on such a screen. If so can you let me know how this can be achieved.

With your code, that would need a serial buffer that can hold at least 240 x 2 = 480 bytes, way bigger than any arduino uses.
Also, at 9600 baud, which is 960 characters/second, it will take 120 seconds per image for a 240 x 240 display.

1 Like

My code is reading one line at a time

The serial object in your code has an underlaying buffer; it's usually smaller than 240 bytes and you will loose data. You will have to check the core code of your processor how big that buffer is.

So the below might never evaluate to true.

Although Robin's updated Serial Input Basics tutorial is for text based communication you can use a similar approach. Each time data is available, store it in your buffer. In you case you just keep a counter instead of checking for markers.

Further coolterm just spits out the data without considering what is receiving it. A hick-up / delay at the receiver side will result in data loss / corruption.

1 Like

Ok. So is there any way the image can be displayed on the TFT screen. I see videos and pictures of this display having images on it. And yet it seems super difficult to make it happen.
Can you suggest any other way to display a prepared image from pc on this display

If you are sending an actual bitmap file in RGB565 format, there is also a header before the actual pixel data. Probably easiest to strip that off and only send the pixel data, otherwise your code will have to look at that to see where the pixel data begins.

Increase the serial speed considerably, should be able to run at least 115200 baud.

I can load bitmap files from a SD card in standard 16 bit 5R6G5B format, header and all. Easier that way. Here is a link to the code I used.

Can you upload the code in code format. With this display It would not work as it does not has chip select pin , so I would not be able to run SPI sd card reader and this display at the same time. This is why I wanted to feed data from PC

I can change the boud rate when I make it work. But honestly I don't think it is going to work.
The coolterm idea came from the youtube video I found. https://www.youtube.com/watch?v=v0TFI2Sv_gI

There is no header. It is RAW data

Which arduino are you using?

See @sterretje link to Serial Input Basics to see how to buffer the input data without having to expand the actual serial buffer. Other than that, you could read the pixel data one pixel (2 bytes) at a time and write each individual pixel to the display. With the 9600 baud rate I doubt you would notice any difference in the amount of time needed per picture.

I use esp8266
Also There is nothing displayed on the screen . No pixels change color which is weird as I would imagine my code would send some data, maybe corrupted, to the display

Add a Serial.print in the 'if' body as shown below to proof that you indeed get in that 'if'. Or switch a LED on or ... That way you will know.

if (Serial.available() >= PIXEL_BUFFER_SIZE * 2) { // 2 bytes per pixel (16-bit color)
{
  Serial.println("Enough bytes received");

  ...
  ...

so there is something wrong when I use writepixels method. When I displayed it pixel at a time it works (code below).
The image loads for few seconds for boud rate 115200. But this brings me to the question about using this display with camera module. How in the world, if one image loads for few seconds, people achieve displaying footage from this camera on this thing.

#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <SPI.h>

#define TFT_DC    D1     // TFT DC pin is connected to NodeMCU pin D1 (GPIO5)
#define TFT_RST   D2     // TFT RST pin is connected to NodeMCU pin D2 (GPIO4)
#define TFT_CS    D8     // TFT CS pin is connected to NodeMCU pin D8 (GPIO15)

// Initialize ST7789 TFT library with hardware SPI module
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

// Constants for bitmap dimensions
const int IMAGE_WIDTH = 240;
const int IMAGE_HEIGHT = 240;
const int PIXEL_BUFFER_SIZE = IMAGE_WIDTH; // One line of pixels

uint16_t pixelBuffer[PIXEL_BUFFER_SIZE]; // Buffer to hold one line of pixel data

void setup() {
    Serial.begin(115200);
    delay(1000);
    
    tft.init(240, 240, SPI_MODE2);  // Initialize the TFT display
    tft.setRotation(0);             // Set rotation (0, 1, 2, or 3)
    tft.fillScreen(ST77XX_BLACK);   // Clear screen
        while (Serial.available() > 0) {
        // Read incoming byte
        char incomingByte = Serial.read();
        // Do nothing with the incoming data
    }
}

void loop() {
    static int currentX = 0;  // Track the current x position
    static int currentY = 0;  // Track the current y position

    // Check if there are at least 2 bytes available (1 pixel in RGB565 format)
    if (Serial.available() >= 2) {
        // Read the high and low bytes of the pixel color
        uint8_t highByte = Serial.read();
        uint8_t lowByte = Serial.read();
        
        // Combine the high and low bytes to form the 16-bit color value
        uint16_t color = (highByte << 8) | lowByte;
        
        // Draw the pixel on the TFT display
        tft.drawPixel(currentX, currentY, color);
        
        // Move to the next pixel position
        currentX++;
        
        // If we reach the end of the row, move to the next row
        if (currentX >= IMAGE_WIDTH) {
            currentX = 0;
            currentY++;
        }
        
        // If we reach the end of the image, reset to the beginning
        if (currentY >= IMAGE_HEIGHT) {
            delay(100000);
            currentY = 0;
            tft.fillScreen(ST77XX_BLACK);  // Clear screen for the next image
        }
    }
}

What do you mean the TFT display has no CS pin? What is TFT_CS?

#define TFT_CS    D8  
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);