I’ve been looking forward to playing with an M5Stack for a few months – since it first came out, really (or at least since I became aware of this project). I have been interested in LoRa for a while, having a specific use for this technology in mind. At the same time, I need a self-contained solution: playing with “nude” platforms is fine when you’re not demoing a concept. However, when you meet potential investors and they see PCB and wires, or, worse, a Tupperware™ box, they tend to be a wee bit dubious.
So a clean, extendable [stackable, hence the name] design, with a nice case, a screen, and, added recently, a LoRa module and a 8,500 mAh battery? Gimme! By the time I had made up my mind, there were three core models out. The newer models have an MPU-9250 sensor, which is not something I need right now. There an extension that transforms the M5Stack into a Calculator, Gameboy, Micropython micro-computer called (quite an unfortunate name if you ask me) Faces. Looks like a cool product too. I have however little need for Micropython (I have one of the original PyBoard Micropython boards, which I supported on KickStarter if memory serves, but for what I need, Python isn’t good enough. I’ll stay a little closer to the iron…), I might, one day, buy one, and rip the Micropython firmware out, if I can figure out a way to use the keyboards (the Gameboy and the calculator keyboards are the most attractive for my use).
So finally I made up my mind and bought set of the original core, the LoRa module, and the battery module. They have two online stores [that I know of], one on AliExpress, and one on Taobao. Considering that:
- I not only live in HK, but I can see Shenzhen from my windows.
- I can have stuff shipped to a Shenzhen address.
- Taobao was 32% cheaper.
- I can read and write Chinese.
I placed my order with Taobao, for a whopping 336 CNY, 52 USD. The order was processed and sent within a couple of days, and I got it today morning. It came by SF Express, not just any 快递. And the goods were well packaged in a small envelope. Compare with a NodeMCU board:
Inside, each module is in its own sturdy plastic box. I’ll have some comments and suggestion about these, actually. Let’s have a look-see first:
So far so good. The boxes are sturdy, and deserve to be kept for later use. Inside, we have the modules, a USB cable (which gave me a lot of headaches – it didn’t work, and had me believe the VCP drivers didn’t work, grrr), some cables for prototyping, some stickers (including stickers for the three buttons), and two leaflets: a one-page Quick Start guide, and a longer, folder guide.
There are you issues with these leaflets. One, as I’m not a young man anymore, with tired eyes, they’re VERY hard to read. Ouchies. Two, some of the information is outdated. For instance, they give
putStr() as a function to draw a string on the LCD. No workee. I went through the M5 library‘s header files (who doesn’t like to read header files, right?), and
drawString() is what you need. Well, *I* need. The buttom functions are wrong too. The idea of a cheatsheet is great, and I’ll produce a (legible) one in a few days, once I’m done reading the header files. [EDIT: Done.]
But besides that, the leaflets are generally helpful. It helped also that I had been salivating about the M5 for a few weeks – I had read everything I could, I had installed the library. I was ready! 🙂
So what would be more helpful in terms of packaging is not a wider box, but a taller one. If the box for the Core was the same square as for the modules, but 3~5 times taller, we could put an assembled stack inside the box and close it. Whether for transport or for outdoors operation, it would be ideal.
Make a better leaflet. Or dispense with most of it. Put a QR Code (who types links, bro?) to your site, and please please please, steal my cheat sheet and put it up on your website (hint: start putting everything on github).
I have been working with Arduino and other IoT devices for a few years. I have all the drivers installed. On the M5 Forum and elsewhere, there have been complaints that upload doesn’t always work, especially on the older models. The current solutions are getting an older version of the SiLabs VCP drivers, or put a 2.2µf cap between ground and reset. The pins are accessible from the outside, so you have this cap sticking out of the case. A little unseemly, but that only when you need to upload. An ingenious Japanese user even soldered a cap inside the case, making it permanent and invisible.
When I plugged in the M5, nothing was detected. Hmmm. Tried with four Macs, two MacBook Air models, two MacBook Pro models, nada. Version 5, then downgrade to version 4, nada. Grrrr. I mentioned this, and the guys at M5Stack were responsive – but there was so much that they could do online of course… Usually the problem was with uploading, not the USB port per se. Then the M5 turned itself off: it wasn’t charging. Oops. Turns out, the Type-C cable, which was way too short, and would have gone to the trash anyway, was bad. One trip to Miniso later, and I was back on track.
The Factory Test. Yes, I hit buttons 3 and 1 twice. CACA. I’m childish.
After that all went well. I have been working with LoRa, LCDs and other stuff long enough to make everything work in literally minutes. I did have to poke around the header files, as I said (and you have to use
M5.Lcd, instead of the more generic SSD1306 code I have already installed, for my TTGO boards. With a different syntax. Grrr. But all in all, it took me an hour to (re)make a LoRa sender and receiver for testing. I started with a sender, attaching a BMP280 barometer sensor to the Grove port [I2C port]. The M5 started pumping out Temperature and Pressure data in a JSON packet, which my TTGO machines happily received and decoded. Bueno.
A better USB cable. and not 10 cm long, kkthxbai.
Now, since the M5 is self-contained, and I have a nice battery plugged in, that’s the machine I’m going to take around my neighbourhood, to test the range. So I put a simple sender sketch in one of my TTGO boards, sending every ten seconds a JSON packet with just a PING, UUID, and sendCount as data. Should be good enough for a test. Later on, when I start working on my mesh, I’ll buy more M5, which I’ll put in various places in my ‘hood that I know are our of range (at least for the weaker TTGO). I can only count on people’s honesty to leave them alone and not run away with them! 🙂
I wish I had included the GPS module in my order, as I could use it to plot geolocations while doing the testing. I have a Grove GPS module from SeeedStudio, which I can probably use in between. I don’t fancy the idea of having a cable and small board dangling out, but, oh well…
Uh oh, no. I forgot that on the ESP32 the SoftwareSerial library isn’t [officially] available, so using the I2C port for this won’t work. Which brings me to one of my gripes: there’s space on the frame for another Grover port (or two, if one wants to be greedy). Having at least a port for
Serial2 would be nice… I know all the pins are exposed on the base, but there’s gotta be a reason they used a Grove port for I2C (hint: because it’s friggin’ convenient).
I connected my SeeedStudio Grove GPS module on the base pins. The M5 started making a whistling sound – and not the man-seeing-a-pretty-girl kind of whistling. More like, some things inside the machine are not enjoying being interconnected-kind of death threat whistling. After a while it subsided, and only came back intermittently. Grrr. The base pins connections seem to produce a lot of noise, physical and electrical: I was getting a lot of garbled text, and wiggling the cables fixes it, sometimes only temporarily. There seems to be room from improvement here (and more argument for another Grove connector).
I uploaded sample code from Mikal Hart’s TinyGPS library, modified to make good use of the M5’s screen, and we were in business.
So my next order will have to include a GPS module then. I really like the idea of being able to able to do logging on the SD Card of GPS coordinates when doing LoRa tests. THAT brings me to two problems, one of which I might be able to fix, the other one not easily.
(1) Unless there is something wrong with *my* LoRa module (as opposed with the M5Stack LoRa module in general), the range is super bleh. I suspect[ed] the internal antenna (and tests show that it might be part of it), but I am getting ranges of 200 meters max, as opposed to 1.2 ~ 1.5 km with my small TTGO machines. Not cool. The first thing I did was disconnect the provided antenna, and use one of the spare antennas I had for my TTGOs. That “improved” the range to about 200 meters. Not exactly what I wanted. So I’ll do further testing, and maybe if I have time, and they’re willing, I’ll go see the guys at @M5Stack to see if we can look into it…
The LoRa module with its original antenna, disconnected, and the new one.
Let’s work on the LoRa module. I’m volunteering to go and see you guys, and help work on a solution. As it is now, your LoRa module (either the specific one I have, or in general) is useless.
Another problem is a software one, this time. There’s a convenient display-related command,
M5.Lcd.drawJpgFile [which, I realize now, isn’t in the cheatsheet. Will fix that in a moment!]. The main issue is that the ESP32 stack uses TJpgDec, which is a nice tiny library. This library however isn’t too refined, and borks on some images. Consider this use-case, which I had in mind for my geoloc LoRa testing:
- Test LoRa reception.
- Acquire GPS coordinates.
- Save RSSI and GPS coordinates to SD Card.
- Call up Google Maps to get a static map as JPEG.
- Save file and display on-screen.
Which I tried. Nnngggggnnnn. It worked very well up to saving the data to the SD card. But displaying the map doesn’t work. Turns out the library borks on Google Maps JFIF images. I’ve tried to use the ArduinoJpeg library instead, but there are incompatibilities, and I need to have a look at the code first.
I might also have a look at GIF decoders — they are usually lightweight — as Google Static Maps can be requested in JPEG, PNG and GIF formats. Another project for later…
While writing this (long!) review, I wrote a bunch of sample sketches, to see what this machine can do. Apart from LoRa, which so far is a disappointment (or let’s call it a challenge…), everything else works well. One of the main things I noticed is that the
M5Stack.h header makes my life (and my code) simpler. All this initialization crap you have to write in an Arduino sketch to setup SPI, Wire, SD, the TFT screen? No need. It’s done for you. Calling
M5.begin(); is about everything you need.
There is, however, a catch. Custom libraries that require the SD library, for instance (or SD_Anywhere, which is usually my favored flavor for Arduino projects), will barf on your shoes. They call
#include , or
#include , and that creates incompatibilities. It solved it by adding in the libraries that call incompatible stuff this code:
// If we're using an M5, don't include outside SD libraries.
Likewise, libraries that load UTFT or other TFT-specific libraries have to be shorted, BZZERT, so that they don’t mess up with your code. Remember, the M5 uses an ILI9341, which is pretty standard, and has a long list of features. And having a specific driver for YOUR screen (it’s not like you’re going to remove the ILI9341 and graft a new one…) saves space and time.
There’s also a lot that is not entirely exposed [at least in a obvious manner] by the M5Stack library. You have to look one floor down, in the ESP32 toolchain. For instance, you can set up the ESP32’s clock via SNTP. Does one really have to code all this by hand? Nah… Espressif has sample code to use LwIP SNTP. I was able to cut down a little on their code and make it more, well, M5Stacky, in a sample app that is growing beyond the reasonable… 🙂
I need to play more with that thing (and possibly buy a few more), but so far here’s my assessment.
The good stuff
- Most of what’s in the box “just works”. Old farts like me remember Apple & Microsoft raving about plug’n’play. Well then. Once the USB issue was solved, plug and play indeed.
- Bright screen. Generally good-quality build of the Core.
- Good central library that simplifies coding.
- Stacker design is a good idea, and the 2×15 pin + breadboard design is clever.
- Pins exposed on all four sides of the base is a good use of real estate. Remember, that thing is tiny.
- The three buttons. Good enough for many basic UI uses.
- The I2C Grove connector.
The less-good stuff
- Hit and miss stuff like crappy USB cable, LoRa reception, outdated info on a microscopic leaflet with printed URLs.
- Slightly flimsy build of the modules. I’m always fearful of breaking them when dismantling the stack.
- Whistling sounds when using the pins on the base.
- No Serial2 Grove connector.
- AFAIK, no way of turning off the M5Stack when charging it.
- Less than obvious “double-click” gesture to turn it off (instead of more obvious long-press).
- The company (or probably the single dude behind it) is not responsive, either on the M5Stack community or Twitter. Most questions stay unanswered, and posts on Twitter get liked/retweeted, but that’s it. I dunno if it’s a language issue, or El Jeffe being overworked, or what, but this has to change.
I’m quite happy, but still grumpy. I look forward to improvements, and will try to support where and when I can.