M5stack is a distribution of esp32 devices – its like an Arduino with superpowers. I am building a hardware AI assistant for kids and am trying to make cores3s display an image from an sdcard. I’m copying official code from their online wysiwyg editor and it crashes:

What’s happening
This is the code that should work according to documentation:
M5.Lcd.drawImage("/sd/my_image.jpg", 0, 0)
And the device immediately crashes. No exception. No error message. Just a hard reset or frozen screen.
But here’s the weird part – you can read the image from SD just fine:
with open("/sd/my_image.jpg", "rb") as f:
data = f.read() # This works!
And you can display the image from flash storage without any issues:
M5.Lcd.drawImage("/flash/my_image.jpg", 0, 0) # This works!
It’s specifically the combination of drawImage() + SD card path that kills everything.
Why this happens
After much frustration, I figured it out: SPI bus conflict.
The LCD and the SD card share the same SPI bus on M5Stack devices. When drawImage() tries to simultaneously read from the SD card and write to the LCD display, it creates a bus conflict that crashes the device.
It’s not a bug in your code. It’s a hardware-level limitation in how the M5Stack firmware handles this operation.
The workaround
The solution is dumb but effective: copy the image to flash first, then display it from there.
import os
import M5
from M5 import *
from hardware import sdcard
def display_sd_image(sd_path, flash_temp="/flash/temp.jpg"):
"""
Display an image from SD card by copying to flash first.
Workaround for M5Stack SPI bus conflict.
"""
# Read from SD into memory
with open(sd_path, "rb") as f:
image_data = f.read()
# Write to flash
with open(flash_temp, "wb") as f:
f.write(image_data)
# Free memory
del image_data
# Now display from flash (this works!)
M5.Lcd.drawImage(flash_temp, 0, 0)
def setup():
M5.begin()
Widgets.setRotation(1)
# Mount SD card (CoreS3 SE pins)
sdcard.SDCard(slot=3, width=1, sck=36, miso=35, mosi=37, cs=4, freq=20000000)
# Display image using the workaround
display_sd_image("/sd/background.jpg")
def loop():
M5.update()
if __name__ == '__main__':
try:
setup()
while True:
loop()
except Exception as e:
print("Error: {}".format(e))
Yes, it adds latency. Yes, flash storage has limited write cycles. But it works, and until M5Stack fixes this in firmware, it’s what we’ve got.
Quick reference
| Operation | Works? |
|---|---|
open("/sd/image.jpg", "rb").read() | ✅ Yes |
M5.Lcd.drawImage("/flash/image.jpg", 0, 0) | ✅ Yes |
M5.Lcd.drawImage("/sd/image.jpg", 0, 0) | ❌ Crashes |
Notes for the future
- For large images, consider reading/writing in chunks to avoid memory issues
- Don’t put this in a tight loop unless you want to burn through your flash storage
- Tested on M5Stack CoreS3 SE with UIFlow2 MicroPython v1.25.0
- I’m building an AI voice assistant for M5Stack – and ran into this while working on the display system