As a developer with a Python background but limited time to dive into the Vobot Mini Dock’s programming framework, I decided to take on the challenge of creating a custom metronome app for this compact, MicroPython-powered device. The Vobot Mini Dock, with its 320x240 LCD screen, single button, rotary encoder, and buzzer, offers a unique platform for building lightweight apps using the LVGL (Light and Versatile Graphics Library) framework. To streamline the process, I leveraged Cursor, an AI-powered coding tool, to generate and debug code efficiently, though tools like Claude Code or Gemini CLI would work similarly. Below, I share my experience, from setting up the environment to crafting a functional metronome app, complete with insights and code to help others get started.
Getting Started: Setting Up the Environment
The Vobot Mini Dock runs MicroPython and follows a specific app development template, which initially seemed daunting given my time constraints. However, the official documentation ( developer - Vobot Mini Dock ) and example repository ( https://github.com/myvobot/dock-mini-apps ) provided a solid starting point. I cloned the examples repository to my local machine to give Cursor context for the Vobot framework:
git clone https://github.com/myvobot/dock-mini-apps
I used Thonny IDE, a lightweight editor for MicroPython, to interact with the device. After connecting the Mini Dock via a USB-C data cable and enabling developer mode (by disconnecting and reconnecting the power), Thonny detected the device as an ESP32 running MicroPython. The /apps directory on the device is where custom apps live, and I created a new folder, myapps/metronome, for my project. Cursor was set up as my primary coding environment, with the cloned examples folder open to reference the hello_world sample.
Understanding the Framework with AI Assistance
The hello_world example (from the cloned repository) was a minimal app that displayed “Hello World” with a counter on the LCD screen. It introduced me to the core components of a Vobot app:
-
App Structure: Each app resides in its own folder (e.g., /apps/my_hello_app) with an _init_.py file defining metadata (NAME, ICON) and lifecycle methods (on_start, on_stop, on_running_foreground).
-
LVGL Basics: The app uses LVGL for GUI elements, like labels (lv.label) and screens (lv.obj), with asynchronous methods for event-driven updates.
-
Hardware Interaction: The Mini Dock has a rotary encoder (scroll wheel with a press function) and an ESC button, generating LVGL key events (lv.KEY.LEFT, lv.KEY.RIGHT, lv.KEY.ENTER, lv.KEY.ESC).
To ensure Cursor understood the framework, I provided this prompt:
I am developing a “metronome” app for Vobot Mini Dock, a device which runs MicroPython interpreter and has its special app development template. The “example/hello_world” folder is a minimum example, which shows “Hello World **” on the LCD screen and counting. Please understand how this example works.
I also shared details about the device’s input controls and supported fonts, as the Vobot framework uses custom components. For example, the encoder and button generate specific key events, and the device supports a limited set of fonts (e.g., font_ascii_18, font_numbers_72). Here’s a snippet of the context I provided:
The Mini Dock has 1 button and 1 encoder (scroll wheel and press button integrated). When operating buttons and encoders, LVGL will generate lv.EVENT.KEY events with key codes:
Encoder rotates clockwise (down): lv.KEY.LEFT
Encoder rotates counter-clockwise (up): lv.KEY.RIGHT
Press encoder: lv.KEY.ENTER
Press the ESC button: lv.KEY.ESC Example to use buttons:
python
def event_handler(e): e_code = e.get_code() if e_code == lv.EVENT.KEY: e_key = e.get_key() if e_key == lv.KEY.RIGHT: print("up") elif e_key == lv.KEY.LEFT: print("down") elif e_key == lv.KEY.ENTER: print("enter") elif e_key == lv.KEY.ESC: print("esc") elif e_code == lv.EVENT.FOCUSED: if not lv.group_get_default().get_editing(): lv.group_get_default().set_editing(True) scr.add_event(event_handler, lv.EVENT.ALL, None) lv.group_get_default().add_obj(scr) lv.group_focus_obj(scr) lv.group_get_default().set_editing(True)Supported fonts: font_ascii_10, font_ascii_14, font_ascii_18, font_ascii_bold_28, font_numbers_32, font_numbers_72, etc.
This context helped Cursor generate code tailored to the Vobot’s constraints, such as the 200KB app size limit and the need for async methods.
Designing the Metronome App
My goal was to create a metronome app that:
-
Displays the current BPM (beats per minute, default 120) and time signature (default 4/4) on the 320x240 screen.
-
Allows users to select and modify BPM, time signature, or a Start/Stop button using the rotary encoder.
-
Highlights the focused item (Start/Stop button by default) in orange-yellow.
-
Plays a buzzer sound at the selected BPM when the metronome is running.
-
Includes debug logs for button presses and focus changes to troubleshoot interactions.
I provided Cursor with this detailed prompt:
Let’s write a new program - “metronome” app in the folder: “myapps/metronome”. The app:
Has one screen as the start, which shows BPM selected, and “time signature” selected on the 320x240 screen;
User can press the button of the rotary encoder to select to make change on “BPM”, or “time signature”, or “Start/Stop”, and then change BPM or time signature by rotating the encoder; default BPM is 120, default time signature is 4/4; the focused item is on “Start/Stop” button which highlighted in orange yellow;
When the “Start/Stop” button is focused, user can press the button of the rotary encoder to start or stop the metronome;
When the metronome is running, the buzzer will play the sound of the selected BPM;
Please add some debug on event_handler(); I cannot see the effect when pressing the button or rotating, meanwhile the focus/defocus is not visible.
Cursor generated the following code, which I refined and tested. Below is the complete _init_.py for the metronome app.
Testing and Deployment
To test the app, I used the Vobot Mini Dock app development Docker container, which simulates the device environment:
bash
docker run \
--rm -it \
-v ./disk:/work/disk \
-v ./myapps/metronome:/work/disk/apps/metronome \
-p 80:80 \
vobot/mini-dock-app-dev:latest
I also deployed the app directly to the device via Thonny:
-
Created the /apps/metronome folder in Thonny’s file browser.
-
Uploaded _init_.py to this folder.
-
Navigated to the app on the Mini Dock’s menu (named “Metronome”) and launched it.
The app displayed BPM, time signature, and a Start/Stop button. Rotating the encoder cycled focus between fields, pressing the encoder toggled editing or started/stopped the metronome, and the ESC button switched focus. Debug logs in Thonny’s Shell (e.g., “Key event: 1”, “BPM increased to 121”) helped troubleshoot issues like focus not updating visually, which I fixed by refining the set_focus_style function.
Reflections and Tips
Using Cursor was a game-changer for rapid prototyping. Its ability to understand the hello_world example and Vobot’s custom components allowed me to focus on app logic rather than framework minutiae. Here are my key takeaways:
-
AI as a Co-Pilot: Cursor’s code suggestions were 90% accurate, but I needed to provide detailed prompts with hardware specifics (e.g., key codes, fonts) to avoid generic LVGL code.
-
Debugging: Adding print statements in event_handler was crucial for tracing button and encoder inputs, especially since focus changes weren’t initially visible.
-
Time Efficiency: From setup to a working app, the process took about 30 minutes, thanks to AI assistance and the clear Vobot documentation.
-
Future Improvements: I could enhance the app with actual buzzer integration (once I find the Vobot buzzer API), add visual beat indicators, or fetch tempo data via urequests.
For others looking to develop for the Vobot Mini Dock:
-
Start with the official examples and use Thonny for quick deployment.
-
Leverage AI tools like Cursor to generate boilerplate code, but validate against the device’s constraints (e.g., 200KB limit, no file I/O).
-
Check debug logs in Thonny to catch subtle issues like focus handling.
This project was a fun dive into vibe coding with the Mini Dock. The combination of Python, LVGL, and AI tools made it accessible and rewarding, even with minimal time. If you’re curious, try cloning the examples, tweaking this metronome app, or sharing your own Vobot creations!