The Nordic Thingy:91 X is a small but powerful development board for IoT and cellular projects. After installing Visual Studio Code, nRF Connect for Desktop, and running the Quick Start nRF Cloud examples, It was time to do some hardware interfacing.
Install SoftwareThe first thing to do is to install Visual Studio Code. Here is the download link:
https://code.visualstudio.com/download
VS code will be used as the code editor with the Nordic nRF Connect SDK extension as the hardware interface.
The next software we need is the Nordic nRF Connect for Desktop.
https://www.nordicsemi.com/Products/Development-tools/nrf-connect-for-desktop/download
Nordic nRF ConnectWhen you run the Quick Start script in the nRF Connect for Desktop application it will set up the board with the firmware you need to talk to the cloud or do some programming. There are some extra tools for directly operating the cloud interface using AT commands directly on the serial port, and checking the RSSI levels for the radio link.
Select "Start prototyping" and the core firmware will be programmed onto the device.
After a few more setup screens, select "VS Code IDE" to launch the editor and load the nRF extension.
The nRF extension in VS Code will direct you to install the toolchain and SDK libraries the Thingy:91 X requires for programming.
I found out quickly that the process for programming the Thingy:91 X was a bit different than I was used to. I couldn't find pin definitions or LED declarations, but after some hair-pulling I found the Nordic "nRF Connect SDK Fundamentals" online courses here:
https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/
I recommend anyone working with the Nordic Thingy:91 X to consider spending the time taking these courses to understand the differences in program structure and file hierarchy.
After the file structure for the project is created, add the build configuration for the Thingy:91 X
I made the mistake of jumping right into compiling Blinky and programming the Thingy, but mistakenly used the wrong target device in VS Code and immediately made the board inoperable and the USB interfaces promptly disappeared from my PC device manager serial port list. Luckily I had a Segger J-Link board in my stash to get the board working again by programming the connectivity_bridge firmware back into the board.
A good reference link to the nRF Connect SDK can be found here:
https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/index.html
So once I got the board back to "normal" I integrated some of the example code from the Nordic academy course into the blinky code to see what I could do.
Blinky + ButtonI first added an #include for the devicetree <zephyr/devicetree.h>
This will include the devicetree for the Thingy:91 X located at:
<install dir>\ncs\v2.9.1\nrf\boards\nordic\thingy91x\thingy91x_nrf9151_common.dts
The definitions for the button and the LEDs are in this file.
These definitions reflect the connections to the ICs on the board. The board schematic can be found in this pdf:
https://docs-be.nordicsemi.com/bundle/ug_thingy91x/attach/Thingy91X_UG_1.0.0.pdf?_LANG=enus
Here's the section I need today.
Add "CONFIG_GPIO=y" into the prj.conf file to enable the GPIO pins.
Blinky + Button Code/*
* Blinky + Button RSC build 24 April 2025
*/
#include <stdio.h>
#include <zephyr/kernel.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/gpio.h>
/* 1000 msec = 1 sec */
#define SLEEP_TIME_MS 100
/* The devicetree node identifier for the "ledx" alias. */
#define LED0_NODE DT_ALIAS(led0)
#define LED1_NODE DT_ALIAS(led1)
/* Get the node identifier for button 1 through its alias sw0 */
#define SW0_NODE DT_ALIAS(sw0)
/* Get the device pointer, pin number, and pin's configuration flags through gpio_dt_spec
*/
static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(SW0_NODE, gpios);
static const struct gpio_dt_spec led0 = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
static const struct gpio_dt_spec led1 = GPIO_DT_SPEC_GET(LED1_NODE, gpios);
int main(void)
{
int ret;
if (!gpio_is_ready_dt(&led0)) {
return 0;
}
if (!gpio_is_ready_dt(&led1)) {
return 0;
}
if (!device_is_ready(button.port)) {
printk("Error: button device %s is not ready\n",
button.port->name);
return -1;
}
ret = gpio_pin_configure_dt(&led0, GPIO_OUTPUT_ACTIVE);
if (ret < 0) {
return -1;
}
ret = gpio_pin_configure_dt(&led1, GPIO_OUTPUT_ACTIVE);
if (ret < 0) {
return -1;
}
ret = gpio_pin_configure_dt(&button, GPIO_INPUT);
if (ret != 0) {
printk("Error %d: failed to configure %s pin %d\n",
ret, button.port->name, button.pin);
return -1;
}
while (1) {
/* Read the status of the button and store it */
bool val = gpio_pin_get_dt(&button);
/* Update the LED to the status of the button */
gpio_pin_set_dt(&led0, val);
gpio_pin_set_dt(&led1, !val);
k_msleep(SLEEP_TIME_MS);
}
return 0;
}
Build and Flash
Next I will try and use the I2C connector to interface to some sensors....stay tuned.
Comments
Please log in or sign up to comment.