本文为 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.第 1 篇:静态 IP 配置与网络基础

2.第 2 篇:DHCP 自动联网与网络诊断

3.第 3 篇:TCP Client 客户端通信

4.第 4 篇:TCP Server 服务端通信

5.第 5 篇:UDP 单播数据通信

6.第 6 篇:UDP 组播/广播数据通信

7.第 7 篇:DNS 域名解析

8.第 8 篇:NTP 从网络获取时间

9.第 9 篇:HTTP Client 客户端请求

10.第 10 篇:HTTP Server 服务端搭建

11.第 11 篇:HTTP 协议与 OneNET 平台数据上云

12.第 12 篇:MQTT 协议基础通信验证

13.第 13 篇:MQTT 协议与阿里云平台对接

14.第 14 篇:MQTT 协议与 OneNET 平台对接

15.第 15 篇:MQTT 协议与 ThingSpeak 平台对接 (本文)

16.第 16 篇:Modbus 工业协议通信

建议收藏本专栏,跟随教程逐步学习,所有代码均会同步更新至官方 Gitee 仓库

目录

前言

系列教程学习路径

 1. 准备工作

1.1 软件准备

1.2 硬件准备

2. 烧录 W55RP20-EVB-MKR 模块专属 MicroPython 固件

3. 硬件连接与开发环境配置

3.1 硬件连接

3.1.1 基础连接(供电+调试)

3.1.2 以太网连接

3.1.3 模块与开发板接线

3.2 Thonny 开发环境配置

4. ThingSpeak平台操作流程

5. 示例流程讲解

5.1 程序流程图

5.2 测试准备

5.3 连接方式

5.4 相关代码

5.5 烧录验证

6. 常见问题一站式排查指南

6.1 烧录相关问题

6.2 网络连接问题

6.3 MQTT对接问题

7. W55RP20核心优势

8. 典型应用场景

9. 系列预告与资源获取

9.1系列预告

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 固件烧录方式,操作简单无需额外烧录器,新手可快速上手:

  1. 按住 RP2040 开发板上的 BOOTSEL 按键不放;
  2. 使用 Micro USB 数据线连接开发板与电脑;
  3. 待电脑识别出名为 RPI-RP2 的 U 盘后,松开 BOOTSEL 按键;
  4. 将下载好的 W5500_RP2040_firmware.uf2 固件文件拖拽到 U 盘中;
  5. 开发板会自动重启,固件烧录完成。

注意:如果电脑没有识别出 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 软件,按以下步骤配置开发环境,确保代码能正常烧录和运行:

  1. 点击顶部菜单栏「运行」→「配置解释器」;
  2. 切换到「解释器」选项卡;
  3. 在「解释器」下拉列表中选择 MicroPython (通用);
  4. 在「端口」下拉列表中选择开发板对应的串口(通常显示为 Board CDC @ COMx);
  5. 勾选「运行代码前先重启解释器」和「同步设备的实时时钟」;
  6. 点击「确定」完成配置。

如果端口列表中没有出现开发板,请尝试:

  • 重新插拔 USB 数据线;

  • 更换支持数据传输的 USB 数据线;

  • 关闭其他占用串口的软件(如串口助手、Arduino IDE 等);

  • 重新烧录 MicroPython 固件;

  • 安装树莓派 Pico USB 驱动。

4. ThingSpeak平台操作流程

ThingSpeak是一款轻量级物联网云平台,支持数据上传、存储与可视化,适合快速验证物联网数据上报功能,操作流程如下:

第一步:创建通道

1. 访问ThingSpeak官方网站(https://thingspeak.com/),注册并登录账号;

2. 点击顶部菜单栏「Channels」→「Create New Channel」,进入通道创建页面;

3. 填写通道基本信息(如通道名称、描述),在「Field 1」填写“Temperature”(温度),「Field 2」填写“Humidity”(湿度),其他参数默认;

4. 点击页面底部「Save Channel」,完成通道创建,记录页面显示的「Channel ID」(后续配置MQTT主题使用)。

第二步:获取MQTT连接参数

1. 进入创建好的通道,点击顶部「API Keys」,查看并保存「Write API Key」(用于数据上报权限验证);

2. 点击顶部「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 测试准备

软件准备:

1. 安装Thonny 4.0及以上版本,配置W55RP20开发环境;

2. 下载W55RP20专属MicroPython固件;

3. 下载umqttsimple.py库,导入W55RP20开发板;

4. 注册ThingSpeak账号,创建通道并获取MQTT连接参数。

硬件准备:

1. 准备W55RP20开发板,确认无硬件损坏;

2. 准备Micro USB数据线、网线,确保路由器开启DHCP功能。

5.3 连接方式

1. 开发板与电脑连接:使用Micro USB数据线连接W55RP20开发板与电脑,用于供电、代码烧录和串口调试;

2. 开发板与网络连接:使用网线连接W55RP20的以太网接口与路由器的LAN口(确保电脑也连接同一路由器);

5.4 相关代码

mqtt_speak代码:

# ==============================
# 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()
#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()

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 烧录验证

烧录与验证步骤如下,确保每一步操作正确,避免出现连接或上报失败问题:

第一步:烧录固件

1. 按住W55RP20开发板上的BOOTSEL按键不放,使用Micro USB数据线连接开发板与电脑;

2. 待电脑识别出名为「RPI-RP2」的U盘后,松开BOOTSEL按键;

3. 将下载好的W55RP20专属MicroPython固件(UF2格式)拖拽到U盘中,开发板会自动重启,固件烧录完成。

第二步:导入库文件

1. 打开Thonny软件,配置解释器为「MicroPython (Raspberry Pi Pico)」,选择开发板对应的串口;

2. 点击Thonny菜单栏「文件」→「新建」,粘贴umqttsimple.py库代码,保存为「umqttsimple.py」并上传到开发板根目录。wiznet_init也要保存到根目录下。

第三步:烧录自定义代码

1. 新建文件,编写自定义代码(参考4.1程序流程图,配置MQTT参数、网络初始化等逻辑);

2. 点击Thonny工具栏「运行」按钮(或按F5键),将代码烧录到开发板并运行。

第四步:验证结果

1. 串口验证:在Thonny的Shell窗口中,查看是否打印网络配置信息、MQTT连接成功信息,以及定时温湿度上报消息;

2. 平台验证:打开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的轻量化通信,适合多种物联网场景,尤其适合快速原型开发和小型物联网项目:

1. 环境监测终端:用于室内、大棚、机房等环境的温湿度、光照等数据采集,通过MQTT上报至云平台,实现远程监控;

2. 智能传感节点:作为物联网边缘节点,采集各类传感器数据(如温湿度、气压、土壤湿度),通过ThingSpeak等平台实现数据可视化与分析;

3. 远程控制终端:接收云平台MQTT命令,控制继电器、LED等外设,实现设备远程开关、参数调节;

4. 工业数据采集:适配工业场景中的传感器,采集设备运行参数,通过MQTT协议上传至工业物联网平台,实现设备状态监测;

5. 教学实验平台:适合嵌入式、物联网相关教学,快速实现网络连接、数据上报等功能,降低教学难度。

9. 系列预告与资源获取

9.1系列预告

下一篇教程:将讲解Modbus 工业协议通信,W55RP20 搭建 Modbus TCP Server等一系列的内容。

9.2 资源获取

本文完整代码:WIZnet 官方 Gitee 仓库
W55RP20 芯片手册:WIZnet 官方资料网址

下一篇我们讲解:W55RP20-EVB-MKR 模块 MicroPython 实战 (16):Modbus 工业协议通信-CSDN博客


如果本文对你有帮助,欢迎点赞、收藏、关注,你的支持是我们持续更新的动力!如有任何问题,欢迎在评论区留言,我们会第一时间回复。

更多推荐