本文为 WIZnet W55RP20 开发板 MicroPython 教程,基于官方最新固件编写,聚焦MQTT协议与ThingSpeak平台对接,流程均经过实际验证,代码可自行编写适配。
前言
上一篇教程中,我们已经完成了 MQTT 协议与ONENET 的开发,实现了设备上云、物模型数据定时上报与云端监控,而Thingspeak凭借注册即用,无需配置服务器,双协议支持,数据格式灵活等特点受到越来越多人的喜爱。
本文将带你从零开始,完成W55RP20的MicroPython环境配置、MQTT协议调试,以及与ThingSpeak物联网平台的对接,实现自定义温湿度数据的定时上报。
学完本文,你将掌握:
W55RP20的硬件了解与开发环境配置
MicroPython中SPI接口初始化与网络配置(DHCP/静态IP)
MQTT协议基础配置与ThingSpeak平台对接
常见故障排查与调试技巧

系列教程学习路径
本专栏共 16 篇,循序渐进覆盖 W55RP20-EVB-Pico 模块 MicroPython 开发全流程:
- 第 1 篇:静态 IP 配置与网络基础
- 第 2 篇:DHCP 自动联网与网络诊断
- 第 3 篇:TCP Client 客户端通信
- 第 4 篇:TCP Server 服务端通信
- 第 5 篇:UDP 单播数据通信
- 第 6 篇:UDP 组播/广播数据通信
- 第 7 篇:DNS 域名解析
- 第 8 篇:NTP 从网络获取时间
- 第 9 篇:HTTP Client 客户端请求
- 第 10 篇:HTTP Server 服务端搭建
- 第 11 篇:HTTP 协议与 OneNET 平台数据上云
- 第 12 篇:MQTT 协议基础通信验证
- 第 13 篇:MQTT 协议与阿里云平台对接
- 第 14 篇:MQTT 协议与 OneNET 平台对接
- 第 15 篇:MQTT 协议与 ThingSpeak 平台对接 (本文)
- 第 16 篇:Modbus 工业协议通信
建议收藏本专栏,跟随教程逐步学习,所有代码均会同步更新至官方 Gitee 仓库
目录
[1. 准备工作](#1. 准备工作)
[1.1 软件准备](#1.1 软件准备)
[1.2 硬件准备](#1.2 硬件准备)
[2. 烧录 W55RP20-EVB-MKR 模块专属 MicroPython 固件](#2. 烧录 W55RP20-EVB-MKR 模块专属 MicroPython 固件)
[3. 硬件连接与开发环境配置](#3. 硬件连接与开发环境配置)
[3.1 硬件连接](#3.1 硬件连接)
[3.1.1 基础连接(供电+调试)](#3.1.1 基础连接(供电+调试))
[3.1.2 以太网连接](#3.1.2 以太网连接)
[3.1.3 模块与开发板接线](#3.1.3 模块与开发板接线)
[3.2 Thonny 开发环境配置](#3.2 Thonny 开发环境配置)
[4. ThingSpeak平台操作流程](#4. ThingSpeak平台操作流程)
[5. 示例流程讲解](#5. 示例流程讲解)
[5.1 程序流程图](#5.1 程序流程图)
[5.2 测试准备](#5.2 测试准备)
[5.3 连接方式](#5.3 连接方式)
[5.4 相关代码](#5.4 相关代码)
[5.5 烧录验证](#5.5 烧录验证)
[6. 常见问题一站式排查指南](#6. 常见问题一站式排查指南)
[6.1 烧录相关问题](#6.1 烧录相关问题)
[6.2 网络连接问题](#6.2 网络连接问题)
[6.3 MQTT对接问题](#6.3 MQTT对接问题)
[7. W55RP20核心优势](#7. W55RP20核心优势)
[8. 典型应用场景](#8. 典型应用场景)
[9. 系列预告与资源获取](#9. 系列预告与资源获取)
[9.2 资源获取](#9.2 资源获取)
1. 准备工作
1.1 软件准备
所需软件均为免费版本,按要求下载安装即可,无需额外付费。
| 软件名称 | 版本要求 | 下载地址 | 说明 |
|---|---|---|---|
| Thonny | 4.0 及以上 | Thonny 官方下载 | 轻量级 MicroPython IDE,支持代码编辑、烧录与串口调试,新手友好 |
| W55RP20-EVB-MKR 模块MicroPython语言驱动库 | 最新稳定版 | WIZnet 官方固件/驱动库下载 | 专为 W55RP20-EVB-MKR 模块编写,已集成 WIZnet 硬件驱动、TCP/IP协议栈及MQTT客户端库 |
| 串口调试助手(如SecureCRT) | 任意版本 | 官方下载或第三方工具 | 用于查看串口输出的运行日志、调试信息,定位连接和数据上传问题 |
| ThingSpeak物联网平台 | 在线版 | ThingSpeak物联网平台官网 | 创建通道、获取MQTT设备凭证,查看上传的温湿度数据及趋势图表 |
1.2 硬件准备

- W55RP20-EVB-MKR × 1
- Micro USB 数据线(必须支持数据传输,不能使用纯充电线)× 1
- 标准网线 × 1
- 开启 DHCP 功能的路由器 / 交换机 × 1(用于获取网络参数,实现 DNS 解析)
W55RP20-EVB-MKR 模块已集成以太网相关器件,无需额外焊接飞线,配合 RP2040 开发板可快速搭建开发环境,大幅降低接线错误和硬件故障概率。
2. 烧录 W55RP20-EVB-MKR 模块专属 MicroPython 固件
W55RP20-EVB-Pico 模块 完全兼容树莓派 Pico 的 UF2 固件烧录方式,操作简单无需额外烧录器,新手可快速上手:
- 按住 RP2040 开发板上的 BOOTSEL 按键不放;
- 使用 Micro USB 数据线连接开发板与电脑;
- 待电脑识别出名为 RPI-RP2 的 U 盘后,松开 BOOTSEL 按键;
- 将下载好的 W5500_RP2040_firmware.uf2 固件文件拖拽到 U 盘中;
- 开发板会自动重启,固件烧录完成。
注意:如果电脑没有识别出 RPI-RP2 U 盘,请尝试更换 USB 数据线、重新插拔开发板,或更换电脑 USB 接口(优先使用 USB 2.0 接口)。
3. 硬件连接与开发环境配置
3.1 硬件连接
W55RP20-EVB-MKR 模块连接分为两步,分别实现供电/调试和以太网连接,操作简单,无需复杂接线:
3.1.1 基础连接(供电+调试)
使用 Micro USB 数据线连接 RP2040 开发板与电脑,用于开发板供电、代码烧录和串口调试。
3.1.2 以太网连接
使用网线连接 W55RP20-EVB-MKR 模块的以太网接口与路由器的 LAN 口(或直接连接电脑网口,需手动配置电脑 IP 与开发板同网段)。
3.1.3 模块与开发板接线
若使用分离式模块与开发板,需按以下引脚对应连接(SPI 通信):

3.2 Thonny 开发环境配置
打开 Thonny 软件,按以下步骤配置开发环境,确保代码能正常烧录和运行:
- 点击顶部菜单栏「运行」→「配置解释器」;
- 切换到「解释器」选项卡;
- 在「解释器」下拉列表中选择 MicroPython (通用);
- 在「端口」下拉列表中选择开发板对应的串口(通常显示为 Board CDC @ COMx);
- 勾选「运行代码前先重启解释器」和「同步设备的实时时钟」;
- 点击「确定」完成配置。
如果端口列表中没有出现开发板,请尝试:
重新插拔 USB 数据线;
更换支持数据传输的 USB 数据线;
关闭其他占用串口的软件(如串口助手、Arduino IDE 等);
重新烧录 MicroPython 固件;
安装树莓派 Pico USB 驱动。
4. ThingSpeak平台操作流程
ThingSpeak是一款轻量级物联网云平台,支持数据上传、存储与可视化,适合快速验证物联网数据上报功能,操作流程如下:
第一步:创建通道

-
访问ThingSpeak官方网站(https://thingspeak.com/),注册并登录账号;
-
点击顶部菜单栏「Channels」→「Create New Channel」,进入通道创建页面;
-
填写通道基本信息(如通道名称、描述),在「Field 1」填写"Temperature"(温度),「Field 2」填写"Humidity"(湿度),其他参数默认;
-
点击页面底部「Save Channel」,完成通道创建,记录页面显示的「Channel ID」(后续配置MQTT主题使用)。
第二步:获取MQTT连接参数

-
进入创建好的通道,点击顶部「API Keys」,查看并保存「Write API Key」(用于数据上报权限验证);
-
点击顶部「MQTT Settings」,获取MQTT连接核心参数,具体如下表(实际参数以个人平台显示为准):
|-------------|--------------------------|
| 参数名 | 参数值 |
| mqttHostUrl | mqtt3.thingspeak.com(固定) |
| port | 1883(固定) |
| clientId | Nx45MSAgCAkFNzQYDwwOOAc |
| username | Nx45MSAgCAkFNzQYDwwOOAc |
| passwd | WGG/tlO7RcEA89G8Ab+vIhmW |
| 发布主题 | channels/2362531/publish |
注意:发布主题中的"2362531"为个人Channel ID,需替换为自己创建通道的ID;passwd需妥善保存,用于MQTT连接身份验证。
5. 示例流程讲解
5.1 程序流程图

程序运行流程如下(代码自行编写时可参考此流程):
开发板上电 → 初始化SPI外设与GPIO(仅需配置DHT11传感器引脚,W5500与RP2040已内置连接) → W5500芯片初始化 → 尝试DHCP自动获取IP地址(失败则使用静态IP) → 初始化MQTT客户端 → 连接ThingSpeak MQTT服务器(失败则重启重连) → 初始化定时器(定时采集数据) → 主循环监听MQTT消息 → 定时器触发,采集DHT11温湿度数据 → 上报数据至ThingSpeak平台 → 重复循环。
5.2 测试准备
软件准备:
-
安装Thonny 4.0及以上版本,配置W55RP20开发环境;
-
下载W55RP20专属MicroPython固件;
-
下载umqttsimple.py库,导入W55RP20开发板;
-
注册ThingSpeak账号,创建通道并获取MQTT连接参数。
硬件准备:
-
准备W55RP20开发板,确认无硬件损坏;
-
准备Micro USB数据线、网线,确保路由器开启DHCP功能。
5.3 连接方式
-
开发板与电脑连接:使用Micro USB数据线连接W55RP20开发板与电脑,用于供电、代码烧录和串口调试;
-
开发板与网络连接:使用网线连接W55RP20的以太网接口与路由器的LAN口(确保电脑也连接同一路由器);
5.4 相关代码
mqtt_speak代码:
python
# ==============================
# W55RP20 以太网初始化
# ==============================
import network
import time
from machine import Pin, WIZNET_PIO_SPI, Timer
from umqttsimple import MQTTClient, MQTTException
# 初始化以太网(稳定版)
def init_w55rp20():
print("[ETH] 初始化 W55RP20...")
spi = WIZNET_PIO_SPI(
baudrate=20000000, # 降速避免驱动报错
sck=Pin(21),
cs=Pin(20),
mosi=Pin(23),
miso=Pin(22)
)
nic = network.WIZNET6K(spi, Pin(20), Pin(25))
nic.active(True)
nic.ifconfig(("192.168.1.129", "255.255.255.0", "192.168.1.1", "8.8.8.8"))
timeout = 0
while not nic.isconnected() and timeout < 20:
time.sleep(0.5)
print("[ETH] 等待网线连接...")
timeout += 1
print("[ETH] 已连接")
print("[ETH] IP:", nic.ifconfig())
return nic
# ==============================
# 🔥🔥🔥 【100% 匹配你截图的真实账号】🔥🔥🔥
# ==============================
TS_CONFIG = {
"host": "mqtt3.thingspeak.com",
"port": 1883,
"client_id": "DhMGLycADBorAAAxFCE9MBE",
"user": "DhMGLycADBorAAAxFCE9MBE",
"password": "lL+FaB1bnWFR9KlYIm7cTSnU", # 你截图里的真实密码
"topic": "channels/3360951/publish",
}
# 固定温湿度(你想改就改这里)
TEMP = 26
HUMI = 52
UPLOAD_INTERVAL = 15
# 全局变量(只创建一次客户端)
client = None
timer_cnt = 0
# 安全连接(修复内存泄漏)
def mqtt_connect():
global client
try:
# 每次连接前清理旧连接
client = MQTTClient(
client_id=TS_CONFIG["client_id"],
server=TS_CONFIG["host"],
port=TS_CONFIG["port"],
user=TS_CONFIG["user"],
password=TS_CONFIG["password"],
keepalive=30
)
client.connect(clean_session=True)
print("[MQTT] 连接成功!")
return True
except MQTTException as e:
print("[MQTT] 认证失败(账号错误):", e)
return False
except Exception as e:
print("[MQTT] 网络错误:", e)
return False
# 上传数据
def upload():
payload = f"field1={TEMP}&field2={HUMI}"
try:
client.publish(TS_CONFIG["topic"], payload)
print("[上传成功]", payload)
except:
print("[上传失败] 重新连接...")
mqtt_connect()
# 定时器回调
def tick(t):
global timer_cnt
timer_cnt += 1
if timer_cnt >= UPLOAD_INTERVAL:
timer_cnt = 0
upload()
# ==============================
# 主程序
# ==============================
def main():
print("=== W55RP20 + ThingSpeak 温湿度上传 ===")
init_w55rp20()
time.sleep(1)
# 只连接一次!避免内存爆炸
while not mqtt_connect():
print("等待 5 秒后重试...")
time.sleep(5)
# 启动定时上传
tim = Timer(period=1000, mode=Timer.PERIODIC, callback=tick)
while True:
time.sleep(1)
if __name__ == "__main__":
main()
python
#umqttsimple.py file
import usocket as socket
import ustruct as struct
from ubinascii import hexlify
class MQTTException(Exception):
pass
class MQTTClient:
def __init__(
self,
client_id,
server,
port=0,
user=None,
password=None,
keepalive=0,
ssl=False,
ssl_params={},
):
if port == 0:
port = 8883 if ssl else 1883
self.client_id = client_id
self.sock = None
self.server = server
self.port = port
self.ssl = ssl
self.ssl_params = ssl_params
self.pid = 0
self.cb = None
self.user = user
self.pswd = password
self.keepalive = keepalive
self.lw_topic = None
self.lw_msg = None
self.lw_qos = 0
self.lw_retain = False
def _send_str(self, s):
self.sock.write(struct.pack("!H", len(s)))
self.sock.write(s)
def _recv_len(self):
n = 0
sh = 0
while 1:
b = self.sock.read(1)[0]
n |= (b & 0x7F) << sh
if not b & 0x80:
return n
sh += 7
def set_callback(self, f):
self.cb = f
def set_last_will(self, topic, msg, retain=False, qos=0):
assert 0 <= qos <= 2
assert topic
self.lw_topic = topic
self.lw_msg = msg
self.lw_qos = qos
self.lw_retain = retain
def connect(self, clean_session=True):
self.sock = socket.socket()
addr = socket.getaddrinfo(self.server, self.port)[0][-1]
self.sock.connect(addr)
if self.ssl:
import ussl
self.sock = ussl.wrap_socket(self.sock, **self.ssl_params)
premsg = bytearray(b"\x10\0\0\0\0\0")
msg = bytearray(b"\x04MQTT\x04\x02\0\0")
sz = 10 + 2 + len(self.client_id)
msg[6] = clean_session << 1
if self.user is not None:
sz += 2 + len(self.user) + 2 + len(self.pswd)
msg[6] |= 0xC0
if self.keepalive:
assert self.keepalive < 65536
msg[7] |= self.keepalive >> 8
msg[8] |= self.keepalive & 0x00FF
if self.lw_topic:
sz += 2 + len(self.lw_topic) + 2 + len(self.lw_msg)
msg[6] |= 0x4 | (self.lw_qos & 0x1) << 3 | (self.lw_qos & 0x2) << 3
msg[6] |= self.lw_retain << 5
i = 1
while sz > 0x7F:
premsg[i] = (sz & 0x7F) | 0x80
sz >>= 7
i += 1
premsg[i] = sz
self.sock.write(premsg, i + 2)
self.sock.write(msg)
# print(hex(len(msg)), hexlify(msg, ":"))
self._send_str(self.client_id)
if self.lw_topic:
self._send_str(self.lw_topic)
self._send_str(self.lw_msg)
if self.user is not None:
self._send_str(self.user)
self._send_str(self.pswd)
resp = self.sock.read(4)
assert resp[0] == 0x20 and resp[1] == 0x02
if resp[3] != 0:
raise MQTTException(resp[3])
return resp[2] & 1
def disconnect(self):
self.sock.write(b"\xe0\0")
self.sock.close()
def ping(self):
self.sock.write(b"\xc0\0")
def publish(self, topic, msg, retain=False, qos=0):
pkt = bytearray(b"\x30\0\0\0")
pkt[0] |= qos << 1 | retain
sz = 2 + len(topic) + len(msg)
if qos > 0:
sz += 2
assert sz < 2097152
i = 1
while sz > 0x7F:
pkt[i] = (sz & 0x7F) | 0x80
sz >>= 7
i += 1
pkt[i] = sz
# print(hex(len(pkt)), hexlify(pkt, ":"))
self.sock.write(pkt, i + 1)
self._send_str(topic)
if qos > 0:
self.pid += 1
pid = self.pid
struct.pack_into("!H", pkt, 0, pid)
self.sock.write(pkt, 2)
self.sock.write(msg)
if qos == 1:
while 1:
op = self.wait_msg()
if op == 0x40:
sz = self.sock.read(1)
assert sz == b"\x02"
rcv_pid = self.sock.read(2)
rcv_pid = rcv_pid[0] << 8 | rcv_pid[1]
if pid == rcv_pid:
return
elif qos == 2:
assert 0
def subscribe(self, topic, qos=0):
assert self.cb is not None, "Subscribe callback is not set"
pkt = bytearray(b"\x82\0\0\0")
self.pid += 1
struct.pack_into("!BH", pkt, 1, 2 + 2 + len(topic) + 1, self.pid)
# print(hex(len(pkt)), hexlify(pkt, ":"))
self.sock.write(pkt)
self._send_str(topic)
self.sock.write(qos.to_bytes(1, "little"))
while 1:
op = self.wait_msg()
if op == 0x90:
resp = self.sock.read(4)
# print(resp)
assert resp[1] == pkt[2] and resp[2] == pkt[3]
if resp[3] == 0x80:
raise MQTTException(resp[3])
return
# Wait for a single incoming MQTT message and process it.
# Subscribed messages are delivered to a callback previously
# set by .set_callback() method. Other (internal) MQTT
# messages processed internally.
def wait_msg(self):
res = self.sock.read(1)
# self.sock.setblocking(True)
if res is None:
return None
if res == b"":
raise OSError(-1)
if res == b"\xd0": # PINGRESP
sz = self.sock.read(1)[0]
assert sz == 0
return None
op = res[0]
if op & 0xF0 != 0x30:
return op
sz = self._recv_len()
topic_len = self.sock.read(2)
topic_len = (topic_len[0] << 8) | topic_len[1]
topic = self.sock.read(topic_len)
sz -= topic_len + 2
if op & 6:
pid = self.sock.read(2)
pid = pid[0] << 8 | pid[1]
sz -= 2
msg = self.sock.read(sz)
self.cb(topic, msg)
if op & 6 == 2:
pkt = bytearray(b"\x40\x02\0\0")
struct.pack_into("!H", pkt, 2, pid)
self.sock.write(pkt)
elif op & 6 == 4:
assert 0
return op
# Checks whether a pending message from server is available.
# If not, returns immediately with None. Otherwise, does
# the same processing as wait_msg.
def check_msg(self):
# self.sock.setblocking(False)
return self.wait_msg()
python
wiznet_init.py
import network
import time
try:
from machine import Pin, WIZNET_PIO_SPI
except ImportError:
WIZNET_PIO_SPI = None
Pin = None
_DEFAULTS = {
# Auto-construct boards (no explicit PIO SPI)
"w5100s-evb-pico": {},
"w5500-evb-pico": {},
"w6100-evb-pico": {},
"w5100s-evb-pico2": {},
"w5500-evb-pico2": {},
"w6100-evb-pico2": {},
# W55RP20 --- single SPI (PIO SPI)
"w55rp20-evb-pico": {"baudrate": 31250000, "sck": 21, "cs": 20, "mosi": 23, "miso": 22, "reset": 25},
# W6300 --- QSPI QUAD(io0..io3)
"w6300-evb-pico": {"baudrate": 31250000, "sck": 17, "cs": 16, "io0": 18, "io1": 19, "io2": 20, "io3": 21, "reset": 22},
"w6300-evb-pico2": {"baudrate": 31250000, "sck": 17, "cs": 16, "io0": 18, "io1": 19, "io2": 20, "io3": 21, "reset": 22},
}
_AUTO = {
"w5100s-evb-pico", "w5500-evb-pico", "w6100-evb-pico",
"w5100s-evb-pico2","w5500-evb-pico2","w6100-evb-pico2",
}
_SINGLE = {"w55rp20-evb-pico"} # PIO single-SPI
_QSPI = {"w6300-evb-pico", "w6300-evb-pico2"}
def _pin(x): return x if isinstance(x, Pin) else Pin(x)
def wiznet(board, *, dhcp=True, spi=None, cs=None, reset=None, **kw):
board = board.strip().lower()
if board not in _DEFAULTS:
raise ValueError("Unsupported board: {}".format(board))
cfg = _DEFAULTS[board].copy()
cfg.update(kw)
# Manual override path: if spi is provided, use it directly
if spi is not None:
if cs is None or reset is None:
raise ValueError("When passing custom spi, also pass cs and reset")
nic = network.WIZNET6K(spi, cs, reset)
else:
if board in _AUTO:
nic = network.WIZNET6K()
elif board in _SINGLE:
if WIZNET_PIO_SPI is None or Pin is None:
raise RuntimeError("WIZNET_PIO_SPI/Pin not available on this port")
required = ["sck", "cs", "mosi", "miso", "reset"]
missing = [k for k in required if k not in cfg]
if missing:
raise ValueError("Missing pins for W55RP20 single-SPI: " + ", ".join(missing))
spi = WIZNET_PIO_SPI(
baudrate=cfg.get("baudrate", 31250000),
sck=_pin(cfg["sck"]), cs=_pin(cfg["cs"]),
mosi=_pin(cfg["mosi"]), miso=_pin(cfg["miso"]),
)
nic = network.WIZNET6K(spi, _pin(cfg["cs"]), _pin(cfg["reset"]))
elif board in _QSPI:
if WIZNET_PIO_SPI is None or Pin is None:
raise RuntimeError("WIZNET_PIO_SPI/Pin not available on this port")
for k in ["sck","cs","io0","io1","io2","io3"]:
if k not in cfg: raise ValueError("Missing pin '{}' for W6300 QSPI".format(k))
spi = WIZNET_PIO_SPI(
baudrate=cfg.get("baudrate", 31250000),
sck=_pin(cfg["sck"]), cs=_pin(cfg["cs"]),
io0=_pin(cfg["io0"]), io1=_pin(cfg["io1"]),
io2=_pin(cfg["io2"]), io3=_pin(cfg["io3"]),
)
nic = network.WIZNET6K(spi, _pin(cfg["cs"]), _pin(cfg.get("reset", cfg["cs"])))
else:
raise ValueError("Unexpected board mapping")
# Bring up (if supported)
try: nic.active(True)
except AttributeError: pass
if dhcp:
try: nic.ifconfig("dhcp")
except Exception: pass
else:
ip = cfg.get("ip"); sn = cfg.get("sn"); gw = cfg.get("gw"); dns = cfg.get("dns", gw or "8.8.8.8")
if not (ip and sn and gw): raise ValueError("Static mode requires ip/sn/gw")
nic.ifconfig((ip, sn, gw, dns))
while not nic.isconnected():
print("Waiting for the network to connect...")
time.sleep(1)
print("MAC Address:", ":".join("%02x" % b for b in nic.config("mac")))
print("IP Address:", nic.ifconfig())
return nic
5.5 烧录验证
烧录与验证步骤如下,确保每一步操作正确,避免出现连接或上报失败问题:
第一步:烧录固件
-
按住W55RP20开发板上的BOOTSEL按键不放,使用Micro USB数据线连接开发板与电脑;
-
待电脑识别出名为「RPI-RP2」的U盘后,松开BOOTSEL按键;
-
将下载好的W55RP20专属MicroPython固件(UF2格式)拖拽到U盘中,开发板会自动重启,固件烧录完成。
第二步:导入库文件
-
打开Thonny软件,配置解释器为「MicroPython (Raspberry Pi Pico)」,选择开发板对应的串口;
-
点击Thonny菜单栏「文件」→「新建」,粘贴umqttsimple.py库代码,保存为「umqttsimple.py」并上传到开发板根目录。wiznet_init也要保存到根目录下。
第三步:烧录自定义代码
-
新建文件,编写自定义代码(参考4.1程序流程图,配置MQTT参数、网络初始化等逻辑);
-
点击Thonny工具栏「运行」按钮(或按F5键),将代码烧录到开发板并运行。
第四步:验证结果
-
串口验证:在Thonny的Shell窗口中,查看是否打印网络配置信息、MQTT连接成功信息,以及定时温湿度上报消息;
-
平台验证:打开ThingSpeak个人通道页面,查看「Field 1」(温度)和「Field 2」(湿度)是否实时更新,若有数据显示,说明整个系统运行正常。

注意:因为MicroPython的print函数启用了stdout缓冲,有时不会第一时间打印内容,可耐心等待1-2秒,或在代码中添加time.sleep(0.5)缓解该问题。
6. 常见问题一站式排查指南
6.1 烧录相关问题
|-------------------|------------------------------------------------------------------------------------------------------|
| 问题现象 | 排查步骤 |
| 电脑无法识别「RPI-RP2」U盘 | 1. 确认按住BOOTSEL按键后再插入USB数据线; 2. 更换支持数据传输的USB数据线(避免使用纯充电线); 3. 更换电脑USB接口(优先使用USB 2.0接口); 4. 尝试使用另一台电脑。 |
| 固件拖拽后开发板无反应 | 1. 确认下载的是W55RP20专属固件,而非通用RP2040固件; 2. 重新烧录固件,确保拖拽过程中数据线未松动; 3. 检查USB供电是否稳定,可更换USB接口或使用外接电源。 |
6.2 网络连接问题
|-------------------|-------------------------------------------------------------------------------------------|
| 问题现象 | 排查步骤 |
| 网络初始化失败,一直打印寄存器信息 | 1. 确认网线插紧,网口指示灯是否闪烁; 2. 检查路由器是否开启DHCP功能,或尝试使用静态IP配置; 3. 更换网线或路由器LAN口; 4. 重新烧录W55RP20专属固件。 |
| IP地址显示为0.0.0.0 | 1. 执行上述网络连接排查步骤; 2. 确认W55RP20固件正确,重新烧录 ;3. 检查路由器DHCP地址池是否充足; 4. 重启路由器后重新尝试。 |
6.3 MQTT对接问题
|--------------------|--------------------------------------------------------------------------------------------------------------------------------------|
| 问题现象 | 排查步骤 |
| 无法连接MQTT服务器,提示连接失败 | 1. 确认MQTT参数(url、port、clientid、username、passwd)填写正确; 2. 检查开发板与电脑是否连接同一路由器,网络通畅; 3. 确认ThingSpeak通道已创建,API Key未错误; 4. 尝试关闭电脑防火墙,重新运行程序。 |
| 能连接MQTT服务器,但无法上报数据 | 1. 检查发布主题是否正确(替换为个人Channel ID); 2. 确认消息格式符合ThingSpeak要求(field1=温度&field2=湿度); 3. 查看Thonny串口打印,确认传感器采集到有效数据;4. 检查umqttsimple库是否正确导入。 |
7. W55RP20核心优势
为了让你更直观地了解W55RP20的价值,对比目前主流的三种嵌入式以太网方案,突出其在MQTT物联网场景中的优势:
|---------|-------------------------------------------|-----------------------------|------------------------|
| 对比维度 | W55RP20方案 | 外接PHY芯片方案 | 外接串口转以太网模块方案 |
| BOM成本 | 低(一体化开发板,无需额外器件) | 中高(MCU + PHY芯片 + 外围器件) | 高(模块+开发板+转接电路) |
| PCB面积 | 极小(一体化设计,布线已集成) | 大(需预留芯片和布线空间) | 中(模块体积较大,需单独固定) |
| 开发难度 | 低(MicroPython成熟固件,API封装完善,无需手动配置SPI引脚) | 中高(需调试SPI接口、编写PHY驱动和软件协议栈) | 低(串口通信,无需调试协议栈) |
| 网络稳定性 | 极高(WIZnet硬件TCP/IP协议栈,抗干扰能力强,适合MQTT长期稳定上报) | 不定(依赖软件协议栈调试水平,易出现丢包、断连) | 一般(串口转以太网存在延迟,易受干扰) |
| CPU资源占用 | 0%(协议栈由W5500硬件处理,RP2040专注传感器采集和MQTT消息处理) | 50%以上(软件协议栈占用大量CPU资源,影响主业务) | 低(串口通信占用少量资源,但数据转发效率低) |
| 网络吞吐量 | 最高15Mbps(满足MQTT高频上报需求) | 视MCU能力而定,一般低于20Mbps | 约3-5Mbps(不适合高频数据上报) |
| MQTT适配性 | 强(支持8路硬件Socket,可同时实现数据上报与命令接收) | 一般(需手动移植MQTT库,适配难度高) | 弱(单路透传,无法同时处理多连接) |
8. 典型应用场景
W55RP20开发板,结合MicroPython的便捷开发和MQTT的轻量化通信,适合多种物联网场景,尤其适合快速原型开发和小型物联网项目:
-
环境监测终端:用于室内、大棚、机房等环境的温湿度、光照等数据采集,通过MQTT上报至云平台,实现远程监控;
-
智能传感节点:作为物联网边缘节点,采集各类传感器数据(如温湿度、气压、土壤湿度),通过ThingSpeak等平台实现数据可视化与分析;
-
远程控制终端:接收云平台MQTT命令,控制继电器、LED等外设,实现设备远程开关、参数调节;
-
工业数据采集:适配工业场景中的传感器,采集设备运行参数,通过MQTT协议上传至工业物联网平台,实现设备状态监测;
-
教学实验平台:适合嵌入式、物联网相关教学,快速实现网络连接、数据上报等功能,降低教学难度。
9. 系列预告与资源获取
9.1系列预告
下一篇教程:将讲解Modbus 工业协议通信,W55RP20 搭建 Modbus TCP Server等一系列的内容。
9.2 资源获取
本文完整代码:WIZnet 官方 Gitee 仓库
W55RP20 芯片手册:WIZnet 官方资料网址
如果本文对你有帮助,欢迎点赞、收藏、关注,你的支持是我们持续更新的动力!如有任何问题,欢迎在评论区留言,我们会第一时间回复。