Maker.io main logo

Qualia S3 Fireplace

2024-12-06 | By Adafruit Industries

License: See Original Project 3D Printing Displays LCD / TFT LEDs / Discrete / Modules Arduino

Courtesy of Adafruit

Guide by by Ruiz Brothers and 2 other contributors‎

Overview

 

Build a miniature fireplace that plays Yule Log video clips using an ‎Adafruit Qualia ESP32-S3 and a 3.2" rectangle bar TFT display.‎

3d_printing_hero-loop-rainbow_1

Load a series of your favorite video files on a micro-SD card and ‎display them on the long TFT bar screen. Cycle through them by ‎touching the screen. ‎

‎3D print the parts to secure the display, Qualia ESP32-S2, and micro ‎SD breakout. The fireplace mantel is decorative and swappable so ‎you can customize it.‎

fireplace_2

fireplace_3

parts_4

Parts

Prerequisite Guides

Take a moment to review the following guides to learn more about ‎the products.‎

3d_printing_hero-decorated-loop_5

Text editor powered by tinymce.‎

Circuit Diagram

The diagram below provides a general visual reference for wiring of ‎the components once you get to the Assembly page. This diagram ‎was created using the software package Fritzing.‎

Adafruit Library for Fritzing

Adafruit uses the Adafruit's Fritzing parts library to create circuit ‎diagrams for projects. You can download the library or just grab ‎individual parts. Get the library and parts from GitHub - Adafruit ‎Fritzing Parts.‎

connections_6

Wired Connections

The Qualia ESP32-S3 is powered by a 5V 1A USB power supply.‎

  • SCK from Qualia S3 to CLK on Micro SD

  • MISO from Qualia S3 to SO on Micro SD

  • MOSI from Qualia S3 to SI on Micro SD

  • CS from Qualia S3 to CS on Micro SD

  • A1 from Qualia S3 to DAT2 on Micro SD

  • A0 from Qualia S3 to D1 on Micro SD

  • 3.3V from Qualia S3 to 3V on Micro SD

  • GND from Qualia to GND on Micro SD

Text editor powered by tinymce.‎

Converting Videos

Video File Preparation

You'll want to use a video file in a common format such as H.264 ‎‎(.MP4 or .MOV) with a duration of anywhere from 10 seconds to 3 ‎minutes in length. Your video clip should ideally have a 16:9 aspect ‎ratio (such as 1920 x 1080 or 1280 x 720). Note: the final video ratio ‎will be ~2.6:1, so there will be some cropping off the top and bottom.‎

The 3.2" display has a screen resolution of 320x820‎

Online Converter

You can use the website linked below to convert your video file into ‎MJPEG. (maximum file size is 100MB.)‎

Convert IO Website

convert_7

Click on the Choose Files icon. Navigate to your video file and ‎click Open. Click on the dropdown icon and select MJPEG under the ‎video section. Then, click on the gear icon to open the settings dialog.‎

files_8

Use the following settings for best playback performance.‎

  • Codec: MJPEG

  • Quality: Highest

  • Resize: Custom / 320 x 820‎

  • Resize Method: Zoom and crop

  • Frame rate : 12 FPS

  • Rotate: Rotate by 90 degrees counterclockwise

Click on the Convert button when finished.‎

button_9

Format SD

Format a micro-SD card to FAT32.‎

‎Create VIDEOS folder

Make a new folder in the SD card and name it VIDEOS.‎

video_10

video_11

Conversion Completed

Click the Download button when the upload and conversion is ‎complete.‎

Use the VLC media player app to playback the video for reviewing.‎

Rename the video file so it only contains the .MJPEG extension. Then, ‎drag and drop it into the VIDEOS folder on the micro-SD card.‎

convertio_12

Mac users may need to delete .DS files inside the VIDEOS folder

Text editor powered by tinymce.‎

CAD Files

‎3D Printed Parts‎

STL files for 3D printing are oriented to print "as-is" on FDM style ‎machines. Parts are designed to 3D print without any support ‎material using PLA filament. Original design source may be ‎downloaded using the links below.‎

cad_13

Edit Victorian Mantel

Edit Design

Download STLs

3-2-Fireplace-step.zip

Parts List

  • button-qualia.stl

  • case-cover.stl

  • case-tft.stl

  • modern-fireplace-base.stl

  • modern-fireplace.stl

  • qualia-tft-mount.stl

  • victorian-fireplace.stl

  • victorian-platform.stl

partlist_14

Build Volume

The parts require a 3D printer with a minimum build volume.‎

  • ‎150mm (X) x 150mm (Y) x 84mm (Z)‎

build_15

Design Source Files

The project assembly was designed in Fusion 360. This can be ‎downloaded in different formats like STEP, STL and more. Electronic ‎components like Adafruit's boards, displays, connectors and more ‎can be downloaded from the Adafruit CAD parts GitHub Repo.‎

repo_16

frame_17

Text editor powered by tinymce.‎

Install Bootloader

The Qualia ESP32-S3 microcontroller ships running a circular ‎rainbow gradient example for the round 480x480 display. It's lovely, ‎but you probably had other plans for the board. As you start working ‎with your board, you may want to return to the original code to ‎begin again, or you may find your board gets into a bad state. Either ‎way, this page has you covered.‎

You're probably used to seeing the TFT_S3BOOT drive when loading ‎CircuitPython or Arduino. The TFT_S3BOOT drive is part of the UF2 ‎bootloader, and allows you to drag and drop files, such as ‎CircuitPython. However, on the ESP32-S3 the UF2 bootloader can ‎become damaged.‎

Factory Reset Firmware UF2‎

If you have a bootloader still installed - which means you can ‎double-click to get the TFT_S3BOOT drive to appear, then you can ‎simply drag this UF2 file over to the BOOT drive.‎

To enter bootloader mode, plug in the board into a USB cable with ‎data/sync capability. Press the reset button once, wait till the RGB ‎LED turns purple, then press the reset button again. Then drag this ‎file over:‎

Qualia S3 RGB-666 Factory Reset

Your board is now back to its factory-shipped state! You can now ‎begin again with your plans for your board.‎

Factory Reset and Bootloader ‎Repair

What if you tried double-tapping the reset button, and you still can't ‎get into the UF2 bootloader? Whether your board shipped without ‎the UF2 bootloader, or something damaged it, this section has you ‎covered.‎

There is no bootloader protection for the UF2 bootloader. That means ‎it is possible to erase or damage the UF2 bootloader, especially if you ‎upload an Arduino sketch to an ESP32-S2/S3 board that doesn't ‎‎"know" there's a bootloader it should not overwrite!‎

It turns out, however, the ESP32-S2/S3 comes with a second ‎bootloader: the ROM bootloader. Thanks to the ROM bootloader, you ‎don't have to worry about damaging the UF2 bootloader. The ROM ‎bootloader can never be disabled or erased, so it’s always there if you ‎need it! You can simply re-load the UF2 bootloader from the ROM ‎bootloader.‎

Completing a factory reset will erase your board's firmware which is ‎also used for storing CircuitPython/Arduino/Files! Be sure to back up ‎your data first.‎

There are two ways to do a factory reset and bootloader repair. The ‎first is using WebSerial through a Chromium-based browser, and the ‎second is using esptool via command line. We highly recommend ‎using WebSerial through Chrome/Chromium.‎

The next section walks you through the prerequisite steps needed ‎for both methods.‎

Download .bin and Enter ‎Bootloader

Step 1. Download the factory-reset-‎and-bootloader.bin file

Save the following file wherever is convenient for you. You will need ‎to access it from the WebSerial ESPTool.‎

Note that this file is approximately 3MB. This is not because the ‎bootloader is 3MB, it is because the bootloader is near the end of the ‎available flash. Most of the file is empty but it’s easier to program if ‎you use a combined file.‎

Qualia S3 RGB-666 Factory Reset .bin File

Step 2. Enter ROM bootloader mode

Entering the ROM bootloader is easy. Complete the following steps.‎

Before you start, make sure your ESP32-S2/S3 is plugged into USB ‎port to your computer using a data/sync cable. Charge-only cables ‎will not work!‎

To enter the bootloader:‎

  1. Press and hold the BOOT/DFU button down. Don't let go of it ‎yet!‎

  2. Press and release the Reset button. You should still have the ‎BOOT/DFU button pressed while you do this.‎

  3. Now you can release the BOOT/DFU button.‎

circuitpython_bootloader_mode_18a

No USB drive will appear when you've entered the ROM bootloader. ‎This is normal!‎

Now that you've downloaded the .bin file and entered the bootloader, ‎you're ready to continue with the factory reset and bootloader repair ‎process. The next two sections walk you through using WebSerial ‎and esptool.‎

The WebSerial ESPTool Method

We highly recommend using WebSerial ESPTool method to perform ‎a factory reset and bootloader repair. However, if you'd rather use ‎esptool via command line, you can skip this section.‎

This method uses the WebSerial ESPTool through Chrome or a ‎Chromium-based browser. The WebSerial ESPTool was designed to ‎be a web-capable option for programming ESP32-S2/S3 boards. It ‎allows you to erase the contents of the microcontroller and program ‎up to four files at different offsets.‎

You will have to use a Chromium browser (like Chrome, Opera, ‎Edge...) for this to work, Safari and Firefox, etc. are not supported ‎because we need Web Serial and only Chromium is supporting it to ‎the level needed.‎

Follow the steps to complete the factory reset.‎

If you're using Chrome 88 or older, see the Older Versions of Chrome ‎section at the end of this page for instructions on enabling Web ‎Serial.‎

Connect

You should have plugged in only the ESP32-S2/S3 that you intend ‎to flash. That way there's no confusion in picking the proper port ‎when it's time!‎

In the Chrome ‎browser visit https://adafruit.github.io/Adafruit_WebSerial_ESPTool/. ‎You should see something like the image shown.

connect_19

Press the Connect button in the top right of the web browser. You ‎will get a pop up asking you to select the COM or Serial port.‎

Remember, you should remove all other USB devices so only the ‎ESP32-S2/S3 board is attached, that way there's no confusion over ‎multiple ports!‎

On some systems, such as MacOS, there may be additional system ‎ports that appear in the list.‎

port_20

The JavaScript code will now try to connect to the ROM bootloader. It ‎may timeout for a bit until it succeeds. On success, you will see that ‎it is Connected and will print out a unique MAC address identifying ‎the board along with other information that was detected.‎

code_21

Once you have successfully connected, the command toolbar will ‎appear.‎

tool_22

Erase the Contents

This will erase everything on your board! If you have access, and wish ‎to keep any code, now is the time to ensure you've backed up ‎everything.

To erase the contents, click the Erase button. You will be prompted ‎whether you want to continue. Click OK to continue or if you ‎changed your mind, just click cancel.‎

erase_22

You'll see "Erasing flash memory. Please wait..." This will eventually ‎be followed by "Finished." and the amount of time it took to erase.‎

Do not disconnect! Immediately continue on to programming the ‎ESP32-S2/S3.‎

flash_23

Do not disconnect after erasing! Immediately continue on to the ‎next step!‎

Program the ESP32-S2/S3‎

Programming the microcontroller can be done with up to four files ‎at different locations, but with the board-specific factory-‎reset.bin file, which you should have downloaded under Step 1 on ‎this page, you only need to use one file.‎

Click on the first Choose a file.... (The tool will only attempt to ‎program buttons with a file and a unique location.) Then, select the ‎‎*-factory-reset.bin file you downloaded in Step 1 that matches your ‎board.‎

Verify that the Offset box next to the file location you used is (0x) 0.‎

verify_24

Once you choose a file, the button text will change to match your ‎filename. You can then select the Program button to begin flashing.‎

programbutton_25

A progress bar will appear and after a minute or two, you will have ‎written the firmware.‎

bar_26

Once completed, you can skip down to the section titled Reset the ‎Board.‎

The esptool Method (for advanced ‎users)‎

If you used WebSerial ESPTool, you do not need to complete the ‎steps in this section!‎

Once you have entered ROM bootloader mode, you can then use ‎Espressif's esptool program to communicate with the chip! esptool is ‎the 'official' programming tool and is the most common/complete ‎way to program an ESP chip.‎

Install ESPTool.py

You will need to use the command line / Terminal to install and ‎run esptool.‎

You will also need to have pip and Python installed (any version!).‎

Install the latest version using pip (you may be able to run pip without ‎the 3 depending on your setup):‎

pip3 install --upgrade esptool

Then, you can run:‎

esptool.py

Make sure you are running esptool v3.0 or higher, which adds ESP32-‎S2/S3 support.‎

Test the Installation

Run esptool.py in a new terminal/command line and verify you get ‎something like the below:‎

run_27

Connect

Run the following command, replacing the identifier after --port with ‎the COMxx, /dev/cu.usbmodemxx or /dev/ttySxx you found above.‎

esptool.py --port COM88 chip_id

You should get a notice that it connected over that port and found ‎an ESP32-S2/S3.‎

notice_28

Erase the Flash

Before programming the board, it is a good idea to erase the flash. ‎Run the following command.‎

esptool.py erase_flash

You must be connected (by running the command in the previous ‎section) for this command to work as shown.‎

command_29

Installing the Bootloader

Run this command and replace the serial port name with your ‎matching port and the file you just downloaded

esptool.py --port COM88 write_flash 0x0 tinyuf2_combo.bin

Don't forget to change the --port name to match.‎

Adjust the bootloader filename accordingly if it differs from ‎tinyuf2_combo.bin.‎

There might be a bit of a 'wait' when programming, where it doesn't ‎seem like it's working. Give it a minute, it has to erase the old flash ‎code which can cause it to seem like it's not running.‎

You'll finally get an output like this:‎

output_30

Once completed, you can continue to the next section.‎

Reset the board

Now that you've reprogrammed the board, you need to reset it to ‎continue. Click the reset button to launch the new firmware.‎

If you have a 480x480 round display plugged in, you should see a ‎circular rainbow gradient appear on the display.‎

You've successfully returned your board to a factory reset state!‎

Older Versions of Chrome

As of chrome 89, Web Serial is already enabled, so this step is only ‎necessary on older browsers.‎

We suggest updating to Chrome 89 or newer, as Web Serial is ‎enabled by default.‎

If you must continue using an older version of Chrome, follow these ‎steps to enable Web Serial.‎

If you receive an error like the one shown when you visit the ‎WebSerial ESPTool site, you're likely running an older version of ‎Chrome.‎

You must be using Chrome 78 or later to use Web Serial.‎

serial_31

To enable Web Serial in Chrome versions 78 through 88:‎

• Visit chrome://flags from within Chrome.‎

• Find and enable the Experimental Web Platform features

Restart Chrome

restart_32

The Flash an Arduino Sketch ‎Method

This section outlines flashing an Arduino sketch onto your ESP32-‎S2/S3 board, which automatically installs the UF2 bootloader as well.‎

Arduino IDE Setup

If you don't already have the Arduino IDE installed, the first thing you ‎will need to do is to download the latest release of the Arduino IDE. ‎ESP32-S2/S3 requires version 1.8 or higher. Click the link to download ‎the latest.‎

Arduino IDE Download

After you have downloaded and installed the latest version of ‎Arduino IDE, you will need to start the IDE and navigate ‎to the Preferences menu. You can access it from the File > ‎Preferences menu in Windows or Linux, or the Arduino > ‎Preferences menu on OS X.‎

The Preferences window will open.‎

In the Additional Boards Manager URLs field, you'll want to add a ‎new URL. The list of URLs is comma separated, and you will only ‎have to add each URL once. The URLs point to index files that the ‎Board Manager uses to build the list of available & installed boards.‎

Copy the following URL.‎

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-‎pages/package_esp32_dev_index.json

Add the URL to the Additional Boards Manager URLs field ‎‎(highlighted in red below).‎

add_33

Click OK to save and close Preferences.‎

In the Tools > Boards menu you should see the ESP32 ‎Arduino menu. In the expanded menu, it should contain the ESP32 ‎boards along with all the latest ESP32-S2 boards.‎

Now that your IDE is setup, you can continue on to loading the ‎sketch.‎

Load the Blink Sketch

In the Tools > Boards menu you should see the ESP32 ‎Arduino menu. In the expanded menu, look for the menu option for ‎the Adafruit Qualia ESP32-S3 RGB666, and click on it to choose it.‎

Open the Blink sketch by clicking through File > Examples > ‎‎01.Basics > Blink.‎

open_34

Once open, click Upload from the sketch window.‎

click_35

Once successfully uploaded, the little red LED will begin blinking ‎once every second. At that point, you can now enter the bootloader.‎

The Qualia ESP32-S3 RGB-666 does not have a little red LED, so the ‎default Blink sketch will fail.‎

If you change LED_BUILTIN to 13, the sketch will compile and upload. Be ‎aware that, once the sketch is loaded, nothing will happen on the ‎board. However, you will have a bootloader. The updated code would ‎look like this:‎

‎Download File

Copy Code
void setup() {
  pinMode(13, OUTPUT);
}

void loop() {
  digitalWrite(13, HIGH);
  delay(1000); 
  digitalWrite(13, LOW); 
  delay(1000); 
}

Alternatively, you could load a different sketch. It doesn't matter ‎which sketch you use.‎

Text editor powered by tinymce.‎

Software Setup and Use

Prep SD Card

Create a folder called VIDEOS on your SD card. Save your converted ‎video files in this folder. Eject the SD card from your computer and ‎place it in the MicroSD reader.‎

Upload UF2 File

The Qualia S3 Fireplace code is available as a pre-compiled .UF2 file ‎for the 3.2" 320x820 display that you can drag and drop onto your ‎Qualia S3 board.‎

Qualia S3 Fireplace UF2 File

Click the link above to download the UF2 file.

Save it wherever is convenient for you.‎

save_36

board_37

Plug your board into your computer, using a known-good data-sync ‎USB cable, directly, or via an adapter if needed.‎

Double-click the reset button (highlighted in red above), wait about ‎a half a second and then tap reset again.‎

You will see a new disk drive appear called TFT_S3BOOT.‎

Drag the Qualia_S3_3.2_320x820_Yule_Log.UF2 file to TFT_S3BOOT.

drag_38

The code will begin running by playing the first video file on the SD ‎card. Touch the right side of the screen to play the next file. Touch ‎the left side of the screen to play the previous file.‎

Advanced Users: Source Code in ‎Arduino IDE

Only attempt this if you are comfortable with Git and advanced ‎Arduino use. Otherwise, use the precompiled UF2.‎

Qualia S3 Fireplace Arduino Code

Download File

Copy Code
// SPDX-FileCopyrightText: 2023 Limor Fried for Adafruit Industries
//
// SPDX-License-Identifier: MIT

/*******************************************************************************
 * Motion JPEG Image Viewer
 * This is a simple Motion JPEG image viewer example

encode with
ffmpeg -i "wash.mp4" -vf "fps=10,vflip,hflip,scale=-1:480:flags=lanczos,crop=480:480" -pix_fmt yuvj420p -q:v 9 wash.mjpeg

 ******************************************************************************/
#define MJPEG_FOLDER       "/videos" // cannot be root!
#define MJPEG_OUTPUT_SIZE  (820 * 320 * 2)      // memory for a output image frame
#define MJPEG_BUFFER_SIZE (MJPEG_OUTPUT_SIZE / 5) // memory for a single JPEG frame
#define MJPEG_LOOPS        0

#include <Arduino_GFX_Library.h>
#include "Adafruit_FT6206.h"
//#include <SD.h>      // uncomment either SD or SD_MMC
#include <SD_MMC.h>

Arduino_XCA9554SWSPI *expander = new Arduino_XCA9554SWSPI(
    PCA_TFT_RESET, PCA_TFT_CS, PCA_TFT_SCK, PCA_TFT_MOSI,
    &Wire, 0x3F);
    
Arduino_ESP32RGBPanel *rgbpanel = new Arduino_ESP32RGBPanel(
    TFT_DE, TFT_VSYNC, TFT_HSYNC, TFT_PCLK,
    TFT_R1, TFT_R2, TFT_R3, TFT_R4, TFT_R5,
    TFT_G0, TFT_G1, TFT_G2, TFT_G3, TFT_G4, TFT_G5,
    TFT_B1, TFT_B2, TFT_B3, TFT_B4, TFT_B5,
    1 /* hsync_polarity */, 50 /* hsync_front_porch */, 2 /* hsync_pulse_width */, 44 /* hsync_back_porch */,
    1 /* vsync_polarity */, 16 /* vsync_front_porch */, 2 /* vsync_pulse_width */, 18 /* vsync_back_porch */
    //,1, 30000000
    );

Arduino_RGB_Display *gfx = new Arduino_RGB_Display(
/* 3.2" bar */
    320 /* width */, 820 /* height */, rgbpanel, 0 /* rotation */, true /* auto_flush */,
    expander, GFX_NOT_DEFINED /* RST */, tl032fwv01_init_operations, sizeof(tl032fwv01_init_operations));

Adafruit_FT6206 ctp = Adafruit_FT6206();  // This library also supports FT6336U!
#define I2C_TOUCH_ADDR 0x38
bool touchOK = false;

#include <SD_MMC.h>

#include "MjpegClass.h"
static MjpegClass mjpeg;
File mjpegFile, video_dir;
uint8_t *mjpeg_buf;
uint16_t *output_buf;

unsigned long total_show_video = 0;

void setup()
{
  Serial.begin(115200);
  Serial.setDebugOutput(true);
  //while(!Serial) delay(10);
  Serial.println("MJPEG Video Playback Demo");

#ifdef GFX_EXTRA_PRE_INIT
  GFX_EXTRA_PRE_INIT();
#endif

  // Init Display
  Wire.setClock(400000); // speed up I2C 
  if (!gfx->begin()) {
    Serial.println("gfx->begin() failed!");
  }
  gfx->fillScreen(BLUE);

  expander->pinMode(PCA_TFT_BACKLIGHT, OUTPUT);
  expander->digitalWrite(PCA_TFT_BACKLIGHT, HIGH);

  //while (!SD.begin(ss, SPI, 64000000UL))
  //SD_MMC.setPins(SCK /* CLK */, MOSI /* CMD/MOSI */, MISO /* D0/MISO */);
  SD_MMC.setPins(SCK, MOSI /* CMD/MOSI */, MISO /* D0/MISO */, A0 /* D1 */, A1 /* D2 */, SS /* D3/CS */); // quad MMC!
  while (!SD_MMC.begin("/root", true))
  {
    Serial.println(F("ERROR: File System Mount Failed!"));
    gfx->println(F("ERROR: File System Mount Failed!"));
    delay(1000);
  }
  Serial.println("Found SD Card");

  //  open filesystem
  //video_dir = SD.open(MJPEG_FOLDER);
  video_dir = SD_MMC.open(MJPEG_FOLDER);
  if (!video_dir || !video_dir.isDirectory()){
     Serial.println("Failed to open " MJPEG_FOLDER " directory");
     while (1) delay(100);
  }
  Serial.println("Opened Dir");

  mjpeg_buf = (uint8_t *)malloc(MJPEG_BUFFER_SIZE);
  if (!mjpeg_buf) {
    Serial.println(F("mjpeg_buf malloc failed!"));
    while (1) delay(100);
  }
  Serial.println("Allocated decoding buffer");

  output_buf = (uint16_t *)heap_caps_aligned_alloc(16, MJPEG_OUTPUT_SIZE, MALLOC_CAP_8BIT);
  if (!output_buf) {
    Serial.println(F("output_buf malloc failed!"));
    while (1) delay(100);
  }

  expander->pinMode(PCA_BUTTON_UP, INPUT);
  expander->pinMode(PCA_BUTTON_DOWN, INPUT);

  if (!ctp.begin(0, &Wire, I2C_TOUCH_ADDR)) {
    Serial.println("No touchscreen found");
    touchOK = false;
  } else {
    Serial.println("Touchscreen found");
    touchOK = true;
  }
}

void loop()
{
  /* variables */
  int total_frames = 0;
  unsigned long total_read_video = 0;
  unsigned long total_decode_video = 0;
  unsigned long start_ms, curr_ms;
  uint8_t check_UI_count = 0;
  int16_t x = -1, y = -1, w = -1, h = -1;
  total_show_video = 0;

  if (mjpegFile) mjpegFile.close();
  Serial.println("looking for a file...");

  if (!video_dir || !video_dir.isDirectory()){
     Serial.println("Failed to open " MJPEG_FOLDER " directory");
     while (1) delay(100);
  }

  // look for first mjpeg file
  while ((mjpegFile = video_dir.openNextFile()) != 0) {
    if (!mjpegFile.isDirectory()) {
      Serial.print("  FILE: ");
      Serial.print(mjpegFile.name());
      Serial.print("  SIZE: ");
      Serial.println(mjpegFile.size());
      if ((strstr(mjpegFile.name(), ".mjpeg") != 0) || (strstr(mjpegFile.name(), ".MJPEG") != 0)) {
        Serial.println("   <---- found a video!");
        break;
      }
    }
    if (mjpegFile) mjpegFile.close();
  }

  if (!mjpegFile || mjpegFile.isDirectory())
  {
    Serial.println(F("ERROR: Failed to find a MJPEG file for reading, resetting..."));
    //gfx->println(F("ERROR: Failed to find a MJPEG file for reading"));

    // We kept getting hard crashes when trying to rewindDirectory or close/open dir
    // so we're just going to do a softreset
    esp_sleep_enable_timer_wakeup(1000);
    esp_deep_sleep_start(); 
  }

  bool done_looping = false;
  while (!done_looping) {
    mjpegFile.seek(0);
    total_frames = 0;
    total_read_video = 0;
    total_decode_video = 0;
    total_show_video = 0;

    Serial.println(F("MJPEG start"));
  
    start_ms = millis();
    curr_ms = millis();
    if (! mjpeg.setup(&mjpegFile, mjpeg_buf, output_buf, MJPEG_OUTPUT_SIZE, true /* useBigEndian */)) {
       Serial.println("mjpeg.setup() failed");
       while (1) delay(100);
    }
  
    while (mjpegFile.available() && mjpeg.readMjpegBuf())
    {
      // Read video
      total_read_video += millis() - curr_ms;
      curr_ms = millis();

      // Play video
      mjpeg.decodeJpg();
      total_decode_video += millis() - curr_ms;
      curr_ms = millis();

      if (x == -1) {
        w = mjpeg.getWidth();
        h = mjpeg.getHeight();
        x = (w > gfx->width()) ? 0 : ((gfx->width() - w) / 2);
        y = (h > gfx->height()) ? 0 : ((gfx->height() - h) / 2);
      }
      gfx->draw16bitBeRGBBitmap(x, y, output_buf, w, h);
      total_show_video += millis() - curr_ms;

      curr_ms = millis();
      total_frames++;
      check_UI_count++;
      if (check_UI_count >= 5) {
        check_UI_count = 0;
        Serial.print('.');
        
        if (! expander->digitalRead(PCA_BUTTON_DOWN)) {
          Serial.println("\nDown pressed");
          done_looping = true;
          while (! expander->digitalRead(PCA_BUTTON_DOWN)) delay(10);
          break;
        }
        if (! expander->digitalRead(PCA_BUTTON_UP)) {
          Serial.println("\nUp pressed");
          done_looping = true;
          while (! expander->digitalRead(PCA_BUTTON_UP)) delay(10);
          break;
        }
  
        if (touchOK && ctp.touched()) {
          TS_Point p = ctp.getPoint(0);
          Serial.printf("(%d, %d)\n", p.x, p.y);
          done_looping = true;
          break;
        }
      }
    }
    int time_used = millis() - start_ms;
    Serial.println(F("MJPEG end"));
    
    float fps = 1000.0 * total_frames / time_used;
    total_decode_video -= total_show_video;
    Serial.printf("Total frames: %d\n", total_frames);
    Serial.printf("Time used: %d ms\n", time_used);
    Serial.printf("Average FPS: %0.1f\n", fps);
    Serial.printf("Read MJPEG: %lu ms (%0.1f %%)\n", total_read_video, 100.0 * total_read_video / time_used);
    Serial.printf("Decode video: %lu ms (%0.1f %%)\n", total_decode_video, 100.0 * total_decode_video / time_used);
    Serial.printf("Show video: %lu ms (%0.1f %%)\n", total_show_video, 100.0 * total_show_video / time_used);
  }
}

View on GitHub

The source code for the Fireplace is available on GitHub. It consists of ‎an Arduino script .ino file and a header file. You will need both files to ‎compile it in the Arduino IDE. There are a few items you'll need to ‎manually configure in the Arduino IDE:‎

  • The header file requires the ESP32_JPEG library, which isn't ‎currently available in the Arduino IDE library bundle. You'll need ‎to install it manually from its GitHub repository.‎

  • Currently the Arduino GFX library is not compatible with the ‎ESP BSP 3.0 since it uses IDF 5. You will need to use an older ‎BSP package and manually add the Qualia S3 board to your ‎local installation.‎

If you defeat these dragons though, you can update the code to run ‎on different RGB-666 displays and customize any other parameters ‎that you want.‎

Text editor powered by tinymce.‎

Assemble

Prep SD breakout

Use an 8 pin matching cable pair to easily connect the SD breakout ‎board to the pins on the Qualia board. ‎

Mount SD to Lid

Use 2.5x5mm screws to secure the breakout to the lid part.‎

assemble_39

assemble_40

Mount display

Take note of how the ribbon cable attaches to the Qualia board. ‎Align the display to the cutout and place face down between the ‎walls inside the case. ‎

Slightly bend the case while gently pressing the edges of the display ‎to fit. ‎

mount_41

mount_42

Mounting The Frame

Align cutout on the mounting frame to the ribbon cable

Slide the mounting frame into the case at an angle, between the ‎snaps on the case.‎

Attach The Buttons

Align buttons to the cutouts on the case.‎

case_43

case_44

Mount The Qualia Board

Use four M2.5x5mm screws to attach the Qualia board to the ‎standoffs on the frame. ‎

Connect the display and SD cables to the Qualia board. ‎

Attach The Lid

Align the snaps on the lid to the snaps on the case to press fit ‎together.

attach_45

attach_46

Power it up with a USB power bank and your fireplace will come to ‎life!‎

3d_printing_hero-loop-rainbow_1

Text editor powered by tinymce.

制造商零件编号 5797
GRAPHIC DISPLAY TFT RGB 3.2"
Adafruit Industries LLC
制造商零件编号 5800
EVAL BOARD FOR ESP32-S3
Adafruit Industries LLC
制造商零件编号 4682
MICROSD SPI/SPIO BREAKOUT BOARD
Adafruit Industries LLC
制造商零件编号 5153
CABLE A PLUG TO C PLUG 3.28'
Adafruit Industries LLC
制造商零件编号 4976
1.25MM PITCH 8-PIN CABLE MATCHIN
Adafruit Industries LLC
Add all DigiKey Parts to Cart
TechForum

Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.

Visit TechForum