Raspberry Pi Pico Wireless & CircuitPython

Was lucky enough to get my hands on a couple Raspberry Pi Pico W recently, and just finished up initial exploration.

I started with a by flashing the CircuitPython .UT2 to the pico, like always Adafruit has a phenomenal write up on just that.

Next I added copied in modules from the 8.x bundle, simply toss the following into your pico’s /lib/ directory:

$ ls -1 /Volumes/CIRCUITPY
boot_out.txt
code.py
lib
$ ls -1 /Volumes/CIRCUITPY/lib/
adafruit_httpserver.mpy
adafruit_requests.mpy

I also needed a .env file for wireless connections.

$ cat .env
WIFI_SSID=nessy
WIFI_PASSWORD=foobar

I then set out on writing a simple python app by starting a blank code.py on the pico, this file is what executes on device power-on.

import os
import wifi
import socketpool

# get wifi info from pico's env, which loads from `.env` file.
ssid      = os.getenv("WIFI_SSID")
password  = os.getenv("WIFI_PASSWORD")

wifi.radio.connect(ssid, password)
pool = socketpool.SocketPool(wifi.radio)

print("Your IP is: %s" % (wifi.radio.ipv4_address))

If everything is setup properly, you should get your DHCP issued IP address from your configured wireless access point.

Your IP is: 192.168.1.54

Next up we can expand upon our code.py script and confirm we have external internet access.

import ipaddress

external_ip = ipaddress.ip_address("8.8.8.8")
print("Internet reached with %sms round trip" % wifi.radio.ping(external_ip))

If successful you will receive the roundtime time:

Internet reached with 0.045ms round trip

At this point I began to get excited, I’ve worked with CircuitPython before, I’ve even worked with RaspberryPi Picos; however, this was the first time I’ve had internet access natively.

One of python’s most elegant http tool is requests, and we placed a request like module into our /lib/ directory early. Using this module lets do a simple GET to fetch our public ip address.

import ssl
import adafruit_requests

requests = adafruit_requests.Session(pool, ssl.create_default_context())
r = requests.get("https://icanhazip.com")

print("Your public IP is: %s" % r.content.decode('utf-8'))

And on success we should see just that:

Your public IP is: X.X.X.X

The last bit of testing was running a HTTP server using adafruit_httpserver.

from adafruit_httpserver import HTTPServer, HTTPResponse

server = HTTPServer(pool)

def get_networks():
    """Returns networks"""
    scan = wifi.radio.start_scanning_networks()
    networks = [ i for i in scan ]
    wifi.radio.stop_scanning_networks()
    return networks

def get_network_details():
    """Return network ssids"""
    networks = get_networks()
    return [ (i.ssid, i.rssi, i.authmode) for i in networks ]

@server.route("/")
def base(request):  # pylint: disable=unused-argument
    """Home page"""

    #return HTTPResponse(filename="static/index.html")
    return HTTPResponse(body=str(get_network_details()))

# Start the HTTP server
print("Starting web server")
server.serve_forever(str(wifi.radio.ipv4_address))

On success you can visit your pico’s website in a browser (http://192.168.1.54) and get a wifi scan of nearby access points:

$ curl -s http://192.168.1.54
[
  ('nessy', -38, [wifi.AuthMode.WPA2, wifi.AuthMode.PSK]),
  ('nessy-guest', -40, [wifi.AuthMode.WPA, wifi.AuthMode.WPA2, wifi.AuthMode.PSK])
]

All that from a Pico sized RaspberryPi!