Jump to content

IPDL - 13: 6LoWPAN Protocol Demonstration

From cognifront

Mini Project: Thread / 6LoWPAN Communication Using XIAO nRF52840

1. Project Title

Implementation of IPv6-Based Thread/6LoWPAN Communication Using Two XIAO nRF52840 Boards

2. Project Objective

The objective of this mini project is to implement a small Thread-based IPv6 wireless network using two Seeed Studio XIAO nRF52840 boards.

The project demonstrates how two low-power IEEE 802.15.4 devices can communicate using the following protocol stack:

IEEE 802.15.4 → Thread → 6LoWPAN → IPv6 → UDP → Application Data

The project specifically demonstrates:

  • Setting up the XIAO nRF52840 development environment.
  • Installing the Nordic nRF Connect SDK and nRF Connect for Visual Studio Code.
  • Understanding and using OpenThread firmware.
  • Flashing OpenThread firmware onto XIAO nRF52840 boards using the UF2 bootloader.
  • Configuring one XIAO as a Thread Leader.
  • Configuring a second XIAO as a Thread Child.
  • Creating an Operational Dataset on the Leader.
  • Transferring the Leader's dataset to the Child.
  • Allowing the Child to join the Thread network.
  • Obtaining IPv6 addresses from both nodes.
  • Testing IPv6 connectivity using ping.
  • Establishing UDP communication between the two XIAOs.
  • Sending application messages over IPv6/UDP through the Thread network.

The final practical demonstrates that a small embedded device can participate in an IPv6-based low-power wireless network without using conventional Wi-Fi or Ethernet.

3. What is 6LoWPAN?

6LoWPAN stands for:

IPv6 over Low-Power Wireless Personal Area Networks.

It is a technology that allows IPv6 packets to be transported over IEEE 802.15.4 networks, which have much smaller frames and considerably lower resources than conventional Ethernet or Wi-Fi networks.

IEEE 802.15.4 provides the low-power wireless radio/link layer, while 6LoWPAN provides mechanisms needed to carry IPv6 traffic over that constrained link.

6LoWPAN is particularly useful for:

  • IoT devices
  • Sensor networks
  • Smart-home devices
  • Industrial sensing
  • Battery-powered nodes
  • Mesh networks

4. What is Thread?

Thread is a low-power, IPv6-based mesh networking protocol designed for IoT devices. Thread uses IEEE 802.15.4 at the wireless link layer and provides an IPv6-based networking architecture. In this project, Thread provides the network layer between the two XIAO boards.

Thread therefore makes it possible for the XIAO boards to communicate using IPv6 addresses while the actual wireless transmission takes place through the nRF52840's IEEE 802.15.4 radio.

5. What is a XIAO nRF52840?

The Seeed Studio XIAO nRF52840 is a very small development board based on Nordic Semiconductor's nRF52840 microcontroller.

The nRF52840 contains a 64 MHz ARM Cortex-M4F processor and supports wireless technologies including Bluetooth Low Energy and IEEE 802.15.4. The XIAO board provides USB connectivity, GPIO, analog interfaces and other peripherals in a very small form factor.

The XIAO nRF52840 is particularly suitable for this project because the nRF52840 provides the IEEE 802.15.4 radio required for Thread.

Important hardware features include:

  • Nordic nRF52840 MCU
  • ARM Cortex-M4F processor
  • 64 MHz operation
  • IEEE 802.15.4 capability
  • Bluetooth 5 capability
  • USB Type-C
  • GPIO
  • ADC
  • SPI
  • I²C
  • UART
  • NFC
  • On-board antenna
  • USB bootloader

The XIAO nRF52840 Sense additionally includes sensors such as an IMU and microphone.

For this project, the important feature is not the sensors. The important feature is the nRF52840's IEEE 802.15.4 capability.

6. Hardware Required

Hardware

  • 2 × Seeed Studio XIAO nRF52840 or XIAO nRF52840 Sense
  • 2 × USB Type-C data cables
  • Windows PC
  • Internet connection

Optional:

  • Sensors
  • LEDs
  • Breadboard
  • Jumper wires

The basic Thread/6LoWPAN experiment does not require any external sensor.

7. Software Required

Install the following:

  • Visual Studio Code
  • nRF Connect for Visual Studio Code
  • nRF Connect SDK
  • nRF Connect SDK Toolchain
  • Required Nordic utilities/drivers
  • USB drivers as required by the development environment

Nordic currently recommends using Visual Studio Code together with nRF Connect for VS Code for nRF Connect SDK development. The nRF Connect extension provides the development environment for building, flashing and monitoring nRF Connect SDK applications.

8. Setting Up Nordic Development Environment in Visual Studio Code

Step 1 — Install Visual Studio Code

Download and install the latest supported version of Visual Studio Code.

After installation, launch Visual Studio Code.

Step 2 — Install nRF Connect for VS Code

Open:

Visual Studio Code → Extensions

Search for:

nRF Connect for VS Code

Install the main Nordic extension.

The current nRF Connect for VS Code installation also provides the associated extensions used for:

  • nRF Connect development
  • DeviceTree
  • Kconfig
  • nRF Terminal

Nordic documents these as the extension set used together with nRF Connect for VS Code.

After installation, restart Visual Studio Code if requested.

9. Install the nRF Connect SDK

Open the nRF Connect for VS Code extension from the VS Code Activity Bar.

On a new installation, the Welcome View provides an:

Install SDK

option.

Click:

Install SDK

Nordic's current installation process can install the SDK and matching toolchain together.

Step 10 — Select the SDK

The installer will ask for the download region.

Select the appropriate region.

Then select:

nRF Connect SDK

You will see available stable versions.

For a teaching/lab project, use a stable SDK release rather than an experimental or development branch.

Nordic recommends working with a specific stable SDK release unless you have a reason to use another revision.

11. Install the Toolchain

The SDK installation can install the corresponding toolchain.

The toolchain contains the development components required to build applications for the nRF Connect SDK.

The installation may take several minutes.

Wait until VS Code reports that the installation has completed successfully.

Nordic's current documentation describes the SDK and toolchain as separate components but recommends installing them together for a first-time setup.

12. Verify the Nordic Installation

Open the nRF Connect extension in VS Code.

The installed SDK should appear in the SDK/toolchain management section.

You should be able to see the installed SDK version and associated toolchain.

If the installation is successful, the development environment is ready.

13. Understanding the OpenThread Firmware

For this project, the XIAO boards need firmware containing an OpenThread CLI.

The firmware provides commands such as:

dataset ifconfig thread state ipaddr ping udp

These commands allow you to configure and control the Thread network directly from the serial terminal.

The OpenThread CLI provides commands for creating and managing Operational Datasets, starting Thread, checking node state and performing UDP communication.

14. Important Concept — Leader and Child Are Not Two Different Firmware Programs

This is very important for the mini project.

You do not need:

  • one special "Leader firmware"
  • one special "Child firmware"

Instead, the same OpenThread-capable firmware can be used on both XIAO boards.

The role is determined by the Thread network configuration and the state of the device.

For this project:

XIAO #1 = configured to create the Thread network → becomes Leader

XIAO #2 = given the Leader's Operational Dataset → joins the existing network → becomes Child

Therefore, the firmware is installed first, and the Leader/Child role is established afterward using OpenThread CLI commands.

15. Flashing OpenThread Firmware to the XIAO

The XIAO nRF52840 uses a UF2-compatible bootloader. Zephyr's current XIAO documentation describes entering UF2 bootloader mode by double-tapping the reset button and copying the generated .uf2 file to the board's USB mass-storage device.

For this mini project, you can use a pre-built OpenThread UF2 firmware if you already have the firmware file used in your previous setup.

The file will normally have:

.uf2

extension.

16. Connect the First XIAO

Connect the first XIAO to the computer using a USB Type-C data cable.

Allow Windows to detect the board.

17. Enter UF2 Bootloader Mode

Locate the small RESET button on the XIAO.

Quickly press the reset button twice.

The board should enter bootloader mode.

A USB mass-storage drive should appear in Windows.

The exact drive name can depend on the bootloader/firmware, but the XIAO's UF2 bootloader exposes a removable drive for firmware copying.

18. Copy the OpenThread UF2 Firmware

Open the bootloader drive.

Copy the OpenThread firmware:

your_openthread_firmware.uf2

into the bootloader drive.

Do not open or modify the UF2 file.

Simply copy it to the board.

The board will automatically reset after the firmware has been written.

19. Verify the Firmware

After flashing, Windows should detect the XIAO again as a USB serial device.

Open:

VS Code → Serial Monitor

Select the XIAO's COM port.

In your previous setup, the boards appeared as:

COM26 COM27

Your COM numbers may be different.

Set the baud rate to:

115200

The OpenThread CLI should now be available.

20. Flash the Second XIAO

Disconnect the first XIAO if necessary.

Connect the second XIAO.

Again:

  1. Connect USB.
  2. Double-click RESET.
  3. Wait for the UF2 drive.
  4. Copy the same OpenThread .uf2 firmware.
  5. Allow the board to reboot.
  6. Open its serial port.
  7. Set baud rate to 115200.

At this point both boards should have the same OpenThread-capable firmware.

21. Enable Serial Monitor in VS Code

After flashing the OpenThread firmware, open Visual Studio Code.

Open the nRF Connect for VS Code extension and select nRF Terminal from the VS Code Activity Bar.

Click the + button to create a new serial terminal.

Select the COM port corresponding to the XIAO board.

For example:

COM26

Set the baud rate to:

115200

Press Enter.

The OpenThread CLI should now appear in the terminal.

For the second XIAO, open another terminal and select its corresponding COM port, for example:

COM27

Use:

115200

You can now enter OpenThread commands directly in the terminal, such as:

state

or:

ipaddr

XIAO nRF52840 — Thread + 6LoWPAN + UDP : Now Communication Time

Assume:

XIAO #1 = LEADER XIAO #2 = CHILD

Leader COM26 Child COM27

UDP Port = 12345

Your actual COM ports can of course change.

1. LEADER — complete command sequence

Start with the Leader XIAO.

Step 1 — Clear old dataset

dataset clear

Expected:

Done

Step 2 — Create a NEW Thread network

dataset init new

Expected:

Done

This generates a new random Thread Operational Dataset containing things such as:

  • Channel
  • PAN ID
  • Extended PAN ID
  • Network Key
  • Network Name
  • Mesh-local prefix
  • PSKc

OpenThread documents dataset init new specifically for creating a new dataset.

Step 3 — Display the dataset

Immediately do:

dataset

You should get something similar to:

Active Timestamp: 1 Channel: 21 Channel Mask: 0x07fff800 Ext PAN ID: xxxxxxxxxxxxxxxx Mesh Local Prefix: fdxx:xxxx:xxxx:xxxx::/64 Network Key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Network Name: OpenThread-xxxx PAN ID: 0xxxxxxx PSKc: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Security Policy: 0, onrcb Done

Important: keep this information.

Step 4 — Commit the dataset

dataset commit active

Expected:

Done

This writes the Operational Dataset as the Active Operational Dataset.

Step 5 — Bring up IPv6

ifconfig up

Expected:

Done

Step 6 — Start Thread

thread start

Expected:

Done

Now check:

state

Initially it may show:

detached

Then after a short time the Leader should become:

leader

You can repeatedly use:

state

The normal target is:

leader

2. Get the Leader's complete dataset

This is the most important command for creating the Child.

On the Leader:

dataset active -x

You will get a long hexadecimal string, for example:

0e080000000000010000000300001035060004001fffe00208xxxxxxxxxxxxxxxx...

Copy the entire line.

OpenThread specifically supports dataset active -x for obtaining a hex-encoded Active Operational Dataset that can then be applied to another device with dataset set active.

3. Check Leader IPv6 addresses

Run:

ipaddr

You may see something like:

fdxx:xxxx:xxxx:xxxx:0:ff:fe00:xxxx fdxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx fe80:....

For our UDP test, we'll normally use the Thread mesh-local IPv6 address, beginning with:

fd...

For example:

fd00:abcd:1234:5678:xxxx:xxxx:xxxx:xxxx

Don't use the fe80:: address for this simple test.

4. Test that Leader is working

You can check:

thread state

or simply:

state

You can also check:

ipaddr

And:

netdata show

For a simple two-node experiment, the important result is:

state leader

5. CHILD — complete command sequence

Now move to the second XIAO.

First clear whatever old network information it has.

dataset clear

Then:

ifconfig down

Then:

thread stop

If the board wasn't running Thread, that's okay.

6. Give the Child the Leader's dataset

This is where your previous procedure needs to be slightly changed.

DO NOT do this on the Child:

dataset init new

because that creates a new network.

Instead, take the hexadecimal string obtained from:

dataset active -x

on the Leader.

Then on the Child:

dataset set active YOUR_LEADER_DATASET_HEX

For example:

dataset set active 0e080000000000010000000300001035060004001fffe00208xxxxxxxxxxxxxxxx...

Expected:

Done

This is the documented way of putting the same Active Operational Dataset onto a new device.

7. Start the Child's Thread interface

On Child:

ifconfig up

Then:

thread start

Expected:

Done

Wait a few seconds.

Then:

state

Expected:

child

You might briefly see:

detached

before:

child

That is normal during attachment.

8. Check Child IPv6 addresses

On Child:

ipaddr

You should get something like:

fdxx:xxxx:xxxx:xxxx:0:ff:fe00:xxxx fdxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx fe80:....

Again, note the fd... address.

For example:

fd00:abcd:1234:5678:1111:2222:3333:4444

We'll call that:

CHILD_IP

9. Verify Leader ↔ Child connectivity

Now go back to the Leader.

Take the Child's fd... address.

Run:

ping CHILD_IP

For example:

ping fd00:abcd:1234:5678:1111:2222:3333:4444

Expected:

16 bytes from fd00:abcd:1234:5678:1111:2222:3333:4444: icmp_seq=1 hlim=64 time=10ms

1 packets transmitted, 1 packets received. Packet loss = 0.0%.

That proves: Leader communicates with the Child through IPv6 over the Thread/6LoWPAN network.

6LoWPAN Communication Flow
6LoWPAN Communication Flow

10. Now configure UDP

This is where your screenshot becomes particularly useful.

Let's make:

Leader = UDP SERVER Child = UDP CLIENT

Port = 12345

11. LEADER — UDP server

On the Leader:

udp open

Expected:

Done

Then:

udp bind :: 12345

Expected:

Done

This means:

IPv6 address = :: UDP port = 12345

The :: means the unspecified IPv6 address, allowing the socket to accept traffic on the available IPv6 addresses. This is the standard OpenThread CLI UDP procedure.

You now have: LEADER UDP socket- port 12345

12. CHILD — UDP client

On Child:

udp open

Expected:

Done

You don't actually have to bind the Child for a simple send test.

Now take the Leader's IPv6 address.

For example:

fd00:abcd:1234:5678:aaaa:bbbb:cccc:dddd

Then:

udp send fd00:abcd:1234:5678:aaaa:bbbb:cccc:dddd 12345 Hello_Leader

Expected:

Done

OpenThread's official UDP example follows exactly this pattern: udp open, optionally udp bind, then udp send <IPv6> <port> <message>.

13. What should happen?

On the Leader, you should see something similar to:

Received UDP message depending on the particular OpenThread CLI build.

Conceptually:

         THREAD NETWORK
  ┌─────────────────────────┐
  XIAO #2                 XIAO #1
  CHILD                   LEADER
    │                       │
    │                       │
    │  IPv6 / UDP           │
    │──────────────────────>│
    │                       │
    │ "Hello_Leader"        │
    │                       │
  COM27                   COM26
  UDP destination port: 12345

14. Reverse direction — Leader → Child

If you want the Leader to send a message back to the Child, bind the Child.

On Child:

udp bind :: 12345

Then on Leader:

udp send CHILD_IP 12345 Hello_Child

For example:

udp send fd00:abcd:1234:5678:1111:2222:3333:4444 12345 Hello_Child

Now you have bidirectional UDP:

Child-to-Leader Communication
Child-to-Leader Communication
Leader-to-Child Communication
Leader-to-Child Communication

15. The complete cheat sheet

LEADER

Run these in this order:

dataset clear dataset init new dataset dataset commit active

ifconfig up thread start

state ipaddr dataset active -x

Then test the Child:

ping CHILD_IP

Then UDP server:

udp open udp bind :: 12345

CHILD

Use the Leader's dataset:

dataset clear ifconfig down thread stop

Then:

dataset set active LEADER_DATASET_HEX

Then:

ifconfig up thread start

Check:

state ipaddr

Expected:

child

Then UDP:

udp open

Send to Leader:

udp send LEADER_IP 12345 Hello_Leader

16. Full two-way UDP setup

LEADER

dataset clear dataset init new dataset dataset commit active ifconfig up thread start state ipaddr dataset active -x

Copy the dataset.

Then:

udp open udp bind :: 12345

CHILD

dataset clear ifconfig down thread stop dataset set active LEADER_DATASET_HEX ifconfig up thread start state ipaddr udp open

Then:

udp send LEADER_IP 12345 Hello_Leader

For reverse communication, on Child:

udp bind :: 12345

Then on Leader:

udp send CHILD_IP 12345 Hello_Child

Sample 6LoWPAN Communication Using XIAO nRF52840
Sample 6LoWPAN Communication Using XIAO nRF52840

17. Useful diagnostic commands

Purpose Command
Show current Thread state state
Show IPv6 addresses ipaddr
Show current dataset dataset
Get dataset as hex dataset active -x
Create new network dataset init new
Clear dataset dataset clear
Commit dataset dataset commit active
Bring IPv6 up ifconfig up
Bring IPv6 down ifconfig down
Start Thread thread start
Stop Thread thread stop
Show Thread neighbors neighbor table
Show Thread network data netdata show
Test IPv6 connectivity ping <IPv6>
Open UDP socket udp open
Bind UDP socket udp bind :: 12345
Send UDP udp send <IPv6> 12345 <message>
Close UDP udp close
UDP help udp help
Thread help thread help
Dataset help dataset help

The current OpenThread CLI reference lists these dataset and UDP operations, including dataset clear, dataset commit active, dataset init, udp open, udp bind, udp send, and udp close.