Skip to content

Instantly share code, notes, and snippets.

@anecdata
Created August 30, 2025 05:27
Show Gist options
  • Save anecdata/875e47c041452b28cb4cdbaf9705fba4 to your computer and use it in GitHub Desktop.
Save anecdata/875e47c041452b28cb4cdbaf9705fba4 to your computer and use it in GitHub Desktop.
CircuitPython Wi-Fi + Ethernet with PoE
# SPDX-FileCopyrightText: 2025 anecdata
# SPDX-License-Identifier: MIT
# Pimoroni Pico Plus 2W
# connected via Adafruit Proto Doubler PiCowbell to
# WIZnet W5500-EVB-Pico2 with WIZPOE-P1
# https://fosstodon.org/@anecdata/115115735846073971
# code is a simplified version of https://gist.github.com/anecdata/456524f8e38c207931afd0dedf6bec89
import time
import os
import traceback
import board
import busio
import digitalio
import wifi
import ssl
import adafruit_connection_manager
import adafruit_requests
from adafruit_wiznet5k.adafruit_wiznet5k import WIZNET5K
URLS = (
"http://wifitest.adafruit.com/testwifi/index.html",
"https://httpbin.org/get",
)
# wifi (native)
def connect_native(radio):
while not radio.connected:
try:
radio.connect(os.getenv("WIFI_SSID"), os.getenv("WIFI_PASSWORD"))
except Exception as ex:
traceback.print_exception(ex, ex, ex.__traceback__)
time.sleep(1)
return radio.ipv4_address
# WIZnet
wiz_pins = (
(
digitalio.DigitalInOut(board.GP17),
digitalio.DigitalInOut(board.GP20),
),
)
def connect_eth(radio):
return radio.pretty_ip(radio.ip_address)
# General
def connect(radio):
if radio.__class__.__name__ == "Radio":
ipv4_str = connect_native(radio)
elif radio.__class__.__name__ == "WIZNET5K":
ipv4_str = connect_eth(radio)
elif radio.__class__.__name__ == "ESP_SPIcontrol":
ipv4_str = connect_esp(radio)
return ipv4_str
time.sleep(3) # wait for serial
# LED
led = digitalio.DigitalInOut(board.LED)
led.switch_to_output(value=False)
radios = []
pools = []
ssl_contexts = []
requestss = []
connection_managers = []
# spi = board.SPI()
spi = busio.SPI(clock=board.GP18, MOSI=board.GP19, MISO=board.GP16)
# wifi (native)
print(f'Initializing native wifi...')
radios.append(wifi.radio)
# WIZnet
print(f'Initializing ethernets...')
for eth in range(0, len(wiz_pins)):
print(f'#{eth}')
cs = wiz_pins[eth][0]
rst = wiz_pins[eth][1]
mac = f'de:ad:be:ef:fe:{(251 + eth):02x}' # avoid DHCP collisions
while True:
try:
radio = WIZNET5K(spi, cs, rst, mac=mac, debug=False)
print(f'{mac} {radio.pretty_ip(radio.ip_address)}')
radios.append(radio)
break
except Exception as ex:
traceback.print_exception(ex, ex, ex.__traceback__)
# set up the socketpools and requests
print(f'Set up socketpools and requests...')
for radio_num in range(0, len(radios)):
pools.append(adafruit_connection_manager.get_radio_socketpool(radios[radio_num]))
ssl_contexts.append(adafruit_connection_manager.get_radio_ssl_context(radios[radio_num]))
requestss.append(adafruit_requests.Session(pools[radio_num], ssl_contexts[radio_num]))
connection_managers.append(adafruit_connection_manager.get_connection_manager(pools[radio_num]))
# requests on all the radios
while True:
print(f'{"="*25}')
for radio_num in range(0, len(radios)):
print(f'{"-"*25}')
for url in URLS:
print(f"Fetching from {url} via {radios[radio_num].__class__.__name__} #{radio_num} {pools[radio_num]} {connection_managers[radio_num]}")
print(f"{connect(radios[radio_num])}")
try:
with requestss[radio_num].get(url) as resp:
print(f'{resp.status_code} {resp.reason.decode()}')
except Exception as ex:
traceback.print_exception(ex, ex, ex.__traceback__)
led.value = not led.value
time.sleep(1)
@anecdata
Copy link
Author

anecdata commented Aug 30, 2025

dual-code.mov

🔌 USB power on both boards is protected with a Schottky diode upstream of VSYS. PoE power is similarly protected with a Schottky diode upstream of VSYS. I've left the 3V3 pins unconnected between the two boards, to keep the two LDO outputs separate. I've also left the VBUS (5V) pins unconnected between the two boards. If any of the three power sources are connected (PoE, or either USB-C), both boards will be powered via VSYS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment