ftDuino32 toy controller running MP, LVGL, Blockly etc

The ftDuino32 is meant to be an addon to the ftDuino controller (http://ftduino.de). which basically is a Arduino Leonardo prepared to interface with the fischertechnik construction toy.

The ftDuino32 is meant to give this (Micro-)Python, a nice touch screen interface and online/web based graphical programming using Blockly. In the end the users should be able to write and run simple (Python) programs to control their fischertechnik robots using nothing but the ftDuino32 and a browser.

The ftDuino32 currently features:

  • Micropython
  • LVGL based touch GUI to e.g. setup the network/wifi and to run local user programs
  • ESP-IDF based web server incl Websocket support
  • Blockly browser based graphical coding
  • Codemirror browser based text/python coding
  • Project management (delete, copy, download, upload, rename files and projects)
  • Live remote view of the ESP32 screen (“remote desktop”)

Find the code at https://github.com/harbaum/ftDuino32

Planned next steps:

  • Add LVGL related blocks to Blockly
  • Add ftduino toy control blocks to Blockly

Looks interesting, thanks for sharing!

Is there a video where we can see how Blockly programming works in the practice?

Not yet. But I’ll do one asap.

Currently I am adding some first LVGL related blocks and some simple “click this button to increase that counter” already works. I’ll make a video once this allows for a nice demo.

This is how a sample Blockly program currently looks like:

The resulting Python code can at any time be loaded into CodeMirror:

And finally the program can be startet from the browser. The program is actually running on the target device. The Live View mirrors its screen.

The code isn’t the nicest as Blockly does not support objects and all variables are global etc etc … but it works.

The whole generated code looks like this

# Blocky generated micropython for ftDuino32 controller

import lvgl as lv

def set_text(obj, str):
    if isinstance(obj, lv.label):
    elif isinstance(obj, lv.btn):
        label = lv.label(obj)

counter = None
lbl = None
btn = None

class Page:
    # name to be used in window title
    def title():
        return "My Little Test";

    def __init__(self, page):
        global counter,lbl,btn
        # set background color
        bg_style = lv.style_t();
        bg_style.set_bg_opa(lv.STATE.DEFAULT, lv.OPA.COVER);
        bg_style.set_bg_color(lv.STATE.DEFAULT, lv.color_hex(0xdddddd));
        page.add_style(lv.obj.PART.MAIN, bg_style);

        counter = 0
        lbl = lv.label(page);
        set_text(lbl, 'No clicks yet!');
        lbl.align(page, lv.ALIGN.CENTER, 0, (-30));
        btn = lv.btn(page);
        set_text(btn, 'Click Me!');
        btn.align(page, lv.ALIGN.CENTER, 0, 30);
        def on_event(obj, evt):
            global counter,lbl,btn
            if evt == lv.EVENT.CLICKED:
                counter = counter + 1
                set_text(lbl, ('Clicks: ' + str(counter)));
                lbl.align(page, lv.ALIGN.CENTER, 0, (-30));


Nice! Thanks for the info.
Please let us know if the video is ready! :slight_smile:

Little video here:



Very impressive! Thank you for sharing!

This still needs lots of improvements and especially some small text output so one can remotely watch the console output.

Some days of real life usage with this showed that I need an even simpler wrapper around LVGL, The kids e,g, expect to just “set a button” color and doing so they expect that various shades of that single color are automatically applied to the object and they don’t expect to have to care for different states. Another example is the alignment. If they center a label they expect it to stay centered even if they change the labels text.

So what I am doing now is to implement a l²vgl (lite little …) python module that does abstractions like this and provides an extremely simplified API based on such expectations.

And finally blockly is totally not aware of OO principles. So I can make this lite API non-OO to make the blockly generated code more readable.

In v8 both are solved :slight_smile:
lv_obj_align() realign the object is its size changes and there are lv_color_palettes to select a base color. See the widgets demo: https://lvgl.github.io/lv_sim_emscripten/

We are still updating the Micrpython port tough.

Excellent. This will be great.

In the meantime I’ve updated the simplified wrapper a little bit:

This results in much shorter and easier to understand Blockly generated code. Beforehand Blockly had to generate all kinds of wrappers and helper functions which would not allow a basic user to understand any of the generated Python code. A simple Blockly generated program now looks like below.

This still isn’t perfect and all this global variables handling Blockly introduces looks ugly. But at least the code is somewhat understandable.

from llvgl import *

btn = None
counter = None
lbl = None

def on_btn_clicked(btn,_e):
    global counter, lbl
    counter = counter + 1
    widget_set_text(lbl, ('Clicks: ' + str(counter)));

window_set_title('My Little Test', "#006600")
counter = 0
lbl = widget_new(TYPE.LABEL);
widget_set_text(lbl, 'No clicks yet!');
widget_set_align(lbl, None, ALIGN.CENTER, 0, -30);
btn = widget_new(TYPE.BUTTON);
widget_set_event_handler(btn, EVENT.CLICKED, on_btn_clicked)
widget_set_text(btn, 'Click Me!');
widget_set_align(btn, None, ALIGN.CENTER, 0, 30);

The result looks like this:


1 Like

Really looks simple!

We are thinking about integrating a Visual script engine into EdgLine. It’s great to see that Blockly works so well! :slight_smile: