Sometimes I wonder, how did they do for just $6?

Some Stats

Chipset: RP2040 microcontroller with 2MB of flash memory
Wireless: single-band 2.4GHz (802.11n)
Port: Micro USB B port for power and data
Pins: Lots of them.

Chipset stats (RP2040): Dual-core cortex M0+ (up to 133 MHz), 264 kB multi-bank high performance SRAM, External Quad-SPI flash, 30 general purpose I/O.

Pinout

Useful Links

  • https://www.raspberrypi.com/documentation/microcontrollers/raspberry-pi-pico.html
  • https://www.raspberrypi.com/documentation/microcontrollers/micropython.html
  • Latest uf2 firmware: https://micropython.org/download/rp2-pico-w/rp2-pico-w-latest.uf2

My setup

  • Pycharm with Micropython installed
  • make sure to name your file “main.py”

Some Notes

First code

Webpage with internal temp, and LED status. Discord integrated. onboard LED controllable via webpage. No additional hardware required, just the Pico W and a Micro USB cable.

import network
import time
import machine
import uasyncio as asyncio
import urequests as requests

myssid = "{YOUR 2.4GHz WIFI SSID HERE}"
myssidpassword ="{YOUR 2.4GHz WIFI PASSWORD HERE}"
mydiscordwebhook = "{INSERT YOUR DISCORD WEBHOOK HERE}"


class MyWifi:
    ssid = ""
    password = ""
    discordwebhookurl = ""
    max_wait = 10  # in Seconds
    httpport = 80
    header = 'HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n'

    def __init__(self, ssid, password, discordwebhook):
        self.ssid = ssid
        self.password = password
        self.wlan = network.WLAN(network.STA_IF)
        self.led = machine.Pin("LED", machine.Pin.OUT)
        self.led.off()
        self.sensor_temp = machine.ADC(4)
        self.discordwebhookurl = discordwebhook

    def connect_to_network(self):
        self.wlan.active(True)
        # self.wlan.config(pm = 0xa11140) # Disable power-save mode
        self.wlan.connect(self.ssid, self.password)

        # wait for connect or fail
        while self.max_wait > 0:
            if self.wlan.status() < 0 or self.wlan.status() >= 3:
                break
            self.max_wait -= 1
            print("waiting for connection...")
            time.sleep(1)

        # Handle Connection Error
        if self.wlan.status() != 3:
            raise RuntimeError("network connection failed.")
        else:
            print("connected.")
            status = self.wlan.ifconfig()
            print('ip = ' + status[0])
            self.led.on()
            self.notifyDiscord("I am now online. IP: " + status[0])

    async def serve_client(self, reader, writer):
        print('client connected')
        request_line = await reader.readline()
        print("Request: ", request_line)
        # We are not interested in HTTP request headers, skip them
        while await reader.readline() != b"\r\n":
            pass

        request = str(request_line)
        led_on = request.find('/light/on')
        led_off = request.find('/light/off')
        print('led on = ' + str(led_on))
        print('led off = ' + str(led_off))

        if led_on == 6:
            print("led on")
            self.led.on()
            # stateis = "LED is ON"
            self.notifyDiscord("led is on")

        if led_off == 6:
            print("led off")
            self.led.off()
            # stateis = "LED is OFF"
            self.notifyDiscord("led is off")

        if self.led.value() == 0:
            stateis = "LED is OFF"
        else:
            stateis = "LED is ON"

        response = self.getHTML() % (stateis, self.getInternalTemperature())
        writer.write(self.header)
        writer.write(response)

        await writer.drain()
        await writer.wait_closed()
        print('client disconnected')

    @staticmethod
    def getHTML():
        html = """<!DOCTYPE html>
        <html>
            <head> <title>Pico W</title> </head>
            <body> <h1>Pico W</h1>
                <p>Hello Kai!</p>
                <p>LED Status: %s</p>
                <p>Internal Temperature: %s deg F</p>
                <a href="/light/on">
                    <input type="button" value="On">
                </a>
                <a href="/light/off">
                    <input type="button" value="Off">
                </a>
            </body>
        </html>
        """
        return html

    def notifyDiscord(self, text):
        print("sending discord the message:" + text)
        embed = {
            "description": text,
            "title": "Raspberry Pi Pico Light Status"
        }
        data = {
            "content": "Pico W #01 Status",
            "username": "Pico Light",
            "embeds": [
                embed
            ],
        }

        result = requests.post(self.discordwebhookurl, json=data)
        if 200 <= result.status_code < 300:
            print(f"Webhook sent {result.status_code}")
        else:
            print(f"Not sent with {result.status_code}, response:\n{result.json()}")

    def getInternalTemperature(self):
        conversion_factor = 3.3 / (65535)
        reading = self.sensor_temp.read_u16() * conversion_factor
        temp_c = 27 - (reading - 0.706)/0.001721
        temp_f = temp_c * 9 / 5 + 32
        return temp_f

async def main():
    test = MyWifi(myssid, myssidpassword, mydiscordwebhook)
    print('connecting to network...')
    test.connect_to_network()

    print('Setting up webserver...')
    asyncio.create_task(asyncio.start_server(test.serve_client, "0.0.0.0", test.httpport))
    while True:
        print("heartbeat")
        await asyncio.sleep(15)

try:
    asyncio.run(main())
finally:
    asyncio.new_event_loop()