Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cant read from SD #78

Open
yiungyiung opened this issue May 6, 2024 · 3 comments
Open

Cant read from SD #78

yiungyiung opened this issue May 6, 2024 · 3 comments

Comments

@yiungyiung
Copy link

I have an st7789 240 * 240 screen

my connections are

#define TFT_MISO -1
#define TFT_MOSI 23
#define TFT_SCLK 18
#define TFT_CS 14 // Chip select control pin
#define TFT_DC 21 // Data Command control pin
#define TFT_RST 4 // Reset pin (could connect to RST pin)
in usersetup

I have a micro sd card adapter
with connections
as
miso 19
mosi 23
cs 5
clk 18

I am not able to read from sd card as its saying file not found,

if I use the esp32 example in tft_espi, my display doesn't work and if I try to use the example in tjpegdecoder I cant get the sdcard to work

// Example for library:
// https://github.com/Bodmer/TJpg_Decoder

// This example if for an ESP8266 or ESP32, it renders a Jpeg file
// that is stored in a SD card file. The test image is in the sketch
// "data" folder (press Ctrl+K to see it). You must save the image
// to the SD card using you PC.

// Include the jpeg decoder library
#include <TJpg_Decoder.h>

// Include SD
#define FS_NO_GLOBALS
#include <FS.h>
#ifdef ESP32
#include "SPIFFS.h" // ESP32 only
#endif

#define SD_CS 5

// Include the TFT library https://github.com/Bodmer/TFT_eSPI
#include "SPI.h"
#include <TFT_eSPI.h> // Hardware-specific library
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library

// This next function will be called during decoding of the jpeg file to
// render each block to the TFT. If you use a different TFT library
// you will need to adapt this function to suit.
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
{
// Stop further decoding as image is running off bottom of screen
if ( y >= tft.height() ) return 0;

// This function will clip the image block rendering automatically at the TFT boundaries
tft.pushImage(x, y, w, h, bitmap);

// This might work instead if you adapt the sketch to use the Adafruit_GFX library
// tft.drawRGBBitmap(x, y, bitmap, w, h);

// Return 1 to decode next block
return 1;
}

void setup()
{
Serial.begin(115200);
Serial.println("\n\n Testing TJpg_Decoder library");

// Initialise SD before TFT
if (!SD.begin(SD_CS)) {
Serial.println(F("SD.begin failed!"));
while (1) delay(0);
}
Serial.println("\r\nInitialisation done.");

// Initialise the TFT
tft.begin();
tft.setTextColor(0xFFFF, 0x0000);
tft.fillScreen(TFT_BLACK);
tft.setSwapBytes(true); // We need to swap the colour bytes (endianess)

// The jpeg image can be scaled by a factor of 1, 2, 4, or 8
TJpgDec.setJpgScale(1);

// The decoder must be given the exact name of the rendering function above
TJpgDec.setCallback(tft_output);
}

void loop()
{
tft.fillScreen(TFT_RED);

// Time recorded for test purposes
uint32_t t = millis();

// Get the width and height in pixels of the jpeg if you wish
uint16_t w = 0, h = 0;
TJpgDec.getSdJpgSize(&w, &h, "/Baboon40.jpg");
Serial.print("Width = "); Serial.print(w); Serial.print(", height = "); Serial.println(h);

// Draw the image, top left at 0,0
TJpgDec.drawSdJpg(0, 0, "/Baboon40.jpg");

// How much time did rendering take
t = millis() - t;
Serial.print(t); Serial.println(" ms");

// Wait before drawing again
delay(2000);
}

@cmcooper1971
Copy link

H i Yiungyiung,

Did you manage to solve this issue as I cannot seem to solve it either?

I'm using an ESP32, ILI9341, which I can control with fill back grounds, draw lines etc. I can read text files and display them from the SD card using Serial.print, but no matter what I try for JPEGs, it says "Jpeg file not found"

I reverted back to the Arduino 1.8 IDE, removed all the libraries and reinstalled. This has made no difference.

Current library list is:

#include <Arduino.h>
#include <SPI.h>
#include <Wire.h>

#include <TJpg_Decoder.h>

#include <SD.h>
#include <FS.h>

#include <Adafruit_ILI9341.h>
#include <Adafruit_ST7735.h>
#include <Adafruit_GFX.h>

#include <Adafruit_MCP23X08.h>

Test calls:

uint16_t wdth = 0, hth = 0;
TJpgDec.getSdJpgSize(&wdth, &hth, "/bobble240.jpg");

Serial.print("Width = "); Serial.print(wdth); Serial.print(", height = "); Serial.println(hth);
Serial.println("");

TJpgDec.getJpgSize(&wdth, &hth, "/bobble240.jpg");

Serial.print("Width = "); Serial.print(wdth); Serial.print(", height = "); Serial.println(hth);
Serial.println("");

TJpgDec.getFsJpgSize(&wdth, &hth, "/bobble240.jpg");

Serial.print("Width = "); Serial.print(wdth); Serial.print(", height = "); Serial.println(hth);
Serial.println("");

Thanks

@yiungyiung
Copy link
Author

yiungyiung commented Jun 20, 2024

Actually yes and no, Its not a library issue btw lol

So the idk much abt electronics and stuff but I found out that either they work individually or don't work at all
so the cycle of read and display doesn't work, probably cos of MOSI and SCL of both being at the same pins and at the same address.

what worked for me for reading all the Images in an array before the intialisation of TFT and then displaying it.

I didn't try changing the address for one of em but if you are successful please do tell me.

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

#define TFT_CS 14
#define TFT_RST 4
#define TFT_DC 21
#define TFT_MOSI 23
#define TFT_SCLK 18
// this function determines the minimum of two numbers
#define minimum(a,b) (((a) < (b)) ? (a) : (b))

Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

#define MAX_FILES 5 // Maximum number of files to handle
const uint16_t COLORS[] = {ST77XX_RED, ST77XX_GREEN, ST77XX_BLUE, ST77XX_YELLOW, ST77XX_CYAN, ST77XX_MAGENTA};
const int NUM_COLORS = sizeof(COLORS) / sizeof(uint16_t);

File jpegFiles[MAX_FILES]; // Array to hold File objects for JPEG files
int fileCount = 0; // Variable to keep track of the number of JPEG files found
int discount=0;
void setup() {
Serial.begin(9600);

Serial.print("Initializing SD card...");
if (!SD.begin(5)) {
Serial.println("failed!");
while (1); // stay here
}
Serial.println("OK!");

File root = SD.open("/"); // open SD card main root
// Open 5 random files
for (int i = 0; i < MAX_FILES; i++) {
String fileName = "/" + String(random(1, 29)) + ".jpg"; // Construct file name
File entry = SD.open(fileName);
if (entry) {
jpegFiles[fileCount] = entry;
fileCount++;
}
}

root.close(); // close the opened root

// initialize ST7735S TFT display
tft.init(240, 240, SPI_MODE3);
tft.setRotation(0);
tft.fillScreen(ST77XX_BLACK);

tft.close();
birthdayLights();
animateText("Happy Birthday Satviki!", tft.width() / 2, tft.height() / 2 - 15, COLORS, NUM_COLORS, 500);
delay(1000);

for(int i= 0;i<=fileCount;i++)
{
File imageFile = jpegFiles[i];
imageFile.seek(0);
JpegDec.decodeSdFile(imageFile);
jpegInfo();
renderJPEG(0, 0);
imageFile.close();
JpegDec.abort();
delay(1000);
}
}

void loop() {
delay(1000);
}
void jpegInfo() {
Serial.println(F("==============="));
Serial.println(F("JPEG image info"));
Serial.println(F("==============="));
Serial.print(F( "Width :")); Serial.println(JpegDec.width);
Serial.print(F( "Height :")); Serial.println(JpegDec.height);
Serial.print(F( "Components :")); Serial.println(JpegDec.comps);
Serial.print(F( "MCU / row :")); Serial.println(JpegDec.MCUSPerRow);
Serial.print(F( "MCU / col :")); Serial.println(JpegDec.MCUSPerCol);
Serial.print(F( "Scan type :")); Serial.println(JpegDec.scanType);
Serial.print(F( "MCU width :")); Serial.println(JpegDec.MCUWidth);
Serial.print(F( "MCU height :")); Serial.println(JpegDec.MCUHeight);
Serial.println(F("==============="));
}

void renderJPEG(int xpos, int ypos) {
// retrieve information about the image
uint16_t *pImg;
uint16_t mcu_w = JpegDec.MCUWidth;
uint16_t mcu_h = JpegDec.MCUHeight;
uint32_t max_x = JpegDec.width;
uint32_t max_y = JpegDec.height;

// Jpeg images are drawn as a set of image blocks (tiles) called Minimum Coding Units (MCUs)
// Typically these MCUs are 16x16 pixel blocks
// Determine the width and height of the right and bottom edge image blocks
uint32_t min_w = minimum(mcu_w, max_x % mcu_w);
uint32_t min_h = minimum(mcu_h, max_y % mcu_h);

// record the current time so we can measure how long it takes to draw an image
uint32_t drawTime = millis();

// save the coordinate of the right and bottom edges to assist image cropping
// to the screen size
max_x += xpos;
max_y += ypos;

// read each MCU block until there are no more
while (JpegDec.read()) {
// save a pointer to the image block
pImg = JpegDec.pImage;

// calculate where the image block should be drawn on the screen
int mcu_x = JpegDec.MCUx * mcu_w + xpos;
int mcu_y = JpegDec.MCUy * mcu_h + ypos;

// calculate how many pixels must be drawn
uint32_t mcu_pixels = mcu_w * mcu_h;

// draw image block if it will fit on the screen
if ((mcu_x + mcu_w <= tft.width()) && (mcu_y + mcu_h <= tft.height())) {
  for (uint32_t y = 0; y < mcu_h; y++) {
    for (uint32_t x = 0; x < mcu_w; x++) {
      tft.writePixel(mcu_x + x, mcu_y + y, *pImg++);
    }
  }
}
// skip drawing blocks that are outside the screen area
else {
  while (mcu_pixels--) pImg++;
}

}

// calculate how long it took to draw the image
drawTime = millis() - drawTime; // Calculate the time it took

// print the results to the serial port
Serial.print("Total render time was : ");
Serial.print(drawTime);
Serial.println(" ms");
Serial.println("=====================================");
}
void printDirectory(File dir, int numTabs) {
while (true) {
File entry = dir.openNextFile();
if (!entry) {
// no more files
break;
}
for (uint8_t i = 0; i < numTabs; i++) {
Serial.print('\t');
}
Serial.print(entry.name());
if (entry.isDirectory()) {
Serial.println("/");
printDirectory(entry, numTabs + 1);
} else {
// files have sizes, directories do not
Serial.print("\t\t");
Serial.println(entry.size(), DEC);
}
entry.close();
}
}

void birthdayLights() {
for (int i = 0; i < 40; i++) {
uint16_t color = random(0, NUM_COLORS);
int x = random(0, tft.width());
int y = random(0, tft.height());
tft.fillCircle(x, y, 3, COLORS[color]); // Increase circle radius to 10
delay(50);
}
delay(1000);
}

void animateText(const String& text, int16_t x, int16_t y, const uint16_t* colors, int numColors, uint16_t delay_ms) {
int colorIndex = 0;
int textWidth = text.length() * 18; // Width of the text
int lineHeight = 26; // Height of each line of text

// Center the text vertically
int centerY = (tft.height() - lineHeight * 2) / 2;

// Draw the first line of text ("Happy Birthday") with each alphabet in a different color
tft.setTextSize(2.8); // Set text size for "Happy Birthday"
tft.setTextColor(colors[colorIndex]);
tft.setCursor(x-75, centerY);
for (int i = 0; i < 15; i++) {
tft.setTextColor(colors[colorIndex % numColors]); // Set color for each alphabet
tft.print(text[i]);
delay(delay_ms);
colorIndex++;
}

// Draw the second line of text ("Satviki") with each alphabet in a different color
tft.setTextSize(3); // Set text size for "Satviki"
tft.setTextColor(colors[colorIndex % numColors]); // Reset color index
tft.setCursor(x - 50, centerY + lineHeight);
for (int i = 15; i < text.length(); i++) {
tft.setTextColor(colors[colorIndex % numColors]); // Set color for each alphabet
tft.print(text[i]);
delay(delay_ms);
colorIndex++;
}
}
I have attached the code that worked for me so u can try out

@ljbeng
Copy link

ljbeng commented Jul 8, 2024

I simply reversed the order so the tft.begin() is first then SD card initialization and that worked! I am using the Pi Pico.
`void setup()
{
Serial.begin(115200);
Serial.println("\n\n Testing TJpg_Decoder library");
// Initialise the TFT
tft.begin();
// Initialise SD before TFT
if (!SD.begin(SS)) {
Serial.println(F("SD.begin failed!"));
while (1) delay(0);
}
Serial.println("\r\nInitialisation done.");
tft.setTextColor(0xFFFF, 0x0000);
tft.fillScreen(TFT_BLACK);
tft.setSwapBytes(true); // We need to swap the colour bytes (endianess)

// The jpeg image can be scaled by a factor of 1, 2, 4, or 8
TJpgDec.setJpgScale(1);

// The decoder must be given the exact name of the rendering function above
TJpgDec.setCallback(tft_output);
}`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants