Skip to content

Instantly share code, notes, and snippets.

@TheHans255
Last active February 18, 2024 21:32
Show Gist options
  • Save TheHans255/c00a4e905f384d742cc12a8c3b12e584 to your computer and use it in GitHub Desktop.
Save TheHans255/c00a4e905f384d742cc12a8c3b12e584 to your computer and use it in GitHub Desktop.
Arduino sketch code for Inkplate 6COLOR digital photo frame
/*
* 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