Raspberry Pi Pico W and Pico 2 W

Overview

This tutorial demonstrates how Mongoose Library can be used to implement a device dashboard on a Raspberry Pi Pico W using the Pico-SDK with FreeRTOS and lwIP. It also works for the Pico 2 W.

This tutorial is an example following on the device dashboard tutorial. You should read and follow that tutorial first.

Project structure

This example uses the Pico-SDK and includes configuration files for lwIP and FreeRTOS:

  • main.c - main application file, contains Mongoose logic and WiFi network initialization code
  • mongoose.c - Mongoose Library source code
  • mongoose.h - Mongoose Library header file
  • net.c - the common code for this example
  • packed_fs.c - a packed filesystem containing the web files to be served
  • lwipopts.h - some lwIP config macros tweaked to suit this implementation
  • FreeRTOSConfig.h - some FreeRTOS config macros tweaked to suit this implementation, defining preferences, and stack and heap sizes
  • CMakeLists.txt - A cmake file that selects the source files and compilation options, including our choice of using FreeRTOS
  • Makefile - mainly pulls FreeRTOS and the Pico-SDK from their Github repos and calls cmake; but it is in this cmake invocation that we indicate for which board we are building

See the actual code examples:

Build the project

  • Follow the Build Tools tutorial to setup your development environment.

  • Start a terminal in the project directory; clone the Mongoose Library repository, and run the make command:

    git clone https://github.com/cesanta/mongoose
    cd mongoose/examples/pico-sdk/pico-w-picosdk-freertos-lwip
    make build
    

    For the Pico 2 W, do cd mongoose/examples/pico-sdk/pico-2-w-picosdk-freertos-lwip instead.

  • Once the build succeeds, boot your Pico W (or Pico 2 W) in USB Mass Storage Mode by holding down the BOOTSEL button while you plug it into the USB port. Once it is connected, then release the BOOTSEL button. It should automatically mount as a new USB disk in your machine. Now either manually copy or drag and drop the generated firmware.uf2 file into this new USB disk device.

  • The Pico W will flash this code and reboot, unmounting this disk and running the flashed code.

  • Now open a second terminal, this will be our serial console to see the logs. Run a serial port software (we use minicom; make sure you configure it at 115200bps). Device name in Linux is usually /dev/ttyACM0

    $ minicom -D /dev/ttyACM0
    

Try it out

Start a browser and connect to http://IP_ADDRESS where IP_ADDRESS is the board's IP address assigned by your DHCP server. You should see a login screen.

From here on, please go to the device dashboard tutorial and repeat some of the steps depicted there

Mongoose task

The mongoose() task has two blocks:

  1. Initialize WiFi and wait until the network is ready (DHCP has assigned us an IP address)
  2. Run Mongoose

Initialize the network

We call the function in charge of initializing the wireless chip, then call the WiFi connect function, which is a blocking function and returns when we have a valid IP address. We could also use another one that also returns if the process has taken too long

Run Mongoose

Next goes Mongoose. It should be run after network initialization is complete. The logic is standard; we initialize the event manager, start a listener, and fall into an infinite event loop:

For this example we have a function to start the listeners, and we've chosen to embed all the web files in a packed filesystem; more information on the embedded filesystem tutorial

Note that Mongoose has been configured to run under the Pico-SDK and lwIP, we do so in mongoose_config.h by defining:

#define MG_ARCH MG_ARCH_PICOSDK
#define MG_ENABLE_LWIP 1

We have covered those aspects that are specific to the Pico W implementation, for the details on the application and the UI, please see the device dashboard tutorial.

Main task

The main() function initializes the board and starts the FreeRTOS scheduler, creating a new task for us:

Configuring Pico-SDK

Pico-SDK is configured to use FreeRTOS and lwIP in the CMakeLists.txt file:

Configuring FreeRTOS

  • Task Memory allocation defaults to dynamic. This means that memory for the stack of each new task, will be allocated from FreeRTOS heap. To work with applications requiring a high stack size, FreeRTOS heap size must be large:
  • Mongoose needs a large stack, we specify that at the task creation function call (in words):

Configuring lwIP

  • Since we'll be using several connections simultaneously, we need to tell lwIP so. Even though we are using the socket interface, internally in lwIP it uses a decoupling API called netconn, so we'll set the number of allowed connections high enough:
    Make sure you don't disable LWIP_NETCONN, the default is for it to be enabled
  • The Pico-SDK arch we chose allows Mongoose to work using sockets, as it works with lwIP. We also need to define how much memory we are going to use for network buffers: