Create Internet-Connected Gadgets with Anvil and the Pico W
The Raspberry Pi Pico W is a $6 microcontroller board with on-board WiFi. Anvil supports connecting the Pico to your Anvil apps via a cut-down version of the Uplink, that runs in MicroPython.
Quickstart
Get started with the Pico W by following the Getting Started tutorial.
The Anvil Pico W Firmware
There is an official Anvil build of MicroPython, which includes everything you need to get started with Anvil on the Pico W - including many of the Pimoroni libraries.
The Getting Started tutorial contains all the steps you need to get going, and this page describes how to use Anvil from your Pico W with the official Anvil Pico W firmware installed.
Connecting to your Pico W
The Anvil Pico W firmware configures your Pico W to appear as a Mass Storage device when connected to your computer via USB. There are two files on this volume by default:
boot.py
runs when the Pico W is powered up. In our firmware, this takes care of connecting to Wifi, so you will need to enter your Wifi credentials in this file.main.py
runs afterboot.py
, and is the main entrypoint for your app. In our firmware, this file contains a sample Anvil Uplink script by default. You should replace this will the code for your app.
Differences from the Anvil Uplink
The standard Anvil Uplink library is designed to run in full Python on a computer running Windows, OS X, or Linux, such as your laptop or a Raspberry Pi. The Pico W is a microcontroller without any operating system, so only a subset of the full Uplink functionality is available. To make the distinction clear, you import anvil.pico
instead of anvil.server
. The behaviour of most anvil.pico
functions does not exactly match those in anvil.server
. As MicroPython does not support threading (yet!), we make use of asyncio
to run multiple tasks at once. Note that in MicroPython, this is imported with import uasyncio
.
As with anvil.server
, you call anvil.pico.connect
to make an initial connection to the Anvil server, and then anvil.pico.call
to call server functions in your app. You can also decorate your functions on the Pico W with anvil.pico.callable
if you want to call them from your Anvil app on the web (although you should probably use anvil.pico.callable_async
- see below).
Only certain Python values can be passed to and from functions in MicroPython. See below for details.
Connecting to Anvil from MicroPython
Call anvil.pico.connect
in main.py
to connect to your Anvil app, providing your Uplink key as an argument:
import anvil.pico
anvil.pico.connect("<UPLINK-KEY>")
boot.py
of the official Anvil Pico W firmware, using ntptime.settime()
. If necessary, you can set the RTC manually yourself using the machine.RTC().datetime(...)
function.Unlike in the full Uplink library, the anvil.pico.connect
function blocks forever, running asyncio
tasks in the background to execute your Pico W program while also listening for function calls from your Anvil app.
To run your own program as well as connecting to Anvil, you can pass coroutines to anvil.pico.connect
via the on_first_connect
and/or on_every_connect
keyword arguments:
import anvil.pico
import uasyncio
from machine import Pin
led = Pin("LED", Pin.OUT, value=0)
# Blink the LED forever
async def my_program():
while True:
led.toggle()
uasyncio.sleep(0.5)
anvil.pico.connect("<UPLINK-KEY>", on_first_connect=my_program())
Alternatively, if you want full control over the asyncio
event loop, you can call anvil.pico.connect_async
instead. This will do nothing on its own, but returns an asyncio
coroutine for you to run manually:
import anvil.pico
import uasyncio
async def my_program():
anvil = anvil.pico.connect("<UPLINK-KEY>")
uasyncio.create_task(anvil)
# ... your code here ...
uasyncio.run(my_program())
Defining callable functions in MicroPython
Use the anvil.pico.callable_async
decorator to make your local async functions on the Pico W callable from your Anvil app:
import anvil.pico
@anvil.pico.callable_async
async def pico_fn():
return 42
anvil.pico.connect("<UPLINK-KEY>")
Providing an async function definition allows the Anvil connection to be maintained in the background, meaning you can make further calls to anvil.pico.call
from inside the function if necessary. It is possible to mark plain functions as anvil.pico.callable
, but be aware that these functions will have exclusive access to the microcontroller until they return, so further messages from the Anvil server will not be received in the meantime. We strongly recommend you use callable_async
instead.
The anvil.pico.callable_async
decorator supports the same arguments and keyword arguments as anvil.server.callable
. You can customise the name of the callable function, and require the user to be logged in in order to call the function. The anvil.users
package is not available in MicroPython, so await anvil.pico.get_user_email()
to get the email address of the currently-logged-in user (or None
if the caller is not logged in).
import anvil.pico
@anvil.pico.callable_async("my_pico_fn", require_user=True)
async def pico_fn():
print(f"pico_fn called by {await anvil.pico.get_user_email()}")
return 42
anvil.pico.connect("<UPLINK-KEY>")
Calling server functions from MicroPython
Functions defined in an Anvil server module can be made callable from the Pico W in the standard way: by adding the @anvil.server.callable
decorator:
@anvil.server.callable
def my_server_function(arg):
return arg
Use anvil.pico.call
to call server functions in your Anvil app from the Pico W. This is an async function, so must be awaited:
import anvil.pico
async def my_program():
x = await anvil.pico.call("my_server_function", 42)
anvil.pico.connect("<UPLINK-KEY>", on_first_connect=my_program())
Passing values to and from MicroPython
You can only pass simple, literal values to and from server functions defined in MicroPython. Anything that can be trivially encoded as JSON will work; rich objects will not. In particular, you cannot pass or return database rows, Portable Classes, or Media objects.
Troubleshooting
Sometimes after loading the Anvil firmware onto your Pico W and reconnecting it to your computer, the USB mass storage device fails to show up. When that happens we have found that fully wiping the Pico W flash memory and then reloading the Anvil firmware can fix the problem. See the section on resetting your flash memory in the Raspberry Pi Pico docs for instructions.
Do you still have questions?
Our Community Forum is full of helpful information and Anvil experts.