RP2040 MicroPython: Developing Applications

7 minute read

Where I begin to develop applications for the RP2040 (Pi Pico and Pi Pico W) using Micropython.


In Getting Started, we created simple programs and used paste mode to enter the programs into the Pico storage. This works well for short programs and particularly well, for debugging. It will continue to be a valuable technique. That said, paste mode becomes cumbersome for developing longer programs and programs with multiple files. For this we want to be able to quickly upload a file or set of files, preferably remaining in our code editor.

Single File Build Process (Edit/Upload/Run)

The five applications I use for developing MicroPython programs are,

  1. Programming editor: Sublime Text 4 (ST4)
  2. Command Line Interface (CLI):Terminal on macOS or Git Bash on Windows
  3. MicroPython utility: mpremote
  4. Micropython cross-compiler: mpy-cross
  5. Serial monitor: CoolTerm


I recommend you use the keyboard for switching applications. For example, use CMD-Tab in macOS (or Alt-Tab in Windows) to switch between applications. I also recommend the three window programming setup as well. While the entry describes a C programming environment, the MicroPython setup would be the same, code editor, CLI and serial monitor.

  1. Edit the file in Sublime Text
  2. Switch to CoolTerm and disconnect it from the board (CMD-k)
  3. Switch CLI to use mpremote to upload the file (mpremote fs cp filename :main.py)
  4. Switch back to CoolTerm to reconnect (CMD-k) and view output
  5. Press reset button on Pico to automatically execute main.py

(A key feature of MicroPython, is that it automatically executes main.py upon boot. There are two programs which it will execute on boot, first, boot.py then main.py)

Write a few programs using the process above before you incorporate the automation in the next step. Its good to have a deep understanding of the process (and to develop the muscle memory) of editing -> uploading -> run application. There are applications in a section below and at this github site as good examples to explore.

Automated Build System with CoolTerm Disconnect (Optional)

This is an optional, however, very valuable step in setting you your system. As ST4 is a programmer’s editor, it has a powerful automation process in which to create executable programs from edited files. It can be found under Tools->Build System->.

This repository provides the details as to how to automate editing/uploading MicroPython programs using Sublime Text and CoolTerm. I recommend adding this automation as allows you to remain focused on your work, without having to manually switch windows. Follow the three steps in Installation, you only need to add the MicroPython build automation for this tutorial.

To use the MicroPython build system, ensure you have completed the following steps:

  1. In Sublime Text, check Tools -> Build System -> MicroPython
  2. In Windows Ctrl-Shift-B or macOS Cmd-Shift-B will bring up the MicroPython build command
    1. Select the main.py option if you wish to upload your program to the name main.py.
    2. Select the same name option if you wish to retain the name of the file.
    3. Use the third option Cross Compile if you wish to create a smaller, possibly faster version of your code
  3. If you find yourself with the same option each time, Ctrl-B/Cmd-B will re-execute the same build command option.


To start developing applications, open ST4, your CLI (Terminal/macOS or git-bash/Windows) and CoolTerm. Again, I’ll emphasize its best to use the three window programming setup.

In your CLI, follow the instructions here(Get the Lab Content), however, using this repository. You won’t need to perform the last step of creating a dev folder. The abbreviated steps are (if you are familar with using git and CLI):

# 1. In your browser, copy the repository address using the green Code button
# 2. In your CLI (from here on), navigate to your main folder, typically called Documents or MyDocuments
cd Documents
# 3. Clone the repository and navigate to it
git clone git@github.com:lkoepsel/mpython.git
cd mpython
# 4. Open the folder using ST4

Using the steps above or the automated build system, begin to develop applications. I recommend using the ones described below as a starting point. The programs below already exist in the mpython repository.


I was having issues having a prompt show up at the beginning of a program, the program seemed to be skipping my initialization code. After other tests, I realized it might be how I was calling print, so I wrote a program which would simply loop printing “hello world” with a delay. It seemed to work fine…until I realized I wasn’t sure when the first “hello world” was printing. I added a counter to determine, when the first print would appear:

# hello - simple test to show the time required to connect to serial monitor
import sys
import time

def Hello():
    i = 0
    while i < 100:
        print(f"{i*10}ms Hello, World!")
        i += 1

if __name__ == '__main__':

When I did that, my results were:

>>> 680ms Hello, World!
690ms Hello, World!
700ms Hello, World!
710ms Hello, World!
720ms Hello, World!
730ms Hello, World!
740ms Hello, World!
750ms Hello, World!
760ms Hello, World!
770ms Hello, World!
780ms Hello, World!
790ms Hello, World!
800ms Hello, World!
810ms Hello, World!
820ms Hello, World!

Oh, my. I was able to see the “Hello World!” only after the 680ms! I need to delay my print statements for about a second for the serial port to connect.

After a series of tests using the program stored on the Pico, it seems to depend on how the Pico is reset. (For this test to work with hardware reset, it must be saved as main.py, that step will be covered in the next entry.)

  1. Press reset button (hardware reset), it appears to be a delay of 550-850ms.
  2. Press Ctrl-d (software reset), and the prompt appears immediately

Keep this in mind when using the serial port to debug program execution. It is probably best to delay for 1 second time.sleep(1) before any serial input or output.

In the AVR_C content, we wanted to have a blink which would be interrupt driven. This would allow us to do other things while the LED is blinking. This program performs a non-blocking delay for our blinking led.

# blink_wo_delay - non-blocking blink using a timer
from machine import Pin, Timer

led = Pin("LED", Pin.OUT)
tim = Timer()

def tick(timer):
    global led

tim.init(freq=1.5, mode=Timer.PERIODIC, callback=tick)

While this seems like a trivial program, it ends up being quite valuable for indicating issues. For example, it is used in our wireless lan program to indicate states of execution.

Interactive Pin Test

This is the program, which had the non-printing header bug. With the fix from above, it is now a very capable program which tests any Pico (or Pico W) pin. The program will prompt for a pin number (1-40), if it is a GPIO pin, it will identify the GP number and will provide the capability to set the pin HIGH, LOW or BLINK (once). If the pin is not a GPIO pin, it will advise its name such as UART0 TX or GND, and await a new pin number. To exit testing the specific pin, enter 0 at the test prompt to select another pin.

I developed the program using another microcontroller board to provide a simple test on each pin, to ensure my soldering work as competent. For the complete code, see here.

Here is an example of the printout as I test pins 4 (GP02) and 15 (GP11).

Running Pin Test:
Tests: 0=> new pin 1=> High 2=> Low  3=> Blink once
Enter pin number (1-40) to test: 4
Pin 4 GP2  enabled as Output
Enter test to run: 1
Pin(GPIO2, mode=OUT)  is High
Enter test to run: 2
Pin(GPIO2, mode=OUT)  is LOW
Enter test to run: 3
Pin(GPIO2, mode=OUT)  will blink once
Enter test to run: 0
Running Pin Test:
Tests: 0=> new pin 1=> High 2=> Low  3=> Blink once
Enter pin number (1-40) to test: 15
Pin 15 GP11  enabled as Output
Enter test to run: 1
Pin(GPIO11, mode=OUT)  is High
Enter test to run: 2
Pin(GPIO11, mode=OUT)  is LOW
Enter test to run: 3
Pin(GPIO11, mode=OUT)  will blink once
Enter test to run: 0


This program comes from MicroPython and is a local system environment. This environment allows you to have a limited CLI on the Pico W to list files, remove files, copy files etc. You load this program not as main, however as upysh then call it using the REPL. For example, use steps or build to upload upysh to the Pico W. Once uploaded, in CoolTerm, enter from upysh import *, then follow the instructions:

MicroPython v1.21.0 on 2023-10-06; Raspberry Pi Pico W with RP2040
Type "help()" for more information.
>>> from upysh import *

upysh is intended to be imported using:
from upysh import *

To see this help text again, type "man".

upysh commands:
clear, ls, ls(...), head(...), cat(...), newfile(...)
cp('src', 'dest'), mv('old', 'new'), rm(...)
pwd, cd(...), mkdir(...), rmdir(...)

>>> ls('/')
      284 main.py
     2603 upysh.py

836k free
>>> pwd
>>> cat('main.py')
# hello - simple test to show the time required to connect to serial monitor
import sys
import time

def Hello():
    i = 0
    while i < 100:
        print(f"{i * 10}ms Hello, World!")
        i += 1

if __name__ == '__main__':

I’ve included a few commands to show the value of using this environment.

By now, you have been successful with uploading single file applications to the Pico. The next step is to increase your knowledge of mpremote and to utilize an utility for uploading multi-file applications, mpbuild.

Comments powered by Talkyard.