SkillAgentSearch skills...

Luapico

A programming environment for Lua for the Raspberry Pi Pico microcontroller

Install / Use

/learn @kevinboone/Luapico
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

picolua

A programming environment for Lua for the Raspberry Pi Pico microcontroller.

Version 0.3, April 2021

What is this?

picolua is a proof-of-concept Lua programming environment for the Pi Pico. As well as the Lua run-time, it includes a rudimentary shell that accepts Linux-like commands, a full-screen editor, and basic file management facilities. picolua is designed to be operated by connecting the Pico's USB to a terminal emulator. Lua functions have been added for controlling the Pico's GPIO and other peripherals. As a result, it is possible to enter and run simple programs that manipulate connected devices, without the need for any particular development tools. There is support for general digital input/output, analog input, PWM output, and I2C.

picolua has some conceptual similarities with MicroPython on the Pico. However, picolua is designed to be completely self-contained, in that no addition tools (other than a terminal) are required to create, edit, and test programs. It's possible (to some extent) to create and test Lua code on a workstation, and then upload it to the Pico. However, this isn't necessary -- picolua is capable of being self-contained.

picolua maintains a filesystem in the Pico's flash ROM, that can store multiple files, perhaps organized into directories.

There is a rudimentary command-line shell that provides a few Unix-like commands, for copying, viewing, and deleting files; and, of course, for running Lua code.

Most of the standard Lua features are available, except those that interact with an operating system. The Lua file handling routines have been replaced by alternatives specific to the picolua filesystem.

The shell

On startup, you will see the shell prompt $. I've used the dollar sign here to distinguish it from the Lua > prompt, and because the shell is a little like a Unix shell. There is a basic line editor for entering shell commands; these commands are similar to Unix shell commands -- cp, rm, mv, etc. The shell supports wilcard expansion ("globbing"), with the ? character matching any single character, and * matching any number of characters. So it's possible, and sometimes useful, to run commands like cp *.lua /backup. There is a full list of shell commands below.

As in Unix shells, any line that starts with a # is taken to be a comment. This is only useful in scripts (see below).

Running Lua on picolua

There are various ways to run Lua in picolua.

  1. Create the Lua file using the built-in editor, or upload it from a terminal using the YModem protocol (described below). Then run it using the shell command lua {filename}.

  2. Run the Lua file directly from the editor, by hitting the Ctrl+
    key combination.

  3. Start an interactive Lua session by running lua at the shell prompt. You can enter Lua code directly at the Lua prompt. From this prompt you can also invoke the editor, using pico.edit "filename".

  4. Run lua -e "lua code..." at the shell prompt.

  5. If the Lua file is in a directory which is in the search path (see "Search path" below), then you can just type the name at the prompt, without the .lua extension. So you can run '/bin/blink.lua' just be entering blink.

  6. Lua files can be grouped into modules, and executed using the require() function -- see "Lua modules" below.

Notes about the Lua implementation

picolua is based on Lua 5.4, and this will probably not change, given the number of changes that I had to make to it.

On start-up, picolua enters interactive mode. You can enter expressions, which are evaluated and displayed, or run a program using dofile or require. At the Lua prompt, you can invoke the (rudimentary) screen editor using edit "file.lua". One change from the conventional Lua interactive mode is that if the result is a table, the contents are displayed. This makes it possible to provide "commands" like ls "/dir" and df() -- these return a table, which gets displayed.

Standard Lua has only one numeric data type (at least, one only one that is accessible outside the Lua runtime). It can be set at compile time, but then it's fixed. At present, it is set to double -- double-precision floating-point. Many functions in the Pico interface of necessity take integer arguments. A GPIO pin number, for example, can only be an integer. Care needs to be take if using the results of calculations as arguments to these functions. At the time of writing, the Pico SDK includes double-precision floating-point support more-or-less as a matter of course, so there's little to be gained by trying to use lower precision.

The implementation uses one Lua context for the whole runtime. So any functions defined, or variables set, by executing a Lua file (e.g, by using dofile "file.lua") remain in effect. This is nearly always the expected behaviour.

As in regular Lua, a file can be loaded using dofile "file.lua" and require "file". There are subtle differences between these methods, that are described in the Lua documentation, and apply here too. Here, though, there's little need to use require, because there isn't a file search path.

Like all Lua functions, the Pico functions can be used without brackets when there is a single string argument. So it's correct to write edit "test.lua" as well as edit ("test.lua"). Although these functions are defined in a library called pico, and should probably be written pico.edit, pico.ls, etc., they are also defined in the global namespace as well, just for convenience.

Since there is no underlying shell, some of the Pico-specific functions provide shell-like functionality. There are functions for editing and copying files, for example, and querying system status.

Interrupts

Sending Ctrl+C should interrupt a running program. The same key is used to abandon a line in the line editor. Ctrl+C is not used to exit the screen editor; in fact, it has no function there -- not even "copy". See the Screen editor section for more information.

The filesystem

picolua maintains a filesystem in the PICO's flash memory. Filesystem storage starts a little after the program code, and extends, more-or-less to the end of the flash memory.

When you flash a .uf2 file on the Pico, only the flash areas specified in the file are re-written. Consequently, and intentionally, the picolua filesystem will survive re-flashing the program itself.

The filesystem supports files and directories, with names up to 255 characters. It has no notion of file permissions, ownership, timestamps, or links. This is to reduce the amount of storage used per file to a minimum.

Line editor

The line editor responds to cursor movement and backspace (delete on some keyboards) keys. Ctrl+Left and Ctrl+Right move the cursor by whole words. Ctrl+Home and Ctrl+End move the cursor to the start and end of the line respectively

Up-arrow and down-arrow scroll through a history of previous lines. By default, the history is limited to the last four lines. The line editor is nowhere near as sophisticated as that found in most Linux shells -- but it's a lot smaller.

Screen editor

The screen editor is fairly rudimentary, and designed specifically to operate from a serial terminal. Some of the key bindings are not very conventional, because I've tried to avoid key combinations that are taken over by terminal emulators and window managers.

The editor is invoked initially by running edit "filename". Thereafter, further files can be opened by sending Ctrl+O and entering a filename. If multiple files are open, you can switch between them using Ctrl+E.

To get a list of key bindings, send Ctrl+@. It would have been nice use Ctrl+H (for "help") but Ctrl+H usually generates a "backspace" keycode.

There are a few oddities that might be worth mentioning.

  • The key combination Ctrl+\ executes the file in the editor as a Lua program.

  • The usual Ctrl+C for "copy" has been replaced by Ctrl-Y, because I wanted to reserve the Ctrl+C combination for an interrupt throughout the environment.

  • If text is selected, the tab key indents the text two spaces. Shift-tab unindents by the same amount. If nothing is selected, the tab key simple enters a tab character.

  • The editor auto-indents using spaces. At present, this behaviour can't be turned off

Shell scripts

picolua does not have well-developed shell script support, because it's unnecessary -- you can run shell commands, should there be a need to, from a Lua script.

However, picolua does have a rudimentary notion of a shell script. A script if a file containing shell commands, one to each line. The shell will process the script line by line to the end, or until some command raises an error.

This facility is mostly intended for initialization.

Command-line arguments

When you run a Lua program from the shell prompt, you can pass command-line arguments if necessary. This mechanism works in Lua the same in regular Lua.

So we can execute a LUa program like this:

$ lua bin/myprog.lua hello world

or

$ myprog hello world

and in both cases the arguments "hello" and "world" are available in the Lua program as arg[1] and arg[2]. By convention, arg[0] is the name of the program.

Search path

The picolua shell has a rudimentary knowledge of search path. At start-up, the path consists (only) of the directory /bin. Any Lua file placed in that directory, with a name ending in .lua, can be executed at the shell prompt simply by entering the name, without the extension. So instead of entering lua /bin/blink.lua, we can enter blink.

The same principle applies to shell scripts. A shell script can be executed by entering only its name, if it is in the /bin directory, and has a name endring in .sh.

Lua modules

picolua supports Lua modules, as ordinary Lua does. However, the module search path contains

Related Skills

View on GitHub
GitHub Stars129
CategoryDevelopment
Updated14d ago
Forks10

Languages

C

Security Score

80/100

Audited on Mar 12, 2026

No findings