# M5Stamp Flying Tiny Map: Controlling a Digital Map with a StampFly Drone
## Introduction
Drone controls and digital map controls are surprisingly similar.
When a drone moves forward, backward, left, or right, a map can pan in the same direction. When the drone turns, the map can rotate. A drone also has one degree of freedom that a ground vehicle does not have: it can move up and down.
This creates a natural mapping between flight controls and map controls:
- Move the drone forward, backward, left or right: **pan** the map
- Turn the drone left or right: **rotate** the map
- Ascend: **zoom out**
- Descend: **zoom in**
This project uses the control commands sent by the operator to control both an M5Stack StampFly and a digital map.
The map does not follow the drone’s measured position or actual flight path. Instead, the same operator input is interpreted in two different ways:
- as a flight command for the drone;
- as a map navigation command for the display.
I call this project **M5Stamp Flying Tiny Map**.
## From a Running Map to a Flying Tiny Map
Before building Flying Tiny Map, I had already created a project called Running Map.
In that project, a small ground vehicle controlled a digital map. Moving the vehicle corresponded to panning the map, while turning the vehicle corresponded to rotating it.
Extending this idea to a drone felt natural.
A drone uses a three-dimensional control system, so its vertical movement could provide an additional map operation. Ascending became zooming out, and descending became zooming in.
The idea was not to create a navigation display for a drone. It was to explore the structural similarity between controlling a moving machine and navigating a digital map.
## Adding a Display to StampFly
To create Flying Tiny Map, I wanted to attach a display directly to an M5Stack StampFly v1.1.
StampFly v1.1 uses an M5StampS3A as its controller. The M5Stack Cardputer Accessory Kit also includes an M5StampS3A and a small display.
Because both products use the same controller module, I wondered whether the display from the Cardputer Accessory Kit could also work with StampFly.
It did.
Here is why it works. The M5StampS3 and M5StampS3A have an 8-pin, 0.5 mm pitch FPC pad on the back of the module, reserved for a TFT display. On a Cardputer, that is where the screen connects. Those six signals are **not** brought out to the 1.27 mm pads that a carrier board
uses:
- G33: reset
- G34: register select (D/C)
- G35: MOSI
- G36: SCK
- G37: CS
- G38: backlight
StampFly uses 23 GPIO through the 1.27 mm pads: four motors, two ToF sensors, the SPI bus for the IMU and optical flow sensor, the internal I2C bus, a buzzer, an RGB LED and two Grove ports. **None of them is G33 to G38.** The display bus lives in a layer the flight board never touches, so there is no conflict at all.
The display operated correctly when attached to StampFly, and the drone was still able to fly with the display installed.
This was the biggest practical surprise of the project.
*The 1.14-inch display sits on the M5StampS3A. The map is centred on Akihabara Station. The left column shows altitude, zoom level, battery voltage and flight mode, plus the number of tiles composed and how long the composition took. The right column shows heading, frame rate, link state and the current latitude and longitude.*
## How It Works
The operator’s control input is sent to both the drone-control system and the map-control system.
For example:
- a forward command moves the drone forward and pans the map;
- a yaw command turns the drone and rotates the map;
- an ascent command raises the drone and zooms the map out;
- a descent command lowers the drone and zooms the map in.
The map responds to the command sent by the operator. It does not currently use the drone’s measured motion, altitude, orientation, or position.
This distinction is important.
Flying Tiny Map is not a drone-tracking map, and the position shown on the map does not represent the real position of the aircraft.
It is an experiment in translating one control system into another.
### Getting the map to render at all
Storing and drawing the tiles turned out to be the hard part, and every decision here came from measurement rather than guesswork.
The map is a pyramid of 125 raster tiles covering zoom levels 0 to 15 around Akihabara Station, 3 x 3 tiles per level. As JPEG at quality 50 the whole pyramid is **974 KB**, which fits in the 1.5 MB data partition that the stock partition table already reserves. Quality 50 is indistinguishable from quality 85 on a 240x135 panel, and it halves the size.
My first attempt put the tiles in a LittleFS filesystem. Reading one tile took **400 to 630 ms**, which made the whole idea unusable. Splitting the measurement showed that `open()` alone took 280 to 440 ms, and that it scaled with the size of the file being opened, which is not what a directory lookup would do. Rather than chase it further I dropped the filesystem, concatenated every tile into a single blob with a compiled-in index, and read it with `esp_partition_read()`. The same tile now loads in **0.7 to 1.6 ms**, several hundred times faster.
What remains is JPEG decoding, at 80 to 115 ms per 256x256 tile. That is not an optimisation problem: switching the compiler from `-O0` to `-O2` changed the decode time by 2 ms, because the decoder lives in a library and the project's build flags only reach the sketch. So the design works around it instead. The renderer composes a 192x192 north-up buffer only when the view actually moves, and rotation and fractional zoom are applied when that buffer is blitted to the screen. Holding the sticks still costs nothing at all:
[map] z14.00(14 x1.00) rot= 0 tiles=4 compose=308ms push=30886us recomp=1 push=1 /71 fps=4.3`recomp=1 push=1 /71` means that over 71 frames the tiles were composed once and the rotated blit ran once. Everything else was skipped.
The whole map runs as a task pinned to the second core at the lowest priority. The flight controller's 400 Hz loop was measured with the map task switching itself on and off every five seconds inside a single boot, and across thirty windows the worst-case loop period differed by 0.007 ms. **Adding the display and the map did not disturb the flight control at all.**
## What the Display Is Good For
Watching the map display while flying is difficult.
StampFly is not easy to operate, and the screen is small. During flight, the operator must pay attention to the aircraft rather than continuously reading the display.
This limitation was expected.
However, adding a display to StampFly is still useful.
While the drone is stopped on the ground, the display can show information about the aircraft and its current state. It provides a local interface without requiring a separate computer or smartphone for every status check.
The display experiment therefore produced two different results:
1. a visual demonstration of the Flying Tiny Map concept;
2. a practical way to add a status display to StampFly.
## Why I Built It
I did not initially attach a display to StampFly because I needed a status screen.
I attached it because I wanted to build a flying map.
The map concept motivated the hardware experiment. The hardware experiment then revealed that the Cardputer Accessory Kit display was compatible with StampFly and remained usable even when the aircraft was flying.
This is what I would like to share with two different communities.
For the M5Stack community, the practical discovery is that a display intended for an M5StampS3A-based Cardputer accessory can also be used with the M5StampS3A-based StampFly.
For the mapping community, the experiment proposes another way to think about map interfaces: movement through physical space and movement through map space can share the same controls.
## Limitations
The current project has several important limitations.
- The map responds to operator commands, not the drone’s actual movement.
- It does not use GNSS to show the aircraft’s real position.
- The map and the drone may diverge because of wind, control error, or differences between commanded and actual motion.
- The screen is too small to inspect continuously during flight.
- The project should not be treated as a flight-navigation or safety system.
- **The display is fragile.** It sits exposed on the top of the aircraft, which is the first thing to hit the ground in a crash. Mine failed after a number of flights. Reseating the FPC did not bring it back, so the panel itself had died. If you build this, leave slack in the FPC, secure it to the frame, and expect to replace the panel.
Flying Tiny Map is an experimental interface and a working physical demonstration, not an operational drone-mapping system.
## What I Learned
The control systems of drones and digital maps are more closely related than I had previously considered.
A ground vehicle can express map translation and rotation. A flying vehicle adds vertical movement, which can naturally represent scale.
I also learned that product compatibility can sometimes be discovered by following an idea that initially has no obvious practical purpose.
Without the motivation to create Flying Tiny Map, I probably would not have tried attaching the Cardputer Accessory Kit display to StampFly.
The artistic and conceptual experiment led to a practical hardware discovery.
## Future Work
Possible next steps include:
- displaying more detailed aircraft status information while the drone is on the ground;
- visualizing control inputs more clearly on the display;
- recording flight commands and replaying the corresponding map movement;
- comparing commanded movement with measured movement;
- using orientation or position sensors to create a map that follows the aircraft itself.
The current version focuses on the simplest form of the idea:
one control input, interpreted simultaneously as movement through the air and movement through a map.
## Software
The firmware is the official M5Stack StampFly flight control code with the map added as two
extra tasks. I deliberately did not touch the flight control path at all. The 400 Hz loop, the
Madgwick attitude filter and the PID gains are exactly as shipped, and the only change inside
the original code is two function calls at the end of `init_copter()` that start my tasks.
That constraint is what made the measurements above trustworthy. When the loop period looked
wrong I could prove it was not my fault, because I could switch my own code off at runtime and
watch the number stay the same.
Everything I added lives in four new files:
- `display.cpp` and `display.hpp`: the map. Tile lookup, the 192x192 north-up buffer, the rotated blit, the instrument panel, stick integration with automatic centre calibration, and ESP-NOW link loss detection
- `monitor.cpp` and `monitor.hpp`: a low rate status log over USB serial. This is what let me keep working after the display died
- `tools/make_pyramid.py`: fetches tiles, converts them to JPEG and builds the single blob plus a compiled-in index
Third party code and licences:
- StampFly flight control firmware: MIT, Copyright (c) 2024 M5Stack and Copyright (c) 2024 Kouhei Ito
- Bosch Sensortec BMI270 driver: BSD-3-Clause
- STMicroelectronics VL53LX driver: dual licensed GPL-2.0+ or BSD-3-Clause
- Map data: (c) OpenStreetMap contributors, ODbL. The tiles were rendered from OpenStreetMap, data with the osm-bright style on my own tile server
## Hardware
- **M5Stack StampFly v1.1** (27.6 g, ESP32-S3 based M5StampS3A, BMI270 IMU, BMP280 barometer, two VL53L3CX ToF sensors, INA3221 power monitor, four 716 coreless motors)
- **M5Stack Cardputer Accessory Kit v1.1**, used for its ST7789V2 1.14-inch 240x135 display (17.6 x 31 x 1.6 mm, 1.7 g). The kit also contains a spare M5StampS3A, which is convenient because the FPC connector is already fitted to it
- **M5Stack ATOM JoyStick**, the controller. Sold separately from StampFly
- 300 mAh / 320 mAh 1S high-voltage LiPo battery
- No extra wiring, no soldering, no additional components. The display plugs into the FPC
connector on the back of the M5StampS3A
## Resources
- StampFly v1.1: https://docs.m5stack.com/en/app/StampFly_v1.1
- StampFly flight control firmware (upstream): https://github.com/m5stack/M5StampFly
- Original flight control code by Kouhei Ito: https://github.com/M5Fly-kanazawa/StampFly
- Cardputer Accessory Kit v1.1: https://docs.m5stack.com/en/accessory/Cardputer_Accessory_Kit_v1.1
- ATOM JoyStick: https://docs.m5stack.com/en/app/Atom%20JoyStick
- Map tiles rendered with my own tile server (OpenStreetMap data, osm-bright style)








Comments