Table of Contents
Today we will look at one of the members of the updated Arduino Nano family of microcontroller boards. The Arduino Nano 33 IoT has the same pinout and form factor as the older 8-bit Nano board, but it packs a lot more power and features.
Let’s take a closer look at the Nano 33 IoT and see what we can do with it.
Introduction
The original Arduino Nano was released in 2008 and has become very popular. It is essentially the equivalent of the popular Arduino Uno in a smaller form-factor, and it even has a couple of extra analog output pins. As with most Arduino designs, this is an open-source product, so it has been copied by a myriad of other manufacturers.
In 2019 Arduino released the Arduino Every, an updated version of the Nano. They subsequently released three more “updated” Nano boards with a variety of different onboard peripherals.
One of these boards is the Arduino Nano 33-IoT board. This low-cost module features a powerful 32-bit processor, integrated WiFi and Bluetooth, and IMU (Inertial Measurement Unit), and onboard RTC (Real Time Clock).
The “IoT” in the board’s name is not only due to the integrated WiFi and Bluetooth connectivity. This board is also supported on the Arduino IoT Cloud, an IoT infrastructure that makes building IoT projects very simple. As of this writing, the Nano 33 IoT was the only one of the “new” Nano boards supported on the cloud.
The “33” in the boards’ name refers to this being a 3.3-volt device, as opposed to the original 5-volt Nano.
With a pinout equivalent to the older Nano board and the ability to tap into the huge collection of existing Arduino software and libraries the Nano 33 IoT board has the potential to add new power to old designs and is a great choice for new IoT products.
The “New” Arduino Nanos
The four “new” Arduino Nano boards are packaged in the same 30-pin module as the original Nano. Unlike the original, the newer boards are produced in a “castellated” form factor. This design, which we have also seen on the Seeeduino XIAO and the Raspberry Pi Pico, allows the board to be directly soldered onto another PCB as a surface-mount device. You can also solder in header pins, the modules are packaged with male Dupont headers for this purpose.
The new family members are as follows:
Arduino Nano Every
This is the “entry-level” Arduino Nano, and it is a direct upgrade for the original ATmega328-based design.
The Arduino Nano Every uses an ATmega4809 microcontroller, which is an 8-bit controller running at 20MHz.
Arduino Nano 33 BLE
As you can probably surmise from its name the Arduino Nano 33 BLE features Bluetooth.
The device uses a NINA-B3 series B306 Bluetooth 5 Low Energy module. This module is based upon the Nordic Semiconductor nRF52840 SoC (System on a Chip), which itself is built around the 32-bit ARM® Cortex-M4 CPU with the floating-point unit running at 64 MHz.
Arduino Nano 33 BLE Sense
This device is similar to the previous one in that it uses the same NINA-B3 module.
It also has a variety of onboard sensors:
- LSM9DS1 9-axis IMU
- LPS22HB Barometric Pressure Sensor
- HTS221 Temperature and Humidity Sensor
- APDS-9960 Proximity, Light, RGB, and Gesture Sensor
- MP34DT05-A MEMS Microphone
It’s pretty obvious where the name “Sense” was derived from!
Arduino Nano 33 IoT
Finally, the module that is the subject of today’s article, the Arduino Nano 33 IoT module.
This 32-bit module features WiFi, Bluetooth, and an integrated RealTime Clock (RTC) and Inertial Measurement Unit (IMU).
Let’s move on and discuss this module in greater detail.
Arduino Nano 33 IoT
The Arduino Nano 33 IoT is a small module with the same form-factor as the original Arduino Nano. Unlike the original Nano, however, this model uses a MicroUSB connector (the original Nano uses a MiniUSB).
Pinouts
Not only does the Arduino Nano 33 IoT have the same 30-pin package as its predecessor, it also has identical pinouts.
However, despite having the same pinouts there are some key differences between this module and the earlier Nano.
Logic Voltage Levels
The biggest, and potentially most important difference is that the Arduino Nano 33 IoT is a 3.3-volt logic device. It is NOT 5-volt tolerant, so substituting it in a circuit designed for the original Nano could possibly destroy it.
The device has an onboard voltage regulator and can be powered either by the MicroUSB port or by a voltage applied to the VIN pin. You can supply a maximum of 14-volts to the device to power it this way.
VUSB Pin
The VUSB pin is an output, as it is on the original Nano. However, by design, it is not connected. The reason for this is that the VUSB pin is a 5-volt output from the MicroUSB connector, and if that 5-volts should ever come into contact (say, through a pull-up resistor) with an input pin it could damage or destroy the Nano 33 IoT.
In order to use this pin, you’ll need to jumper a set of pads on the underside of the module. These pads are located right next to the VUSB pin.
Note that once the pads are jumpered the VUSB pin will output 5-volts ONLY if powered via the MicroUSB connector. If the module is powered by the VIN pin then there will be no output voltage on the VUSB pin.
I2C Pullup Resistors
As with many of the other Arduino’s, including the original Nano, the Arduino Nano 33 IoT shares its I2C connections with two of the analog input pins, A4 and A5. But, unlike other Arduino models, the Arduino Nano 33 IoT has internal pullup resistors attached to these pins.
These pullups are required as the IMU is an I2C device, so the bus is used internally.
Since it is not possible to disable the pullups you won’t be able to make use of the A4 and A5 pins as analog inputs. In fact, you are best to restrict your use of these pins to I2C connections if you plan on using the internal IMU.
Features
As I’ve already mentioned briefly, the Arduino Nano 33 IoT board has several useful features and onboard peripherals. Let’s take a look at them.
SAMD21G Microcontroller
The heart of the Arduino Nano 33 IoT module is the SAMD21G 32-bit microcontroller. This is the same microcontroller that we examined when we looked at the Seeeduino XIAO.
The processor runs at 48MHz, giving the Nano 33 IoT considerable speed and power advantages over the 16MHz 8-bit ATMega328 power of the original Nano.
This processor has six SERCOM p[orts, which are general-purpose serial ports. You can configure a SERCOM port as an SPI, I2C, or Serial UART connection. By default the Arduino Nano 33 IoT has the I2C port configured on address pins A4 and A5, to maintain compatibility with older designs.
WiFi & Bluetooth
The Arduino Nano 33 IoT uses a ublox NINA-W102 Bluetooth and WiFi module for its wireless communications functions. This module contains an ESP-32 chip and has an integrated antenna.
The NIN-W102 can provide Bluetooth and BLE 4.2 host and slave services.
The WiFi is 2.4GHz and conforms to IEEE standards b, g, and n.
The NINOA-W102 module is connected to the SAMD21G microcontroller using the SPI bus.
Real-Time Counter
The SAMD21G microcontroller has an integrated 32-bit RTC. This device measures the number of elapsed seconds since the beginning of the Unix Epoch and can be used to provide time and date functions.
Inertial Measurement Unit (IMU)
The Arduino Nano 33 IoT includes an LSM6DS3 Inertial Measurement Unit or IMU.
This IMU features a 3D digital accelerometer and a 3D digital gyroscope, and the associated library makes it very easy to work with.
The LSM6DS3 is an I2C device, and internally it is connected to the same I2C bus used on pins A4 and A5. This is the reason that there are two internal pull-up resistors on the module. The IMU has an I2C address of 0x6A.
Getting Started with the Nano 33 IoT
The Arduino Nano 33 IoT comes packaged in a small box that also includes two sets of 20-pin male headers. You’ll need to solder those to the module unless you plan to take advantage of the castellated pins and use the board in your own design.
The package also includes warranty information (when was the last time you got warranty information with a microcontroller?) and a set of cute little Arduino-themed stickers.
If you happen to also own an Arduino Nano, the older 8-bit 12MHz variety, you can compare the size of the two modules, they are very similar. In fact if you own any Nano-specific prototyping adapters, such as the one I illustrated in the previous image, they will fit perfectly.
Once you have the pins soldered (you can also do most of the experiments without the pins soldered) all that remains to start working with your new-improved Nano is to connect it to your computer.
You’ll need a MicroUSB cable for this. Make sure it’s a cable designed to exchange data, as some MicroUSB cables are for power and recharging only.
Arduino IDE Setup
We will be using the Arduino IDE to work with our board, as after all, it is an Arduino board! Before we can start working with it, however, we need to add a few things.
The following instructions assume that you are using a recent version of the Arduino IDE
Boards Manager
We will begin by installing the Arduino SAMD21 board extension using the Boards Manager.
Open the Boards Manager in the Arduino IDE by clicking on the Tools menu item on the top menu, and then moving down to the current board selection (I.e. Arduino Uno). A menu will open to the right, with “Boards Manager” the first item.
Select Boards Manager. The Boards Manager dialog box will open, and you’ll get a searchable list of the boards you can install.
You will want to look for Arduino SAMD Boards (32-Bit ARM Cortex-M0+) board manager. You can search for “SAMD”, but you likely won’t need to as it’s the fourth item on the boards list!
Select the board and click the Install button. It will take a while to download all the files and example code for the board, so be patient. Once it is done you may close the Boards Manager.
It is usually a good idea to restart (i.e. close and open) the Arduino IDE after doing this, although it usually isn’t really necessary.
You should now see an “Arduino SAMD Boards” selection when you go to select your board. You can open this and select the Arduino Nano 33 IoT board.
Install New Libraries
Many of the advanced features of the Arduino Nano 33 IoT will require additional libraries. They can all be installed using the Library Manager.
We will begin by installing the library that we will use to communicate over WiFi.
Open the Sketch menu item, and then open Include Libraries. The Library Manager is the first selection on the menu that opens to your right. Select it to open the Library Manager window.
Once you have the library manager open you will want to search for the library you require, which in this case is the Arduino WiFiNINA Library. Search for “WiFiNINA” and it should be the first result.
Click the Install button to install the WiFiNINIA library and all of its code samples.
You will want to repeat the process with the following libraries:
- Arduino LSM6DS3 library
- Arduino RTCZero
- ArduinoBLE
Once you have all of these libraries installed you can close the Library Manager. We are now ready to work with our Arduino Nano 33 IoT board.
An easy test is the familiar Blink sketch. Plush in your board and select the appropriate port. Now upload Blink and watch the results. Play with the timing and upload it again.
The Yellow LED by the MicroUSB connector is the Built IN LED, the equivalent of pin 13 on any other Arduino.
WiFi & Real Time Clock
Now that we have run the obligatory Blink sketch we can fire up a few of the demo sketches and see how to use a few of the elements of the Arduino Nano 33 IoT board.
The first two features we will demonstrate are the WiFi connectivity and the Real-Time Clock. While those two functions might seem to be pretty independent (and they are) we can actually use both of them to set the time on our click using our WiFi network.
Before we get to that let’s see how the WiFi works.
WiFi Scan
The first demo sketch that we will run is the WiFi Scan. As the name would imply, this sketch scans the area for available WiFi connections and displays them on the serial monitor.
No attempt is made to actually connect to these signals, and both encrypted and unencrypted networks are displayed.
You can load this sketch by opening up the File menu in the Arduino IDE and then opening the Examples sub-menu. Scroll down the sub-menu until you see WIFININA. Open that menu item and you’ll see a number of example sketches. Load the ScanNetworks example.
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 |
/* This example prints the board's MAC address, and scans for available WiFi networks using the NINA module. Every ten seconds, it scans again. It doesn't actually connect to any network, so no encryption scheme is specified. Circuit: * Board with NINA module (Arduino MKR WiFi 1010, MKR VIDOR 4000 and UNO WiFi Rev.2) created 13 July 2010 by dlf (Metodo2 srl) modified 21 Junn 2012 by Tom Igoe and Jaymes Dec */ #include <SPI.h> #include <WiFiNINA.h> 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 } // 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"); } // print your MAC address: byte mac[6]; WiFi.macAddress(mac); Serial.print("MAC: "); printMacAddress(mac); } void loop() { // scan for existing networks: Serial.println("Scanning available networks..."); listNetworks(); delay(10000); } void listNetworks() { // scan for nearby networks: Serial.println("** Scan Networks **"); int numSsid = WiFi.scanNetworks(); if (numSsid == -1) { Serial.println("Couldn't get a WiFi connection"); while (true); } // print the list of networks seen: Serial.print("number of available networks:"); Serial.println(numSsid); // print the network number and name for each network found: for (int thisNet = 0; thisNet < numSsid; thisNet++) { Serial.print(thisNet); Serial.print(") "); Serial.print(WiFi.SSID(thisNet)); Serial.print("\tSignal: "); Serial.print(WiFi.RSSI(thisNet)); Serial.print(" dBm"); Serial.print("\tEncryption: "); printEncryptionType(WiFi.encryptionType(thisNet)); } } void printEncryptionType(int thisType) { // read the encryption type and print out the name: switch (thisType) { case ENC_TYPE_WEP: Serial.println("WEP"); break; case ENC_TYPE_TKIP: Serial.println("WPA"); break; case ENC_TYPE_CCMP: Serial.println("WPA2"); break; case ENC_TYPE_NONE: Serial.println("None"); break; case ENC_TYPE_AUTO: Serial.println("Auto"); break; case ENC_TYPE_UNKNOWN: default: Serial.println("Unknown"); break; } } void printMacAddress(byte mac[]) { for (int i = 5; i >= 0; i--) { if (mac[i] < 16) { Serial.print("0"); } Serial.print(mac[i], HEX); if (i > 0) { Serial.print(":"); } } Serial.println(); } |
One thing to make note of is that both the WiFiNINA and SPI libraries are used in this sketch. This is because the NINA module requires SPI to communicate.
Otherwise, the sketch is fairly straightforward. Most of it involves setting up the WiFi module and checking its availability.
The listNetworks function is the heart of the sketch, using the WiFiNINA library to scan and then print out the SSID and power and encryption details for every network it finds.
Make sure that you have the Arduino Nano 33 IoT plugged into the computer, and then select it as your board type. Also, select the proper port for the device, it will say “Arduino Nano 33 IoT USB” in the port name.
Now upload the sketch and open your serial monitor. You should see a list of nearby WiFi networks, as well as their signal strengths.
WiFi Connect Test
Here is a simple sketch that illustrates how to connect to a WiFi network and obtain an IP address. You can use this as the basis for a more complicated sketch.
You can download this sketch from the link in the Resources section at the end of this article.
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 |
/* Arduino Nano 33 IoT WiFi Test nano-33-iot-wifi-test.ino Demonstrates use of WiFiNINA library for WiFi Connectivity Results on serial monitor DroneBot Workshop 2021 https://dronebotworkshop.com */ // Include SPI and WiFi Libraries #include <SPI.h> #include <WiFiNINA.h> // WiFi Credentials (edit as required) char ssid[] = "xxxxxxxxx"; // Wifi SSID char pass[] = "xxxxxxxxx"; // Wifi password int status = WL_IDLE_STATUS; // Initialize the Wifi client WiFiSSLClient client; void connectToAP() { // Connect to Wifi Access Point while ( status != WL_CONNECTED) { Serial.print("Attempting to connect to SSID: "); Serial.println(ssid); // Connect to WPA/WPA2 network status = WiFi.begin(ssid, pass); // wait 1 second for connection: delay(1000); Serial.println("Connected..."); } } void printWifiStatus() { // Print results to serial monitor // Network SSID Serial.print("SSID: "); Serial.println(WiFi.SSID()); // Device IP address IPAddress ip = WiFi.localIP(); Serial.print("IP Address: "); Serial.println(ip); } void setup() { // Start the Serial port Serial.begin(9600); while (!Serial) { ; // Wait for serial port to connect. } // Check for the WiFi module: if (WiFi.status() == WL_NO_MODULE) { Serial.println("WiFi module failed!"); while (true); } connectToAP(); printWifiStatus(); } void loop() { } |
Once again we require both the WiFiNINA and SPI libraries.
You’ll need to provide your WiFi SSID (network name) and password to use this sketch.
The connectToAP function does the actual connecting, by using WiFi.begin along with the SSID and password.
The function printWifiStatus prints the status to the serial monitor, including the IP address assigned to the board.
Run the sketch and observe the activity in the serial monitor. It’s a simple sketch, and it can be the basis for all of your future WiFi-enabled projects.
WiFi RTC
As promised, a sketch that sets the Real-Time Clock using WiFi. So how exactly does it accomplish this?
The answer is by using the NTP, or Network Time Protocol, information that is embedded in up-ir WiFi signal. As long as your router is attached to a NTP server (and most are by default) you’ll have this signal, which can be used to determine the Linux Epoch number.
The Linux Epoch Number, if you are curious, is the number of seconds that have elapsed since the beginning of 1970. It is the method most Linux computers (and indeed most computers) use to tell time.
The sketch to do this, which is also in the files you can download in the Resources section, is as follows:
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 |
/* Arduino Nano 33 IoT WiFi RTC Demo nano-33-iot-wifi-rtc.ino Demonstrates use of Real Time Clock Gets Linux epoch from network NTP service and determines current time Results on serial monitor DroneBot Workshop 2021 https://dronebotworkshop.com Based upon Arduino example by Arturo Guadalupi */ // Include required libraries #include <SPI.h> #include <WiFiNINA.h> #include <WiFiUdp.h> #include <RTCZero.h> // WiFi Credentials (edit as required) char ssid[] = "xxxxxxx"; // Wifi SSID char pass[] = "xxxxxxxxx"; // Wifi password int keyIndex = 0; // Network key Index number (needed only for WEP) // Object for Real Time Clock RTCZero rtc; int status = WL_IDLE_STATUS; // Time zone constant - change as required for your location const int GMT = -5; void printTime() { print2digits(rtc.getHours() + GMT); Serial.print(":"); print2digits(rtc.getMinutes()); Serial.print(":"); print2digits(rtc.getSeconds()); Serial.println(); } void printDate() { Serial.print(rtc.getDay()); Serial.print("/"); Serial.print(rtc.getMonth()); Serial.print("/"); Serial.print(rtc.getYear()); Serial.print(" "); } void printWiFiStatus() { // Print the network SSID Serial.print("SSID: "); Serial.println(WiFi.SSID()); // Print the IP address IPAddress ip = WiFi.localIP(); Serial.print("IP Address: "); Serial.println(ip); // Print the received signal strength long rssi = WiFi.RSSI(); Serial.print("signal strength (RSSI):"); Serial.print(rssi); Serial.println(" dBm"); } void print2digits(int number) { if (number < 10) { Serial.print("0"); } Serial.print(number); } void setup() { // Start Serial port Serial.begin(115200); // Check if the WiFi module works if (WiFi.status() == WL_NO_SHIELD) { // Wait until WiFi ready Serial.println("WiFi adapter not ready"); while (true); } // Establish a WiFi connection while ( status != WL_CONNECTED) { Serial.print("Attempting to connect to SSID: "); Serial.println(ssid); status = WiFi.begin(ssid, pass); // Wait 10 seconds for connection: delay(10000); } // Print connection status printWiFiStatus(); // Start Real Time Clock rtc.begin(); // Variable to represent epoch unsigned long epoch; // Variable for number of tries to NTP service int numberOfTries = 0, maxTries = 6; // Get epoch do { epoch = WiFi.getTime(); numberOfTries++; } while ((epoch == 0) && (numberOfTries < maxTries)); if (numberOfTries == maxTries) { Serial.print("NTP unreachable!!"); while (1); } else { Serial.print("Epoch received: "); Serial.println(epoch); rtc.setEpoch(epoch); Serial.println(); } } void loop() { printDate(); printTime(); Serial.println(); delay(1000); } |
This sketch is an adaptation of an Arduino example by Arturo Guadalupi. It has been slightly altered to work properly with the Nano 33 IoT board.
The sketch uses the same two libraries (WiFiNINA and SPI) along with the RTCZero library for the clock.
Note the time zone constant on line 31. You will need to adjust this for your locale, as it represents the number of hours you are offset from GMT (or “UTC” as it is properly called).
If you don’t know your GMT offset you can determine it here. I have a value of -5 (offsets can be positive or negative) as I am in the Eastern time zone in North America.
Many of the functions in the sketch just format the output for printing.
The getTime property of the WiFi library is used to get the time from an NTP server, you will see that on line 125.
On line 139 the rtc.setEpoch sets the clock based upon the received epoch number.
In the loop, we call the printDate and printTime functions, then delay by a second. This will display our time, updated every second.
Load the sketch and open the serial monitor. You should observe the correct time in the serial monitor.
Note that in my demo the time is off by exactly one hour, this is because I filmed this while we were under Daylight Savings Time. The sketch does not take DST into account.
Inertial Measurement Unit
The Inertial Measurement Unit, or IMU, is an easy-to-use device that can act as both a gyroscope and accelerometer.
Note that the LSM6DS3 used in the Nano 33 IoT is not as complex a device as some IMUs, which also include magnetometers. But it still has several applications, such as gesture controllers and position sensors.
The library for the LSM6DS3 makes working with the device very simple, as you’ll see in the following two examples.
You can find these sketches by going to the Arduino IDE File menu and selecting Examples. Then navigate down to the Arduino LSM6DS3 selection (in Examples for any board) and you’ll see two sketches, SimpleAccelerometer and SimpleGyroscope.
Simple Accelerometer
Here is the Simple Accelerometer 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 |
/* Arduino LSM6DS3 - Simple Accelerometer This example reads the acceleration values from the LSM6DS3 sensor and continuously prints them to the Serial Monitor or Serial Plotter. The circuit: - Arduino Uno WiFi Rev 2 or Arduino Nano 33 IoT created 10 Jul 2019 by Riccardo Rizzo This example code is in the public domain. */ #include <Arduino_LSM6DS3.h> void setup() { Serial.begin(9600); while (!Serial); if (!IMU.begin()) { Serial.println("Failed to initialize IMU!"); while (1); } Serial.print("Accelerometer sample rate = "); Serial.print(IMU.accelerationSampleRate()); Serial.println(" Hz"); Serial.println(); Serial.println("Acceleration in G's"); Serial.println("X\tY\tZ"); } void loop() { float x, y, z; if (IMU.accelerationAvailable()) { IMU.readAcceleration(x, y, z); Serial.print(x); Serial.print('\t'); Serial.print(y); Serial.print('\t'); Serial.println(z); } } |
As you can see it really is quite simple! The IMU library is the only library required, and it does most of the work.
On line 23 the IMU is initialized as part of the Setup function. Then, in the Loop, the IMU.readAcceleration function is called to read the x, y, and z components of the acceleration.
Load the sketch up and observe it on the serial monitor. Now move the board around, slowly and then quickly. Note the readings you get for the three different axises.
The effect is much more dramatic if you use the Serial Plotter instead. You’ll find it next to the Serial Monitor in the Tools menu.
The graphical representation of the three acceleration vectors makes it very easy to interpret the results. Try moving the board in different directions and observe the results on the plotter.
Simple Gyroscope
This sketch is nearly identical to the simple accelerometer we just looked at.
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 |
/* Arduino LSM6DS3 - Simple Gyroscope This example reads the gyroscope values from the LSM6DS3 sensor and continuously prints them to the Serial Monitor or Serial Plotter. The circuit: - Arduino Uno WiFi Rev 2 or Arduino Nano 33 IoT created 10 Jul 2019 by Riccardo Rizzo This example code is in the public domain. */ #include <Arduino_LSM6DS3.h> void setup() { Serial.begin(9600); while (!Serial); if (!IMU.begin()) { Serial.println("Failed to initialize IMU!"); while (1); } Serial.print("Gyroscope sample rate = "); Serial.print(IMU.gyroscopeSampleRate()); Serial.println(" Hz"); Serial.println(); Serial.println("Gyroscope in degrees/second"); Serial.println("X\tY\tZ"); } void loop() { float x, y, z; if (IMU.gyroscopeAvailable()) { IMU.readGyroscope(x, y, z); Serial.print(x); Serial.print('\t'); Serial.print(y); Serial.print('\t'); Serial.println(z); } } |
This time we are measuring our position in 3D space, along an x, y, and z axis. And, once again, the Arduino LSM6DS3 library makes getting this information very simple.
Load the sketch and observe it on both the serial monitor and serial plotter
Once again it is easier to interpret the data when viewed in the serial plotter.
With this library adding an accelerometer or gyroscope to your project is very simple indeed!
Bluetooth
Bluetooth connectivity allows the Arduino Nano 33 IoT to be used in a number of projects that the original Nano would have been incapable of. As the device can act as either a Bluetooth slave or master it can be used as either a controlled device or as a controller itself.
Bluetooth Scan
This sketch acts just like the WiFi scan we performed earlier, the difference being that this time we are scanning for Bluetooth peripherals.
As with the earlier sketch, we are only displaying detected devices, we are not making any attempt to connect to them.
You can find this sketch in the Examples section. Navigate to the ArduinoBLE menu, and you’ll notice that it is divided into two sections. In the Central section look for the Scan sketch and load it.
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 |
/* Scan This example scans for BLE peripherals and prints out their advertising details: address, local name, advertised service UUID's. The circuit: - Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT, Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board. This example code is in the public domain. */ #include <ArduinoBLE.h> void setup() { Serial.begin(9600); while (!Serial); // begin initialization if (!BLE.begin()) { Serial.println("starting BLE failed!"); while (1); } Serial.println("BLE Central scan"); // start scanning for peripheral BLE.scan(); } void loop() { // check if a peripheral has been discovered BLEDevice peripheral = BLE.available(); if (peripheral) { // discovered a peripheral Serial.println("Discovered a peripheral"); Serial.println("-----------------------"); // print address Serial.print("Address: "); Serial.println(peripheral.address()); // print the local name, if present if (peripheral.hasLocalName()) { Serial.print("Local Name: "); Serial.println(peripheral.localName()); } // print the advertised service UUIDs, if present if (peripheral.hasAdvertisedServiceUuid()) { Serial.print("Service UUIDs: "); for (int i = 0; i < peripheral.advertisedServiceUuidCount(); i++) { Serial.print(peripheral.advertisedServiceUuid(i)); Serial.print(" "); } Serial.println(); } // print the RSSI Serial.print("RSSI: "); Serial.println(peripheral.rssi()); Serial.println(); } } |
The sketch is pretty simple, as most of the work is done with the Arduino BLE library.
The library has a BLE.scan function, which pretty well does exactly what we want to do.
Whenever a Bluetooth peripheral is discovered it is queried to see its advertised services. This information is then displayed on the serial monitor.
Load the sketch, open the serial monitor and observe the results. Of course, you’ll need to have a couple of Bluetooth peripherals handy for any results to display. I found that the receiver was so sensitive that it also picked up devices I didn’t own, which I assume belong to my neighbors!
Bluetooth Central & Peripheral Demo
This is the only demonstration that will require a few external components. It also is the only demo we will look at that requires two Arduino Nano 33 IoT boards.
The extra components are very simple, in fact, only two are really required (and you can even eliminate one of those by changing the sketch).
In addition to two Arduino Nano 33 IoT boards you will need:
- An SPST momentary-contact NO pushbutton switch
- A 10K pulldown resistor for that switch (you could do this in code as well)
- An LED (optional, as the built-in LED will work)
- A dropping resistor for that LED, I used 220 ohms.
The purpose of this demonstration is to show how we can use the Arduino Nano 33 IoT as both a Central Bluetooth controller and as a Peripheral or slave device. We will demonstrate this by having a pushbutton on the Central unit control an LED on the Peripheral unit.
The hookup is as follows:
Note that we are using the 3.3-volt output as a HIGH signal when the pushbutton is pressed. Remember that the Arduino Nano 33 IoT is a 3.3-volt logic device and cannot handle 5-volts.
You’ll probably want to assemble these circuits on two independent breadboards. You can also eliminate the LED and dropping resistor and just observe the built-in resistor on the Nano 33 IoT that acts as the Peripheral device.
We will obviously need two sketches, one for each board. You will find them in the Examples section under ArduinoBLE.
The ArduinoBLE examples are divided into two folders, one for the Central controller and the other for the Peripheral device. We will need a sketch from each of these folders.
- The LedControl sketch from the Central folder
- The LED sketch from the Peripheral folder.
The key element to note in each sketch is that they use a common (and very long) identity string to identify the peripheral and establish a match.
The peripheral establishes an “advertised service” with a “characteristic”, which in this case is the LED. The central controller looks for this advertised service once it establishes a connection.
The “characteristic” is the state of the LED, on or off.
If the peripheral has an LED characteristic then the central sketch knows it can control it. It reads the state of the pushbutton and modifies the characteristic. The Peripheral receives the modified characteristic and sets the LED state accordingly.
Load both sketches, it is helpful if you can switch serial monitors between them while establishing an initial connection.
Once you do you should be able to control the LED state with the pushbutton. The serial monitor on both devices will display the pushbutton or LED state.
A very simple example, but it can be extended to control a number of devices over Bluetooth with a couple of Arduino Nano 33 IoT boards.
Conclusion
The Arduino Nano 33 IoT is certainly a significant update to the original Nano, but of course, you’d expect that after over a decade between models.
Keeping the form factor and pinout the same was an interesting design choice, however, as this is a 3.3-volt device it’s not exactly feasible to just unplug the old chip and plug in the new one. And a few more pins would allow us to take advantage of some of the other SAMD21 features, like analog output pins.
Price-wise it isn’t as cost-effective as an ESP-32 Node MCU board, although it should be remembered that the included NINA-W103 module actually includes an ESP-32. But as that ESP-32 is isolated by the SPI bus connection it really can’t be used as anything except for WiFi and Bluetooth communications link.
It’s a high-quality board, and the inclusion of the IMU along with the WiFi and Bluetooth should lend itself to some interesting controller designs.
But the real shining feature of the Arduino Nano 33 IoT is the one that I have only mentioned briefly – the ability to connect to the Arduino Cloud. This will allow the board to be used for what it is intended for, as an IoT controller device.
We will be doing exactly that with the Arduino Nano 33 IoT board very soon, so keep your eyes peeled for more articles and videos featuring this board.
Until then, there are some links in the Resources section below that will get you started on the Arduino Cloud.
Even without the Cloud connection, this is a very powerful little microcontroller that will be the heart of a number of interesting projects, both IoT and non-IoT. So keep looking out for more adventures with the Arduino Nano 33 IoT!
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 the article in one ZIP file.
Getting Started with the Arduino Nano 33 IoT – Official guide from Arduino.
Arduino Nano 33 IoT – Ultimate Guide – A guide from GitHub user “ostaquet”.
Arduino Cloud – The Arduino Cloud IoT Service.
Getting started with the Arduino IoT Cloud – Arduinos guide to using their cloud service.
NINA-W10 Datasheet – Datasheet for the NINA-W10 series of radio modules.
SAMD21 Datasheet – Datasheet for the SAMD21 series of 32-bit microcontrollers.
LSM6DS3 Datasheet – Datasheet for the LSM6DS3 IMU.
Arduino LSM6DS3 library – The library for the IMU.
A big thank you Bill for this very clear and very well-documented tutorial. Great!
For those who want to experiment with the Wifi RTC sketch and get the message “NTP unreachable!!”, just give your Wifi a chance to reach the NTP server by increasing the maxTries variable as Bill’s sketch invites to adapt it. For me, it didn’t work until I set maxTries to 10,000.
Thank you so much! The real time clock using WiFi tutorial helps me a lot! Thanks again!
Thank you so much for the time and trouble you take to write these wonderful articles. Your explanations, both in text and in your videos, are models of clarity. Bravo!
Hello,
I am constructing a spherical parallel actuator and was wondering what you would suggest using for motors. I have been researching the three main ones (dc, stepper & servo) but am still undecided. However, I am leaning towards dc motors with encoder… although I have to get better at using them. Lmk if you get any thoughts on the matter and have a great day!
Regards,
SP
Are there any nano IOT 33 clones available? I’ve purchased nanos from Lafvin and RexQualis, but didn’t see any nano IOT 33 on Amazon except the official Arduino.
Great website. Very clear information, not to mention educational. This has become my go to site for Arduino.
love my new nano33 IoT. I also love your instructions, sketches and videos on how to connect. Excellent.
hi
i want to use the nano 33 IOT with a GPS device BN 880 but how can I use RX en TX without software serial, because that does not exists for the nano 33 IOT
I’m in the same boat, did you ever figure this out Ronald? In my project I’m trying to read air quality (from a PMS5003) and it sends it to RX/TX, which is confusing to designate on the nano because the nano has dedicated RX/TX ports. So trying to code it is weird.
Great site Bill.
Im from Baracoa. Cuba. My nano33 IoT is on hand but is real plesure learning with you. I will do weather station God willing.
I am getting the following output when trying to compile SacnNetwroks: /usr/local/bin/arduino-cli compile –fqbn arduino:mbed_nano:nano33ble –libraries /home/builder/opt/libraries/latest –build-cache-path /tmp –output-dir /tmp/607932693/build –build-path /tmp/arduino-build-3FA81EE6BBD30C272B40D23737810CA1 /tmp/607932693/ScanNetworks Using library SPI in folder: /home/builder/.arduino15/packages/arduino/hardware/mbed_nano/3.2.0/libraries/SPI (legacy) Using library wifinina_1_8_13 at version 1.8.13 in folder: /home/builder/opt/libraries/wifinina_1_8_13 /home/builder/opt/libraries/latest/wifinina_1_8_13/src/utility/spi_drv.cpp: In static member function ‘static void SpiDrv::begin()’: /home/builder/opt/libraries/latest/wifinina_1_8_13/src/utility/spi_drv.cpp:103:15: error: ‘NINA_GPIO0’ was not declared in this scope pinMode(NINA_GPIO0, OUTPUT); ^~~~~~~~~~ /home/builder/opt/libraries/latest/wifinina_1_8_13/src/utility/spi_drv.cpp:103:15: note: suggested alternative: ‘NINA_GPIOIRQ’ pinMode(NINA_GPIO0, OUTPUT); ^~~~~~~~~~ NINA_GPIOIRQ /home/builder/opt/libraries/latest/wifinina_1_8_13/src/utility/spi_drv.cpp: In static member function ‘static int SpiDrv::available()’: /home/builder/opt/libraries/latest/wifinina_1_8_13/src/utility/spi_drv.cpp:66:25: error: ‘NINA_GPIO0’ was not declared in this scope #define NINA_GPIOIRQ NINA_GPIO0 ^ /home/builder/opt/libraries/latest/wifinina_1_8_13/src/utility/spi_drv.cpp:597:25: note: in expansion of macro ‘NINA_GPIOIRQ’ return (digitalRead(NINA_GPIOIRQ) !=… Read more »
Good job. Thanks
Great tutorial as usual. I had a question about the BLE sketch, mine worked okay but I want to put the one unit outside however when I disconnect it the LED won’t work. How to I make it work remotely.
Great job and video as always.
I tried the wifi rtc sketch in nano33 iot and I had the following problem:
After 3 times of day and time display in the serial monitor, then it stopped displaying. Can you please help me?
Thanks for your time.
Thanks used my Arduino nano 33 today
still getting the same error trying to run the Arduino sample program to use the WiFi on the Nano 33 BLM Sense. C:\Users\rspoo\Documents\Arduino\libraries\WiFiNINA\src\utility\spi_drv.cpp: In static member function ‘static void SpiDrv::begin()’: C:\Users\rspoo\Documents\Arduino\libraries\WiFiNINA\src\utility\spi_drv.cpp:103:15: error: ‘NINA_GPIO0’ was not declared in this scope pinMode(NINA_GPIO0, OUTPUT); ^~~~~~~~~~ C:\Users\rspoo\Documents\Arduino\libraries\WiFiNINA\src\utility\spi_drv.cpp:103:15: note: suggested alternative: ‘NINA_GPIOIRQ’ pinMode(NINA_GPIO0, OUTPUT); ^~~~~~~~~~ NINA_GPIOIRQ C:\Users\rspoo\Documents\Arduino\libraries\WiFiNINA\src\utility\spi_drv.cpp: In static member function ‘static int SpiDrv::available()’: C:\Users\rspoo\Documents\Arduino\libraries\WiFiNINA\src\utility\spi_drv.cpp:66:25: error: ‘NINA_GPIO0’ was not declared in this scope #define NINA_GPIOIRQ NINA_GPIO0 ^ C:\Users\rspoo\Documents\Arduino\libraries\WiFiNINA\src\utility\spi_drv.cpp:597:25: note: in expansion of macro ‘NINA_GPIOIRQ’ return (digitalRead(NINA_GPIOIRQ) != LOW); ^~~~~~~~~~~~ C:\Users\rspoo\Documents\Arduino\libraries\WiFiNINA\src\utility\spi_drv.cpp:66:25: note: suggested alternative: ‘NINA_GPIOIRQ’ #define NINA_GPIOIRQ NINA_GPIO0 ^ C:\Users\rspoo\Documents\Arduino\libraries\WiFiNINA\src\utility\spi_drv.cpp:597:25: note: in expansion of macro ‘NINA_GPIOIRQ’ return (digitalRead(NINA_GPIOIRQ)… Read more »