Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: MicroLua – Lua for the RP2040 Microcontroller (github.com/microlua)
121 points by rblank on Nov 3, 2023 | hide | past | favorite | 29 comments
MicroLua allows programming the RP2040 microcontroller in Lua. It packages the latest Lua interpreter with bindings for the Pico SDK and a cooperative threading library.

MicroLua is licensed under the MIT license.

I wanted to learn about Lua and about the RP2040 microcontroller. This is the result :)




The name made me think about Micro Lua for the Nintendo DS : https://www.gamebrew.org/wiki/Micro_Lua_DS

When I was 12-13 and had an R4 for my DS, I managed to install MicroLua and program some simple apps that showed shapes when the screen was touched in specific areas.

Looking at the page, I see it even has full Wi-Fi and Local Wireless support !


This is very cool! I'm curious if it'd be relatively straightforward to use Fennel‡ with MicroLua?

https://fennel-lang.org/


MicroLua currently compiles Lua files to binary at built time. It seems that Fennel is capable of transpiling to Lua source code, so it should be easy to add that step to the build process.


FTR, Fennel support was indeed fairly easy to add.

https://github.com/MicroLua/MicroLua/commit/b9dfa2407afe932b...


Whoa — that's amazing!


OpenWRT's LuCI WebUI, Torch ML, and embedded interpreters in game engines are also written in Lua.

Apache Arrow's C GLib implementation works with Lua. From https://news.ycombinator.com/item?id=38103326 :

> Apache Arrow already supports C, C++, Python, Rust, Go and has C GLib support Lua: https://github.com/apache/arrow/tree/main/c_glib/example/lua

LearnXinYminutes Lua: https://learnxinyminutes.com/docs/lua/

OpenWRT is a Make-based Linux distro for embedded devices with limited RAM and flash ROM, x86, and docker. OpenWRT is built on `uci` (and procd and ubusd instead of systemd and dbus). UCI is an /etc/config/* dotted.key=value configuration system which procd sys-v /etc/init.d/* scripts read values in from when regenerating their configuration when $1 is e.g. 'start', 'restart', or 'reload' per sys-v. LuCI is the OpenWRT web UI which is written in Lua; which is now implemented mostly as a JSON-RPC API instead of with server-side HTML templates for usability and performance on embedded devices.

Notes on how to write a LuCI app in Lua: https://github.com/x-wrt/luci/commit/73cda4f4a0115bb05bbd3d1...

applications/luci-app-example: https://github.com/openwrt/luci/tree/master/applications/luc...

openwrt/luci//docs: https://github.com/openwrt/luci/tree/master/docs

https://openwrt.org/supported_devices

It's probably impossible to build OpenWRT (and opkg packages) for an RP2040W.


Yes, it's impossible (i'm dev on OpenWRT) because it build toolchain first then, Linux kernel, drives and userland apps.


> probably impossible

https://github.com/raspberrypi/pico-sdk/ links to a PDF about connecting to the interwebs with a pi pico: "Connecting to the Internet with Raspberry Pi Pico W" https://rptl.io/picow-connect

micropython/micropython//ports/rp2/boards/RPI_PICO_W: https://github.com/micropython/micropython/tree/master/ports...

micropython/micropython//lib: https://github.com/micropython/micropython/blob/master/lib

micropython/micropython//examples/network/http_server_simplistic.py: https://github.com/micropython/micropython/blob/master/examp...

micropython/micropython//examples/network/http_server_ssl.py: https://github.com/micropython/micropython/blob/master/examp...

raspberrypi/pico-sdk//lib: btstack, cyw43-driver, lwip, mbedtls, tinyusb https://github.com/raspberrypi/pico-sdk/tree/master/lib

raspberrypi/pico-examples//pico_w/wifi/access_point/picow_access_point.c: https://github.com/raspberrypi/pico-examples/blob/master/pic...

There's an iperf opkg pkg, or is it just netperf (which works with the flent CLI and GUI)?

raspberrypi/pico-examples//pico_w/wifi/iperf/picow_iperf.c: https://github.com/raspberrypi/pico-examples/blob/master/pic...

raspberrypi/pico-examples//pico_w/wifi/freertos/iperf/picow_iperf.c: https://github.com/raspberrypi/pico-examples/blob/master/pic...

FreeRTOS > Process management: https://en.wikipedia.org/wiki/FreeRTOS#Process_managememt

elf2uf2: https://github.com/raspberrypi/pico-sdk/tree/master/tools/el...

adafruit/circuitpython//tests/micropython: https://github.com/adafruit/circuitpython/tree/main/tests/mi...

adafruit/circuitpython//tools: https://github.com/adafruit/circuitpython/tree/main/tools

adafruit/circuitpython//tools/cortex-m-fault-gdb.py: https://github.com/adafruit/circuitpython/blob/main/tools/co...

RP2040 > Features: 2x ARM Cortex-M0 https://en.wikipedia.org/wiki/RP2040#Features


There is a Lua for the ESP8266 (nodeMCU) - I wonder how much difference there is


It looks like noceMCU uses Lua 5.1.4 or Lua 5.3.5, while MicroLua uses 5.4.6.

Other than that, nodeMCU is much more advanced :)


Does Lua have primitive arrays now? When I looked at it some years ago, it seemed to support only hash maps, and arrays were emulated using hash maps, which I found to be completely bizarre. There were discussions online where Lua folks were saying, no, you don't really need arrays. And I'm thinking to myself, hell yeah, I really needs arrays on resource-constrained microcontroller systems without garage collection.


If a table is contiguously indexed by integers from 1, the storage is optimized into an array.


That discussion must have been really long ago, otherwise you missed the point. Since Lua 5.0 (2003) tables are implemented as a pair of an array and a hashmap, and the array part can even handle small nil gaps. So tables used as arrays are implemented as arrays as well.


Yeah, tables serve as both lists and maps. You can even have a table with _both_.


This is very cool. Thanks for sharing this.

I have wanted to do something similar for either an existing language or a subset of such or for a minimal language I create. Do you have any suggestions on how to get started on that in terms of high-level steps?


I can't really give advice for creating a new language, or even for creating a new implementation of an existing one. MicroLua uses the existing Lua implementation from lua.org, and just packages it to make it useful on a specific platform.

For that, it helps if the existing implementation is already cross-platform and has few dependencies. Lua is great in this respect, as it only depends on a libc. The first step is to get it to compile for the target platform and have it execute a hard-coded "hello world" script. After that, it's only a matter of adding more libraries, one at a time.


There's also a Lua that runs on AVRs: https://code.google.com/archive/p/ulua/

I think it's inactive now, though.


How does it do in performance/efficiency? (Lua is pretty low overhead, but I guess for something embedded like this maybe latency in responding to an input, rather than a "normal" benchmark, would make more sense?)


I haven't run any benchmarks yet, and TBH performance isn't a high priority, but event dispatch latency is currently fairly bad, between 100 and 150 us (when overclocking the Pico at 250 MHz). It feels like it should be possible to bring it down to <30 us. I suspect the bad latency is due to my very naive implementation of thread scheduling and timers.


Another Lua implementation for MCUs posted recently:

https://news.ycombinator.com/item?id=38067457


I can't get my head around a 1 based language.


It helps if you realize that there are no arrays in Lua. Instead, everything is an optimized hash map that can be indexed by any value of any type. A single table can have some elements indexed by integers, others indexed by strings, function pointers (useful for a table of debug hooks), etc.

The few convenient things that expect tables to be indexed using integers starting at 1 are the # operator to get the number of elements, and the ipairs function, used in the common idiom “for index, value in ipairs(t) do . . . end”.


Normally education or human oriented languages start arrays at 1 (Smalltalk, Cobol, Lua, APL, Wolfram, etc) while hardware oriented languages start arrays at 0 (C and friends, Oberon, Forth, Scheme and so on). Human oriented languages that have to play nice with C also tend to use 0. As do Python and Basic, which contradicts my rule.

Probably the number one reason not to start arrays at 0 in an educational language is that having the last element of an array of size 10 have an index of 9 causes quite a bit of confusion.


I have to admit that this was one reason why it took me so long to start a project with Lua. Now that I've had some exposure to the language, I can say that it's not as bad as it seems, but it's also not "nothing". I frequently have to think about indices to avoid making mistakes in Lua, while in zero-based language indexing is pretty much muscle memory.


I can give you some tips to help; Tip #0 ..,.


Oh good! Any plans to include fennel? It would be awesome to have another embedded LISP-like language.


You've got an eye for detail. Impressive work!

Roughly how long did it take you to get to this point?


Thanks for the kind words :)

I've been working on this in my spare time since March, so roughly 8 months.


Worth mentioning eLuaProject, seemingly abandoned now.

https://eluaproject.net/




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: