#include <Arduino.h>
#include <U8g2lib.h> // u8g2 library used for drawing on the OLED display
#include <Wire.h> // library requires for IIC communication
// I´m using two different displays, 128x64px in the WOKWI emulation and 72x40px for real Arduino
// Please uncomment the correct initialization line and comment out the other one
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); // initialization for the 128x64px display
//U8G2_SSD1306_72X40_ER_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);// 72x40px display [full framebuffer, size = 360 bytes]
// images below are generated using the image2cpp website
// 'battery_indicator', 70x40px
const unsigned char epd_bitmap_battery_indicator [] PROGMEM = {
0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf3, 0xff, 0xff, 0xff, 0x7f,
0x00, 0x00, 0x00, 0x06, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x06, 0xfb, 0xff, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x06, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x06, 0xfb,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x06, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
0x06, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x06, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x00,
0x00, 0x00, 0x06, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x06, 0xfb, 0xff, 0xff, 0xff,
0xff, 0x00, 0x00, 0x00, 0x1e, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x3e, 0xfb, 0xff,
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x3e, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x3e,
0xfb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x3e, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
0x00, 0x3e, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x3e, 0xfb, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x3e, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x3e, 0xfb, 0xff, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x3e, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x3e, 0xfb,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x3e, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
0x3e, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x3e, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x00,
0x00, 0x00, 0x3e, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x1e, 0xfb, 0xff, 0xff, 0xff,
0xff, 0x00, 0x00, 0x00, 0x06, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x06, 0xfb, 0xff,
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x06, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x06,
0xfb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x06, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
0x00, 0x06, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x06, 0xfb, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x06, 0xf3, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x06, 0x07, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01
};
// 'battery_outline', 70x40px
const unsigned char epd_bitmap_battery_outline [] PROGMEM = {
0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e,
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x07, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01
};
// 'blob_02', 32x34px
const unsigned char epd_bitmap_blob_02 [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0xe0, 0x00,
0x01, 0x00, 0xe0, 0x00, 0x01, 0x00, 0xe0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x07, 0xe0, 0x00, 0x00, 0x07, 0xf0, 0x01, 0x00, 0x0f, 0xf0, 0x03, 0x00, 0x1f, 0xf0, 0x01, 0x00,
0x3f, 0xf0, 0x03, 0x00, 0x7f, 0x40, 0x01, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
0xff, 0x00, 0x60, 0x00, 0xff, 0x00, 0xe0, 0x00, 0x7f, 0x00, 0x40, 0x00, 0x7f, 0x00, 0x00, 0x00,
0x7f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
};
// 'blob_03', 32x34px
const unsigned char epd_bitmap_blob_03 [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x20, 0x00,
0x01, 0x00, 0x70, 0x00, 0x01, 0x00, 0x70, 0x00, 0x01, 0x00, 0x70, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x07, 0xf0, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x1f, 0xfc, 0x01, 0x00, 0x3f, 0xfc, 0x01, 0x00,
0x7f, 0xfc, 0x01, 0x00, 0x7f, 0xf0, 0x01, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x0c, 0x00,
0x7f, 0x00, 0x3c, 0x00, 0x7f, 0x00, 0x78, 0x00, 0x7f, 0x00, 0x30, 0x00, 0x3f, 0x00, 0x00, 0x00,
0x3f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00
};
// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 4800)
const int epd_bitmap_allArray_LEN = 2;
const unsigned char* epd_bitmap_allArray[2] = {
epd_bitmap_blob_02,
epd_bitmap_blob_03,
};
int battery_fill_perc = 0; // battery fill percentage 0-100%
int anim_frame = 0; // animation frame for the blob / metaballs animation
int xoff = 29;//0;//29; // x offset for the battery
int yoff = 12;//0;//24; // y offset for the battery
void setup(void) {
u8g2.begin(); // start the u8g2 library
}
void loop(void) {
u8g2.clearBuffer(); // clear the internal memory
u8g2.setBitmapMode(1); // draw transparent images
u8g2.drawXBMP(xoff, yoff, 70, 40, epd_bitmap_battery_outline); // draw the image of the outline of the battery icon
int fill_width = map(battery_fill_perc, 0, 100, 4, 61); // width of the fill rectangle
u8g2.drawRBox(xoff+3, yoff+3, fill_width, 34, 1); // battery fill, rounded filled rectangle
u8g2.setClipWindow(xoff+3, yoff+3, xoff + 3 + 61, yoff+3 + 34); // restrict all graphics output to the specified range
u8g2.drawXBMP(xoff + 3 + fill_width - 1, yoff+3, 32, 34, epd_bitmap_allArray[anim_frame]); // draw blob animation
u8g2.setMaxClipWindow(); // restore writing to the complete window
//u8g2.drawFrame(29, 24, 70, 40); // draw fullscreen rectangle - this was only used for testing
u8g2.sendBuffer(); // transfer internal memory to the display
// increase battery fill percentage 0-100
battery_fill_perc++;
if (battery_fill_perc > 100) {battery_fill_perc = 0;}
// current frame for the blob animation, 0-29
anim_frame = (anim_frame + 1) % 4;
}