Google Chat:---
+86-0755-88291180
sales@spotpear.com
dragon_manager@163.com
tech-support@spotpear.com
zhoujie@spotpear.com
WhatsApp:13246739196
WhatsApp:13424403025




This chapter contains the following sections. Please read as needed:
New to Pico MicroPython development and want to get started quickly? We have prepared a general introductory tutorial for you. This tutorial is designed to help developers quickly become familiar with Thonny IDE and start developing. It covers environment setup, project creation, component usage, and peripheral programming, helping you take the first step in MicroPython programming.
Please refer to the Install and Configure Thonny IDE Tutorial to download and install the Thonny IDE.
The MicroPython examples are located in the examples/MicroPython directory of the example package.
| Example | Basic Program Description | Dependency Library |
|---|---|---|
| 01_MQTT | MQTT example | - |
Example Description
broker.emqx.io:1883 by default) under MicroPython, and implements:Sub/ed229f15Pub/ed229f15Client ID be globally unique at any given time: if two devices use the same MQTT_CLIENT_ID to log in, the later one will kick off the earlier one, resulting in frequent disconnections.MQTT_CLIENT_ID, MQTT_SUB_TOPIC, and MQTT_PUB_TOPIC. If you set up your own broker or enable authentication, also modify MQTT_USERNAME and MQTT_PASSWORD.In the source code for this example, the relevant configuration is located in:
main.py: Topic definitions + reading MQTT parameters from config.py# Constants for MQTT Topics
MQTT_SUB_TOPIC = 'Sub/ed229f15'
MQTT_PUB_TOPIC = 'Pub/ed229f15'
# MQTT Parameters
MQTT_SERVER = config.mqtt_server
MQTT_PORT = config.mqtt_port
MQTT_USERNAME = config.mqtt_username
MQTT_PASSWORD = config.mqtt_password
MQTT_CLIENT_ID = config.mqtt_client_id
MQTT_KEEPALIVE = config.mqtt_keepalive
config.py: MQTT broker and account informationmqtt_server = b'broker.emqx.io'
mqtt_port = 1883
mqtt_client_id = b'ed229f15'
mqtt_keepalive = 60
mqtt_username = b'w6300_test'
mqtt_password = b'0123456789'
Hardware Connection
broker.emqx.io:1883).poe_inserted status in the reported JSON).Code Analysis
main.pyethernet_init()network.WIZNET6K() initializes the Ethernet interfacenic.ifconfig('dhcp') enables DHCP to obtain an IP address and waits for nic.isconnected()mqtt_connect()from umqtt.simple import MQTTClientclient.set_callback(mqtt_recv_callback) and subscribes to MQTT_SUB_TOPICmain.py):MQTT_SUB_TOPIC = 'Sub/ed229f15'
MQTT_PUB_TOPIC = 'Pub/ed229f15'
PUBLISH_INTERVAL = 10device/system/message (note: get_network_info() is implemented in the current code but not yet included in the payload; you can extend it as needed):{
"device": { "chip": "RP2350A", "client_id": "ed229f15" },
"system": {
"cpu_mhz": 150,
"ram_kb": 520,
"temp_c": 36.2,
"vsys_voltage_v": 5.021,
"vsys_adc_raw": 2048,
"usb_inserted": true,
"poe_inserted": false,
"uptime": "0:00:01:23"
},
"message": "Hello, waveshare!"
}
mqtt_recv_callback(topic, message){"adc": 1}: reads VSYS voltage (GPIO29 ADC) and replies to Pub/...{"led": 2}: sets WS2812 color (GPIO25, values 0-8){"io_dect": 1}: reads USB/POE insertion status (GPIO24/23) and replies to Pub/...{"vsys_voltage":5.021,"vsys_adc_raw":2048}
{"led_color":2,"led_name":"RED"}
{"usb_inserted":true,"poe_inserted":false}
lib/umqtt/simple.py: basic MQTT protocol implementation (connect/publish/subscribe/wait_msg/check_msg)robust.py: adds automatic reconnection logic on top of simple.py (this example currently uses umqtt.simple; you can switch to robust for more resilience if needed)Operation Result
Before running, please complete the Hardware Connections and follow the steps below for programming and deployment:
RP2350-POE-ETH.uf2 file from the firmware/MicroPython directory onto the development board's USB drive to complete programming.examples/MicroPython/01_MQTT directory:main.py (MicroPython auto‑start entry on power‑up)config.pylib/umqtt/simple.pylib/umqtt/robust.pylib/ directory structure must be preserved; the final layout on the board should resemble:/
main.py
config.py
lib/
umqtt/
simple.py
robust.py
Initialize Ethernet (W6300)
Waiting for Ethernet connection...
Ethernet connection successful!
IP address: 192.168.1.100
Subscribe to topic: Sub/ed229f15
Published: {...} -> Pub/ed229f15
...
Verify with any MQTT client (MQTTX recommended)

RP2350-POE-ETH connection parameters:broker.emqx.io1883w6300_test0123456789ed229f15Pub/ed229f15 to receive the JSON reported by the board every 10 seconds.Sub/ed229f15, for example:{"led":2}
{"adc":1,"io_dect":1}

This chapter contains the following sections. Please read as needed:
Please refer to the Raspberry Pi Pico C/C++ Getting Started to download and install the Pico VS Code.
The C/C++ examples are located in the examples/C directory of the example package.
| Example | Basic Program Description | Dependency Library |
|---|---|---|
| 01_MQTT | MQTT example | - |
Example Description
broker.emqx.io:1883 by default) over Ethernet and implements:Sub/ed229f15Pub/ed229f15broker.emqx.io via DNS to obtain the broker IP before connecting. It also supports switching to static IPv4 and a static broker IP.pico_enable_stdio_usb(main 1)), which can be used for debugging and viewing MQTT interactions.Client ID be globally unique at any given time: if two devices use the same MQTT_CLIENT_ID to log in, the later one will kick off the earlier one, resulting in frequent disconnections.MQTT_CLIENT_ID, MQTT_PUBLISH_TOPIC, and MQTT_SUBSCRIBE_TOPIC. If you are using your own Broker or have enabled authentication, also modify MQTT_USERNAME and MQTT_PASSWORD.The default configuration is located in mqtt_app/mqtt_app.c (macro definition area):
#define MQTT_USERNAME "w6300_test"
#define MQTT_CLIENT_ID "ed229f15"
#define MQTT_PASSWORD "0123456789"
#define MQTT_PUBLISH_TOPIC "Pub/ed229f15"
#define MQTT_SUBSCRIBE_TOPIC "Sub/ed229f15"
Hardware Connection
broker.emqx.io:1883).poe_inserted status in the JSON payload).Code Analysis
Entry file: main.c
main() as the entry point; after board/peripheral/network initialization, it enters the infinite loop of mqtt_service_run() (internal while(1)), which handles MQTT keep‑alive, packet reception, and periodic publishing.main() (text description)DEV_Module_Init() (clock/stdio, etc.) + WS2812_init() (status LED)bsp_adc_voltage_detection_init(...) (VSYS sampling configuration) + adc_set_temp_sensor_enabled(true) (temperature channel)usb_detect_io_init() / poe_detect_io_init()mqtt_app_init() (Ethernet + DHCP/DNS + MQTT) → mqtt_service_run() (MQTT main loop: keep‑alive, packet reception, periodic publishing)while(1) and lights the error indicator (LED_INDICATOR_ERROR())MQTT logic file: mqtt_app/mqtt_app.c
g_dns_target_domain = "broker.emqx.io": Broker domain name (default uses DNS resolution).PORT_MQTT (1883): MQTT TCP port.#if 0 to #if 1 in mqtt_connect() to use MQTT_BROKER_IP_0~3.MQTT_CLIENT_ID / MQTT_USERNAME / MQTT_PASSWORD: Account information for connecting to the broker (the example uses fixed values by default; also supports auto‑generation based on the Unique ID)MQTT_PUBLISH_TOPIC / MQTT_SUBSCRIBE_TOPIC: Publish/subscribe topicsMQTT_PUBLISH_PERIOD (10s): Periodic publish intervalstatic eth_NetInfo g_net_info = {
.ip = {192, 168, 1, 100},
.sn = {255, 255, 255, 0},
.gw = {192, 168, 1, 1},
.dns = {8, 8, 8, 8},
.dhcp = NETINFO_DHCP,
.ipmode = NETINFO_DHCP_V4
};
.ip/.sn/.gw/.dns are placeholder values; they will be overwritten by parameters assigned by the router after ethchip_dhcp_run() succeeds. The gateway and DNS are also provided by the router.int mqtt_app_init(void)
{
if (g_net_info.dhcp == NETINFO_DHCP) {
ethchip_dhcp_init(ethchip_dhcp_assign, ethchip_dhcp_assign, ethchip_dhcp_conflict);
return ethchip_dhcp_run();
}
return mqtt_connect();
}
static uint8_t g_dns_target_domain[] = "broker.emqx.io";
#if 0
g_mqtt_broker_ip[0] = MQTT_BROKER_IP_0;
g_mqtt_broker_ip[1] = MQTT_BROKER_IP_1;
g_mqtt_broker_ip[2] = MQTT_BROKER_IP_2;
g_mqtt_broker_ip[3] = MQTT_BROKER_IP_3;
#else
ethchip_dns_init();
ethchip_dns_get_domain_ip(g_net_info.dns, g_dns_target_domain, g_mqtt_broker_ip);
#endif
#if 0 to #if 1 in the code above; it will then use MQTT_BROKER_IP_0~3#if 1
snprintf(g_mqtt_client_id, sizeof(g_mqtt_client_id), "%s", MQTT_CLIENT_ID);
#else
snprintf(g_mqtt_client_id, sizeof(g_mqtt_client_id), "%s%02X%02X%02X%02X",
MQTT_CLIENT_ID_PREFIX, board_id.id[4], board_id.id[5], board_id.id[6], board_id.id[7]);
#endif
#if 1
snprintf(g_mqtt_username, sizeof(g_mqtt_username), "%s", MQTT_USERNAME);
#else
snprintf(g_mqtt_username, sizeof(g_mqtt_username), "%s%02X%02X%02X%02X",
MQTT_USERNAME_PREFIX, board_id.id[4], board_id.id[5], board_id.id[6], board_id.id[7]);
#endif
Switch to dynamic generation: Change the two #if 1 above to #if 0; and it will compose a unique identity for each device using the prefix + Unique ID.
Note: The current publish/subscribe topics are fixed (multiple devices will have mixed data).
message_arrived(MessageData *msg_data)
printf("%.*s\n", ...): Prints the received message content.mqtt_parse_and_execute_commands(...): Passes the subscribed message to the command parsing module (located in mqtt_execute_commands.c), which executes instructions according to the JSON fields and replies.static const mqtt_cmd_map_t g_cmd_map[] = {
{"adc", adc_op_handle},
{"led", led_op_handle},
{"io_dect", io_dect_op_handle},
};
{"adc":1}: Reads VSYS voltage and ADC raw value, and publishes a JSON to MQTT_PUBLISH_TOPIC{"vsys_voltage":5.021,"vsys_adc_raw":2048}
{"led":N}: Sets the onboard WS2812 color (N ranges from 0-8), and publishes the result to MQTT_PUBLISH_TOPIC{"led_color":2,"led_name":"RED"}
{"error":"invalid_led_color","value":99,"valid_range":"0-8"}
{"io_dect":1}: Reads USB/POE insertion detection IOs and publishes the status to MQTT_PUBLISH_TOPIC{"usb_inserted":true,"poe_inserted":false}
build_mqtt_payload(...)0 to avoid reporting abnormal values.Operation Result
Import and compile the 01_MQTT project using VS Code. After compilation, flash the .uf2 file from the build directory, or directly flash 01_MQTT.uf2 file from the firmware/C directory for quick verification.
After programming the example, open the USB serial port (common serial tools default to 115200 baud) and you should see logs similar to:
DEV_Module_Init OK
========== Device Identity ==========
MAC: 02:08:DC:xx:xx:xx
ClientID: ed229f15
UserName: w6300_test
======================================
DHCP initialization succeed
DHCP success
DHCP assign succeed
mqtt disconnect
mqtt connect
DNS initialized successfully
DNS success
Target domain : broker.emqx.io
IP of target domain : 34.243.217.54
MQTT connected
Published
Subscribed
Published
Published
...
Verify using any MQTT client (MQTTX recommended)

RP2350-POE-ETH connection parameters (consistent with macro configuration):broker.emqx.io1883w6300_test0123456789ed229f15Pub/ed229f15. You will receive the JSON reported by the board every 10 seconds, for example:{
"device": { "chip": "RP2350A", "mac": "02:08:DC:xx:xx:xx", "client_id": "ed229f15" },
"system": {
"cpu_mhz": 150,
"ram_kb": 520,
"flash_mb": 16,
"temp_c": 36.2,
"vsys_voltage_v": 5.021,
"vsys_adc_raw": 2048,
"usb_inserted": true,
"poe_inserted": false,
"uptime": "0:00:01:23"
},
"network": { "mode": "DHCP", "ip": "192.168.1.100", "subnet": "255.255.255.0", "gateway": "192.168.1.1", "dns": "8.8.8.8" },
"message": "Hello, waveshare!"
}
Sub/ed229f15:Publish any string: the board will print it verbatim to the serial port (see the message_arrived(...) code snippet earlier).
Publish a JSON command (e.g., {"led":2}): it will execute the corresponding action and republish the result to Pub/ed229f15 (it is recommended to subscribe to Pub/ed229f15 to see the execution reply).

This chapter contains the following sections. Please read as needed:
Please refer to the Install and Configure Arduino IDE Tutorial to download and install the Arduino IDE.
The Arduino examples are located in the examples/Arduino directory of the example package.
| Example | Basic Program Description | Dependency Library |
|---|---|---|
| 01_MQTT | MQTT example | Adafruit_NeoPixel |

Example Description
Adafruit_NeoPixel; it must be installed in advance.broker.emqx.io:1883) via Ethernet, and implements:Sub/ed229f15Pub/ed229f15broker.emqx.io via DNS to get the Broker IP before connecting.Client ID be globally unique at any given time: if two devices use the same MQTT_CLIENT_ID to log in, the later one will kick off the earlier one, resulting in frequent disconnections.MQTT_CLIENT_ID, MQTT_PUBLISH_TOPIC, and MQTT_SUBSCRIBE_TOPIC. If you are using your own Broker or have enabled authentication, also modify MQTT_USERNAME and MQTT_PASSWORD.#define MQTT_USERNAME "w6300_test"
#define MQTT_CLIENT_ID "ed229f15"
#define MQTT_PASSWORD "0123456789"
#define MQTT_PUBLISH_TOPIC "Pub/ed229f15"
#define MQTT_SUBSCRIBE_TOPIC "Sub/ed229f15"
Hardware Connection
broker.emqx.io:1883).poe_inserted status in the JSON payload).Code Analysis
Entry file 01-MQTT.ino
extern "C" int _write(...): Redirects printf() output to Serial, so that printf printouts from C files can also be seen in the serial monitor.setup()Serial.begin(115200): Initializes the serial port at 115200 baud rate.DEV_Module_Init(): Initializes board-level hardware (GPIO/SPI/Ethernet chip, etc., implemented internally in the BSP).bsp_adc_voltage_detection_init(...): Initializes VSYS voltage detection (later reports vsys_voltage_v and vsys_adc_raw).usb_detect_io_init() / poe_detect_io_init(): Initializes USB/POE insertion detection IOs (later reports usb_inserted/poe_inserted).mqtt_app_init(): Initializes Ethernet + DHCP/DNS + MQTT connection.loop()mqtt_service_run(): The MQTT main loop (internally a while(1)), responsible for maintaining the connection, processing subscribed messages, and publishing periodically.MQTT logic file mqtt_app.c
g_dns_target_domain = "broker.emqx.io": Broker domain name (default uses DNS resolution).#if 0 to #if 1 in mqtt_connect() to use MQTT_BROKER_IP_0~3.PORT_MQTT (1883): MQTT TCP port.MQTT_CLIENT_ID / MQTT_USERNAME / MQTT_PASSWORD: Credentials for connecting to the Broker (hardcoded in the example).MQTT_PUBLISH_TOPIC / MQTT_SUBSCRIBE_TOPIC: Publish/subscribe topics.MQTT_PUBLISH_PERIOD (10s): Periodic publish interval.g_dns_target_domain = "broker.emqx.io": Default Broker domain.static eth_NetInfo g_net_info = {
.ip = {192, 168, 1, 100},
.sn = {255, 255, 255, 0},
.gw = {192, 168, 1, 1},
.dns = {8, 8, 8, 8},
.dhcp = NETINFO_DHCP,
.ipmode = NETINFO_DHCP_V4
};
.ip/.sn/.gw/.dns are only placeholders; they will be overwritten by the parameters assigned by the router after ethchip_dhcp_run() succeeds. The gateway (gw) and DNS are also provided by the router, so there is no need to manually change them to match "your own router".int mqtt_app_init(void)
{
if (g_net_info.dhcp == NETINFO_DHCP) {
ethchip_dhcp_init(ethchip_dhcp_assign, ethchip_dhcp_assign, ethchip_dhcp_conflict);
return ethchip_dhcp_run();
}
return mqtt_connect();
}
static eth_NetInfo g_net_info = {
.ip = {192, 168, 1, 100},
.sn = {255, 255, 255, 0},
.gw = {192, 168, 1, 1},
.dns = {8, 8, 8, 8},
.dhcp = NETINFO_STATIC,
.ipmode = NETINFO_STATIC_V4
};
How to fill in static IP parameters (incorrect values will cause "network not working / MQTT connection failure")
.ip: The fixed IP of the development board. It must be in the same subnet as the router and must not conflict with other devices on the LAN.192.168.1.1 with subnet mask 255.255.255.0, you could choose 192.168.1.123..sn (Subnet Mask): Must match the subnet configuration of the router.255.255.255.0..gw (Gateway): The default gateway, usually the router's LAN IP.192.168.1.1..dns: DNS server IP.192.168.1.1) or a public DNS (e.g., 8.8.8.8, 114.114.114.114).Broker address: Static IP ↔ DNS (dynamic domain name resolution)
static uint8_t g_dns_target_domain[] = "broker.emqx.io";
#if 0
g_mqtt_broker_ip[0] = MQTT_BROKER_IP_0;
g_mqtt_broker_ip[1] = MQTT_BROKER_IP_1;
g_mqtt_broker_ip[2] = MQTT_BROKER_IP_2;
g_mqtt_broker_ip[3] = MQTT_BROKER_IP_3;
#else
ethchip_dns_init();
ethchip_dns_get_domain_ip(g_net_info.dns, g_dns_target_domain, g_mqtt_broker_ip);
#endif
#if 0 to #if 1 in the code above; it will then use MQTT_BROKER_IP_0~3 (currently fixed to 34.243.217.54).#define MQTT_USERNAME "w6300_test"
#define MQTT_CLIENT_ID "ed229f15"
#if 1
snprintf(g_mqtt_client_id, sizeof(g_mqtt_client_id), "%s", MQTT_CLIENT_ID);
#else
snprintf(g_mqtt_client_id, sizeof(g_mqtt_client_id), "%s%02X%02X%02X%02X",
MQTT_CLIENT_ID_PREFIX, board_id.id[4], board_id.id[5], board_id.id[6], board_id.id[7]);
#endif
#if 1
snprintf(g_mqtt_username, sizeof(g_mqtt_username), "%s", MQTT_USERNAME);
#else
snprintf(g_mqtt_username, sizeof(g_mqtt_username), "%s%02X%02X%02X%02X",
MQTT_USERNAME_PREFIX, board_id.id[4], board_id.id[5], board_id.id[6], board_id.id[7]);
#endif
#if 1 above to #if 0; it will then compose a unique identity for each device using MQTT_CLIENT_ID_PREFIX / MQTT_USERNAME_PREFIX + Unique ID.#define MQTT_PUBLISH_TOPIC "Pub/ed229f15"
#define MQTT_SUBSCRIBE_TOPIC "Sub/ed229f15"
generate_device_identity()pico_get_unique_board_id) to generate a MAC address (first 3 bytes fixed OUI: 02:08:DC, last 3 bytes taken from the chip's Unique ID).client_id and username (the example currently uses static macros; it also supports automatic generation based on Unique ID).mqtt_app_init()g_net_info.dhcp == NETINFO_DHCP:ethchip_dhcp_init(...) + ethchip_dhcp_run(): Starts DHCP to obtain an IP address (upon success, the DHCP callback is invoked and automatically triggers MQTT connection).mqtt_connect() to establish MQTT.mqtt_connect()network_initialize(g_net_info): Writes the current network parameters to the Ethernet chip (IP/gateway/DNS, etc.).ethchip_dns_get_domain_ip(...): Resolves broker.emqx.io to obtain g_mqtt_broker_ip.#if 0 to #if 1 to use MQTT_BROKER_IP_0~3).ConnectNetwork(...): Establishes a TCP connection to the Broker.MQTTClientInit(...) + MQTTConnect(...): Initializes the MQTT client and completes the CONNECT.MQTTSubscribe(..., message_arrived): Subscribes to MQTT_SUBSCRIBE_TOPIC; received messages are passed to message_arrived().message_arrived(MessageData *msg_data)printf("%.*s\n", ...): Prints the received message content.mqtt_parse_and_execute_commands(...): Passes the subscribed message to the command parsing module. The current subscribe topic is Sub/ed229f15. The behavior upon receiving a message is as follows:Pub/ed229f15 (it is recommended to subscribe to Pub/ed229f15 to see the response).// Supported control commands (payload is JSON; executes only if the field exists and value >= 0)
// {"adc":1} Read VSYS voltage and report
// {"led":2} Set WS2812 color (0-8)
// {"io_dect":1} Read USB/POE insertion status and report
static const mqtt_cmd_map_t g_cmd_map[] = {
{"adc", adc_op_handle},
{"led", led_op_handle},
{"io_dect", io_dect_op_handle},
};
{"adc":1}: Reads VSYS voltage and ADC raw value, and publishes a JSON to Pub/ed229f15:{"vsys_voltage":5.021,"vsys_adc_raw":2048}
{"led":N}: Sets the onboard WS2812 color (N ranges from 0-8: OFF/WHITE/RED/ORANGE/YELLOW/GREEN/CYAN/BLUE/PURPLE), and publishes the execution result to Pub/ed229f15.{"led_color":2,"led_name":"RED"}
{"error":"invalid_led_color","value":99,"valid_range":"0-8"}
{"io_dect":1}: Reads USB/POE insertion detection IOs and publishes the status to Pub/ed229f15:{"usb_inserted":true,"poe_inserted":false}
build_mqtt_payload(...)read_chip_temp()), flash size, system uptime, VSYS voltage, USB/POE insertion status, network parameters, etc., and composes them into a JSON string.g_mqtt_message.payload).mqtt_service_run()MQTTYield(...): Allows the MQTT client to handle packet reception, keep‑alive, callbacks, etc.MQTT_PUBLISH_PERIOD interval: calls MQTTPublish(...) to publish device status to MQTT_PUBLISH_TOPIC.ethchip_dhcp_run() is called periodically to maintain the lease; when DHCP reassigns an address, ethchip_dhcp_assign() disconnects and reconnects MQTT.Operation Result
=== System Start ===
DHCP initialization succeed
...(after obtaining IP)...
MQTT connected
Published
Subscribed
Published
Published
...
Verify using any MQTT client (MQTTX recommended)

RP2350-POE-ETH connection parameters:broker.emqx.io1883w6300_test0123456789ed229f15Pub/ed229f15. You will receive the JSON reported by the board every 10 seconds, for example:{
"device": { "chip": "RP2350A", "mac": "02:08:DC:xx:xx:xx", "client_id": "ed229f15" },
"system": {
"cpu_mhz": 150,
"ram_kb": 520,
"flash_mb": 16,
"temp_c": 36.2,
"vsys_voltage_v": 5.021,
"vsys_adc_raw": 2048,
"usb_inserted": true,
"poe_inserted": false,
"uptime": "0:00:01:23"
},
"network": { "mode": "DHCP", "ip": "192.168.1.100", "subnet": "255.255.255.0", "gateway": "192.168.1.1", "dns": "8.8.8.8" },
"message": "Hello, waveshare!"
}
Publish any string to topic Sub/ed229f15; the board's serial port will print the received message (and pass it to the command parsing function, which is convenient for customizing control logic in secondary development).

Development Board Design Files
Monday-Friday (9:30-6:30) Saturday (9:30-5:30)
Email: services01@spotpear.com