The Slowest Video Player with 7-Colors!

Watch your favorite films at 1 frame per minute

Similar projects worth following
This is like a digital picture frame, but instead of showing a sequence of photos, it plays a movie frame by frame. Images appear on a 7-Color E-Paper display. The whole movie is stored as a sequence of jpeg images on an SD-Card. An STM32 microcontroller reads the files from the SD-Card and updates the display at a rate of one frame per minute.
The goal is to have a battery-powered standalone unit in a nice 3D printed case.

This project is only at the beginning stage, I'll be posting updates as it progresses.

All the code and 3D models are available on GitHub.

Last year I saw this video on Youtube that featured a 7-Color E-Paper display from Waveshare. I immediately thought it was cool and after seen the Slowmovie project by Mike Szczys I had to make my own.

As far as I know, nobody has made something like this with a color E-Paper display so even if it isn't a new concept, it brings a new twist to the game.

The plan is to make a standalone battery-powered device in a nice 3D printed case. It has to be as low power as possible since I want the batteries to last at least a couple of months. I haven't decided yet on what battery chemistry to use, the two candidates are lithium-ion or rechargeable NiMH AA. If I go with lithium-ion it will be rechargeable via USB, otherwise, AA batteries will have to be replaced when empty.

Eventually, I plan on making a custom PCB with all the components, but for the initial prototype/proof of concept, I'll be using an STM32F4 Discovery board. The following picture shows the connections between the SD-Card, the display, and the development board.

E-Paper displays ara ideal for this task because they draw power only when the image is changing. The display module comes mounted on a breakout board that converts the flat flex cable into a convenient connector, but it also has some additional circuitry. When the RST line is held LOW a MOSFET in series with the VCC line cuts power to the module. The SD-Card on the other hand as a non-zero quiescent current and so to prolong battery life, a switch must be added. This is not shown in the schematic because I will focus on the firmware side first: reading files from the SD-Card, decoding the jpeg images, dithering algorithms to increase the available number of colors.

RAR Archive - 582.78 kB - 02/13/2021 at 16:25


  • PCB and 3D Printed Enclosure

    Manuel Tosone15 hours ago 0 comments

    PCB Layout

    PCB layout is done, design files are sent to JLCPCB for manufacturing and assembling.

    There is a timelapse video of the layout if you are interested.


    3D Printed Enclosure

    I designed an enclosure to hold the display, the circuit board, and 6 AA batteries.

    3D Models are on GitHub. If you want to make your own, for the battery holder, you need to salvage the contacts from somewhere or you can get them from Mouser 5210 5223 5211 5201.

    The PCB is held in place by 4 M3x6 screws while the two halves are held together by 4 M3x8 screws.

    Enclosure side
    Enclosure back

    The following video shows how the enclosure goes together.

    I put the display in its case and connected it to the STM32 Discovery. Now I can enjoy a movie while I wait for the circuit boards.

  • Schematic and Power Consumption

    Manuel Tosone02/22/2021 at 13:41 0 comments


    I spent the last two days working on the schematic for the first prototype, here is what I came up with.

    I finally decided on what battery to use, the board will be powered by 6 AA. I have a design in mind for a case in which 6 AAs fit well.

    The plan is to have the board assembled by JLCBCB and so I tried to optimize the BOM.

    Power Section

    The board can be powered either from batteries or from the USB connector. The power supply is divided into two paths, there is a switching regulator and an LDO to supply power during sleep. The reason for having two regulators is that the MP2451DT DC-DC converter has an efficiency greater than 85% with a 100mA current load but, due to the switching losses, the efficiency drops drastically at low loads. The datasheet for the microcontroller states a power consumption of 4uA in Stand-By mode. The HT7533 LDO has a quiescent current of only 2.5uA. The two SY6280A are power-distribution switches. U2 switches power to the microcontroller and is used to isolate VDD from the 3.3V when the DC-DC converter is disabled. U3 switches power to the SD-Card, it is used to disable the SD-Card while the screen is busy updating to save power.

    R16, R17, R18, R24 form a potential divider that's used to measure the battery voltage. This makes it possible to detect when the batteries are running low and to display a low battery icon on the screen.

    R10 is a Light Dependent Resistor, it's used to measure the ambient light. Since e-paper displays have no backlight and are not visible in the dark, there's no point in updating the display if nobody is able to see it. An LDR has a resistance that varies with the amount of light that shines on it. The resistance varies from a couple of hundred ohms, when shining a bright flashlight on it, to hundreds of kiloohms, when in complete darkness. The way the resistance is measured is by determining how long a known capacitor takes to charge from a fixed supply voltage. This mechanism is quite clever and doesn't consume any power when the resistor is not measured.

    MCU Section

    The microcontroller is an STM32F405RG, it has 1024KB of FLASH and 192 KB of RAM plus all the required peripherals. There are two quarts crystals, the 8MHz one is the main oscillator, the USB requires an external crystal. The 32.768KHz one drives the RTC that's used to wake the microcontroller every 24 minutes to update the display.

    All unused pins are connected to test pads in case they are needed in the future.

    C19, C20, C30 in conjunction with the 47mF supercapacitor C31, provide the energy required to power the microcontroller when the batteries are removed. C31 has enough stored energy to power the microcontroller for 24 minutes in standby mode when the power consumption is 4uA. The additional 30uF of capacitance on the VDD line are enough to power the microcontroller for 10ms after it exits standby mode. This is used to store the currently displayed frame in the internal FLASH so that the movie doesn't restart from the beginning every time the batteries are changed.

    Programming the Microcontroller

    There are three ways to program the microcontroller. The first is using the SWD debug interface, the second and third methods involve the bootloader. STM32 MCUs ship with a preprogrammed bootloader that can be used to program the device, in this case, either from the serial port or through the USB.

    The MCU automatically enters into boot loader mode the first time it is powered on when the flash memory is empty. By pressing the BOOT button while performing a reset, the bootloader can be started at any time.

    Power consumption estimation

    The display updates every 24 minutes, that period of time is divided into 5 steps.

    1. DISPLAY INIT: The MCU wakes from sleep, enables the DC-DC converter, and initializes the display.
    2. DISPLAY CLEARING: During this phase, the display is busy clearing itself, the MCU is not needed.
    3. JPEG DECODE: The SD-Card is initialized,...
    Read more »

  • JPEG Decoding

    Manuel Tosone02/17/2021 at 15:53 0 comments

    The frames to be displayed will be stored on an SD-Card as a sequence of jpeg files. Considering the time it takes to refresh the display and that I want to maximize battery life, I decided to update the display every 24 minutes, showing only one every 24 frames. This will make the battery last 24 times longer. The display resolution is 600x448 and, since only one every 24 frames must be stored on the SD-Card, the storage requirement is 144MB/hour (with 60% quality). An average length of 90 minutes movie can be stored in 200MB.

    Time to implement a jpeg decoder and... I wrote my own from scratch. You see I want to learn something new with each project, this was the perfect opportunity for learning how jpegs work. The best resource that I can find on the subject is a video series entitled Everything You Need to Know About JPEG.

    If you are not familiar with how jpeg works here is a brief overview. The first step in the encoding process is to convert the image from RGB to YCbCr, each color component is encoded independently. Next, each color component is divided into blocks of 8x8 pixels, each block goes through to the encoding process independently. The encoding starts with the forward DCT that converts the 8x8 block into a frequency domain representation. After that, the quantization step removes high-frequency data, and then the entropy coding is used to more efficiently store the coefficients.

    JPEG Encoding/Decoding

    The decoding process works the same way only backward, it starts with the compressed data stream, the first step is to undo the entropy coding then the coefficients are dequantized and, after that, the inverse DCT returns an 8x8 block of pixels. The final step is to convert back from the YCbCr color space to RGB. 

    The tricky part is how to interpret the bytes in the file since to decode the compressed data more information is needed other than the compressed bitstream. To undo the entropy coding the decoder must have a copy of the Huffman table that has been used by the encoder and to dequantize, the decoder must have a copy of the quantization table. This information is encoded into the file and is separated by markers. Markers are two-byte codes that precede and identify a block of data.

    The implementation of a decoder on a microcontroller poses some challenges, there is not enough RAM for a frame buffer and so the pixels must be sent to the display as they are decoded. Fortunately, the way 8x8 blocks from each color component are interleaved makes this straightforward.

    The problem is that the pixels to the display must be sent in order from left to right top to bottom and the decoder produces 8x8 blocks of pixels instead. The solution is to have a small buffer, with the height of a block and the width of the screen. The decoder fills the buffer with pixels and, when it's full, it is sent to the display.

    To make the images look good with only 7 colors, before sending the buffer to the display, the Floyd Steinberg dithering algorithm is applied.

    The following video shows the display updating with some test images. It is noted that even if the display has only 7 colors, the dithering algorithm does a good job. If viewed from a couple of meters away the image looks almost perfect.

  • Display Test Fixture

    Manuel Tosone02/13/2021 at 16:25 0 comments

    Quick update on the test setup.

    I was tired of having the display and the development board floating around on the bench, I wanted to make some kind of a test fixture. My first thought was to 3D print something to keep it all together but I didn't want to design and 3D print a frame only to be used one time. The idea I came up with is to have a perforated base on which all the components are placed. The advantages of this are quite obvious, it is possible to rapidly move components around and it can be reused for future projects.

    The base is made of squares that can be joined together. Each square has a 15x15 grid of 6mm holes. The spacing between holes is 10mm

    The squares are joined with round pins.

    The display and the discovery board are kept in place by holders with pins on the bottom.

    The 3D models for this test fixture are available on this site. If you like the concept, feel free to use it for your own prototypes. For now, I only printed a holder for the discovery board, in the future I'll make holders for the boards that I'm working on.

    The following video shows the display mounted in the test fixture, as it goes through some test patterns.

  • Display Testing

    Manuel Tosone02/06/2021 at 19:13 1 comment

    Power Consumption

    Being this an ePaper display, it draws power only when the image is changing. When the display is in deep sleep mode, the datasheet gives a typical current draw of 1µA but it doesn't say anything about the power consumption during an update. The only thing it says is that the inrush current is 100mA. I guess that means that when the display comes out of reset and powers on it will draw up to 100mA, but that's not what I'm looking for, I want to know how much energy it takes to update the display.

    Panel DC characteristics

    To measure the current waveform, as the display is updating, I put a small resistor in series with the power supply and measured the voltage drop with an oscilloscope.

    Display test circuit

    The diagram on the left shows the test circuit.

    The datasheet specifies a typical inrush current of 100mA, with a  10Ω resistor the voltage drop will be 1V living enough margin. Plus having the resistance power of 10 makes the maths easier.

    Energy is measured in Joules 1[J] = 1[W]*1[sec], to compute the energy is just a matter of integrating the power over time.

    The breakout board for the display has an integrated LDO that regulates the input voltage to 3.3V. The quiescent current for the LDO is 130µA, it is so low that can be ignored, the current flowing through the resistor should be almost identical to that flowing into the display. In the final application, the display will be powred from 3.3V thus it is important to use 3.3V in the formula above otherwise we are taking into account the power that is dissipated by the regulator.

    Display power supply
    Display breakout board power section

    After connecting the oscilloscope I was able to capture some waveforms. Note that the scale is 20mA/div, I'm using a 1x probe across a 10Ω resistor, setting the probe multiplier on the oscilloscope to 0.1x makes it possible to read the current directly without conversion. It is also noted that the display draws current in bursts as it goes through the update sequence.

    Display update current

    display update current waveform

    Here is a video showing the update sequence. It is noted that as the display updates, it goes through more than 7 colors. Maybe it's possible to modify the lookup tables to increase the available colors or to change the displayable colors. Sounds like a future project ;)

    The datasheet specifies two test patterns, one for the typical and one for the maximum power consumption. To make it easy to display different patterns quickly, I wrote a simple command parser on the STM32 that listens for commands from the serial port and updates the display accordingly.

    Display test waveforms

    Typical Power Consumption

    The typical power consumption is measured as the displayed image changes from full white to the colored horizontal stripes shown in the picture above. Using the maths function of the oscilloscope it's straightforward to integrate the current during the update cycle. Using the cursors the total energy required is determined to be 0.864J.

    Maximum Power Consumption

    The maximum power consumption is measured as the displayed image changes from full white to a sequence of horizontal black and white lines. Applying the same procedure as above, the energy required is determined to be 1J.


    The typical and maximum energy required to update the display are respectively 0.864J = 240µWh and 1J = 278µWh.

    To wrap this up let's now roughly estimate how many update cycles we can get out of a battery. Since the rest of the circuit is not designed yet let's assume for now that the display is the only load. Let's also assume that we have a 2000mAh battery whose voltage is 3.3V. The energy stored inside the battery is

    Since the display uses 1J for each update the total number of updates is 23760. The display will be updated once every 24 minutes so the total run time is 23760 * 24 min = 396 days. This is in the ideal case where only the display draws power and at least shows that this display is...

    Read more »

View all 5 project logs

Enjoy this project?



Manuel Tosone wrote 02/20/2021 at 08:41 point

Thanks for the suggestion @Wayne but the problem is that this display doesn't support partial updates. The documentation provided by Waveshare states that the display must be completely cleared before every update.

The documentation doesn't specify what controller is used in the display, searching the internet I found that it can be an IST7106 but I can't confirm it because the datasheet is not available.

  Are you sure? yes | no

hatonthecat wrote 02/17/2021 at 18:09 point

Nice project! Glad to see the power consumption measured. 

  Are you sure? yes | no

Mike Szczys wrote 02/16/2021 at 15:57 point

I loved seeing @CNLohr build that color photo fame. Looking forward to where you go with this one.

I wonder if the refresh rate will be sufficient for 1 frame per minute? My slow movie player is still going (and I have some larger panels for a future upgrade) but I'm thinking of going to refreshing the frame every 24 minutes so there's not quite so much blinking.

  Are you sure? yes | no

Manuel Tosone wrote 02/18/2021 at 08:22 point

I was thinking the same thing, to refresh the display every 24 minutes, displaying only one every 24 frames. This will make the battery last 24 times longer. The update process takes roughly 30 seconds because the display must be cleared completely between every frame to prevent ghosting.

In the interest of increasing battery life, I'm thinking of implementing a light sensor to update the display only when it is visible and to use the RTC inside the microcontroller to stop updating the display at night.

  Are you sure? yes | no

Wayne wrote 02/19/2021 at 03:14 point

Have you considered preprocessing to avoid completely refreshing each time? I am thinking that if part of the scene remains static you could skip that area. Before uploading the frames you would run something like this on each adjacent one:

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates