I was pleased to be asked to evaluate the new Seeed Studio XIAO nRF54LM20A Sense module and review the Wiki documentation before the official release.
Link to the XIAO nRF54LM20 Getting Started Wiki Page:https://wiki.seeedstudio.com/xiao_nrf54lm20a_getting_started/
I received two modules, one soldered to a GPIO breakout board and the other set as separate boards. Two 2.4 GHz IPEX antennas were also included.
My goal is to run through the published examples and determine how this new XIAO will fit into my portfolio of dev boards for new projects.
I really like the XIAO form factor, and I've used them and various expansion boards and displays on a few home and work projects.
The BlinkyButton Project:https://www.hackster.io/r-scott-coppersmith/blinkybutton-eea7fd
The Screaming Halloween Scary Mask with TFT Eyes Project:Link to the XIAO wiki page:https://wiki.seeedstudio.com/SeeedStudio_XIAO_Series_Introduction/
The XIAO nRF54LM20A Evaluationkit:
The evaluation kit of parts included two XIAO modules, one soldered to a GPIO breakout board, and one unsoldered, along with a couple of 2.4ghz antennas for BLE.
To get started, Seeed Studio developed a nice set of wiki pages for the XIAO nRF54LM20A
Link to the XIAO nRF54LM20Awiki page:
https://wiki.seeedstudio.com/xiao_nrf54lm20a_getting_started/
There's not much sense in me copying all that information here, so I will let you read those pages at your leisure.
The long-standing approved method of exploring the features and capabilities of a new development board is to try and make a led blink. Luckily, Seeed Studio included a rgb led for me to attempt the blink ceremony and prove my worthiness to continue the quest. Of course the ridiculous amount of time it took to accomplish this task was not as satisfying as it should have been. My VS Code and Nordic nRF Connect software was a bit out of date, so I spent most of a day updating toolchains and SDKs to the latest revisions, then after reading the documentation, having to install an earlier version of the nRF toolchain and SDK v3.2.4 because of compatibility issues.
In the end, the led did blink as it should. And I was pleased, somewhat. I couldn't tell if the PWM was actually PWM-ing however, so I needed to investigate further.
Seeed Studio is currently supporting VS Code and nRF Connect for software development.
lolren is working on an Arduino library for the nRF54LM20 and his code can be found here:
https://github.com/lolren/nrf54-arduino-core
Once I understood the process flow it was easier to run though the example code on the wiki pages. After successfully running the blinky code, the bluetooth UART code, IMU, and the NFC read text code, I determined it was time to try and write some custom code.
This is the output as read from my iphone NFC tag app.
I have a few Seeed Studio round tft displays, and I saw some example code for this display on the wiki, so let's work with this hardware and see what can be done.
Links to the Seeed Round TFT display wiki pages:https://wiki.seeedstudio.com/using_lvgl_and_tft_on_round_display/
https://wiki.seeedstudio.com/xiao_nrf54lm20a_pin_multiplexing/#spi
After compiling the example SPI code for the round tft display, I wanted to do more and managed to port some of my previous code to the new XIAO.
Here's the example code from the wiki for showing colorbars on the tft display
/* -------------------------------------------------------
* Scene 2: Color vertical bars (6 bars, 40px width each)
* ------------------------------------------------------- */
static void demo_color_bars2(const struct device *dev)
{
static const uint16_t bar_colors[] = {
COLOR_RED, COLOR_ORANGE, COLOR_YELLOW,
COLOR_GREEN, COLOR_BLUE, COLOR_MAGENTA,
};
static const int BAR_W = LCD_W / ARRAY_SIZE(bar_colors); /* = 40 */
for (int y = 0; y < LCD_H; y++) {
for (int x = 0; x < LCD_W; x++) {
uint16_t c = bar_colors[x / BAR_W];
uint16_t be = (c >> 8) | (c << 8);
fb[y * LCD_W + x] = be;
}
}
struct display_buffer_descriptor desc = {
.buf_size = sizeof(fb),
.width = LCD_W,
.height = LCD_H,
.pitch = LCD_W,
};
display_write(dev, 0, 0, &desc, fb);
LOG_INF("Color bars");
k_sleep(K_MSEC(2000));
}Here's an example of showing a filled circle on the tft display
// Draw a filled circle in the framebuffer
void draw_circle(const struct device *dev, uint16_t centerX, uint16_t centerY, uint16_t radius, uint16_t color) {
uint16_t be_color = swap_bytes(color); // Convert to LCD byte order
for (int y = 0; y < LCD_H; y++) {
for (int x = 0; x < LCD_W; x++) {
int dx = x - centerX;
int dy = y - centerY;
if ((dx * dx + dy * dy) <= (radius * radius)) {
fb[y * LCD_W + x] = be_color; // Inside circle
}
else {
fb[y * LCD_W + x] = swap_bytes(0x0000); // Background (black)
}
}
}
struct display_buffer_descriptor desc = {
.buf_size = sizeof(fb),
.width = LCD_W,
.height = LCD_H,
.pitch = LCD_W,
};
display_write(dev, 0, 0, &desc, fb);
}With some minor changes, the code to display a bitmap image is developed.
// display a bitmap using the framebuffer
void display_bitmap(const struct device *dev,const uint16_t *bitmap) {
if (!bitmap) return; // Null check
for (int y = 0; y < LCD_H; y++) {
for (int x = 0; x < LCD_W; x++) {
// Read pixel from bitmap
uint16_t pixel = bitmap[y * LCD_W + x];
// Swap bytes if LCD requires big-endian
fb[y * LCD_W + x] = swap_bytes(pixel);
}
}
struct display_buffer_descriptor desc = {
.buf_size = sizeof(fb),
.width = LCD_W,
.height = LCD_H,
.pitch = LCD_W,
};
display_write(dev, 0, 0, &desc, fb);
}I used this online RGB image-to-code converter to get the uint16_t arrays
https://mischianti.org/rgb-image-to-byte-array-converter-for-arduino-tft-displays/
With 3 full 240 x 240 pixel RGB images loaded in RAM, only %30 was used at compile time. On some of the XIAOs, I could barely fit one image in the RAM.
Conclusions:I believe once the Arduino IDE libraries are updated for this new XIAO board and some more example projects are published to show off more of the internal features, this will be a popular IOT solution at a reasonable price.










Comments