M5Stack Core2

at first glance

The product description of M5Stack’s new Core2 suggested correction of all hardware flaws of the Fire (see this earlier post), so I decided to give it a try and get me one, also because the Core2 has a capacitive touch screen.

The device arrived nicely packed and, like all M5Stack products, looks quite nice and well built. The included usb-C cable, although a bit short, enables you to get started right away.


The Core2 comes preloaded with a Factory-test application, showing some of its features. A first impression already revealed the following improvements compared to the Fire:

  • Separate (properly working) buttons for On/Off and Reset
  • No more unwanted noises from the speaker
  • Useless Grove port (exposing hard-wired PSRAM pins 16 & 17) has been dropped

And the most notable new features:

  • Capacitive touch screen (works great)
  • Real Time Clock (RTC)
  • Vibration motor
  • AXP192 Power Management Chip
  • I2S amplifier

There’s one design choice that I don’t understand. The broken out GPIO pins of the so called M Bus are hidden behind what looks like a simple plastic cover, but in fact this cover holds a circuit board that contains the microphone and the IMU sensor. Removing the cover can easily damage the circuit or its components, so I decided to leave it in place. That still gives access to the external I2C bus (pins 32 & 33) via the red Grove Port A (standard I2C pins 21 & 22 are internally used by the touch screen, the RTC, the IMU sensor and the power management chip).

In order to program the Core2 from the Arduino IDE, you have to:

Add the board via the Boards Manager. Make sure to add the following link to the ‘Additional Boards Manager URLs’ field (File->Preferences->Settings):


The board will then appear in the boards list as M5Stack-Core2.

Install the M5Core2 library. At the time of writing, I recommend to install it by importing a zip file from https://github.com/m5stack/M5Core2. Installing it via Arduino IDE’s Library Manager will give you an older version with the same version number! (version 0.0.1). The older version has a very basic Touch library, whereas the Github version supports multiple touch, drag, swipe etc. and uses an easier and more powerful API. Moreover, the newer touch.h file opens with an extended comment section that explains its usage in great detail. Very well done!

You may also have to install a driver for the CP2104 USB to serial chip, if your PC doesn’t already have it. It can be found here.

Although I’m still starting to explore the Core2 myself, here are some tips that may be useful for other starters.

Setting the RTC

The preloaded Factory-test application shows a button for setting the Real Time Clock, but that function is not implemented. I found a very well written sketch on Github that not only lets you sync the RTC with an NTP server, but also demonstrates basic touch functions (using the older touch library) in very readable code. It can be found here.

Use all features of the touch screen

As mentioned earlier, the comment section in touch.h of the newer library version (on Github) explains everything very clearly and even gives some examples. Note that the touch screen is larger than the LCD display: 320×280 pixels, so it can be used for emulating the three buttons on earlier models (note the red circles)

Control the green LED and the vibration motor

Both the green power LED and the vibration motor are controlled directly by the AXP192 Power Management chip. This small sketch continuously switches them on an off.

(the internal speaker can be enabled/disabled by similar commands, e.g. M5.Axp.SetSpkEnable (true); )

Using the TFT display

Under the hood, M5Stack uses Bodmer’s TFT_eSPI library. Once you have included <M5Core2.h>, the display object can be referred to as M5.Lcd. All TFT_eSPI methods will work fine on this object. Sprites can also be associated with it:

This means that existing ESP32 sketches that include the TFT_eSPI library can easily be ported to M5Stack versions that use the M5Stack library instead. Don’t forget to initialize the display by including the following line in setup() :

(the four parameters enable the display, SD slot, UART and I2C, respectively)

Using the AXP192 Power Management chip

A look at the file AXP192.h from the M5Core2 library shows an impressive list of status values that can be retrieved from this chip. There’s also a lot of useful functions, most of them with descriptive names. The ScreenBreath() function is supposed to set the display’s brightness, but it doesn’t work in my sketches…







View·Master goes 360°

Working on a couple of new display techniques, I turned my Webcam·View·Master into this endlessly looping 360° Panorama viewer. The results were smoother than expected.


The video shows the Seiser Alm – Punta d’Oro “Panocam” on my M5Stack Fire. The sketch will run on any ESP32 board with PSRAM, and the TFT display can have any size, since the downloaded webcam footage will be resized to make its vertical dimension match the display’s shortest side (‘landscape mode’, which makes sense here 😉 )

Reason why I used the M5Stack (with a 2″ display) for this video was its photogenic quality, but the Dolomite landscape definitely looks much better on my 2.2″ TTGO T4 v1.3 display. Partly responsible for the video’s pale colors is also my smartphone’s camera.

Now that I finished the prototype, the next step will be to use the buttons for selecting other panorama webcams and for pausing the pan movement.

3 * (esp32 + tft) = ?


ESP32 boards with a mounted TFT display can be so hard to resist that, in a moment of shameless weakness, I purchased three of them in one buy, without consulting reviews…


So here’s a report of my first acquaintances with these new Chinese kids on my block.


  LilyGO TTGO T4 v1.3

This board with 8MB PSRAM, an SD card slot and a 2.2″ TFT display makes development of graphics oriented sketches very convenient.

I2C pins are available via a connector (cable included). Unfortunately they didn’t break out the standard SPI pins to the 20 (inconveniently short) pin male header. On my board, different from what some internet pictures suggest, not GPIO25 but GPIO26 is broken out (labeling on the module is correct).

Compared with the LOLIN 2.4″ TFT shield, this display is a bit smaller (with the same resolution) and has no touch screen. Its 3 buttons allow for some basic feedback to the application. Build quality is excellent.

Driving the display was easy, but it took me some time to make it show images from an SD card. That’s because the board’s SD slot requires its own SPI bus on pins 2, 13, 14 & 15. Note that TFT_eSPI library’s standard user_setup.h file for this board contains the line #define USE_HSPI_PORT, making the display use HSPI (SPI2). This means that VSPI (SPI3) is available for the SD card. The following code snippets show how I got it working.

In the main section:


In setup():


EDIT (31-12-2020): after some tweaking, I managed to drive the board’s SD card reader over the SD_MMC bus in 1-bit mode, which is considerably faster than SPI. Now this small device can play full length videos in a 320×180 format!


The above code also shows that this board requires you to explicitely switch the backlight on. This can be done by writing HIGH to TFT_BL but I prefer the sigmaDelta method as shown because it lets you control the display’s brightness.

So far, my overall impression of this board and its manufacturer is positive. It would have been perfect with a more Dupont friendly header, including standard SPI pins. Price: €19.

  LilyGo TTGO T-Display v1.1.

The 1.14″ display has 240×135 pixels. To be honest, fontsize 1 starts to become a bit of a visual challenge here, but I do not intend to use this board for text anyway. Actually, I currently have no specific application in mind for it at all, but I’m sure I’ll find one.

Bodmer’s indispensable TFT_eSPI library supports its ST7789 chip, so I expected no less than turbo speed, especially with ‘only’ 32400 pixels to push. Although this ESP32 WROOM module has no PSRAM and less memory than the T4, there’s still enough memory available for double buffering the display.

Information on github is to the point and up to date, so in no time I ported my most recent Webcam·View·Master sketch to this mini display for testing the board.

Note that the real size of the display is only 2.5 x 1.4 cm!

Like with the T4 board, TFT_BL has to be set HIGH in order to switch the backlight on.

Price: €9. Definitely a bargain for an ESP32 with such a cute display. And it even has a LiPo charging circuit and comes with header pins and a battery cable. Make sure you have an usb-C to usb-A cable because that is not included.

M5Stack Core Gray

After my rather negative review for the M5Stack Fire, this purchase may be a bit surprising. Perhaps I secretly hoped that this Gray model wouldn’t have the same issues and annoyances, but that soon turned out to be false hope. Actually, it’s even more noisy than the Fire and my dacWrite(25, 0) trick doesn’t change that. It is, however, less sensitive to usb power issues during sketch uploads. No ‘brown out detections’ so far.

But then, ESP32 development boards don’t come any better looking than the M5Stack family. Once you can work around its electronic design flaws, the Gray makes a perfect housing for ESP32 gadgets, especially when combined with a matching standing base power supply, equipped with a DHT12 temperature and humidity sensor.

I found a DHT12 library and an example sketch for reading the DHT12 sensor here, but the example didn’t compile. Here’s a corrected version that displays temperature and humidity when an M5Stack Core model is put on the standing base.


Compared with the Fire, the Gray has no Neopixel led bars and no PSRAM, making three extra GPIO pins availabe for other purposes, including GPIO16 and GPIO 17 for UART communication. Its battery is only 150 mAh, but I don’t mind because I couldn’t resist that standing base either. Prices: €30 for the Gray and €7.50 for the standing base.


The two LilyGo boards were my first from this manufacturer (is Lily Zhong the Chinese LadyAda?). I like both displays, so they will not be the last TTGOs.

As for the M5Stack ecosystem: now that I have everything I need for making great looking gadgets, I don’t think I’ll invest in it any further. Maybe they should ask some seasoned analog nerd to improve their electronic design with a couple of dirt cheap components.




Currently ‘lockdown-ed’ at sea level, my thoughts often wander to the majestic heights of my beloved Alps. After visiting one of those Alpine webcam sites, I wondered if I could turn my M5Stack Fire into a handheld Alpenpanorama. Or, to reverse Francis Bacon’s words: if you can’t go to the mountain, then the mountain must come to you…

This project was a bit more challenging than expected, as showing JPEG-encoded web images on a 320×240 TFT display requires extracting, decoding and resizing binary data from a chunked-encoded http response. After two days of bit-wrestling, here’s the result:

The time interval between images was reduced for this video. Music: “Schwärzen-Polka”

At startup, the program reads a list of 60+ webcam links from my web server. This enables me to change the displayed webcams without updating the software. Once running, the middle button pauses/resumes the loop, the left button removes the currently displayed webcam from the loop and the right button restores the original webcam list.

Because these live photo webcams refresh their pictures every 10 minutes, this gadget continuously gives me an up to date view of places where I would so much rather be….

P.S. I recommend not to use the official M5Stack library. In this project, decoding jpeg images with Bodmer’s fast JPEGDecoder library became more than 3 times faster after I replaced M5Stack (that has TFT_eSPI built in) with native TFT_eSPI. This could very well be caused by their library’s interrupt based button functions that are also notorious for causing WiFi crashes.



M5Stack Fire


It looked like the perfect hardware for a couple of gadgets that I have in mind, but my enthusiasm for the M5Stack Fire development board quickly cooled down after my first experiments.

Meanwhile, I’ve been able to tackle most software issues, but it’s the hardware flaws that worry me most. My verdict is at the bottom of this post.


M5Stack is a clever concept, built around an ESP32 core that can be expanded by stackable (magnetic) modules. Also, special purpose units can be connected via Grove connector cables. A growing number of modules and units are available and it all looks very appealing indeed. But then, this is definitely an expensive way of prototyping.

I chose the Fire variant because it houses an ESP32 WROVER module with 16 MB Flash and 4 MB PSRAM. This is what you get:

  • 320×240 ili9342 display (M5Stack library uses Bodmer’s unrivaled TFT_eSPI)
  • 3 buttons
  • microphone
  • speaker (1 Watt)
  • 10 Neopixels
  • accelerometer MPU6886 (not an MPU9250!)
  • magnetometer BMM150
  • SD card slot (max. 16 GB)
  • 600 MAh battery
  • stackable charger module
  • plastic storage box with USB-C cable, hexagonal wrench and some LEGO…

At first, it looked like I had received a defective device that did nothing more than producing a ticking noise. It turned out that this behaviour occurs when the battery is completely empty, even if the module is powered by USB. Fair enough (once you know it).

The device comes pre-loaded with UIFlow firmware, a graphical programming environment. Apart from the self-started demo, I didn’t test it. Instead, I added the board and its official library to the Arduino IDE and uploaded one of my most hardware demanding sketches (Perrier Loop). Everything worked fine, but all colors were inverted. In sketches that use the original TFT_eSPI library, adding the following lines in the setup() section of your sketch fixes the issue:


The module’s speaker is a bit noisy: it cracks on ESP32 resets and hisses while the power/reset button is being pressed. For its price, I would have expected a better hardware design. Besides, I personally would have liked a more ergonomic power button and a more consistent on/off/reset behaviour.

When I tried the official library’s example sketch for reading the IMU sensors, the ESP32 crashed. It turned out that my Fire did not have the MPU9250 sensor that the example had been written for, but a MPU6886 and a BMM150 instead. Wonder why they never updated their 2.5 years old example.

After this crash, I was no longer able to upload new sketches to the Fire (A fatal error occurred: Timed out waiting for packet content…). I managed to fix it, but unfortunately this behaviour keeps returning. And there’s more strange behaviour, like on-board neopixels being lit while the running sketch doesn’t even use them,  as well as spontaneous beeps.

Things got worse: the power/reset switch stopt working after I had uploaded the library example WiFiSetting.ino sketch (that worked OK, by the way). The module would no longer switch off, despite many double clicks, executed at different intervals….

Finally, after lots of randomly clicking the button, the device appeared to be off, but could no longer be switched on…. The Serial monitor then showed that the ESP32 was actually still running, but also continuously crashing. This also blocked uploading new sketches completely 🙁

In the end, I had to remove the battery module. After reconnecting it, I managed to erase ESP32’s flash memory. Then I used a tool called M5Burner for uploading the original UIFlow firmware.

The error messages when the device is crashing in a loop seem to suggest that not all ESP32 strapping pins are properly being pulled up or down during boot:

flash read err, 1000
ets_main.c 371
ets Jun 8 2016 00:22:57

My provisional verdict, based on an ongoing struggle with (my copy of) the M5Stack Fire:



  • clever concept
  • nice look and mostly decent physical build quality
  • high quality 2″ display, supported by Bodmer’s TFT_eSPI library.


  • seriously flawed reset/power circuit!
  • noisy speaker (poor audio isolation; use dacWrite(25, 0); if you don’t need audio)
  • SD card slot not properly aligned
  • The official library’s interrupt-based button functions can crash your WiFi (and worse)
  • Grove port C  appears to be useless by design (hard-wired to PSRAM pins 16 & 17)
  • 5V tolerancy of Grove ports A and B (pins 21, 22, 26 & 36) remains unclear

This nice looking ESP32 toy may need a few electronic design changes to enhance its usefulness and stability. Until then, I’ll keep my distance from the Fire….