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.
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.
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.
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
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
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
}
}
}