Nano Matter User Manual

Learn about the hardware and software features of the Arduino® Nano Matter.

Overview

This user manual will guide you through a practical journey covering the most interesting features of the Arduino Nano Matter. With this user manual, you will learn how to set up, configure and use this Arduino board.

RGB Lightbulb with Nano Matter

Hardware and Software Requirements

Hardware Requirements

Software Requirements

Board Core and Libraries

The Silicon Labs core contains the libraries and examples you need to work with the board's components, such as its Matter, Bluetooth® Low Energy, and I/Os. To install the Nano Matter core, navigate to File > Preferences and in the Additional boards manager URLs, add the following:

https://siliconlabs.github.io/arduino/package_arduinosilabs_index.json

Now navigate to Tools > Board > Boards Manager or click the Boards Manager icon in the left tab of the IDE. In the Boards Manager tab, search for

Nano Matter
and install the latest
Silicon Labs
core version.

Installing the Silicon Labs core in the Arduino IDE
Installing the Silicon Labs core in the Arduino IDE

Product Overview

The Nano Matter merges the well-known Arduino way of making complex technology more accessible with the powerful MGM240S from Silicon Labs, to bring Matter closer to the maker world, in one of the smallest form factors in the market.

It enables 802.15.4 (Thread®) and Bluetooth® Low Energy connectivity, to interact with Matter-compatible devices with a user-friendly software layer ready for quick prototyping.

Board Architecture Overview

The Nano Matter features a compact and efficient architecture powered by the MGM240S (32-bit Arm® Cortex®-M33) from Silicon Labs, a high-performance wireless module optimized for the needs of battery and line-powered IoT devices for 2.4 GHz mesh networks.

Nano Matter's main components
Nano Matter's main components

Here is an overview of the board's main components, as shown in the image above:

  • Microcontroller: at the heart of the Nano Matter is the MGM240S, a high-performance wireless module from Silicon Labs. The MGM240S is built around a 32-bit Arm® Cortex®-M33 processor running at 78 MHz.
  • Wireless connectivity: the Nano Matter microcontroller also features multi-protocol connectivity to enable Matter IoT protocol and Bluetooth® Low Energy. This allows the Nano Matter to be integrated with smart home systems and communicate wirelessly with other devices.

Pinout

Nano Matter Simple pinout
Nano Matter Simple pinout

The full pinout is available and downloadable as PDF from the link below:

Datasheet

The complete datasheet is available and downloadable as PDF from the link below:

Schematics

The complete schematics are available and downloadable as PDF from the link below:

STEP Files

The complete STEP files are available and downloadable from the link below:

Form Factor

The Nano Matter board features castellated pins, which are ideal for integrating the board into final solutions.

You can easily solder the Nano Matter in your custom PCB, since the board does not present any bottom-mounted components.

Nano Matter castellated pins
Nano Matter castellated pins

First Use

Powering the Board

The Nano Matter can be powered by:

  • A USB-C® cable (not included).
  • An external 5 V power supply connected to
    IN5V
    pin (please, refer to the board pinout section of the user manual).

Nano Matter externally powered
Nano Matter externally powered

For low-power consumption applications, the following hacks are recommended:

  • Cut the power status LED jumper off to save energy.
  • Power the board with an external 3.3 V power supply connected to 3.3V pin. This will not power the USB bridge IC, so more energy will be saved.

Image showing the LED jumper and external 3.3 V power
Image showing the LED jumper and external 3.3 V power

To power the board through the VIN pin you need to close the jumper pads with solder. The maximum voltage supported is +5 VDC.

Install Board Core and Libraries

The Silicon Labs core contains the libraries and examples you need to work with the board's components, such as its Matter, Bluetooth® Low Energy, and I/Os. To install the Nano Matter core, navigate to File > Preferences and in the Additional boards manager URLs, add the following:

https://siliconlabs.github.io/arduino/package_arduinosilabs_index.json

Now navigate to Tools > Board > Boards Manager or click the Boards Manager icon in the left tab of the IDE. In the Boards Manager tab, search for

Nano Matter
and install the latest
Silicon Labs
core version.

Installing the Silicon Labs core in the Arduino IDE
Installing the Silicon Labs core in the Arduino IDE

Hello World Example

Let's program the Nano Matter with the classic

hello world
example typical of the Arduino ecosystem: the
Blink
sketch. We will use this example to verify that the board is correctly connected to the Arduino IDE and that the Silicon Labs core and the board itself are working as expected.

Copy and paste the code below into a new sketch in the Arduino IDE.

1// the setup function runs once when you press reset or power the board
2void setup() {
3 // initialize digital pin LED_BUILTIN as an output.
4 pinMode(LED_BUILTIN, OUTPUT);
5}
6
7// the loop function runs over and over again forever
8void loop() {
9 digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
10 delay(1000); // wait for a second
11 digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
12 delay(1000); // wait for a second
13}

In the Nano Matter, the

LED_BUILTIN
macro represents the red LED of the built-in RGB LED of the board. Please refer to the image below.

To upload the code to the Nano Matter, click the Verify button to compile the sketch and check for errors; then click the Upload button to program the board with the sketch.

Uploading a sketch to the Nano Matter in the Arduino IDE
Uploading a sketch to the Nano Matter in the Arduino IDE

You should now see the red LED of the built-in RGB LED turning on for one second, then off for one second, repeatedly.

Hello World example running in the Nano Matter

If everything works as expected, you are ready to continue searching and experimenting with this mighty board.

Matter

Developing Matter-compatible IoT solutions has never been easier with the Arduino ecosystem.

Nano Matter
Nano Matter

The Nano Matter can communicate with Matter hubs through a Thread® network, so the hubs used must be Thread® border routers.

The Silicon Labs core in the Arduino IDE comes with several Matter examples ready to be tested with the Nano Matter and works as a starting point for almost any IoT device we can imagine building.

Matter examples
Matter examples

The matter_lightbulb example is the only officially Matter-certified profile for the Nano Matter Community Preview. Consequently, while running any of the other available profile examples, it is expected to get an Uncertified device message in the different Matter-compatible apps. This does not prevent the user from prototyping a solution with different configurations.

First, to start creating Matter-enabled solutions, we need to select the Matter protocol in Tools > Protocol stack > Matter:

Matter Protocol stack selected
Matter Protocol stack selected

In the example below, we are going to use the Nano Matter as a RGB Lightbulb. For this, navigate to File > Examples > Matter and open the built-in sketch called nano_matter_lightbulb_color.

1#include <Matter.h>
2#include <MatterLightbulb.h>
3
4#define LED_R LED_BUILTIN
5#define LED_G LED_BUILTIN_1
6#define LED_B LED_BUILTIN_2
7
8MatterColorLightbulb matter_color_bulb;
9
10void update_led_color();
11void led_off();
12void handle_button_press();
13volatile bool button_pressed = false;
14
15void setup()
16{
17 Serial.begin(115200);
18 Matter.begin();
19 matter_color_bulb.begin();
20 matter_color_bulb.boost_saturation(51); // Boost saturation by 20 percent
21
22 // Set up the onboard button
23 pinMode(BTN_BUILTIN, INPUT_PULLUP);
24 attachInterrupt(BTN_BUILTIN, &handle_button_press, FALLING);
25
26 // Turn the LED off
27 led_off();
28
29 Serial.println("Arduino Nano Matter - color lightbulb");
30
31 if (!Matter.isDeviceCommissioned()) {
32 Serial.println("Matter device is not commissioned");
33 Serial.println("Commission it to your Matter hub with the manual pairing code or QR code");
34 Serial.printf("Manual pairing code: %s\n", Matter.getManualPairingCode().c_str());
35 Serial.printf("QR code URL: %s\n", Matter.getOnboardingQRCodeUrl().c_str());
36 }
37 while (!Matter.isDeviceCommissioned()) {
38 delay(200);
39 }
40
41 Serial.println("Waiting for Thread network...");
42 while (!Matter.isDeviceThreadConnected()) {
43 delay(200);
44 }
45 Serial.println("Connected to Thread network");
46
47 Serial.println("Waiting for Matter device discovery...");
48 while (!matter_color_bulb.is_online()) {
49 delay(200);
50 }
51 Serial.println("Matter device is now online");
52}
53
54void loop()
55{
56 // If the physical button state changes - update the lightbulb's on/off state
57 if (button_pressed) {
58 button_pressed = false;
59 // Toggle the on/off state of the lightbulb
60 matter_color_bulb.toggle();
61 }
62
63 // Get the current on/off state of the lightbulb
64 static bool matter_lightbulb_last_state = false;
65 bool matter_lightbulb_current_state = matter_color_bulb.get_onoff();
66
67 // If the current state is ON and the previous was OFF - turn on the LED
68 if (matter_lightbulb_current_state && !matter_lightbulb_last_state) {
69 matter_lightbulb_last_state = matter_lightbulb_current_state;
70 Serial.println("Bulb ON");
71 // Set the LEDs to the last received state
72 update_led_color();
73 }
74
75 // If the current state is OFF and the previous was ON - turn off the LED
76 if (!matter_lightbulb_current_state && matter_lightbulb_last_state) {
77 matter_lightbulb_last_state = matter_lightbulb_current_state;
78 Serial.println("Bulb OFF");
79 led_off();
80 }
81
82 static uint8_t hue_prev = 0;
83 static uint8_t saturation_prev = 0;
84 static uint8_t brightness_prev = 0;
85 uint8_t hue_curr = matter_color_bulb.get_hue();
86 uint8_t saturation_curr = matter_color_bulb.get_saturation_percent();
87 uint8_t brightness_curr = matter_color_bulb.get_brightness_percent();
88
89 // If either the hue, saturation or the brightness changes - update the LED to reflect the latest change
90 if (hue_prev != hue_curr || saturation_prev != saturation_curr || brightness_prev != brightness_curr) {
91 update_led_color();
92 hue_prev = hue_curr;
93 saturation_prev = saturation_curr;
94 brightness_prev = brightness_curr;
95 }
96}
97
98// Updates the color of the RGB LED to match the Matter lightbulb's color
99void update_led_color()
100{
101 if (!matter_color_bulb.get_onoff()) {
102 return;
103 }
104 uint8_t r, g, b;
105 matter_color_bulb.get_rgb(&r, &g, &b);
106 // If our built-in LED is active LOW, we need to invert the brightness values
107 if (LED_BUILTIN_ACTIVE == LOW) {
108 analogWrite(LED_R, 255 - r);
109 analogWrite(LED_G, 255 - g);
110 analogWrite(LED_B, 255 - b);
111 } else {
112 analogWrite(LED_R, r);
113 analogWrite(LED_G, g);
114 analogWrite(LED_B, b);
115 }
116 Serial.printf("Setting bulb color to > r: %u g: %u b: %u\n", r, g, b);
117}
118
119// Turns the RGB LED off
120void led_off()
121{
122 // If our built-in LED is active LOW, we need to invert the brightness values
123 if (LED_BUILTIN_ACTIVE == LOW) {
124 analogWrite(LED_R, 255);
125 analogWrite(LED_G, 255);
126 analogWrite(LED_B, 255);
127 } else {
128 analogWrite(LED_R, 0);
129 analogWrite(LED_G, 0);
130 analogWrite(LED_B, 0);
131 }
132}
133
134void handle_button_press()
135{
136 static uint32_t btn_last_press = 0;
137 if (millis() < btn_last_press + 200) {
138 return;
139 }
140 btn_last_press = millis();
141 button_pressed = true;
142}

Here is the example sketch main functions explanation:

  • In the

    setup()
    function, Matter is initialized with
    Matter.begin()
    alongside the initial configurations of the board to handle the different inputs and outputs.

  • The device commissioning is verified with

    Matter.isDeviceCommissioned()
    to show the user the network pairing credentials if needed, and the connection is confirmed with the
    Matter.isDeviceThreadConnected()
    function.

  • With the

    matter_color_bulb.is_online()
    function, we confirm that the device is online and reachable by the coordinator app.

  • In the

    loop()
    function, the RGB LED is controlled on and off with
    matter_color_bulb.set_onoff(state)
    , the current state is retrieved with
    matter_color_bulb.get_onoff()
    and the button state is read to control the LED manually.

  • In the

    update_led_color()
    function, the color defined in the app is retrieved using the function
    matter_color_bulb.get_rgb(&r, &g, &b)
    that stores the requested color code in RGB format variables.

To upload the code to the Nano Matter, click the Verify button to compile the sketch and check for errors; then click the Upload button to program the board with the sketch.

Upload the Matter RGB example
Upload the Matter RGB example

After the code is uploaded, open the Arduino IDE Serial Monitor and reset the board by clicking on the reset button. To commission a Matter device to the network you will need the credentials shown in the terminal.

Nano Matter Reset Button
Nano Matter Reset Button

You will find a Manual pairing code and a QR code URL as follows:

Commissioning credentials
Commissioning credentials

Open the QR code URL on your browser to generate the QR code.

With Google Home™

To create your first IoT device with the Nano Matter and the Google Home ecosystem, you first need to have a Matter-compatible hub. The Google Home products that can work as a Matter hub through Thread® are listed below:

  • Nest Hub (2nd Gen)
  • Nest Hub Max
  • Nest Wifi Pro (Wi-Fi 6E)
  • Nest Wifi

Other Google devices are compatible with Matter but not Thread®.

To commission your device, open the Google Home app, navigate to devices, click on add device and select the matter-enabled device option:

Adding a new Matter device to Google Home
Adding a new Matter device to Google Home

Then, wait for the device to be commissioned and added to the Google Home app:

Device added
Device added

Finally, you will be able to control the Nano Matter built-in RGB LED as a native smart device. You can turn it on and off and control its color and brightness.

RGB Lightbulb with Nano Matter

You are also able to control your device using voice commands with your personal assistant.

If you want to commission your Nano Matter solution with another service, follow the steps in the decommissioning section.

With Amazon Alexa

The Amazon Alexa products that can work as a Matter hub through Thread® are listed below:

  • Echo (4th Gen)
  • Echo Show 10 (3rd Gen)
  • Echo Show 8 (3rd Gen)
  • Echo Hub
  • Echo Studio (2nd Gen)
  • Echo Plus (2nd Gen)
  • eero Pro 6 and 6E
  • eero 6 and 6+
  • eero PoE 6 and gateway
  • eero Pro
  • eero Beacon
  • eero Max 7

Other Amazon devices are compatible with Matter but not Thread®.

To commission your device, open the Amazon Alexa app, click on the upper right + symbol, select device and select the Matter logo option:

Adding a new Matter device to Amazon Alexa
Adding a new Matter device to Amazon Alexa

Read the QR code generated by the Nano Matter sketch, select the Thread® network available and then wait for the device to be commissioned and added to the Alexa app:

Device added
Device added

Finally, you will be able to control the Nano Matter built-in RGB LED as a native smart device. You can turn it on and off and control its color and brightness.

RGB Lightbulb with Nano Matter

You are also able to control your device using voice commands with your personal assistant.

If you want to commission your Nano Matter solution with another service, follow the steps in the decommissioning section.

With Apple Home

The Apple Home products that can work as a Matter hub through Thread® are listed below:

  • Apple TV 4K (3rd generation) Wi-Fi + Ethernet
  • Apple TV 4K (2nd generation)
  • HomePod (2nd generation)
  • HomePod mini

To commission your device, open the Apple Home app, click on the upper right + symbol, select Add Accessory and scan the QR code generated by the Nano Matter in the Serial Monitor:

Adding a new Matter device to Apple Home
Adding a new Matter device to Apple Home

If this is your first Matter device, you may be asked to define the Matter hub to be used. Select its house location and give it a name:

Selecting the Matter hub (Bridge)
Selecting the Matter hub (Bridge)

Then, follow the steps for adding and naming the Matter Light bulb:

Adding the Light bulb
Adding the Light bulb

Finally, you will be able to control the Nano Matter built-in RGB LED as a native smart device. You can turn it on and off and control its color and brightness.

RGB Lightbulb with Nano Matter

You are also able to control your device using voice commands with your personal assistant.

If you want to commission your Nano Matter solution with another service, follow the steps in the decommissioning section.

With Home Assistant

To use Matter with Home Assistant, you will need one of the Google Home or Apple Home devices that can work as a Thread® Border Router, as listed in the previous sections.

To set up Home Assistant so that it can manage Matter devices, we need first to install the Matter Server add-on. For this, navigate to Settings > Add-Ons > Add-On Store and search for Matter server:

Installing the Matter Server
Installing the Matter Server

When the Matter server is correctly installed, navigate to Settings > Devices & Services > Add Integration and search for Matter:

Installing the Matter integration
Installing the Matter integration

A prompt will show up asking for a connection method; if you are working with custom containers running the Matter server, uncheck the box.

In our case, we leave it checked as the Matter server is running in Home Assistant.

You will receive a Success message if everything is okay. With the Home Assistant integration ready, we can start with the Nano Matter commissioning.

To commission your device, open the Home Assistant app on your smartphone, go to Settings > Devices & Services, in the lower tabs bar, go to Devices and tap on Add Device. Tap on Add Matter device and scan the QR code generated by the Nano Matter in the Serial Monitor:

Adding a new Matter device to Home Assistant
Adding a new Matter device to Home Assistant

Then, wait for the device to be commissioned and added to the Home Assistant app:

Device Added
Device Added

Finally, you will be able to control the Nano Matter built-in RGB LED as a native smart device. You can turn it on and off and control its color and brightness.

You can use the Home Assistant web view or mobile app to control your device.

RGB Lightbulb with Nano Matter

If you want to commission your Nano Matter solution with another service, follow the steps in the decommissioning section.

We tested the Matter integration with the Home Assistant OS and hosting Home Assistant in Docker containers.

Home Assistant Tips

  • Make sure you are using a 64-bit Home Assistant version (OS or Docker containerized version).
  • Use the Thread® add-on to verify your available Thread® networks.
  • You can just have a Matter device commissioned to one platform at a time.

Be aware that the Matter integration for Home Assistant is still in BETA, it can receive major updates and its functionality may vary between different vendors.

Device Decommissioning

If you have a Matter device configured and working with a specific platform, for example with the Google Home ecosystem, and you want to integrate it with Alexa or Apple Home instead, you need to decommission it first from the previous service.

In simple terms, decommissioning refers to unpairing your device from a current service to be able to pair it with a new one.

You can integrate this method in your solutions to leverage the Nano Matter built-in button to handle decommissioning:

1#include <Matter.h>
2
3void setup() {
4 // put your setup code here, to run once:
5 Serial.begin(115200);
6
7 Matter.begin();
8 pinMode(BTN_BUILTIN, INPUT_PULLUP);
9 pinMode(LEDR, OUTPUT);
10 digitalWrite(LEDR, HIGH);
11}
12
13void loop() {
14 // put your main code here, to run repeatedly:
15 decommission_handler();
16}
17
18
19void decommission_handler() {
20 if (digitalRead(BTN_BUILTIN) == LOW) { //Push button pressed
21 // measures time pressed
22 int startTime = millis();
23 while (digitalRead(BTN_BUILTIN) == LOW) {
24
25 int elapsedTime = (millis() - startTime) / 1000.0;
26
27 if (elapsedTime > 10) {
28 Serial.printf("Decommissioning!\n");
29 for (int i = 0; i < 10; i++) {
30 digitalWrite(LEDR, !(digitalRead(LEDR)));
31 delay(100);
32 };
33
34 if (!Matter.isDeviceCommissioned()) {
35 Serial.println("Decommission done!");
36 digitalWrite(LEDR, LOW);
37 } else {
38 Serial.println("Matter device is commissioned-> Starting Decommission process");
39 nvm3_eraseAll(nvm3_defaultHandle); // Decomission command
40 digitalWrite(LED_BUILTIN, LOW);
41 Serial.println("Decommission done!");
42 }
43 break;
44 }
45 }
46 }
47}

The sketch above allows you to decommission your board manually after pressing the Nano Matter user button for 10 seconds. You can monitor the status in the Arduino IDE Serial Monitor.

Arduino Cloud

The Nano Matter has no built-in Wi-Fi® but can be seamlessly integrated with the Arduino Cloud using its API and Matter.

We are going to use the Home Assistant Matter integration to create automations and scripts that help us forward the Nano Matter data to the Arduino Cloud.

In case it is the first time you are using the Arduino Cloud:

  • To use the Arduino Cloud, you need an account. If you do not have an account, create one for free here.
  • See the Arduino Cloud plans and choose one that features API support.

As a practical example, we are going to use the Nano Matter CPU temperature sensor and send the data to Arduino Cloud for monitoring. We will leverage the variety of widgets to create a professional and nice-looking user interface.

Nano Matter Programming

The application sketch below is based on the

matter_temp_sensor
example that can be also found in File > Examples > Matter. This variation includes the decommission feature to show it implemented in a real application.

1#include <Matter.h>
2#include <MatterTemperature.h>
3
4MatterTemperature matter_temp_sensor;
5
6void setup()
7{
8 Serial.begin(115200);
9 Matter.begin();
10
11 pinMode(BTN_BUILTIN, INPUT_PULLUP);
12 pinMode(LEDR, OUTPUT);
13 digitalWrite(LEDR, HIGH);
14
15 matter_temp_sensor.begin();
16
17 Serial.println("Matter temperature sensor");
18
19 if (!Matter.isDeviceCommissioned()) {
20 Serial.println("Matter device is not commissioned");
21 Serial.println("Commission it to your Matter hub with the manual pairing code or QR code");
22 Serial.printf("Manual pairing code: %s\n", Matter.getManualPairingCode().c_str());
23 Serial.printf("QR code URL: %s\n", Matter.getOnboardingQRCodeUrl().c_str());
24 }
25 while (!Matter.isDeviceCommissioned()) {
26 delay(200);
27 decommission_handler(); // if the user button is pressed for 10 seconds
28 }
29
30 Serial.println("Waiting for Thread network...");
31 while (!Matter.isDeviceThreadConnected()) {
32 delay(200);
33 decommission_handler();
34 }
35 Serial.println("Connected to Thread network");
36
37 Serial.println("Waiting for Matter device discovery...");
38 while (!matter_temp_sensor.is_online()) {
39 delay(200);
40 decommission_handler();
41 }
42 Serial.println("Matter device is now online");
43}
44
45void loop()
46{
47 decommission_handler(); // if the user button is pressed for 10 seconds
48
49 float current_cpu_temp = getCPUTemp();
50 matter_temp_sensor.set_measured_value_celsius(current_cpu_temp);
51 Serial.printf("Current CPU temperature: %.02f C\n", current_cpu_temp);
52 delay(2000);
53}
54
55void decommission_handler() {
56 if (digitalRead(BTN_BUILTIN) == LOW) { //Push button pressed
57 // measures time pressed
58 int startTime = millis();
59 while (digitalRead(BTN_BUILTIN) == LOW) {
60 //delay(50);
61
62 int elapsedTime = (millis() - startTime) / 1000.0;
63
64 if (elapsedTime > 10) {
65 Serial.printf("Decommissioning!\n");
66 for (int i = 0; i < 10; i++) {
67 digitalWrite(LEDR, !(digitalRead(LEDR)));
68 delay(100);
69 };
70
71 if (!Matter.isDeviceCommissioned()) {
72 Serial.println("Decommission done!");
73 digitalWrite(LEDR, LOW);
74 } else {
75 Serial.println("Matter device is commissioned-> Starting Decommission process");
76 nvm3_eraseAll(nvm3_defaultHandle); // Decomission command
77 digitalWrite(LED_BUILTIN, LOW);
78 Serial.println("Decommission done!");
79 }
80 break;
81 }
82 }
83 }
84}

The main code functions are explained below:

  • The temperature sensor object is created with the
    MatterTemperature matter_temp_sensor;
    statement. To initiate it, in the
    setup()
    function, we used
    matter_temp_sensor.begin();
  • The
    decommission_handler()
    lets us unpair the device from a previous platform.
  • The microcontroller's internal temperature is measured with the function
    getCPUTemp();
    .
  • The temperature value is advertised using the
    matter_temp_sensor.set_measured_value_celsius(current_cpu_temp);
    function.

After uploading the code to the Nano Matter, verify it is decommissioned from any other service previously used. For this, open the Serial Monitor and reset the board by clicking on the reset button.

If it is not decommissioned you will see temperature readings printed in the Serial Monitor. To decommission it, follow these steps:

  • Press the user button for 10 seconds until the board's built-in LED starts blinking in red. You will also see a message confirming the process in the Serial Monitor.

  • Finally, reset the board by clicking on the reset button and you should see the Matter commissioning credentials in the Serial Monitor.

Device Commissioning

Now it is time to commission the Nano Matter with Home Assistant, for this, follow the steps explained in this section.

Once you have everything set up and running you will be able to monitor the Nano Matter temperature in Home Assistant:

Nano Matter Temperature in Home Assistant
Nano Matter Temperature in Home Assistant

Be aware that the Matter integration for Home Assistant is still in BETA, it can receive major updates and its functionality may vary between different vendors.

Arduino Cloud Set-Up

Let's walk through a step-by-step demonstration of how to set up the Arduino Cloud.

Log in to your Arduino Cloud account; you should see the following:

Arduino Cloud Initial Page
Arduino Cloud Initial Page

Navigate to Things in the left bar menu and click on + Thing to add a Thing:

Creating a Thing
Creating a Thing

Give your Thing a name and click on ADD to add the temperature variable:

Adding a variable
Adding a variable

Define the variable with the following settings:

  • Name: temperature
  • Type: Floating Point Number
  • Permission: Read & Write
  • Update Policy: On change

Setting up the variable
Setting up the variable

Click on the created variable and copy its ID, we will need it later.

Variable ID
Variable ID

Navigate to your Thing metadata and copy the Thing ID, we will need it later.

Thing ID
Thing ID

In the left bar menu, navigate to Space Settings and copy the Space ID, we will need it later.

Space ID
Space ID

If you can't see the Space Settings section is because you are using an Arduino Cloud free plan, check the plans with the API feature enabled.

At this point you should have three IDs related to your project:

  • Variable ID
  • Thing ID
  • Space ID

To properly authenticate the requests we are going to use to upload the data to the Arduino Cloud we need to create API Keys.

For this, navigate to API Keys in the upper left corner drop-down menu and click on Create API Key:

API Keys generation
API Keys generation

You should get a Client ID and a Client Secret. Save these credentials in a safe place, you will not be able to see them again.

Home Assistant Set-Up

Now, let's configure Home Assistant to set the forwarding method to Arduino Cloud.

First, we are going to save and define our project IDs, credentials and Keys in a safe place inside the Home Assistant directory called secrets.yaml. Use the File Editor Add-on to easily edit this file, and format the data as follows:

1arduino_organization: <Space ID>
2
3token_get_payload: '{"grant_type":"client_credentials","client_id":"<your client ID>","client_secret":"<your client secret>","audience":"https://api2.arduino.cc/iot"}'
4
5arduino_temp_url: https://api2.arduino.cc/iot/v2/things/<your Thing ID>/properties/<temperature variable ID>/publish

This will let us use this data without exposing it later.

Secrets.yaml file to store credentials
Secrets.yaml file to store credentials

Now, let's define the services that will help us do the HTTP requests to Arduino Cloud sending the temperature value to it. Using the File Editor navigate to the configuration.yaml file and add the following blocks:

1rest:
2 - resource: "https://api2.arduino.cc/iot/v1/clients/token"
3 scan_interval: 240 #4 min
4 timeout: 60
5 method: "POST"
6 headers:
7 content_type: 'application/json,application/x-www-form-urlencoded'
8 payload: !secret token_get_payload
9 sensor:
10 - name: "API_Token_Bearer"
11 value_template: "OK"
12 json_attributes_path: '$..'
13 json_attributes:
14 - 'access_token'

The RESTful integration lets us periodically gather from our Arduino Cloud account a token that is mandatory to authenticate our requests. This token expires every 5 minutes, this is why we generate it every 4 minutes. The token is stored in a sensor attribute called API_Token_Bearer.

1rest_command:
2 send_temperature:
3 method: PUT
4 headers:
5 Authorization: "Bearer {{ state_attr('sensor.api_token_bearer', 'access_token') }}"
6 accept: "application/vnd.arduino.property+json,application/vnd.goa.error+json"
7 content_type: 'application/json,application/x-www-form-urlencoded'
8 X-Organization: !secret arduino_organization
9 url: !secret arduino_temp_url
10 payload: "{\"value\":{{states('sensor.matter_device_temperature')}}}"

The RESTful command integration lets us define the HTTP request structure to be able to send the Nano Matter temperature sensor data to the Arduino Cloud. We can call this service from an automation.

As you may noticed, the sensitive data we stored in the "secrets.yaml" file is being called here with the !secret prefix.

configuration.yaml file to define services
configuration.yaml file to define services

To learn more about the Arduino Cloud API, follow this guide.

For the changes to take effect, navigate to Developers Tools and click on Check Configuration, if there are no errors, click on Restart and restart Home Assistant.

Restarting Home Assistant
Restarting Home Assistant

Finally, let's set up the automation that will call the send_temperature service every time the temperature sensor values change.

For this, navigate to Settings > Automations & scenes and click on Create Automation.

Automation setting
Automation setting

In the upper right corner, click on the "three dots" menu and select Edit in YAML, replace the text there with the following:

1alias: Nano Matter Temperature
2description: ""
3trigger:
4 - platform: state
5 entity_id:
6 - sensor.matter_device_temperature
7condition: []
8action:
9 - service: rest_command.send_temperature
10 data: {}
11mode: single

This automation will be triggered if the Nano Matter sensor temperature value changes and will act by calling the rest_command.send_temperature service.

Automation defining
Automation defining

If you used different names for the services or devices, make sure to update them in the YAML code above.

Final Results

With this done, Home Assistant should be forwarding the Nano Matter sensor data to Arduino Cloud where you can monitor it with different widgets and charts as follows:

Arduino Cloud Demo

Bluetooth® Low Energy

To enable Bluetooth® Low Energy communication on the Nano Matter, you must enable the "BLE" protocol stack in the Arduino IDE board configurations.

In the upper menu, navigate to Tools > Protocol stack and select BLE.

Enable "BLE" Protocol Stack
Enable "BLE" Protocol Stack

For this Bluetooth® Low Energy application example, we are going to control the Nano Matter built-in LED and read the onboard button status. The example sketch to be used can be found in File > Examples > Silicon Labs > ble_blinky:

1/*
2 BLE blinky example
3*/
4
5bool btn_notification_enabled = false;
6bool btn_state_changed = false;
7uint8_t btn_state = LOW;
8static void btn_state_change_callback();
9static void send_button_state_notification();
10static void set_led_on(bool state);
11
12void setup()
13{
14 pinMode(LED_BUILTIN, OUTPUT);
15 digitalWrite(LED_BUILTIN, LED_BUILTIN_INACTIVE);
16 set_led_on(false);
17 Serial.begin(115200);
18 Serial.println("Silicon Labs BLE blinky example");
19
20 // If the board has a built-in button configure it for usage
21 #ifdef BTN_BUILTIN
22 pinMode(BTN_BUILTIN, INPUT_PULLUP);
23 attachInterrupt(BTN_BUILTIN, btn_state_change_callback, CHANGE);
24 #else // BTN_BUILTIN
25 // Avoid warning for unused function on boards without a button
26 (void)btn_state_change_callback;
27 #endif // BTN_BUILTIN
28}
29
30void loop()
31{
32 if (btn_state_changed) {
33 btn_state_changed = false;
34 send_button_state_notification();
35 }
36}
37
38static void ble_initialize_gatt_db();
39static void ble_start_advertising();
40
41static const uint8_t advertised_name[] = "Blinky Example";
42static uint16_t gattdb_session_id;
43static uint16_t generic_access_service_handle;
44static uint16_t name_characteristic_handle;
45static uint16_t blinky_service_handle;
46static uint16_t led_control_characteristic_handle;
47static uint16_t btn_report_characteristic_handle;
48
49/**************************************************************************//**
50 * Bluetooth stack event handler
51 * Called when an event happens on BLE the stack
52 *
53 * @param[in] evt Event coming from the Bluetooth stack
54 *****************************************************************************/
55void sl_bt_on_event(sl_bt_msg_t *evt)
56{
57 switch (SL_BT_MSG_ID(evt->header)) {
58 // -------------------------------
59 // This event indicates the device has started and the radio is ready.
60 // Do not call any stack command before receiving this boot event!
61 case sl_bt_evt_system_boot_id:
62 {
63 Serial.println("BLE stack booted");
64
65 // Initialize the application specific GATT table
66 ble_initialize_gatt_db();
67
68 // Start advertising
69 ble_start_advertising();
70 Serial.println("BLE advertisement started");
71 }
72 break;
73
74 // -------------------------------
75 // This event indicates that a new connection was opened
76 case sl_bt_evt_connection_opened_id:
77 Serial.println("BLE connection opened");
78 break;
79
80 // -------------------------------
81 // This event indicates that a connection was closed
82 case sl_bt_evt_connection_closed_id:
83 Serial.println("BLE connection closed");
84 // Restart the advertisement
85 ble_start_advertising();
86 Serial.println("BLE advertisement restarted");
87 break;
88
89 // -------------------------------
90 // This event indicates that the value of an attribute in the local GATT
91 // database was changed by a remote GATT client
92 case sl_bt_evt_gatt_server_attribute_value_id:
93 // Check if the changed characteristic is the LED control
94 if (led_control_characteristic_handle == evt->data.evt_gatt_server_attribute_value.attribute) {
95 Serial.println("LED control characteristic data received");
96 // Check the length of the received data
97 if (evt->data.evt_gatt_server_attribute_value.value.len == 0) {
98 break;
99 }
100 // Get the received byte
101 uint8_t received_data = evt->data.evt_gatt_server_attribute_value.value.data[0];
102 // Turn the LED on/off according to the received data
103 if (received_data == 0x00) {
104 set_led_on(false);
105 Serial.println("LED off");
106 } else if (received_data == 0x01) {
107 set_led_on(true);
108 Serial.println("LED on");
109 }
110 }
111 break;
112
113 // -------------------------------
114 // This event is received when a GATT characteristic status changes
115 case sl_bt_evt_gatt_server_characteristic_status_id:
116 // If the 'Button report' characteristic has been changed
117 if (evt->data.evt_gatt_server_characteristic_status.characteristic == btn_report_characteristic_handle) {
118 // The client just enabled the notification - send notification of the current button state
119 if (evt->data.evt_gatt_server_characteristic_status.client_config_flags & sl_bt_gatt_notification) {
120 Serial.println("Button state change notification enabled");
121 btn_notification_enabled = true;
122 btn_state_change_callback();
123 } else {
124 Serial.println("Button state change notification disabled");
125 btn_notification_enabled = false;
126 }
127 }
128 break;
129
130 // -------------------------------
131 // Default event handler
132 default:
133 break;
134 }
135}
136
137/**************************************************************************//**
138 * Called on button state change - stores the current button state and
139 * sets a flag that a button state change occurred.
140 * If the board doesn't have a button the function does nothing.
141 *****************************************************************************/
142static void btn_state_change_callback()
143{
144 // If the board has a built-in button
145 #ifdef BTN_BUILTIN
146 // The real button state is inverted - most boards have an active low button configuration
147 btn_state = !digitalRead(BTN_BUILTIN);
148 btn_state_changed = true;
149 #endif // BTN_BUILTIN
150}
151
152/**************************************************************************//**
153 * Sends a BLE notification the the client if notifications are enabled and
154 * the board has a built-in button.
155 *****************************************************************************/
156static void send_button_state_notification()
157{
158 if (!btn_notification_enabled) {
159 return;
160 }
161 sl_status_t sc = sl_bt_gatt_server_notify_all(btn_report_characteristic_handle,
162 sizeof(btn_state),
163 &btn_state);
164 if (sc == SL_STATUS_OK) {
165 Serial.print("Notification sent, button state: ");
166 Serial.println(btn_state);
167 }
168}
169
170/**************************************************************************//**
171 * Sets the built-in LED to the desired state accounting for the inverted LED
172 * logic on select boards.
173 *****************************************************************************/
174static void set_led_on(bool state)
175{
176 if (state) {
177 digitalWrite(LED_BUILTIN, LED_BUILTIN_ACTIVE);
178 } else {
179 digitalWrite(LED_BUILTIN, LED_BUILTIN_INACTIVE);
180 }
181}
182
183/**************************************************************************//**
184 * Starts BLE advertisement
185 * Initializes advertising if it's called for the first time
186 *****************************************************************************/
187static void ble_start_advertising()
188{
189 static uint8_t advertising_set_handle = 0xff;
190 static bool init = true;
191 sl_status_t sc;
192
193 if (init) {
194 // Create an advertising set
195 sc = sl_bt_advertiser_create_set(&advertising_set_handle);
196 app_assert_status(sc);
197
198 // Set advertising interval to 100ms
199 sc = sl_bt_advertiser_set_timing(
200 advertising_set_handle,
201 160, // minimum advertisement interval (milliseconds * 1.6)
202 160, // maximum advertisement interval (milliseconds * 1.6)
203 0, // advertisement duration
204 0); // maximum number of advertisement events
205 app_assert_status(sc);
206
207 init = false;
208 }
209
210 // Generate data for advertising
211 sc = sl_bt_legacy_advertiser_generate_data(advertising_set_handle, sl_bt_advertiser_general_discoverable);
212 app_assert_status(sc);
213
214 // Start advertising and enable connections
215 sc = sl_bt_legacy_advertiser_start(advertising_set_handle, sl_bt_advertiser_connectable_scannable);
216 app_assert_status(sc);
217}
218
219/**************************************************************************//**
220 * Initializes the GATT database
221 * Creates a new GATT session and adds certain services and characteristics
222 *****************************************************************************/
223static void ble_initialize_gatt_db()
224{
225 sl_status_t sc;
226 // Create a new GATT database
227 sc = sl_bt_gattdb_new_session(&gattdb_session_id);
228 app_assert_status(sc);
229
230 // Add the Generic Access service to the GATT DB
231 const uint8_t generic_access_service_uuid[] = { 0x00, 0x18 };
232 sc = sl_bt_gattdb_add_service(gattdb_session_id,
233 sl_bt_gattdb_primary_service,
234 SL_BT_GATTDB_ADVERTISED_SERVICE,
235 sizeof(generic_access_service_uuid),
236 generic_access_service_uuid,
237 &generic_access_service_handle);
238 app_assert_status(sc);
239
240 // Add the Device Name characteristic to the Generic Access service
241 // The value of the Device Name characteristic will be advertised
242 const sl_bt_uuid_16_t device_name_characteristic_uuid = { .data = { 0x00, 0x2A } };
243 sc = sl_bt_gattdb_add_uuid16_characteristic(gattdb_session_id,
244 generic_access_service_handle,
245 SL_BT_GATTDB_CHARACTERISTIC_READ,
246 0x00,
247 0x00,
248 device_name_characteristic_uuid,
249 sl_bt_gattdb_fixed_length_value,
250 sizeof(advertised_name) - 1,
251 sizeof(advertised_name) - 1,
252 advertised_name,
253 &name_characteristic_handle);
254 app_assert_status(sc);
255
256 // Start the Generic Access service
257 sc = sl_bt_gattdb_start_service(gattdb_session_id, generic_access_service_handle);
258 app_assert_status(sc);
259
260 // Add the Blinky service to the GATT DB
261 // UUID: de8a5aac-a99b-c315-0c80-60d4cbb51224
262 const uuid_128 blinky_service_uuid = {
263 .data = { 0x24, 0x12, 0xb5, 0xcb, 0xd4, 0x60, 0x80, 0x0c, 0x15, 0xc3, 0x9b, 0xa9, 0xac, 0x5a, 0x8a, 0xde }
264 };
265 sc = sl_bt_gattdb_add_service(gattdb_session_id,
266 sl_bt_gattdb_primary_service,
267 SL_BT_GATTDB_ADVERTISED_SERVICE,
268 sizeof(blinky_service_uuid),
269 blinky_service_uuid.data,
270 &blinky_service_handle);
271 app_assert_status(sc);
272
273 // Add the 'LED Control' characteristic to the Blinky service
274 // UUID: 5b026510-4088-c297-46d8-be6c736a087a
275 const uuid_128 led_control_characteristic_uuid = {
276 .data = { 0x7a, 0x08, 0x6a, 0x73, 0x6c, 0xbe, 0xd8, 0x46, 0x97, 0xc2, 0x88, 0x40, 0x10, 0x65, 0x02, 0x5b }
277 };
278 uint8_t led_char_init_value = 0;
279 sc = sl_bt_gattdb_add_uuid128_characteristic(gattdb_session_id,
280 blinky_service_handle,
281 SL_BT_GATTDB_CHARACTERISTIC_READ | SL_BT_GATTDB_CHARACTERISTIC_WRITE,
282 0x00,
283 0x00,
284 led_control_characteristic_uuid,
285 sl_bt_gattdb_fixed_length_value,
286 1, // max length
287 sizeof(led_char_init_value), // initial value length
288 &led_char_init_value, // initial value
289 &led_control_characteristic_handle);
290
291 // Add the 'Button report' characteristic to the Blinky service
292 // UUID: 61a885a4-41c3-60d0-9a53-6d652a70d29c
293 const uuid_128 btn_report_characteristic_uuid = {
294 .data = { 0x9c, 0xd2, 0x70, 0x2a, 0x65, 0x6d, 0x53, 0x9a, 0xd0, 0x60, 0xc3, 0x41, 0xa4, 0x85, 0xa8, 0x61 }
295 };
296 uint8_t btn_char_init_value = 0;
297 sc = sl_bt_gattdb_add_uuid128_characteristic(gattdb_session_id,
298 blinky_service_handle,
299 SL_BT_GATTDB_CHARACTERISTIC_READ | SL_BT_GATTDB_CHARACTERISTIC_NOTIFY,
300 0x00,
301 0x00,
302 btn_report_characteristic_uuid,
303 sl_bt_gattdb_fixed_length_value,
304 1, // max length
305 sizeof(btn_char_init_value), // initial value length
306 &btn_char_init_value, // initial value
307 &btn_report_characteristic_handle);
308
309 // Start the Blinky service
310 sc = sl_bt_gattdb_start_service(gattdb_session_id, blinky_service_handle);
311 app_assert_status(sc);
312
313 // Commit the GATT DB changes
314 sc = sl_bt_gattdb_commit(gattdb_session_id);
315 app_assert_status(sc);
316}

Here are the main functions explanations of the example sketch:

The

sl_bt_on_event(sl_bt_msg_t *evt)
function is the main one of the sketch and it is responsible for:

  • Initiating the Bluetooth® Low Energy radio, and start advertising the defined services alongside its characteristics.
  • Handling the opening and closing of connections.
  • Handling incoming and outgoing Bluetooth® Low Energy messages.

The

ble_initialize_gatt_db()
function is responsible for:

  • Adding the Generic Access service with the
    1800
    UUID.
  • Adding the Blinky service with the
    de8a5aac-a99b-c315-0c80-60d4cbb51224
    UUID.
  • Creating the device name characteristic so we can find the device as "Blinky Example" with the
    2A00
    UUID.
  • Adding the LED Control characteristic to the Blinky service with the
    5b026510-4088-c297-46d8-be6c736a087a
    UUID.
  • Adding the Button report characteristic to the Blinky service with the
    61a885a4-41c3-60d0-9a53-6d652a70d29c
    UUID.

Note that if you want to implement a different or custom Bluetooth® Low Energy service or characteristic, the UUID arrays have to start with the least significant bit (LSB) from left to right.

After uploading the sketch to the Nano Matter, it is time to communicate with it through Bluetooth® Low Energy. For this, Silicon Labs has developed a mobile app that you can download from here:

Open the EFR Connect BLE Mobile APP on your smartphone, in the lower menu, navigate to Demo and select Blinky:

Blinky demo controlling the Nano Matter through Bluetooth® Low Energy

You can also manage the LED control and button status manually from the Scan tab in the lower menu.

Onboard User Interface

User Button

The Nano Matter includes an onboard push button that can be used as an input by the user. The button is connected to the GPIO

PA0
and can be read using the
BTN_BUILTIN
macro.

Nano Matter Built-in Push Button
Nano Matter Built-in Push Button

The button pulls the input to the ground when pressed, so is important to define the pull-up resistor to avoid undesired behavior by leaving the input floating.

Here you can find a complete example code to blink the built-in RGB LED of the Nano Matter:

1volatile bool button_pressed = false;
2
3void handle_button_press();
4
5void setup() {
6 Serial.begin(115200);
7
8 pinMode(BTN_BUILTIN, INPUT_PULLUP);
9 attachInterrupt(BTN_BUILTIN, &handle_button_press, FALLING);
10}
11
12void loop() {
13 // If the physical button state changes - update the state
14 if (button_pressed) {
15 button_pressed = false;
16 Serial.println("Button Pressed!");
17 }
18}
19
20void handle_button_press()
21{
22 static uint32_t btn_last_press = 0;
23 if (millis() < btn_last_press + 200) {
24 return;
25 }
26 btn_last_press = millis();
27 button_pressed = true;
28}

After pressing the push button, you will see a "Button Pressed!" message in the Serial Monitor.

RGB LED

The Nano Matter features a built-in RGB LED that can be a visual feedback indicator for the user. The LED is connected through the board GPIO's; therefore, usual digital pins built-in functions can be used to operate the LED colors.

LED Color SegmentArduino NameMicrocontroller Pin
RedLEDR or LED_BUILTINPC01
GreenLEDG or LED_BUILTIN_1PC02
BlueLEDB or LED_BUILTIN_2PC03

The RGB LED colors are activated with zeros, this means that you need to set to LOW the color segment you want to turn on.

Built-in RGB LED
Built-in RGB LED

Here you can find a complete example code to blink the built-in RGB LED of the Nano Matter:

1void setup() {
2 // initialize LED digital pins as outputs.
3 pinMode(LEDR, OUTPUT);
4 pinMode(LEDG, OUTPUT);
5 pinMode(LEDB, OUTPUT);
6}
7
8// the loop function runs over and over again forever
9void loop() {
10 digitalWrite(LEDR, LOW); // turn the LED on (LOW is the voltage level)
11 digitalWrite(LEDG, HIGH); // turn the LED off (HIGH is the voltage level)
12 digitalWrite(LEDB, HIGH); // turn the LED off (HIGH is the voltage level)
13 delay(1000); // wait for a second
14 digitalWrite(LEDR, HIGH); // turn the LED off by making the voltage HIGH
15 digitalWrite(LEDG, LOW); // turn the LED on by making the voltage LOW
16 digitalWrite(LEDB, HIGH); // turn the LED off by making the voltage HIGH
17 delay(1000); // wait for a second
18 digitalWrite(LEDR, HIGH); // turn the LED off by making the voltage HIGH
19 digitalWrite(LEDG, HIGH); // turn the LED off by making the voltage HIGH
20 digitalWrite(LEDB, LOW); // turn the LED on by making the voltage LOW
21 delay(1000);
22}

Nano Matter built-in LED blink

Pins

Digital Pins

The Nano Matter has 22 digital pins, mapped as follows:

Microcontroller PinArduino Pin MappingPin Functionality
PB00A0 / DAC0GPIO / ADC / DAC
PB02A1 / DAC2GPIO / ADC / DAC
PB05A2GPIO / ADC
PC00A3GPIO / ADC
PA06A4 / SDAI2C / GPIO / ADC
PA07A5 / SCLI2C / GPIO / ADC
PB01A6 / DAC1GPIO / ADC / DAC
PB03A7 / DAC3GPIO / ADC / DAC
PB04D13 / SCKSPI / GPIO / ADC
PA08D12 / MISOSPI / GPIO / ADC
PA09D11 / MOSISPI / GPIO / ADC
PD05D10 / SSSPI / GPIO
PD04D9GPIO
PD03D8GPIO / ADC
PD02D7GPIO / ADC
PC09D6GPIO / ADC
PC08D5 / SCL1I2C / GPIO / ADC
PC07D4 / SDA1I2C / GPIO / ADC
PC06D3 / SS1GPIO / SPI / ADC
PA03D2 / SCK1SPI / GPIO
PA05D1 / PIN_SERIAL_RX1 / MISO1UART / SPI / GPIO / ADC
PA04D0 / PIN_SERIAL_TX1 / MOSI1UART / SPI / GPIO / ADC

The digital pins of the Nano Matter can be used as inputs or outputs through the built-in functions of the Arduino programming language.

The configuration of a digital pin is done in the

setup()
function with the built-in function
pinMode()
as shown below:

1// Pin configured as an input
2pinMode(pin, INPUT);
3
4// Pin configured as an output
5pinMode(pin, OUTPUT);
6
7// Pin configured as an input, internal pull-up resistor enabled
8pinMode(pin, INPUT_PULLUP);

The state of a digital pin, configured as an input, can be read using the built-in function

digitalRead()
as shown below:

1// Read pin state, store value in a state variable
2state = digitalRead(pin);

The state of a digital pin, configured as an output, can be changed using the built-in function

digitalWrite()
as shown below:

1// Set pin on
2digitalWrite(pin, HIGH);
3
4// Set pin off
5digitalWrite(pin, LOW);

The example code shown below uses digital pin

D5
to control an LED and reads the state of a button connected to digital pin
D4
:

Digital I/O example wiring
Digital I/O example wiring

1// Define button and LED pin
2int buttonPin = D4;
3int ledPin = D5;
4
5// Variable to store the button state
6int buttonState = 0;
7
8void setup() {
9 // Configure button and LED pins
10 pinMode(buttonPin, INPUT_PULLUP);
11 pinMode(ledPin, OUTPUT);
12
13 // Initialize Serial communication
14 Serial.begin(115200);
15}
16
17void loop() {
18 // Read the state of the button
19 buttonState = digitalRead(buttonPin);
20
21 // If the button is pressed, turn on the LED and print its state to the Serial Monitor
22 if (buttonState == LOW) {
23 digitalWrite(ledPin, HIGH);
24 Serial.println("- Button is pressed. LED is on.");
25 } else {
26 // If the button is not pressed, turn off the LED and print to the Serial Monitor
27 digitalWrite(ledPin, LOW);
28 Serial.println("- Button is not pressed. LED is off.");
29 }
30
31 // Wait for 1000 milliseconds
32 delay(1000);
33}

PWM Pins

All the digital and analog pins of the Nano Matter can be used as PWM (Pulse Width Modulation) pins.

You can only use 5 PWM outputs simultaneously.

This functionality can be used with the built-in function

analogWrite()
as shown below:

1analogWrite(pin, value);

By default, the output resolution is 8 bits, so the output value should be between 0 and 255. To set a greater resolution, do it using the built-in function

analogWriteResolution
as shown below:

1analogWriteResolution(bits);

Using this function has some limitations, for example, the PWM signal frequency is fixed at 1 kHz, and this could not be ideal for every application.

Here is an example of how to create a 1 kHz variable duty-cycle PWM signal:

1const int analogInPin = A0; // Analog input pin that the potentiometer is attached to
2const int pwmOutPin = D13; // PWM output pin
3
4int sensorValue = 0; // value read from the pot
5int outputValue = 0; // value output to the PWM (analog out)
6
7void setup() {
8 // initialize serial communications at 9600 bps:
9 Serial.begin(115200);
10 analogWriteResolution(12);
11}
12
13void loop() {
14 // read the analog in value:
15 sensorValue = analogRead(analogInPin);
16 // map it to the range of the analog out:
17 outputValue = sensorValue;
18 // change the analog out value:
19 analogWrite(pwmOutPin, outputValue);
20
21 // print the results to the Serial Monitor:
22 Serial.print("sensor = ");
23 Serial.print(sensorValue);
24 Serial.print("\t output = ");
25 Serial.println(outputValue);
26
27 // wait 2 milliseconds before the next loop for the analog-to-digital
28 // converter to settle after the last reading:
29 delay(2);
30}

PWM output signal using the PWM at a lower level
PWM output signal using the PWM at a lower level

If you need to work with a higher frequency PWM signal, you can do it with the following PWM class-specific function:

1PWM.frequency_mode(output_pin, frequency);

Here is an example of how to create a 10 kHz fixed duty-cycle PWM signal:

1const int analogOutPin = D13; // PWM output pin to use
2
3void setup() {
4 analogWriteResolution(12);
5}
6
7void loop() {
8 PWM.frequency_mode(analogOutPin, 10000);
9}

PWM output signal using the PWM at a lower level
PWM output signal using the PWM at a lower level

Analog Input Pins (ADC)

The Nano Matter has 20 analog input pins, mapped as follows:

Microcontroller PinArduino Pin MappingPin Functionality
PB00A0 / DAC0GPIO / ADC / DAC
PB02A1 / DAC2GPIO / ADC / DAC
PB05A2GPIO / ADC
PC00A3GPIO / ADC
PA06A4 / SDAI2C / GPIO / ADC
PA07A5 / SCLI2C / GPIO / ADC
PB01A6 / DAC1GPIO / ADC / DAC
PB03A7 / DAC3GPIO / ADC / DAC
PB04D13 / SCKSPI / GPIO / ADC
PA08D12 / MISOSPI / GPIO / ADC
PA09D11 / MOSISPI / GPIO / ADC
PD03D8GPIO / ADC
PD02D7GPIO / ADC
PC09D6GPIO / ADC
PC08D5 / SCL1I2C / GPIO / ADC
PC07D4 / SDA1I2C / GPIO / ADC
PC06D3 / SS1GPIO / SPI / ADC
PA03D2 / SCK1SPI / GPIO
PA05D1 / PIN_SERIAL_RX1 / MISO1UART / SPI / GPIO / ADC
PA04D0 / PIN_SERIAL_TX1 / MOSI1UART / SPI / GPIO / ADC

Digital I/O's can also be used as analog inputs except for

D9
and
D10
.

Analog input pins can be used through the built-in functions of the Arduino programming language.

Nano Matter ADC resolution is fixed to 12 bits and cannot be changed by the user.

The Nano Matter ADC reference voltage is 3.3 V by default, it can be configured using the function

analogReference()
with the following arguments:

ArgumentDescription
AR_INTERNAL1V2Internal 1.2V reference
AR_EXTERNAL_1V25External 1.25V reference
AR_VDDVDD (unbuffered to ground)
AR_08VDD0.8 * VDD (buffered to ground)
AR_MAXMaximum value

To set a different analog reference from the default one, see the following example:

1analogReference(AR_INTERNAL1V2);

The example code shown below reads the analog input value from a potentiometer connected to

A0
and displays it on the IDE Serial Monitor. To understand how to properly connect a potentiometer to the Nano Matter, take the following image as a reference:

ADC input example wiring
ADC input example wiring

1int sensorPin = A0; // select the input pin for the potentiometer
2
3int sensorValue = 0; // variable to store the value coming from the sensor
4
5void setup() {
6 Serial.begin(115200);
7}
8
9void loop() {
10 // read the value from the sensor:
11 sensorValue = analogRead(sensorPin);
12
13 Serial.println(sensorValue);
14 delay(100);
15}

Analog Output Pins (DAC)

The Nano Matter has two DACs with two channels each, mapped as follows:

Microcontroller PinArduino NameBoard Pin OutputPeripheral
PB00DAC0A0DAC0_CH0
PB01DAC1A6DAC0_CH1
PB02DAC2A1DAC1_CH0
PB03DAC3A7DAC1_CH1

The digital-to-analog converters of the Nano Matter can be used as outputs through the built-in functions of the Arduino programming language.

The DAC output resolution can be configured from 8 to 12 bits using the

analogWriteResolution()
function as follows:

1analogWriteResolution(12); // enter the desired resolution in bits (8,10,12)

The DAC voltage reference can be configured using the

analogReferenceDAC()
function. The available setups are listed below:

ArgumentDescription
DAC_VREF_1V25Internal 1.25V reference
DAC_VREF_2V5Internal 2.5V reference
DAC_VREF_AVDDAnalog VDD
DAC_VREF_EXTERNAL_PINExternal AREF pin
1analogReferenceDAC(DAC_VREF_2V5); // enter the desired reference as argument

To output an analog voltage value through a DAC pin, use the

analogWrite()
function with the DAC channel as an argument. See the example below:

1analogWrite(DAC0, value); // the value should be in the range of the DAC resolution (e.g. 0-4095 with a 12 bits resolution)

If a normal GPIO is passed to the analogWrite() function, the output will be a PWM signal.

The following sketch will create a sine wave signal in the

A0
Nano Matter pin:

1float sample_rate = 9600.0, freq = 60.0; //samples/second, AC waveform freq.
2int npts = sample_rate / freq;
3
4void setup()
5{
6 Serial.begin(115200);
7 // Set the DAC resolution to 12 bits
8 analogWriteResolution(12);
9 // Select the 1.25V reference voltage (feel free to change it)
10 analogReferenceDAC(DAC_VREF_1V25);
11}
12
13void loop()
14{
15
16 for (int i = 0; i < npts; i++) {
17 int x = 2000 + 1000.0 * sin(2 * PI * (freq / sample_rate) * i);
18 analogWrite(DAC0, x);
19 delayMicroseconds(1.0E6 / sample_rate); //adjust constant to get correct rate
20 }
21}

The DAC output should look like the image below:

DAC sine wave output
DAC sine wave output

The following sketch will create a sawtooth wave signal in the

A0
Nano Matter pin:

1void setup()
2{
3 Serial.begin(115200);
4 // Set the DAC resolution to 8 bits
5 analogWriteResolution(8);
6 // Select the 2.5V reference voltage (feel free to change it)
7 analogReferenceDAC(DAC_VREF_2V5);
8}
9
10void loop()
11{
12 static int value = 0;
13 analogWrite(DAC0, value);
14 Serial.println(value);
15
16 value++;
17 if (value == 255) {
18 value = 0;
19 }
20}

The DAC output should look like the image below:

DAC sawtooth wave output
DAC sawtooth wave output

Communication

This section of the user manual covers the different communication protocols that are supported by the Nano Matter, including the Serial Peripheral Interface (SPI), Inter-Integrated Circuit (I2C) and Universal Asynchronous Receiver-Transmitter (UART). The Nano Matter features dedicated pins for each communication protocol, simplifying the connection and communication with different components, peripherals, and sensors.

SPI

The Nano Matter supports SPI communication, which enables data transmission between the board and other SPI-compatible devices. It counts with two SPI interfaces and the pins used in the Nano Matter for the SPI communication protocol are the following:

Microcontroller PinArduino Pin Mapping
PD05SS or D10
PA09MOSI or D11
PA08MISO or D12
PB04SCK or D13
PA04MOSI1 or D0
PA05MISO1 or D1
PA03SCK1 or D2
PC06SS1 or D3

Please, refer to the board pinout section of the user manual to localize them on the board.

You can not use SPI1 and UART interfaces at the same time because they share pins.

Include the

SPI
library at the top of your sketch to use the SPI communication protocol. The SPI library provides functions for SPI communication:

1#include <SPI.h>

In the

setup()
function, initialize the SPI peripheral, define and configure the chip select (
SS
) pin:

Use SPI.begin() for SPI0 and SPI1.begin() for SPI1.

1void setup() {
2 // Set the chip select pin as output
3 pinMode(SS, OUTPUT);
4
5 // Pull the CS pin HIGH to unselect the device
6 digitalWrite(SS, HIGH);
7
8 // Initialize the SPI communication
9 SPI.begin();
10}

To transmit data to an SPI-compatible device, you can use the following commands:

1// Replace with the target device's address
2byte address = 0x35;
3
4// Replace with the value to send
5byte value = 0xFA;
6
7// Pull the CS pin LOW to select the device
8digitalWrite(SS, LOW);
9
10// Send the address
11SPI.transfer(address);
12
13// Send the value
14SPI.transfer(value);
15
16// Pull the CS pin HIGH to unselect the device
17digitalWrite(SS, HIGH);

The example code above should output this:

SPI logic data output
SPI logic data output

I2C

The Nano Matter supports I2C communication, which enables data transmission between the board and other I2C-compatible devices. The Nano Matter features two I2C interfaces and the pins used in the Nano Matter for the I2C communication protocol are the following:

Microcontroller PinArduino Pin Mapping
PA06SDA or A4
PA07SCL or A5
PC07SDA1 or D4
PC08SCL1 or D5

Please, refer to the board pinout section of the user manual to localize them on the board.

To use I2C communication, include the

Wire
library at the top of your sketch. The
Wire
library provides functions for I2C communication:

1#include <Wire.h>

In the

setup()
function, initialize the I2C library:

Use Wire.begin() for I2C0 and Wire1.begin() for I2C1.

1// Initialize the I2C communication
2Wire.begin();

To transmit data to an I2C-compatible device, you can use the following commands:

1// Replace with the target device's I2C address
2byte deviceAddress = 0x35;
3
4// Replace with the appropriate instruction byte
5byte instruction = 0x00;
6
7// Replace with the value to send
8byte value = 0xFA;
9
10// Begin transmission to the target device
11Wire.beginTransmission(deviceAddress);
12
13// Send the instruction byte
14Wire.write(instruction);
15
16// Send the value
17Wire.write(value);
18
19// End transmission
20Wire.endTransmission();

The output data should look like the image below, where we can see the device address data frame:

I2C output data
I2C output data

To read data from an I2C-compatible device, you can use the

requestFrom()
function to request data from the device and the
read()
function to read the received bytes:

1// The target device's I2C address
2byte deviceAddress = 0x1;
3
4// The number of bytes to read
5int numBytes = 2;
6
7// Request data from the target device
8Wire.requestFrom(deviceAddress, numBytes);
9
10// Read while there is data available
11while (Wire.available()) {
12 byte data = Wire.read();
13}

UART

The Nano Matter features two UARTs. The pins used in the Nano Matter for the UART communication protocol are the following:

Microcontroller PinArduino Pin Mapping
PA05PIN_SERIAL_RX1 or D1
PA04PIN_SERIAL_TX1 or D0
PC05PIN_SERIAL_RX (internal)
PC04PIN_SERIAL_TX (internal)

Please, refer to the board pinout section of the user manual to localize them on the board.

You can not use UART and SPI1 interfaces at the same time because they share pins.

Use Serial.begin() for UART0 (internal) and Serial1.begin() for UART1 (exposed).

To begin with UART communication, you will need to configure it first. In the

setup()
function, set the baud rate (bits per second) for UART communication:

1// Start UART communication at 115200 baud
2Serial1.begin(115200);

To read incoming data, you can use a

while()
loop to continuously check for available data and read individual characters. The code shown below stores the incoming characters in a String variable and processes the data when a line-ending character is received:

1// Variable for storing incoming data
2String incoming = "";
3
4void loop() {
5 // Check for available data and read individual characters
6 while (Serial1.available()) {
7 // Allow data buffering and read a single character
8 delay(2);
9 char c = Serial1.read();
10
11 // Check if the character is a newline (line-ending)
12 if (c == '\n') {
13 // Process the received data
14 processData(incoming);
15
16 // Clear the incoming data string for the next message
17 incoming = "";
18 } else {
19 // Add the character to the incoming data string
20 incoming += c;
21 }
22 }
23}

To transmit data to another device via UART, you can use the

write()
function:

1// Transmit the string "Hello world!
2Serial1.write("Hello world!");

You can also use the

print
and
println()
to send a string without a newline character or followed by a newline character:

1// Transmit the string "Hello world!"
2Serial1.print("Hello world!");
3
4// Transmit the string "Hello world!" followed by a newline character
5Serial1.println("Hello world!");

Serial communication example
Serial communication example

Support

If you encounter any issues or have questions while working with the Nano Matter, we provide various support resources to help you find answers and solutions.

Help Center

Explore our Help Center, which offers a comprehensive collection of articles and guides for the Nano Matter. The Arduino Help Center is designed to provide in-depth technical assistance and help you make the most of your device.

Forum

Join our community forum to connect with other Nano Matter users, share your experiences, and ask questions. The forum is an excellent place to learn from others, discuss issues, and discover new ideas and projects related to the Nano Matter.

Contact Us

Please get in touch with our support team if you need personalized assistance or have questions not covered by the help and support resources described before. We're happy to help you with any issues or inquiries about the Nano Matter.

Suggest changes

The content on docs.arduino.cc is facilitated through a public GitHub repository. If you see anything wrong, you can edit this page here.

License

The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike 4.0 license.