Table of Contents
Today we are going to be looking at the brand new Arduino Nano RP2040 Connect, the much-anticipated Arduino board with a Raspberry Pi RP2040 processor.
We’ll see how to get our Arduino IDE prepared and how to use some of the onboard peripherals included with this great new board. So let’s get started!
Introduction
Earlier this year we were surprised to see a new board from the folks at Raspberry Pi. Unlike all of their other offerings, this board was not a microcomputer, instead, they released their first microcontroller – the Raspberry Pi Pico.
The heart of the Pico was a new microcontroller, the RP2040. Built for the Raspberry Pi Foundation, this new 32-bit MCU sports a wealth of advanced features and could be programmed using MicroPython, CircuitPython, or C++.
Wanting to increase support for their new microcontroller, and being all-around great members of the maker community, the folks at the Raspberry Pi Foundation didn’t keep all of this goodness to themselves. Instead, they have licensed the RP2040 to other manufacturers, so they could create their own unique boards with it.
We have already seen RP2040 designs from Adafruit, Pimoroni, and Sparkfun, along with a few other manufacturers. But the real surprise came when Arduino announced that they would also be releasing an RP2040-based design.
And finally, at the end of May 2021, the new board arrived – the Arduino Nano RP2040 Connect.
Let’s examine this board and see what we can do with it!
Arduino Nano RP2040 Connect
The Arduino Nano RP2040 Connect has the same form-factor and pinout as the original Arduino Nano 8-bit AVR board, but that’s where the similarities end. This is a powerful board with both an RP2040 and an ESP32, the latter embedded within a u-blox NINA-W102 WiFi and Bluetooth module.
The board has some pretty impressive features:
- RP2040 Dual-core MCU
- WiFi 801.11b/g/n
- Bluetooth and BLE 4.2
- 6-axis IMU with Machine Learning
- MEMS Microphone Module
- Cryptographic Coprocessor
- Internal switching power supply
- 16Mb Flash Memory
- Onboard RGB LED
Let’s take a quick look at some of these items in detail.
RP2040 Microcontroller
The RP2040 is a 32-bit microcontroller that was designed for the Raspberry Pi Pico board. This is a dual-core Cortex M0+ device that operates at up to 133MHz
Internally the core of the MCU operates at 1.8-volts, however, it has internal level-converters to work with 3.3-volt logic devices.
The RP2040 has 264Kb of embedded SRAM, 30 multi-function GPIO pins, and a 4-channel, 12-bit analog to digital converter.
NINA-W102 Wifi & Bluetooth Module
The NINA-W102 module from u-blox is based upon the popular ESP32 microcontroller. It provides both WiFi and Bluetooth capabilities for the Arduino Nano RP2040 Connect, and it is also used to drive the onboard RGB LED indicator.
This module has its own internal antenna and has a maximum WiFi range of 400 meters. It operates on the 2.4GHz band.
LSM6DSOXTR 6-axis IMU
The LSM6DSOXTR Inertial Measurement Unit (IMU) has both a 3D accelerometer and a 3D gyroscope.
One unique feature is that this IMU also has a Machine Learning component that can sense the type of motion. This feature allows for some very advanced projects such as pedometers and gesture trackers to be easily constructed with the Arduino Nano RP2040 Connect board.
MP34DT05 MEMS Microphone
The MP34DT05 is an omnidirectional MEMS microphone. MEMS is an abbreviation for Micro-Electromechanical Systems. This type of microphone is also referred to as a “solid-state microphone”.
This microphone outputs data in Pulse Density Modulation (PDM) format, a digital representation of an analog signal.
The microphone connects to the RP2040 using the I2C bus.
ATECC608A Cryptographic Coprocessor
The ATECC608A Cryptographic Coprocessor provides protected storage for up to 16 keys or certificates in its built-in EEPROM.
This device is used to store network endpoint keys for IoT devices, allowing the Arduino Nano RP2040 Connect to be used in secure IoT applications.
This device has been used in all of the Arduino MKR Family boards.
AT25SF128A-MHB-T Flash Memory
The AT25SF128A-MHB-T is a 16MB (128 megabits) Flash Memory chip that allows you to store data for over 20 years. It connects to the RP2040 using the SPI bus.
In the Arduino Nano RP2040 Connect, this chip is operated in dual-channel mode, allowing data transfers of up to 240 Mbps.
This is an enhanced Flash memory chip that can be programmed and erased over 100,000 times.
RGB LED
The surface-mounted RGB LED on the Arduino Nano RP2040 Connect is connected to the ESP32 in the NINA-W102 module.
Because of this, you will need to use the WiFiNINA Library to address this LED. In your code you can use the following constants to control it:
- Red – LEDR
- Green – LEDG
- Blue – LEDB
The board also has an orange LED connected to I/O pin 13, this is the “built-in” LED common to most Arduino boards. There is also a green Power LED.
Arduino Nano RP2040 Pinouts
The Arduino Nano RP2040 has the same form-factor and the same pinout as the original 8-bit AVR-based Arduino Nano.
This arrangement allows you to use existing prototype tools and adapters with the board.
Unlike the original Nano the RP2040 Connect uses a MicroUSB connector for data transfer, it can also be used to power the board. When the MicroUSB connector is used to power the board the 5-volts supplied by the host computer is available on the VUSB pin, but only if you solder a jumper on the bottom of the board.
The board has an internal step-down converter and may be powered either by the MicroUSB connector or by applying a voltage of 5 to 21 volts to the VIN pin.
The 3V3 jumper on the bottom of the board provides access to the internal step-down converter output.
Design Considerations
As with the Arduino Nano 33 IoT board that we looked at earlier, the Nano Rp2040 Connect also has some similar design considerations that you need to be aware of before you start using it.
There are two very important considerations you should note if you are porting an older Nano-based design to the new Nano RP2040:
- Logic levels – This is a 3.3-volt logic device and it is not 5-volt tolerant.
- I2C – Pins A4 and A5 are the I2C SDA and SCL pins respectively. They have internal pull-up resistors, so they cannot be used as analog input pins.
The board itself is available both with or without the header pins soldered in, boards without pins have a set included. As with many new microcontrollers this board uses a castellated design, allowing it to also be used as a surface-mount device.
Arduino IDE Setup
We will start by setting up our development environment. There are three IDE’s currently supported:
- Arduino IDE 1.8.X – The “classic” Arduino IDE that most of us are pretty familiar with.
- Arduino IDE 2.0.X – The new IDE, which is still in Beta as of this writing.
- Arduino Web Editor – An online IDE from Arduino
I will be providing details for the installation using the classic Arduino IDE 1.8.X here. Arduino has installation instructions for all of these IDE’s on their website.
Boards Manager
You’ll want to be sure that you have a recent version of the classic Arduino IDE, as of this writing that would be version 1.8.15.
In order to use the Arduino Nano RP2040 Connect you’ll need to install a new board into the IDE. You do that using the Boards Manager.
- Open the Arduino IDE.
- Click on Tools. A menu will drop down.
- Look for the section of the menu that lists the microcontroller board you are currently using (i.e. Arduino Uno) and highlight the board name.
- A sub-menu will appear when you highlight the board.
- The first item in the menu is Boards Manager. Click on it, and the Boards Manager window will open.
In the filter (search) box at the top of the Boards Manager type “mbed”. This will filter the list to boards with that word in their names.
Look for Arduino Mbed OS Nano Boards. Make sure to avoid the one marked “DEPRECIATED”, the one we want was at version 2.1.0 as of this writing and it lists the Arduino Nano RP2040 Connect as one of its supporting boards.
When you move your mouse over the board you’ll get an Install button on the height side. Click the button to install the new board. Be patient, as it can take a while for all of the files and examples to load.
After the installation has completed you can close the Boards Manager.
Mandatory Blink Test
New computer systems and languages are generally initiated by running a “Hello World” program, and with the Arduino microcontrollers that program is called Blink. It’s an extremely simple sketch that simply flashes the onboard LED. If you have ANY experience with microcontrollers then you’re very familiar with it.
While it certainly isn’t the most thrilling application, Blink is a great test to see if everything is working properly.
Most new microcontrollers come out of the factory running Blink, so what I usually do is modify the Blink sketch so I can be sure I’m not being fooled by the board’s existing program. However, the Arduino Nano RP2040 comes packaged with a very unusual Blink-type sketch that uses the onboard LED and also uses the RGB LED. So uploading Blink as it is will be sufficient to confirm that we can successfully program our board.
So let’s upload the Blink sketch!
Before we do that, however, we’ll need to connect our new Nano RP2040 to a MicroUSB cable that is attached to a USB port on our workstation. This will also power the board for us, so as soon as you hook up the cable you should observe a green LED lighting up on the board, along with the “fancy Blink” that I just mentioned.
Next, we need to select the Arduino Nano RP2040 from our list of boards:
- Open the Arduino IDE.
- Click on Tools. A menu will drop-down.
- Look for the section of the menu that lists the microcontroller board you are currently using (i.e. Arduino Uno) and highlight the board name.
- A sub-menu will appear when you highlight the board.
- Look for Arduino Mbed OS Nano Boards in the list of board menus and highlight it.
- A list of boards (currently two boards) will be displayed.
- Select the Arduino Nano RP2040 Connect from the list.
We also need to select the correct Port to write the data to:
- Click on the Tools menu again, which will result in a menu dropping down.
- Look for the Port selection (under the Board selection you just set).
- A sub-menu will open, listing the ports available
The names of the ports will differ depending upon your operating system, so look for the listing that has “Arduino Nano 2040 Connect” in its name and select it.
Now we can load Blink.
- Click on the File menu.
- Navigate down to Examples. A sub-menu will appear.
- At the top of this sub-menu is a section labeled Built-in Examples. Open the first sub-menu in this section, labeled 01. Basics.
- In this final sub-menu open the Blink sketch.
Now use the Upload button (the “Arrow” button at the top-left of the Arduino IDE) to upload Blink to your Arduino Nano RP2040 Connect board.
If you are successful the “fancy Blink” the board was preloaded with wil be replaced by a flashing orange LED. And you are now ready to move on to bigger and better things!
Upload Errors
Uploading Blink is generally pretty trivial, but you may run into an error message saying that the board at your selected COM port is not available. This is not uncommon, and can usually be ignored.
In some cases, however, you will still be unsuccessful. You will also notice that the Arduino Nano RP2040 is now visible in your File Manager, indicating that the bootloader is in the wrong mode.
You can fix this as follows:
- Unplug the MicroUSB cable from the Arduino Nano RP2040 Connect board.
- Take a jumper wire and short out the GND and RESET puns (the Reset pin is also labeled REC on the bottom of the Nano RP2040 board).
- Reconnect the MicroUSB cable to the board.
- Remove the jumper.
This should reset the bootloader.
Linux Post Install Fix
On some Linux workstations, you may find that you still cannot upload to the Arduino Nano RP2040 board. I had this issue with three of my Ubuntu workstations.
There is a fix for this, packaged with the board files you installed with the Boards Manager (a similar fix is also available for Windows). It’s in the form of a BASH file called post_install.sh.
Here is how I ran the fix on my workstation.
First, you need to find the post_install.sh file within your Arduino boards installation. The way I did this was to open my Linux Nano File Manager and perform a search (Ctrl-F) for it.
Once you find the file highlight it, right-click, and choose Open Containing Folder. The file manager will open in the folder containing the desired BASH script.
Now click anywhere in this folder and choose “Open in Terminal”, which will naturally open the Terminal in this location.
Now type the following:
1 |
sudo ./post_install.sh |
You’ll be prompted for your password so you can run the file with root permissions. Note that you won’t get any visual feedback while typing your password.
Press Enter when you’ve typed it, and the BASH file will run.
Now try uploading Blink again, it should work this time.
Web Server AP Mode
Now that we have our development environment all prepared we can move on to more interesting experiments.
There is no additional wiring or components required for this or any of the other experiments we will do today. And all of the code we will be using are examples provided by Arduino in their tutorials.
In the first experiment, we will demonstrate the WiFi capabilities of the Arduino Nano RP2040 Connect by configuring the NINA-W102 module as an access point. We will also be using the RGB LED that is connected to the ESP32 within the NINA-W102 module.
We are going to create a WiFi access point and a web-based interface to allow us to control the RGB LED. You can use the techniques shown here to control other projects with a web-based interface.
The code for our demo is here:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
#include <SPI.h> #include <WiFiNINA.h> char ssid[] = "NANOTEST"; // your network SSID (name) char pass[] = "12345678"; // your network password (use for WPA, or use as key for WEP) int keyIndex = 0; // your network key index number (needed only for WEP) int status = WL_IDLE_STATUS; WiFiServer server(80); void setup() { //Initialize serial and wait for port to open: Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } Serial.println("Access Point Web Server"); pinMode(LEDR, OUTPUT); pinMode(LEDG, OUTPUT); pinMode(LEDB, OUTPUT); // check for the WiFi module: if (WiFi.status() == WL_NO_MODULE) { Serial.println("Communication with WiFi module failed!"); // don't continue while (true); } String fv = WiFi.firmwareVersion(); if (fv < WIFI_FIRMWARE_LATEST_VERSION) { Serial.println("Please upgrade the firmware"); } // by default the local IP address will be 192.168.4.1 // you can override it with the following: // WiFi.config(IPAddress(10, 0, 0, 1)); // print the network name (SSID); Serial.print("Creating access point named: "); Serial.println(ssid); // Create open network. Change this line if you want to create an WEP network: status = WiFi.beginAP(ssid, pass); if (status != WL_AP_LISTENING) { Serial.println("Creating access point failed"); // don't continue while (true); } // wait 10 seconds for connection: delay(10000); // start the web server on port 80 server.begin(); // you're connected now, so print out the status printWiFiStatus(); } void loop() { // compare the previous status to the current status if (status != WiFi.status()) { // it has changed update the variable status = WiFi.status(); if (status == WL_AP_CONNECTED) { // a device has connected to the AP Serial.println("Device connected to AP"); } else { // a device has disconnected from the AP, and we are back in listening mode Serial.println("Device disconnected from AP"); } } WiFiClient client = server.available(); // listen for incoming clients if (client) { // if you get a client, Serial.println("new client"); // print a message out the serial port String currentLine = ""; // make a String to hold incoming data from the client while (client.connected()) { // loop while the client's connected if (client.available()) { // if there's bytes to read from the client, char c = client.read(); // read a byte, then Serial.write(c); // print it out the serial monitor if (c == '\n') { // if the byte is a newline character // if the current line is blank, you got two newline characters in a row. // that's the end of the client HTTP request, so send a response: if (currentLine.length() == 0) { // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) // and a content-type so the client knows what's coming, then a blank line: client.println("HTTP/1.1 200 OK"); client.println("Content-type:text/html"); client.println(); // the content of the HTTP response follows the header: client.print("<style>"); client.print(".container {margin: 0 auto; text-align: center; margin-top: 100px;}"); client.print("button {color: white; width: 100px; height: 100px;"); client.print("border-radius: 50%; margin: 20px; border: none; font-size: 20px; outline: none; transition: all 0.2s;}"); client.print(".red{background-color: rgb(196, 39, 39);}"); client.print(".green{background-color: rgb(39, 121, 39);}"); client.print(".blue {background-color: rgb(5, 87, 180);}"); client.print(".off{background-color: grey;}"); client.print("button:hover{cursor: pointer; opacity: 0.7;}"); client.print("</style>"); client.print("<div class='container'>"); client.print("<button class='red' type='submit' onmousedown='location.href=\"/RH\"'>ON</button>"); client.print("<button class='off' type='submit' onmousedown='location.href=\"/RL\"'>OFF</button><br>"); client.print("<button class='green' type='submit' onmousedown='location.href=\"/GH\"'>ON</button>"); client.print("<button class='off' type='submit' onmousedown='location.href=\"/GL\"'>OFF</button><br>"); client.print("<button class='blue' type='submit' onmousedown='location.href=\"/BH\"'>ON</button>"); client.print("<button class='off' type='submit' onmousedown='location.href=\"/BL\"'>OFF</button>"); client.print("</div>"); // The HTTP response ends with another blank line: client.println(); // break out of the while loop: break; } else { // if you got a newline, then clear currentLine: currentLine = ""; } } else if (c != '\r') { // if you got anything else but a carriage return character, currentLine += c; // add it to the end of the currentLine } // Check to see if the client request was /X if (currentLine.endsWith("GET /RH")) { digitalWrite(LEDR, HIGH); } if (currentLine.endsWith("GET /RL")) { digitalWrite(LEDR, LOW); } if (currentLine.endsWith("GET /GH")) { digitalWrite(LEDG, HIGH); } if (currentLine.endsWith("GET /GL")) { digitalWrite(LEDG, LOW); } if (currentLine.endsWith("GET /BH")) { digitalWrite(LEDB, HIGH); } if (currentLine.endsWith("GET /BL")) { digitalWrite(LEDB, LOW); } } } // close the connection: client.stop(); Serial.println("client disconnected"); } } void printWiFiStatus() { // print the SSID of the network you're attached to: Serial.print("SSID: "); Serial.println(WiFi.SSID()); // print your WiFi shield's IP address: IPAddress ip = WiFi.localIP(); Serial.print("IP Address: "); Serial.println(ip); // print where to go in a browser: Serial.print("To see this page in action, open a browser to http://"); Serial.println(ip); } |
What we are setting up here is an access point with a web page that listens for GET requests. Here are a few key points in the sketch.
On lines 4 & 5 you will see an SSID and Password. These are NOT the SSID and password for your WiFi network, rather these are the SSID and Password for the wireless access point that we are setting up. You can change them to another SSID and Password if you wish, however you should note that each field needs to be at least 8-characters long.
Also, note how the three segments of the RGB LED are set up as outputs on lines 20-22. The LEDs are addresses with constants that are part of the WiFiNINA library.
In the Loop, we look for a client connection. If we get one then we create the webpage, which you’ll see starting on line 94.
The webpage we are creating consists of 6 button elements, two (on & off) for each LED segment. You can see these on lines 110-115. Each button element sends a GET request when a mousedown event occurs. Each get request is appended by a 2-letter code, indicating which button has been pressed.
Now if you look at lines 130-146 you will see the receiving end of this transaction. The GET requests are checked to determine the two characters at the end. Then these characters are used in an “if” statement to determine which LED segment to turn on or off.
So, for example, if we click on the Red ON button we send a GET request appended by “RH”. On the receiving end, we examine the request, extract the “RH” and in the “if” statement we set the Red segment of the LED HIGH.
Load the code into the Arduino Nano RP2040 Connect and observe the serial monitor. You should see your new access point has been created.
Now use a computer or mobile device to connect to that access point, using the specified password. Once connected go to 192.168.4.1 in your device’s web browser. You should see a webpage with six buttons.
Try clicking the buttons and observe the state of the RGB LED on the RP2040 Connect board. You should be able to control it using the web-based interface.
IMU Machine Learning Core
The LSM6DSOX IMU is not just a gyroscope and accelerometer, it also has a Machine Learning component that can pre-process the data to determine the type of movement detected.
In order to make use of the Machine Learning core we will need to use an appropriate library, the STM32duino X-NUCLEO-IKS01A3 library. You can find this in your Library Manager:
- Open your Arduino IDE.
- Click the Tools menu item, this will cause a menu to drop down.
- Look for the Manage Libraries item in the menu and click it.
- The Library Manager will open in a new window.
- Filter (search) for “STM32duino X-NUCLEO-IKS01A3” (the easiest method is to copy this text and paste it into the filter box)
- Hover over the result and click the Install button.
- The library will be installed. You may close the Library Manager when you are done.
The code that we will be using for our experiment is an example that is included with the STM32duino X-NUCLEO-IKS01A3 library, however, it was written for a different microcontroller. So we will need to modify it for the Arduino Nano RP2040 Connect board. I’ll show you how to do that in a moment, but first, let’s see what the code actually does.
In this experiment, we’ll construct a somewhat amusing device that measures movement and tries to determine what type of movement it is detecting. It can look for a number of different movements:
- Stationary
- Walking
- Jogging
- Biking
- Driving
It accomplices this by feeding the IMU measurements into the Machine Learning core and allowing the data to be processed for three seconds. The resulting data is inserted into an array, whose value determines what type of movement has been detected.
You can get this sketch in the examples included with the STM32duino X-NUCLEO-IKS01A3 library:
- Open the Arduino IDE.
- Click on the File menu item. A menu will drop down.
- Scroll down to Examples. A sub-menu will appear.
- Scroll down the Examples sub-menu until you get to the last item, INCOMPATIBLE. These are sketches incompatible with your currently selected microcontroller board.
- In the INCOMPATIBLE menu look for STM32duino X-NUCLEO-IKS01A3 and highlight it to reveal yet another sub-menu.
- Look for the X_NUCLEO_IKS01A3_LSM6DSOX_MLC sketch and open it.
You’ll get a warning message in the Arduino IDE status bar indicating that this sketch is not made for your current processor. You can ignore it, because we are going to make a one-line modification to it so that it works with the RP2040.
The modification is pretty simple, all you need to do is add the following line somewhere inside the declarations section of the sketch:
1 |
#define INT_1 INT_IMU |
The following is an example of the modified sketch:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
/** ****************************************************************************** * @file X_NUCLEO_IKS01A3_LSM6DSOX_MLC.ino * @author SRA * @version V1.1.0 * @date March 2020 * @brief Arduino test application for the STMicrolectronics X-NUCLEO-IKS01A3 * MEMS Inertial and Environmental sensor expansion board. * This application makes use of C++ classes obtained from the C * components' drivers. ****************************************************************************** * @attention * * <h2><center>© COPYRIGHT(c) 2020 STMicroelectronics</center></h2> * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ //NOTE: This example isn't compatible with Arduino Uno. //NOTE: For this example you need the STEVAL-MKI197V1 board connected to the DIL24 connector of the X-NUCLEO-IKS01A3 // Includes #include "LSM6DSOXSensor.h" #include "lsm6dsox_activity_recognition_for_mobile.h" #ifdef ARDUINO_SAM_DUE #define DEV_I2C Wire1 #elif defined(ARDUINO_ARCH_STM32) #define DEV_I2C Wire #elif defined(ARDUINO_ARCH_AVR) #define DEV_I2C Wire #else #define DEV_I2C Wire #endif #define SerialPort Serial #define INT_1 INT_IMU //Interrupts. volatile int mems_event = 0; // Components LSM6DSOXSensor AccGyr(&DEV_I2C, LSM6DSOX_I2C_ADD_L); // MLC ucf_line_t *ProgramPointer; int32_t LineCounter; int32_t TotalNumberOfLine; void INT1Event_cb(); void printMLCStatus(uint8_t status); void setup() { uint8_t mlc_out[8]; // Led. pinMode(LED_BUILTIN, OUTPUT); // Force INT1 of LSM6DSOX low in order to enable I2C pinMode(INT_1, OUTPUT); digitalWrite(INT_1, LOW); delay(200); // Initialize serial for output. SerialPort.begin(115200); // Initialize I2C bus. DEV_I2C.begin(); AccGyr.begin(); AccGyr.Enable_X(); AccGyr.Enable_G(); /* Feed the program to Machine Learning Core */ /* Activity Recognition Default program */ ProgramPointer = (ucf_line_t *)lsm6dsox_activity_recognition_for_mobile; TotalNumberOfLine = sizeof(lsm6dsox_activity_recognition_for_mobile) / sizeof(ucf_line_t); SerialPort.println("Activity Recognition for LSM6DSOX MLC"); SerialPort.print("UCF Number Line="); SerialPort.println(TotalNumberOfLine); for (LineCounter=0; LineCounter<TotalNumberOfLine; LineCounter++) { if(AccGyr.Write_Reg(ProgramPointer[LineCounter].address, ProgramPointer[LineCounter].data)) { SerialPort.print("Error loading the Program to LSM6DSOX at line: "); SerialPort.println(LineCounter); while(1) { // Led blinking. digitalWrite(LED_BUILTIN, HIGH); delay(250); digitalWrite(LED_BUILTIN, LOW); delay(250); } } } SerialPort.println("Program loaded inside the LSM6DSOX MLC"); //Interrupts. pinMode(INT_1, INPUT); attachInterrupt(INT_1, INT1Event_cb, RISING); /* We need to wait for a time window before having the first MLC status */ delay(3000); AccGyr.Get_MLC_Output(mlc_out); printMLCStatus(mlc_out[0]); } void loop() { if (mems_event) { mems_event=0; LSM6DSOX_MLC_Status_t status; AccGyr.Get_MLC_Status(&status); if (status.is_mlc1) { uint8_t mlc_out[8]; AccGyr.Get_MLC_Output(mlc_out); printMLCStatus(mlc_out[0]); } } } void INT1Event_cb() { mems_event = 1; } void printMLCStatus(uint8_t status) { switch(status) { case 0: SerialPort.println("Activity: Stationary"); break; case 1: SerialPort.println("Activity: Walking"); break; case 4: SerialPort.println("Activity: Jogging"); break; case 8: SerialPort.println("Activity: Biking"); break; case 12: SerialPort.println("Activity: Driving"); break; default: SerialPort.println("Activity: Unknown"); break; } } |
The sketch has two files, the second one is the activity recognition file for the Machine Learning core in the IMU.
The Machine Learning core is called in line 127. It is called three seconds after an interrupt is received, the interrupt indicates that the IMU has detected a change in motion. The three-second delay gives the Machine Learning core time to process the data.
Load the sketch onto your Arduino Nano RP2040 board and open your serial monitor, note that the sketch sets up the serial monitor at a baud rate of 115200 instead of 9600 (although I accidentally opened mine at 9600 and it seemed to work fine).
Now you need to simulate some motion while looking at your serial monitor. In my test, I was able to simulate walking and jogging by shaking the breadboard that I had my Arduino Nano RP2040 mounted upon.
Of course, to really test this you would need to be able to battery power it (or power it with a notebook) and take it for a walk, jog, or drive!
Reading Microphone Data
Our final experiment will involve the MP34DT05 MEMS microphone.
I thought that this was a fun sketch, as it essentially emulates that marvelous 80’s invention called ‘The Clapper”. For those of you unfamiliar with this electronic marvel, the Clapper was a sound-activated switch that allowed you to control the power to your appliances by clapping your hands!
In this sketch we will be turning on and off the blue segment of the RGB LED on the Arduino Nano RP2040 Connect board. Not as much fun as controlling your television, but the same principle.
The sketch requires the PDM library, which was installed when you installed the RP2040 board using the Boards Manager. It also uses the WiFiNINA library, which may surprise you as it has no WiFi features. Remember, the RGB LED is connected to the ESP32 in the NINIA-W102 modules, so the WiFiNINA library is used to control the LED.
Here is our sketch:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
#include <WiFiNINA.h> #include <PDM.h> bool LED_SWITCH = false; // default number of output channels static const char channels = 1; // default PCM output frequency static const int frequency = 16000; // Buffer to read samples into, each sample is 16-bits short sampleBuffer[512]; // Number of audio samples read volatile int samplesRead; void setup() { Serial.begin(9600); pinMode(LEDB, OUTPUT); while (!Serial); // Configure the data receive callback PDM.onReceive(onPDMdata); // Optionally set the gain // Defaults to 20 on the BLE Sense and -10 on the Portenta Vision Shield // PDM.setGain(30); // Initialize PDM with: // - one channel (mono mode) // - a 16 kHz sample rate for the Arduino Nano 33 BLE Sense // - a 32 kHz or 64 kHz sample rate for the Arduino Portenta Vision Shield if (!PDM.begin(channels, frequency)) { Serial.println("Failed to start PDM!"); while (1); } } void loop() { // Wait for samples to be read if (samplesRead) { // Print samples to the serial monitor or plotter for (int i = 0; i < samplesRead; i++) { if (channels == 2) { Serial.print("L:"); Serial.print(sampleBuffer[i]); Serial.print(" R:"); i++; } Serial.println(sampleBuffer[i]); if (sampleBuffer[i] > 10000 || sampleBuffer[i] <= -10000) { LED_SWITCH = !LED_SWITCH; if (LED_SWITCH) { Serial.println(); digitalWrite(LEDB, HIGH); Serial.println("ON!"); Serial.println(); delay(1000); } else { Serial.println(); digitalWrite(LEDB, LOW); Serial.println("OFF!"); Serial.println(); delay(1000); } } } // Clear the read count samplesRead = 0; } } /** Callback function to process the data from the PDM microphone. NOTE: This callback is executed as part of an ISR. Therefore using `Serial` to print messages inside this function isn't supported. * */ void onPDMdata() { // Query the number of available bytes int bytesAvailable = PDM.available(); // Read into the sample buffer PDM.read(sampleBuffer, bytesAvailable); // 16-bit, 2 bytes per sample samplesRead = bytesAvailable / 2; } |
The sketch samples the microphone’s PDM output and measures its level. If it exceeds a value of 10,000 or -10,000 (remember, audio waveforms have both a positive and negative component) it toggles the blue LED.
In the Setup, we set up the parameters for the microphone. There are some comments in the sketch that show you how to change the microphone’s sensitivity, but you shouldn’t need to do that.
In the Loop, we read the samples and determine their level. If it exceeds the thresholds described earlier we will toggle the LED_SWITCH variable. This in turn sets the state of the LED.
Load the sketch and start clapping! You should see the LED toggle on and off.
Congratulations, you’ve now built your own Clapper!
Conclusion
At 25 US dollars, the Arduino Nano RP2040 is not exactly inexpensive, especially when compared to the original Raspberry Pi Pico that lists for four just dollars. And, undoubtedly, many people will make a somewhat inaccurate comparison to the cost of an ESP32 module, most of which are much cheaper.
First, let’s keep in mind that this is a genuine Arduino product, and all of these products come with a higher price tag. They are high-quality boards made in Italy (and a few other places), not China or Malaysia, so labor costs are obviously higher.
Second, when comparing this to the ESP32 we should remember that the Arduino Nano RP2040 actually HAS an ESP32 on board, inside the NINA-W102 module, as well as the RP2040. So naturally, it will be more expensive!
Third, the onboard peripherals are pretty impressive, especially the built-in IMU with Machine Learning capabilities and its cryptographic coprocessor. Things you don’t find on many ESP32 boards.
Finally, when weighing the cost of this board we should keep in mind the incredible contributions Arduino has made, and continues to make, to the maker and hobbyist community. They have created a free IDE that is useful for many other boards, including the ESP32. And they have released all of their designs, including the RP2040 Connect, as open source products, allowing other manufacturers to create lower-quality but less expensive clones. So giving them a little money is a pretty good thing.
Considering all of the above I’d say 25 dollars is a fair price for a board with these capabilities. And you can be sure that you’ll be seeing more of the Arduino Nano RP2040 Connect in future articles and videos here in the workshop!
Parts List
Here are some components that you might need to complete the experiments in this article. Please note that some of these links may be affiliate links, and the DroneBot Workshop may receive a commission on your purchases. This does not increase the cost to you and is a method of supporting this ad-free website.
COMING SOON!
Resources
Code used in Article – All of the code used in today’s experiments, in one ZIP file.
Arduino Nano RP2040 Connect Overview – Arduino’s guide to the features of the new Nano RP2040 Connect board.
Arduino Nano RP2040 Connect Technical Reference – Arduino’s reference guide for the Arduino Nano RP2040 Connect board
Raspberry Pi RP2040 Datasheet – Guide to the Raspberry Pi RP2040 MCU
Another well written, informative, and unbiased article. Please keep up your good work so that we may have a place to go to learn and ask questions when needed. Thank you again
great article Bill. I preordered mine and it arrived last week. Excited to get started. For what it is worth, I read this article before I have seen your video…I love your videos, but I really appreciate the effort you put into the articles and when I have questions or am working on a project I always refer back to your written articles. The well produced vids are just icing on the cake!
The first part works fine, but the clapper does not.
With the gain set to -90 (db, I assume) the LED switches with sound AND at random.
Any thoughts?
Thanks
Hi Bill,
I’m only about 3 months old in the world of microcontroller. Thanks to you and your friendly workshops to teach and guide me in these new horizons.
I just bought a Nano RP2040 and I can’t wait to see more of it in your next workshops…
Keep up with your great site!
Hi Bill, do you know if platform IO will eventually support the Nano RP2040? I haven’t found this board…
Thanks always for your great videos.
I leave this comment since I am facing program uploading issue for this “arduino rp4020 connect” using platformio.
For “pi pico”, I successfully got it worked by re-installing usb driver to work on Windows.
But the same solution doesn’t seems to work for “arduino rp4020 connect”.
If you have a solution for this, please share it! ^^
I am trying to get a web based interface running for a portable application using an ESP32S2 board and your “Web Server AP Mode” example was a big help. Thanks sir!
Great article! Thanks for your time building it. It has been most helpful.
Hi
I was wondering if you could help me out, I am tring to run @file X_NUCLEO_IKS01A3_LSM6DSO_Pedometer.ino
from the same library but the step counter wont increment. The above example works fine .I kow it uses a different header file, any help would be appreciated. Thanks A