Trying to open gif animation from SD Card #315
Replies: 1 comment 7 replies
-
Finally got it working from original example with very little modifications: `// Example sketch which shows how to display a 64x32 animated GIF image stored in FLASH memory /* INSTRUCTIONS
#define FILESYSTEM SPIFFS // Micro SD Card Module Pinout /* Refer to the example '2_PatternPlasma' on the new / correct way to setup this library */ #define PANEL_RES_X 64 // Number of pixels wide of each INDIVIDUAL panel module. //MatrixPanel_I2S_DMA dma_display; uint16_t myBLACK = dma_display->color565(0, 0, 0); SPIClass *spi = NULL; // Draw a line of image directly on the LED Matrix iWidth = pDraw->iWidth; usPalette = pDraw->pPalette; s = pDraw->pPixels; void * GIFOpenFile(const char *fname, int32_t *pSize) void GIFCloseFile(void *pHandle) int32_t GIFReadFile(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen) int32_t GIFSeekFile(GIFFILE *pFile, int32_t iPosition) unsigned long start_tick = 0; void ShowGIF(char *name) if (gif.open(name, GIFOpenFile, GIFCloseFile, GIFReadFile, GIFSeekFile, GIFDraw)) } /* ShowGIF() */ /************************* Arduino Sketch Setup and Loop() *******************************/ // HUB75_I2S_CFG mxconfig( mxconfig.gpio.e = 18; // Display Setup // Serial.begin(115200); spi = new SPIClass(HSPI); SD.begin(HSPI_CS, *spi); if (!SD.begin(HSPI_CS, *spi)) { if (cardType == CARD_NONE) { Serial.print("SD Card Type: "); if (cardType == CARD_MMC) { uint64_t cardSize = SD.cardSize() / (1024 * 1024); dma_display->begin(); /* all other pixel drawing functions can only be called after .begin() */ } String gifDir = "/gifs"; // play all GIFs in this directory on the SD card void loop()
} // while Thanks anyway. |
Beta Was this translation helpful? Give feedback.
-
Hello, I'm trying to make the gif animation example work from Sd card.
I have inserted the Sd part in the code, which recognizes the size of the memory, but keeps trying to read the gifs from the internal memory I think.
I don't know how to remove the SPIFFS part.
Here´s the code:
`// Example sketch which shows how to display a 64x32 animated GIF image stored in FLASH memory
// on a 64x32 LED matrix
//
// Credits: https://github.com/bitbank2/AnimatedGIF/tree/master/examples/ESP32_LEDMatrix_I2S
//
/* INSTRUCTIONS
First Run the 'ESP32 Sketch Data Upload Tool' in Arduino from the 'Tools' Menu.
https://github.com/me-no-dev/arduino-esp32fs-plugin
the ESP32 itself.
You can drop any animated GIF you want in there, but keep it to the resolution of the
MATRIX you're displaying to. To resize a gif, use this online website: https://ezgif.com/
Have fun.
*/
#define FILESYSTEM SPIFFS
#include <SPIFFS.h>
#include <AnimatedGIF.h>
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
#include "SD.h"
#include "SPI.h"
#include "FS.h"
// Micro SD Card Module Pinout
// VCC = 5V
// GND = GND
#define HSPI_MISO 32
#define HSPI_MOSI 21
#define HSPI_SCLK 33
#define HSPI_CS 22
SPIClass * hspi = NULL;
int count = 0;
// ----------------------------
// constants won't change. They're used here to set pin numbers:
const int buttonPin = 0; // the number of the pushbutton pin
const int ledPin = 2; // the number of the LED pin
// variables will change:
int buttonState = 0; // variable for reading the pushbutton status
/*
Below is an is the 'legacy' way of initialising the MatrixPanel_I2S_DMA class.
i.e. MATRIX_WIDTH and MATRIX_HEIGHT are modified by compile-time directives.
By default the library assumes a single 64x32 pixel panel is connected.
Refer to the example '2_PatternPlasma' on the new / correct way to setup this library
for different resolutions / panel chain lengths within the sketch 'setup()'.
*/
#define PANEL_RES_X 64 // Number of pixels wide of each INDIVIDUAL panel module.
#define PANEL_RES_Y 32 // Number of pixels tall of each INDIVIDUAL panel module.
#define PANEL_CHAIN 1 // Total number of panels chained one to another
//MatrixPanel_I2S_DMA dma_display;
MatrixPanel_I2S_DMA *dma_display = nullptr;
uint16_t myBLACK = dma_display->color565(0, 0, 0);
uint16_t myWHITE = dma_display->color565(255, 255, 255);
uint16_t myRED = dma_display->color565(255, 0, 0);
uint16_t myGREEN = dma_display->color565(0, 255, 0);
uint16_t myBLUE = dma_display->color565(0, 0, 255);
AnimatedGIF gif;
File f;
int x_offset, y_offset;
// Draw a line of image directly on the LED Matrix
void GIFDraw(GIFDRAW *pDraw)
{
uint8_t *s;
uint16_t *d, *usPalette, usTemp[320];
int x, y, iWidth;
iWidth = pDraw->iWidth;
if (iWidth > MATRIX_WIDTH)
iWidth = MATRIX_WIDTH;
usPalette = pDraw->pPalette;
y = pDraw->iY + pDraw->y; // current line
s = pDraw->pPixels;
if (pDraw->ucDisposalMethod == 2) // restore to background color
{
for (x = 0; x < iWidth; x++)
{
if (s[x] == pDraw->ucTransparent)
s[x] = pDraw->ucBackground;
}
pDraw->ucHasTransparency = 0;
}
// Apply the new pixels to the main image
if (pDraw->ucHasTransparency) // if transparency used
{
uint8_t *pEnd, c, ucTransparent = pDraw->ucTransparent;
int x, iCount;
pEnd = s + pDraw->iWidth;
x = 0;
iCount = 0; // count non-transparent pixels
while (x < pDraw->iWidth)
{
c = ucTransparent - 1;
d = usTemp;
while (c != ucTransparent && s < pEnd)
{
c = *s++;
if (c == ucTransparent) // done, stop
{
s--; // back up to treat it like transparent
}
else // opaque
{
*d++ = usPalette[c];
iCount++;
}
} // while looking for opaque pixels
if (iCount) // any opaque pixels?
{
for (int xOffset = 0; xOffset < iCount; xOffset++ ) {
dma_display->drawPixel(x + xOffset, y, usTemp[xOffset]); // 565 Color Format
}
x += iCount;
iCount = 0;
}
// no, look for a run of transparent pixels
c = ucTransparent;
while (c == ucTransparent && s < pEnd)
{
c = *s++;
if (c == ucTransparent)
iCount++;
else
s--;
}
if (iCount)
{
x += iCount; // skip these
iCount = 0;
}
}
}
else // does not have transparency
{
s = pDraw->pPixels;
// Translate the 8-bit pixels through the RGB565 palette (already byte reversed)
for (x = 0; x < pDraw->iWidth; x++)
{
dma_display->drawPixel(x, y, usPalette[s++]); // color 565
}
}
} / GIFDraw() */
void * GIFOpenFile(const char *fname, int32_t *pSize)
{
Serial.print("Playing gif: ");
Serial.println(fname);
f = FILESYSTEM.open(fname);
if (f)
{
*pSize = f.size();
return (void )&f;
}
return NULL;
} / GIFOpenFile() */
void GIFCloseFile(void *pHandle)
{
File *f = static_cast<File >(pHandle);
if (f != NULL)
f->close();
} / GIFCloseFile() */
int32_t GIFReadFile(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen)
{
int32_t iBytesRead;
iBytesRead = iLen;
File *f = static_cast<File >(pFile->fHandle);
// Note: If you read a file all the way to the last byte, seek() stops working
if ((pFile->iSize - pFile->iPos) < iLen)
iBytesRead = pFile->iSize - pFile->iPos - 1; // <-- ugly work-around
if (iBytesRead <= 0)
return 0;
iBytesRead = (int32_t)f->read(pBuf, iBytesRead);
pFile->iPos = f->position();
return iBytesRead;
} / GIFReadFile() */
int32_t GIFSeekFile(GIFFILE *pFile, int32_t iPosition)
{
int i = micros();
File *f = static_cast<File >(pFile->fHandle);
f->seek(iPosition);
pFile->iPos = (int32_t)f->position();
i = micros() - i;
// Serial.printf("Seek time = %d us\n", i);
return pFile->iPos;
} / GIFSeekFile() */
unsigned long start_tick = 0;
void ShowGIF(char *name)
{
start_tick = millis();
if (gif.open(name, GIFOpenFile, GIFCloseFile, GIFReadFile, GIFSeekFile, GIFDraw))
{
x_offset = (MATRIX_WIDTH - gif.getCanvasWidth()) / 2;
if (x_offset < 0) x_offset = 0;
y_offset = (MATRIX_HEIGHT - gif.getCanvasHeight()) / 2;
if (y_offset < 0) y_offset = 0;
Serial.printf("Successfully opened GIF; Canvas size = %d x %d\n", gif.getCanvasWidth(), gif.getCanvasHeight());
Serial.flush();
while (gif.playFrame(true, NULL))
{
if ( (millis() - start_tick) > 8000) { // we'll get bored after about 8 seconds of the same looping gif
break;
}
}
gif.close();
}
} /* ShowGIF() */
/************************* Arduino Sketch Setup and Loop() *******************************/
void setup() {
// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT_PULLUP);
//
HUB75_I2S_CFG mxconfig(
PANEL_RES_X, // module width
PANEL_RES_Y, // module height
PANEL_CHAIN // Chain length
);
mxconfig.gpio.e = 18;
mxconfig.clkphase = false;
mxconfig.driver = HUB75_I2S_CFG::FM6126A;
// Display Setup
dma_display = new MatrixPanel_I2S_DMA(mxconfig);
dma_display->begin();
dma_display->setBrightness8(90); //0-255
dma_display->clearScreen();
dma_display->fillScreen(myWHITE);
//
Serial.begin(115200);
Serial.println("Starting AnimatedGIFs Sketch");
// Start filesystem
Serial.println(" * Loading SPIFFS");
if (!SPIFFS.begin()) {
Serial.println("SPIFFS Mount Failed");
}
// SD Part
Serial.println("Micro SD Card Mounting...");
SPIClass spi = SPIClass(HSPI);
spi.begin(HSPI_SCLK, HSPI_MISO, HSPI_MOSI, HSPI_CS);
SD.begin(HSPI_CS, spi);
delay(50);
if (!SD.begin(HSPI_CS,spi,80000000)) {
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD.cardType();
if (cardType == CARD_NONE) {
Serial.println("No SD card attached");
return;
}
Serial.print("SD Card Type: ");
if (cardType == CARD_MMC) {
Serial.println("MMC");
} else if(cardType == CARD_SD){
Serial.println("SDSC");
} else if(cardType == CARD_SDHC){
Serial.println("SDHC");
} else {
Serial.println("UNKNOWN");
}
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
Serial.printf("SD Card Size: %lluMB\n", cardSize);
// End of SD Part
dma_display->begin();
/* all other pixel drawing functions can only be called after .begin() */
dma_display->fillScreen(dma_display->color565(0, 0, 0));
gif.begin(LITTLE_ENDIAN_PIXELS);
}
String gifDir = "/gifs"; // play all GIFs in this directory on the SD card
char filePath[256] = { 0 };
File root, gifFile;
void loop()
{
count++;
Serial.println(count);
if (count < 2) {
root = FILESYSTEM.open(gifDir);
gifFile = root.openNextFile();
}
buttonState = digitalRead(buttonPin);
// check if the pushbutton is pressed. If it is, the buttonState is HIGH:
if (buttonState == LOW) {
}
if (buttonState == HIGH) {
}
}`
and this is what i can see on serial monitor:
00:13:25.694 -> Starting AnimatedGIFs Sketch 00:13:25.694 -> * Loading SPIFFS 00:13:25.833 -> Micro SD Card Mounting... 00:13:25.879 -> SD Card Type: SDSC 00:13:25.879 -> SD Card Size: 971MB 00:13:25.879 -> 1 00:13:26.065 -> Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled. 00:13:26.065 -> 00:13:26.065 -> Core 1 register dump: 00:13:26.065 -> PC : 0x40086e61 PS : 0x00060830 A0 : 0x800d1ed3 A1 : 0x3ffb27d0 00:13:26.065 -> A2 : 0x3ffc13f8 A3 : 0x00000000 A4 : 0x000000ff A5 : 0x0000ff00 00:13:26.065 -> A6 : 0x00ff0000 A7 : 0xff000000 A8 : 0x00000000 A9 : 0x3ffb27a0 00:13:26.065 -> A10 : 0x3ffc13f8 A11 : 0x00000000 A12 : 0xa7351116 A13 : 0x3ffc7868 00:13:26.065 -> A14 : 0x3ffc7868 A15 : 0x000005db SAR : 0x00000000 EXCCAUSE: 0x0000001c 00:13:26.111 -> EXCVADDR: 0x00000000 LBEG : 0x40086e61 LEND : 0x40086e75 LCOUNT : 0xffffffff 00:13:26.111 -> 00:13:26.111 -> 00:13:26.111 -> Backtrace:0x40086e5e:0x3ffb27d00x400d1ed0:0x3ffb27e0 0x400d7ee1:0x3ffb2820 00:13:26.111 -> 00:13:26.111 -> 00:13:26.111 -> 00:13:26.111 -> 00:13:26.111 -> ELF file SHA256: 0000000000000000 00:13:26.111 -> 00:13:26.111 -> Rebooting...
This is a loop where matrix keep flashing white.
Any help will be apreciated .
Beta Was this translation helpful? Give feedback.
All reactions