Last active
February 18, 2024 21:32
-
-
Save TheHans255/c00a4e905f384d742cc12a8c3b12e584 to your computer and use it in GitHub Desktop.
Arduino sketch code for Inkplate 6COLOR digital photo frame
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* This project is adapted from the Inkplate6COLOR_Image_Frame_From_SD example for Soldered Inkplate 6COLOR. | |
* (available at https://github.com/SolderedElectronics/Inkplate-Arduino-library/blob/master/examples/Inkplate6COLOR/Projects/Inkplate6COLOR_Image_Frame_From_SD/Inkplate6COLOR_Image_Frame_From_SD.ino). | |
* | |
* It is modified to display the images in a random order as opposed to a sequential order. | |
*/ | |
// Next 3 lines are a precaution, you can ignore those, and the example would also work without them | |
#ifndef ARDUINO_INKPLATECOLOR | |
#error "Wrong board selection for this example, please select Soldered Inkplate 6COLOR in the boards menu." | |
#endif | |
/******************CHANGE HERE***********************/ | |
// Set the time between changing 2 images in seconds | |
// Note: It will take a couple of seconds more (or longer if there is a file that must be skipped because it can't be | |
// drawn) than the specified time because Inkplate needs time for loading and display the image | |
#define SECS_BETWEEN_PICTURES 300 | |
// Path to the folder with pictures (e.g. there is a folder called images on the SD card) | |
const char rootPath[] = "/images/"; // NOTE: Must end with / | |
/****************************************************/ | |
#include "Inkplate.h" // Include Inkplate library to the sketch | |
#include "include/Image.h" | |
Inkplate display; // Create an object on Inkplate library | |
const uint8_t low_battery_icon[] PROGMEM = { | |
0x80,0x0,0x70, | |
0x7f,0xff,0xb0, | |
0x5f,0xff,0xb0, | |
0x5f,0xff,0x80, | |
0x4f,0xff,0xa0, | |
0x4f,0xff,0xa0, | |
0x47,0xff,0xa0, | |
0x47,0xff,0xa0, | |
0x43,0xff,0x80, | |
0x43,0xff,0xb0, | |
0x7f,0xff,0xb0, | |
0x80,0x0,0x70, | |
}; | |
int low_battery_icon_w = 20; | |
int low_battery_icon_h = 12; | |
void setup() | |
{ | |
display.begin(); // Init Inkplate library (you should call this function ONLY ONCE) | |
display.clearDisplay(); // Clear frame buffer of display | |
display.setCursor(0, 0); // Set the cursor on the beginning of the screen | |
display.setTextColor(BLACK); // Set text color to black | |
display.rtcGetRtcData(); | |
{ | |
int randSeed = display.rtcGetEpoch(); | |
srand(randSeed); | |
} | |
if (!display.sdCardInit()) { | |
display.println("SD Card Error!"); | |
display.display(); | |
deepSleep(); | |
} | |
SdFile rootFolder; | |
if (!rootFolder.open(rootPath)) { | |
display.println("Failed to open images folder!"); | |
display.println("Please verify that a folder called images"); | |
display.println("exists on the inserted SD card."); | |
display.display(); | |
deepSleep(); | |
return; | |
} | |
if (!exploreFolder(&rootFolder)) { | |
display.println("No available files to display."); | |
} | |
if (display.readBattery() < 3.4) { | |
display.fillRect(600 - (low_battery_icon_w + 4), 0, low_battery_icon_w + 4, low_battery_icon_h + 4, INKPLATE_WHITE); | |
display.drawBitmap(598 - low_battery_icon_w, 2, low_battery_icon, low_battery_icon_w, low_battery_icon_h, INKPLATE_RED); | |
} | |
display.display(); | |
esp_sleep_enable_timer_wakeup(SECS_BETWEEN_PICTURES * 1000000LL); | |
deepSleep(); | |
} | |
bool exploreFolder(SdFile *folder) { | |
for (int attemptCount = 0; attemptCount < 3; attemptCount++) { | |
bool result = exploreFolderInner(folder); | |
if (result) return result; | |
} | |
return 0; | |
} | |
bool exploreFolderInner(SdFile *folder) { | |
display.print("Exploring folder "); | |
printlnFilename(folder); | |
int fileCount = 0; | |
{ | |
SdFile file; | |
folder->rewind(); | |
while (file.openNext(folder, O_READ)) { | |
fileCount++; | |
file.close(); | |
} | |
} | |
if (fileCount <= 0) { | |
display.println("Folder contains no files"); | |
return 0; | |
} | |
int fileIndex = abs(rand() % fileCount); | |
display.print("Selecting index "); | |
printNum(fileIndex); | |
display.print(" /"); | |
printNum(fileCount); | |
display.println(); | |
{ | |
SdFile file; | |
folder->rewind(); | |
for (int currentIndex = 0; currentIndex <= fileIndex; currentIndex++) { | |
if (!file.openNext(folder, O_READ)) { | |
display.println("Error while seeking folder"); | |
return 0; | |
} | |
if (currentIndex < fileIndex) { | |
file.close(); | |
} | |
} | |
display.print("Selecting file "); | |
printlnFilename(&file); | |
if (file.isHidden()) { | |
display.println("File is hidden, skipping"); | |
file.close(); | |
return 0; | |
} else if (file.isDir()) { | |
return exploreFolder(&file); | |
} else { | |
return displayImage(&file); | |
} | |
} | |
} | |
bool displayImage(SdFile *file) { | |
int16_t byte1 = file->read(); | |
int16_t byte2 = file->read(); | |
file->rewind(); | |
bool result; | |
if (byte1 == 0x42 && byte2 == 0x4d) { | |
// it's a bitmap | |
result = display.drawBitmapFromSd(file, 0, 0, 1, 0); | |
} else if (byte1 == 0xff && byte2 == 0xd8) { | |
// it's a JPEG | |
result = display.drawJpegFromSd(file, 0, 0, 1, 0); | |
} else if (byte1 == 0x89 && byte2 == 0x50) { | |
// it's a PNG | |
result = display.drawPngFromSd(file, 0, 0, 1, 0); | |
} | |
if (!result) { | |
display.print("Cannot display "); | |
printlnFilename(file); | |
return 0; | |
} | |
return 1; | |
} | |
void printNum(int value) { | |
char itoaBuffer[13]; | |
itoa(value, itoaBuffer, 10); | |
display.print(itoaBuffer); | |
} | |
void printlnFilename(SdFile *file) { | |
int maxFileNameLen = 128; | |
char nameBuffer[maxFileNameLen]; | |
file->getName(nameBuffer, maxFileNameLen); | |
display.println(nameBuffer); | |
} | |
/** | |
* @brief Turn off all peripherals, go to deep sleep, and enable wakeup on the wake button. | |
*/ | |
void deepSleep() | |
{ | |
// Turn off the power supply for the SD card | |
display.sdCardSleep(); | |
// Enable wakeup from deep sleep on GPIO 36 (wake button) | |
esp_sleep_enable_ext0_wakeup(GPIO_NUM_36, LOW); | |
// Put ESP32 into deep sleep (low power mode) | |
esp_deep_sleep_start(); | |
} | |
void loop() { | |
// Should never be reached | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment