Google Chat:---
+86-0755-88291180
sales@spotpear.com
dragon_manager@163.com
tech-support@spotpear.com
zhoujie@spotpear.com
WhatsApp:13246739196

This product is a high-performance, highly integrated microcontroller development board designed by Waveshare. It features the ESP32-S3 microcontroller, supporting dual-mode Wi-Fi and BLE communication. The board comes with a 3.97inch e-Paper display, which offers extremely low power consumption, is viewable under ambient light, and is suitable for portable devices and long-endurance scenarios. It integrates an RTC real-time clock, an SHTC3 temperature and humidity sensor, a TF card slot, a low-power audio codec chip, and a power management chip. It provides a flexible and reliable development platform for applications such as IoT endpoints, electronic shelf labels, and portable displays.


The ESP32-S3-ePaper-3.97 supports two development frameworks: Arduino IDE and ESP-IDF, offering flexibility for developers. You can choose the appropriate development tool based on project requirements and personal preference.
Each method has its advantages, and developers can select based on their needs and skill level. Arduino is simple to learn and easy to get started with, suitable for beginners and non-professionals; ESP-IDF provides more advanced development tools and stronger control capabilities, suitable for developers with professional backgrounds or those with higher performance requirements, and is more suitable for complex project development.
Arduino IDE is a convenient, flexible, and easy-to-use open-source electronics prototyping platform. It requires minimal foundational knowledge, allowing for rapid development after a short learning period. Arduino has a vast global community that provides a wealth of open-source code, project examples, tutorials, and rich libraries that encapsulate complex functionalities, enabling developers to implement various features quickly. You can refer to the Working with Arduino to complete the initial setup, and the tutorial also provides related demos for reference.
ESP-IDF (Espressif IoT Development Framework) is a professional development framework released by Espressif for its ESP series chips. It is developed based on the C language, including a compiler, debugger, and flashing tool, etc. It supports development via command line or an Integrated Development Environment (such as Visual Studio Code with the Espressif IDF plugin), which provides features like code navigation, project management, and debugging, etc. We recommend using VS Code for development. For the specific configuration process, please refer to the Working with ESP-IDF. The tutorial also provides relevant demos for reference.
Please refer to the tutorial Installing and Configuring Arduino IDE Tutorial to download and install the Arduino IDE and add ESP32 support.
Arduino\libraries directory within the package already includes all the library files required for this tutorial.| Library/File Name | Description | Version | Installation Method |
|---|---|---|---|
| SensorLib | Sensor library | v0.3.1 | "Install Online" or "Install Offline" |

The Arduino demos are located in the Arduino/examples directory of the demo package.
| Demo | Basic Program Description | Dependency Library |
|---|---|---|
| 01_Audio_Test | Drives ES8311 to play audio | - |
| 02_E-Paper_Example | 3.97inch e-Paper display demo | - |
| 03_I2C_PCF85063 | RTC demo | - |
| 04_I2C_SHTC3 | Temperature and humidity sensor demo | SensorLib |
| 05_SD_Test | TF card demo | - |
| 06_QMI8658A | 6-axis gyroscope demo | SensorLib |
Demo Description
Hardware Connection
Code Analysis
Configure and initialize the ES8311 audio codec.
void setup() {
Serial.begin(115200);
Wire.begin(I2C_SDA, I2C_SCL);
pinMode(PA_CTRL, OUTPUT);
digitalWrite(PA_CTRL, HIGH);
es8311_codec_init();
setupI2S();
Serial.println("I2S Initialized");
}
Continuously write built-in audio data to the I2S bus for looped playback.
i2s.write((uint8_t *)audio_data, AUDIO_SAMPLES * 2);
Operation Result
Demo Description
Hardware Connection
Code Analysis
Display a predefined image.
#if 1 // show bmp
EPD_3IN97_Init_Fast();
printf("show image for array\r\n");
EPD_3IN97_Display(gImage_image);
DEV_Delay_ms(1500);
#endif
Draw basic shapes, Chinese/English text, numbers, and refresh the display.
#if 1 // Drawing on the image
//1.Select Image
EPD_3IN97_Init();
printf("SelectImage:BlackImage\r\n");
Paint_SelectImage(BlackImage);
Paint_Clear(WHITE);
// 2.Drawing on the image
Debug("Drawing:BlackImage\r\n");
Paint_DrawPoint(10, 80, BLACK, DOT_PIXEL_1X1, DOT_STYLE_DFT);
Paint_DrawPoint(10, 90, BLACK, DOT_PIXEL_2X2, DOT_STYLE_DFT);
Paint_DrawPoint(10, 100, BLACK, DOT_PIXEL_3X3, DOT_STYLE_DFT);
Paint_DrawLine(20, 70, 70, 120, BLACK, DOT_PIXEL_1X1, LINE_STYLE_SOLID);
Paint_DrawLine(70, 70, 20, 120, BLACK, DOT_PIXEL_1X1, LINE_STYLE_SOLID);
Paint_DrawRectangle(20, 70, 70, 120, BLACK, DOT_PIXEL_1X1, DRAW_FILL_EMPTY);
Paint_DrawRectangle(80, 70, 130, 120, BLACK, DOT_PIXEL_1X1, DRAW_FILL_FULL);
Paint_DrawCircle(45, 95, 20, BLACK, DOT_PIXEL_1X1, DRAW_FILL_EMPTY);
Paint_DrawCircle(105, 95, 20, WHITE, DOT_PIXEL_1X1, DRAW_FILL_FULL);
Paint_DrawLine(85, 95, 125, 95, BLACK, DOT_PIXEL_1X1, LINE_STYLE_DOTTED);
Paint_DrawLine(105, 75, 105, 115, BLACK, DOT_PIXEL_1X1, LINE_STYLE_DOTTED);
Paint_DrawString_EN(10, 0, "waveshare", &Font16, BLACK, WHITE);
Paint_DrawString_EN(10, 20, "hello world", &Font12, WHITE, BLACK);
Paint_DrawNum(10, 33, 123456789, &Font12, BLACK, WHITE);
Paint_DrawNum(10, 50, 987654321, &Font16, WHITE, BLACK);
Paint_DrawString_CN(130, 0, " 你好 abc", &Font12CN, BLACK, WHITE);
Paint_DrawString_CN(130, 20, "微雪电子", &Font24CN, WHITE, BLACK);
printf("EPD_Display\r\n");
EPD_3IN97_Display_Base(BlackImage);
DEV_Delay_ms(3000);
#endif
Operation Result
The screen refreshes and displays the content.

Demo Description
Hardware Connection
Code Analysis
Continuously reads the RTC time, formats it into a string, and performs a partial refresh on the e-paper to display it.
void i2c_rtc_loop_task(void *arg)
{
char buff[80];
for(;;)
{
RtcDateTime_t datetime = rtc_dev->get_rtcTime();
printf("%d/%d/%d %d:%d:%d \n",datetime.year,datetime.month,datetime.day,datetime.hour,datetime.minute,datetime.second);
Paint_NewImage(BlackImage, Font20.Height *3, Font20.Width * 8, 270, WHITE);
Paint_SelectImage(BlackImage);
Paint_Clear(WHITE);
sprintf(buff, "%d-%d-%d", datetime.year,datetime.month,datetime.day);
Paint_DrawString_EN(0, 5, buff, &Font20, WHITE, BLACK);
sprintf(buff, "%d:%d:%d", datetime.hour,datetime.minute,datetime.second);
Paint_DrawString_EN(0, 35, buff, &Font20, WHITE, BLACK);
EPD_3IN97_Display_Partial(BlackImage, 50, 250, 50 + Font20.Height*3 , 250 + Font20.Width * 8);
vTaskDelay(pdMS_TO_TICKS(500));
}
}
Operation Result
The e-Paper display partially refreshes to show the time.

Demo Description
Hardware Connection
Code Analysis
Continuously reads sensor data and partially refreshes the e-Paper to display temperature and humidity.
void i2c_SHTC3_loop_task(void *arg)
{
char buff[80];
for(;;)
{
shtc3_data_t shtc3_data = shtc3_dev->readTempHumi();
printf("RH:%.2f%%,Temp:%.2f°C \n",shtc3_data.RH,shtc3_data.Temp);
Paint_NewImage(BlackImage, Font20.Height *3, Font20.Width * 8, 270, WHITE);
Paint_SelectImage(BlackImage);
Paint_Clear(WHITE);
sprintf(buff, "%.2f%%",shtc3_data.RH);
Paint_DrawString_EN(0, 5, buff, &Font20, WHITE, BLACK);
sprintf(buff, "%.2f", shtc3_data.Temp);
Paint_DrawString_EN(0, 35, buff, &Font20, WHITE, BLACK);
Paint_DrawString_CN(Font20.Width * 5, 30, "℃", &Font12CN, WHITE, BLACK);
EPD_3IN97_Display_Partial(BlackImage, 50, 250, 50 + Font20.Height*3 , 250 + Font20.Width * 8);
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
Operation Result
The e-Paper display partially refreshes to show the temperature and humidity.

Demo Description
Hardware Connection
Code Analysis
Configure and mount the TF card.
//sdcard init
Serial.begin(115200);
delay(1000);
SD_MMC.setPins(SD_CLK, SD_CMD, SD_D0, SD_D1, SD_D2, SD_D3);
if (!SD_MMC.begin( "/sdcard", true)) {
printf("TF card failed to mount\r\n");
return;
}
printf("TF card success to mount\r\n");
Display images.
printf("show BMP-------------------------\r\n");
EPD_3IN97_Init_Fast();
Paint_Clear(WHITE);
GUI_ReadBmp("/sdcard/bmp/100x100.bmp", 50, 50);
EPD_3IN97_Display_Fast(Image);
printf("100*100 BMP Load OK!\r\n");
DEV_Delay_ms(1000);
Paint_Clear(WHITE);
GUI_ReadBmp("/sdcard/bmp/3in97.bmp", 50, 0);
EPD_3IN97_Display_Fast(Image);
printf("800*480 BMP Load OK!\r\n");
DEV_Delay_ms(3000);
Display 4-grayscale BMP image.
EPD_3IN97_Init_4GRAY();
Paint_NewImage(Image, EPD_3IN97_WIDTH, EPD_3IN97_HEIGHT, 0, WHITE);
Paint_SetScale(4);
Paint_Clear(WHITE);
if(GUI_ReadBmp_4Gray("/sdcard/bmp/3in97_4Gray.bmp", 0, 0) == 0){
printf("4Gray BMP Load OK!\r\n");
}else{
printf("4Gray BMP Load Failed!\r\n");
}
EPD_3IN97_Display_4Gray(Image);
DEV_Delay_ms(3000);
Operation Result
Reads and displays images from the TF card.



Demo Description
Hardware Connection
Code Analysis
Check if the data is ready, read and print the sensor data, and call the display function to update the display data on the e-Paper screen.
if (qmi.getDataReady()) {
if (qmi.getAccelerometer(acc.x, acc.y, acc.z)) {
Serial.print("ACCEL.x:"); Serial.print(acc.x); Serial.print(",");
Serial.print("ACCEL.y:"); Serial.print(acc.y); Serial.print(",");
Serial.print("ACCEL.z:"); Serial.print(acc.z); Serial.println();
}
if (qmi.getGyroscope(gyr.x, gyr.y, gyr.z)) {
Serial.print(" GYRO.x:"); Serial.print(gyr.x); Serial.print(",");
Serial.print(" GYRO.y:"); Serial.print(gyr.y); Serial.print(",");
Serial.print(" GYRO.z:"); Serial.print(gyr.z); Serial.println();
}
qmi8658_data_show();
}
Operation Result
The e-Paper display partially refreshes to show 6-axis gyroscope sensor data.

For the ESP32-S3-ePaper-3.97 development board, you need to use ESP-IDF V5.5.0 or higher.
The following guide uses Windows as an example, demonstrating development using VS Code + the ESP-IDF extension. macOS and Linux users should refer to the official documentation.
Download the installation manager from the ESP-IDF Installation Manager page. This is Espressif's latest cross-platform installer. The following steps demonstrate how to use its offline installation feature.
Click the Offline Installer tab on the page, then select Windows as the operating system and choose your desired version from the filter bar.

After confirming your selection, click the download button. The browser will automatically download two files: the ESP-IDF Offline Package (.zst) and the ESP-IDF Installer (.exe).

Please wait for both files to finish downloading.
Once the download is complete, double-click to run the ESP-IDF Installer (eim-gui-windows-x64.exe).
The installer will automatically detect if the offline package exists in the same directory. Click Install from archive.

Next, select the installation path. We recommend using the default path. If you need to customize it, ensure the path does not contain Chinese characters or spaces. Click Start installation to proceed.

When you see the following screen, the ESP-IDF installation is successful.

We recommend installing the drivers as well. Click Finish installation, then select Install driver.

Download and install Visual Studio Code.
During installation, it is recommended to check Add "Open with Code" action to Windows Explorer file context menu to facilitate opening project folders quickly.
In VS Code, click the Extensions icon in the Activity Bar on the side (or use the shortcut Ctrl + Shift + X) to open the Extensions view.
Enter ESP-IDF in the search box, locate the ESP-IDF extension, and click Install.

For ESP-IDF extension versions ≥ 2.0, the extension will automatically detect and recognize the ESP-IDF environment installed in the previous steps, requiring no manual configuration.
The ESP-IDF demos are located in the ESP-IDF directory of the demo package.
| Demo | Basic Description |
|---|---|
| 01_E-Paper_Example | 3.97inch e-Paper display demo |
| 02_Mic_test | Playback of sound recorded by the microphone through the speaker |
| 03_Music | Mount TF card and read/play music files from it |
| 04_SD_Test | Mount TF card, read images from it, and refresh the display |
| 05_QMI8658A | 6-axis gyroscope demo |
| 06_I2C_PCF85063 | RTC demo |
| 07_I2C_SHTC3 | Temperature and humidity sensor demo |
| 08_ESP32-S3_e-Paper-3.97 | Integrate file browser, clock, calendar, alarm, weather, network configuration, audio playback, and e-reader functions |
Code Analysis
Display a predefined image:
#if 1
ESP_LOGI(TAG,"2.show BMP");
EPD_Init_Fast();
EPD_Display(gImage_image);
vTaskDelay(pdMS_TO_TICKS(2000));
#endif
Draw basic shapes, Chinese/English text, numbers, and refresh the display:
#if 1
ESP_LOGI(TAG,"3.Paint_NewImage");
EPD_Init();
Paint_NewImage(Image_Mono, EPD_WIDTH, EPD_HEIGHT, 0, WHITE);
Paint_SelectImage(Image_Mono);
Paint_Clear(WHITE);
// Drawing on the image
Paint_DrawPoint(5, 10, BLACK, DOT_PIXEL_1X1, DOT_STYLE_DFT);
Paint_DrawPoint(5, 25, BLACK, DOT_PIXEL_2X2, DOT_STYLE_DFT);
Paint_DrawPoint(5, 40, BLACK, DOT_PIXEL_3X3, DOT_STYLE_DFT);
Paint_DrawPoint(5, 55, BLACK, DOT_PIXEL_4X4, DOT_STYLE_DFT);
Paint_DrawLine(20, 10, 70, 60, BLACK, DOT_PIXEL_1X1, LINE_STYLE_SOLID);
Paint_DrawLine(70, 10, 20, 60, BLACK, DOT_PIXEL_1X1, LINE_STYLE_SOLID);
Paint_DrawLine(170, 15, 170, 55, BLACK, DOT_PIXEL_1X1, LINE_STYLE_DOTTED);
Paint_DrawLine(150, 35, 190, 35, BLACK, DOT_PIXEL_1X1, LINE_STYLE_DOTTED);
Paint_DrawRectangle(20, 10, 70, 60, BLACK, DOT_PIXEL_1X1, DRAW_FILL_EMPTY);
Paint_DrawRectangle(85, 10, 130, 60, BLACK, DOT_PIXEL_1X1, DRAW_FILL_FULL);
Paint_DrawCircle(170, 35, 20, BLACK, DOT_PIXEL_1X1, DRAW_FILL_EMPTY);
Paint_DrawCircle(170, 85, 20, BLACK, DOT_PIXEL_1X1, DRAW_FILL_FULL);
Paint_DrawNum(5, 180, 123456789, &Font24, BLACK, WHITE);
Paint_DrawString_CN(5, 100,"你好 abc", &Font16_UTF8, BLACK, WHITE);
Paint_DrawString_CN(5, 130, "微雪电子", &Font24_UTF8, WHITE, BLACK);
EPD_Display_Base(Image_Mono);
vTaskDelay(pdMS_TO_TICKS(2000));
#endif

Code Analysis
i2c_master_Init();: Initializes the I2C bus.user_ui_init();: Initializes the global UI.user_button_init();: Initializes the audio interface.The screen shows nothing.
Long press the BOOT button to enter recording mode. Speak into the MIC, and it will automatically stop after 3 seconds.
Click the BOOT button to play the recorded sound. (If no recording exists, the played sound will be very harsh.)
Serial port prints:

Code Analysis
_sdcard_init();: Initializes the TF card and reads the audio files from it.i2c_master_init();: Initializes the I2C bus, providing a communication link for configuration command transmission to the ES8311 audio codec.audio_player_play(audio_fp);: Starts the audio player, reads the opened MP3 file, and drives the speaker through the ES8311 for playback.Code Analysis
_sdcard_init();: Initializes the TF card and reads the audio files from it.epaper_port_init();: Initializes the low-level hardware ports for the e-Paper (pins, communication bus, etc.).EPD_Init();/EPD_Clear();: Initializes the e-Paper driver parameters and clears the screen to a white background.GUI_ReadBmp("/sdcard/bmp/100x100.bmp", 50, 50);/EPD_Display_Fast(BlackImage);: Reads a BMP image from the TF card and performs a fast refresh to display it.GUI_ReadBmp_4Gray("/sdcard/bmp/3in97_4Gray.bmp", 0, 0);/EPD_Display_4Gray(BlackImage);: Reads and displays a 4-grayscale BMP image from the TF card.Reads and displays images from the TF card.



Code Analysis
epaper_port_init();/EPD_Init();/EPD_Clear(); calling EPD_Display_Partial for a partial e-Paper refresh after drawing values: Initializes the e-Paper's low-level hardware ports and driver parameters, clears the screen to a white background.i2c_master_init();: Initializes the I2C bus, providing a communication link for configuring and reading data from the QMI8658 sensor.xTaskCreate(qmi8658_test_task, "qmi8658_test_task", 4096, i2c_bus_handle, 5, NULL);: Creates a FreeRTOS task to execute the QMI8658 sensor data reading logic.qmi8658_is_data_ready(&dev, &ready);: Checks if the sensor data is ready, and only reads data when it is ready.qmi8658_read_sensor_data(&dev, &data);: Reads the sensor's acceleration, gyroscope, temperature, and timestamp data, and prints them via the serial port.draw_qmi8658_data_to_epaper(&data);: After drawing the values, calls EPD_Display_Partial for a partial refresh to display the data.The e-Paper display partially refreshes to show 6-axis gyroscope sensor data.

Code Analysis
epaper_port_init();/EPD_Init();/EPD_Clear(); calling EPD_Display_Partial for a partial e-Paper refresh after drawing values: Initializes the e-Paper's low-level hardware ports and driver parameters, clears the screen to a white background.i2c_master_init();: Initializes the I2C bus, providing a communication link for configuring and reading time from the PCF85063 RTC module.PCF85063_init();: Initializes the PCF85063 RTC module, completing the default clock register configuration.PCF85063_GetTime();/PCF85063_SetTime();: Reads the RTC's current time and sets the default time.xTaskCreate(rtc_test_task, "rtc_display", 4096, NULL, 5, NULL);: Creates a FreeRTOS task to execute the RTC time reading and display logic.display_time_on_epaper(): After drawing the values, calls EPD_Display_Partial for a partial refresh to display the data.The e-Paper display partially refreshes to show the time.

Code Analysis
epaper_port_init();/EPD_Init();/EPD_Clear(); calling EPD_Display_Partial for a partial e-Paper refresh after drawing values: Initializes the e-Paper's low-level hardware ports and driver parameters, clears the screen to a white background.i2c_master_init();: Initializes the I2C bus.i2c_shtc3_init();: Initializes the SHTC3 temperature and humidity sensor module.xTaskCreatePinnedToCore(i2c_SHTC3_loop_task, "i2c_SHTC3_loop_task", 3 * 1024, NULL , 2, NULL,0);: Creates a FreeRTOS task.i2c_SHTC3_loop_task(): Obtains temperature and humidity values and prints them, then calls EPD_Display_Partial for a partial refresh to display the data.The e-Paper display partially refreshes to show the temperature and humidity.

Code Analysis
app_main(), the initialization of NVS, TF card, I2C peripherals (sensors/clock/audio), buttons, and the e-Paper is completed. Configuration (WiFi enable, operating mode) is loaded from NVS, and corresponding tasks are created based on the mode.void user_Task(void *arg) is responsible for drawing the e-Paper main menu (8 function icons + text), responding to button events (up/down selection, confirm to enter subpage, global refresh, shutdown), managing e-Paper low-power states (sleep after 5 seconds of inactivity, soft shutdown after 10 minutes of inactivity), and refreshing the top status bar (time/battery/WiFi status).file_browser_task(); File browsing module.page_clock_show(); Clock module.page_calendar_show(); Calendar module.page_alarm_menu(); Alarm module.page_weather_city_select(); Weather module.page_handle_network_key_event(); Network configuration module.page_audio_main(); Audio playback module.page_fiction_file(); E-reader module.After the program is flashed, it enters the network configuration interface. Configure the network by connecting to the WiFi name displayed on the e-Paper.

After network configuration is complete, it enters the main page. Control is via the rotary encoder button and the BOOT and PWR side buttons. The e-Paper automatically sleeps after 60 seconds of inactivity and soft shuts down after 10 minutes of inactivity.

File Browser Module

Clock Module


Calendar Module

Alarm Module
Main interface of the alarm module, supporting up to 5 alarm settings.

After deleting an alarm, the time resets to 00:00 by default and the status is OFF. Click confirm to enter alarm editing mode. Use the rotary encoder up/down (↑↓) to select the content to edit (hour/minute/switch).

Hour/Minute editing: Click confirm to enter value adjustment. The rotary encoder up/down (↑↓) buttons allow single-step adjustment or continuous adjustment when held. Switch editing: Click confirm to toggle the ON/OFF state once. Double-click confirm or press Boot to exit editing mode.

Alarm trigger: When the set alarm time arrives, it automatically plays a built-in audio. Press any button to stop playback. Double-click confirm or press Boot to exit the alarm module and return to the main page.
Weather Module (Requires WiFi connection to be enabled first. It uses a Chinese weather service API and code tables, and is currently in the testing phase for adaptation to an English API.)


Network Configuration Module

Audio Playback Module



E-reader Module
Main interface of the e-reader module.

Reads .txt text files from the fiction folder in the TF card root directory. Use the rotary encoder up/down (↑↓) to select a file, then click confirm to start reading. While reading, use the rotary encoder up/down (↑↓) to turn pages.

Double-click the rotary encoder to enter the font selection interface. Click confirm to select a font and apply it.

Click the rotary encoder to enter the bookmark management interface. Click again to perform a bookmark operation. Double-click confirm to add a bookmark. Reading progress and bookmarks are automatically saved to the bookmarks folder on the TF card.

System Settings Module


System Power ON/OFF
Development Board Design File
Official ESP32-S3 Chip Manuals
Onboard Component Datasheets
Monday-Friday (9:30-6:30) Saturday (9:30-5:30)
Email: services01@spotpear.com