Dimmable LED and environmental measurements: we interface the Arduino Nano ESP32 to the Arduino Cloud


Dimmable LED and environmental measurements with Arduino Nano ESP32 connected in the Cloud. After getting the basics in our previous article Independent control of two LEDs with Arduino Nano ESP32: a practical introduction, it’s time to do something more complex. In this second article on the Arduino Nano ESP32, you will be guided through the interfacing with the Arduino Cloud for the control of two LEDs (as in the previous case, one which can only be turned on or off and the other of which the brightness via PWM signal) and monitoring environmental conditions with a DHT22 sensor (therefore measuring environmental temperature and humidity). Through the dashboard that we will create on the Cloud we will be able to control the two LEDs and we will be able to view the temperature and humidity values ​​measured in the environment.

As usual, for the development of the project, we will use the excellent IDE PlatformIO.

Arduino Nano ESP32: A Powerful and Versatile Microcontroller


The Arduino Nano ESP32 is a microcontroller development board based on the ESP32-S2FH4 chip. It offers a wide range of features in a compact and convenient form factor, making it ideal for a variety of IoT and embedded projects.

Main features:

  • Microcontroller ESP32-S2FH4: CPU dual-core Tensilica Xtensa LX106 a 240 MHz, 4 MB di Flash SPI, 200 KB di SRAM, 802.11 b/g/n Wi-Fi e Bluetooth 4.2 BLE.
  • Integrated connectivity: Wi-Fi and Bluetooth 4.2 BLE for wireless communication with other devices and the Internet.
  • Wide range of I/O: 14 GPIO pins, 1 12-bit ADC, 1 8-bit DAC, SPI, I2C, UART and JTAG.
  • Support for expansion boards: Compatible with Arduino Nano expansion boards.
  • Power supply: Power supply via USB or external 5V.
  • Compact size: 45 mm x 18 mm x 7 mm.


  • Powerful and versatile: The ESP32-S2FH4 offers high performance and a wide range of features.
  • Integrated connectivity: Wi-Fi and Bluetooth 4.2 BLE for wireless communication.
  • Wide range of I/O: Suitable for a variety of sensors, actuators and other devices.
  • Support for expansion boards: Expand functionality with Arduino Nano expansion boards.
  • Easy to use: Compatible with the Arduino IDE and the Arduino programming language.


  • IoT: Home automation, wearable tech, environmental and industrial monitoring projects.
  • Robotics: Control of robots and drones.
  • Wearable electronics: Smart watches, fitness trackers and other wearable devices.
  • Rapid prototyping: Quickly create prototypes of electronic devices.

The Arduino Nano ESP32 is a powerful and versatile microcontroller development board that offers a wide range of functionality in a compact and affordable form factor. It is an excellent choice for a variety of IoT and embedded projects.

What is the PWM technique (which allows us to have a dimmable LED)

PWM, an acronym for Pulse Width Modulation, is a technique used to modulate the pulse width of a periodic signal, generating a waveform with a variable duty cycle.

PWM varies the ratio of the time the signal is at a high level to the total period of the signal. This allows you to control the power delivered to a load without having to vary the supply voltage. PWM is implemented through the use of a hardware timer within the microcontroller. The timer generates a periodic signal at a constant frequency, while the signal’s duty cycle (i.e. the ratio of the time the signal is high to the period) is adjusted as needed.

In practice, the PWM signal is a periodic rectangular waveform in which the ratio between the time the signal is at a high level (ON) and the total period of the signal determines the intensity or power of the signal. Visually, a PWM signal can be represented as a series of rectangular pulses. The period of the signal corresponds to the length of a complete cycle, while the duty cycle represents the fraction of time that the signal is at a high level during each cycle. The duty cycle can vary from 0% (the signal is always low) to 100% (the signal is always high).

When the duty cycle is at 50%, the signal has a 1:1 ratio between the time it is high and the total period time, and appears as a rectangular waveform with the same period length and the same duration both in the half-period in which the signal is high and in the one in which it is low.

If the duty cycle is less than 50%, the signal has a shorter working period than the total period, and if it is more than 50%, the working period is longer.

PWM finds numerous applications in various sectors, including:

  • Motor speed control: by adjusting the duty cycle of the PWM signal, it is possible to control the rotation speed of the electric motors.
  • Brightness control of LED lights: by modulating the duty cycle of the PWM signal, it is possible to control the light intensity of the LEDs.
  • Servomotor control: PWM is used to control the position of servo motors in robotics and model making applications.
  • Digital audio: in the field of digital audio, PWM is used to generate audio signals at variable frequencies.

The main advantages of PWM include energy efficiency, simplicity of implementation, and the ability to precisely control the power delivered to a load without having to vary the supply voltage.

PWM therefore represents a fundamental technique for controlling electronic devices and is widely used in a wide range of industrial, commercial and hobby applications.

What is DHT22

The DHT22 is a digital temperature and humidity sensor designed to precisely measure these environmental parameters. It uses a capacitive humidity sensor and a thermistor to measure the humidity and temperature of the surrounding environment respectively. When powered, the sensor captures data and converts it into digital signals that can be read by a microcontroller or other electronic device.
The DHT22 is characterized by good precision and stability in temperature and humidity measurements. It has a wide operating temperature range and claimed accuracy in measurements. The range of temperatures measured goes from -40°C to +80°C (with a resolution of 0.1°C) while that of relative humidity goes from 0% to 100% (with a resolution of 0.1%). Furthermore, the DHT22 is capable of carrying out a complete measurement in approximately 2 seconds.
The sensor usually has three pins for interfacing: one for power, one for ground and one for digital data transmission. It uses a serial communications protocol to transmit readings to the controller. The data is directly digital so there is no need to acquire it with an analog-to-digital converter.
The DHT22 is widely used in environmental monitoring projects, climate control systems, DIY weather stations and other devices that require precise measurement of temperature and humidity.

Advantages: Among the advantages of the DHT22 are its compact size, ease of use, low power requirement and relative cost-effectiveness compared to other similar sensors.

Limitations: While accurate, the DHT22 may be subject to slight measurement fluctuations in environments with high temperature or humidity variations. Furthermore, its digital interface may require some attention in programming and interpreting the data read.

But what is Arduino Cloud?

Arduino Cloud is an online service developed by Arduino, , the Italian company known for its open-source prototyping platform. The main purpose of Arduino Cloud is to provide a simple and effective way to connect and control Arduino-based devices remotely over the Internet. It is part of the Arduino IoT (Internet of Things) ecosystem which aims to allow developers to create IoT projects in an easy and extremely intuitive way using Arduino resources. Furthermore, it is also possible to use other types of devices (not strictly Arduino) such as, for example, the ESP8266 and ESP32 boards.

Here are some of its features:

  • Remote connection: Arduino Cloud offers a way to connect various devices to the Internet so they can be monitored and controlled from anywhere via an online Dashboard or mobile application;
  • Control and Monitoring: once the devices are connected, you can use the online interface to monitor various sensors and variables on your device and control its actuators. For example, you could read data from a temperature and humidity sensor and activate a motor or relay connected to your device;
  • Automation: Arduino Cloud lets you create automation rules and scenarios so your device can respond to certain conditions or trigger specific actions. This is useful for creating home automation systems or advanced IoT projects;
  • Safety: Arduino Cloud generally takes security measures to ensure that connections between devices and the service are protected. This may include data encryption and secure authentication;
  • Support for multiple devices: Arduino Cloud is compatible with a variety of devices and boards.

What components do we need?

The list of components is not particularly long:

Project implementation

The electrical diagram

Before creating the actual circuit let’s take a look at the pinout of the board:

Pinout of the Arduino Nano ESP32 board
Pinout of the Arduino Nano ESP32 board

The DHT22 sensor pinout:

The DHT22 sensor pinout
The DHT22 sensor pinout

We will use GPIOs D2 and D5 to connect the LEDs and GPIO D7 to connect the DHT22.

At this point you can proceed with the creation of the circuit by following the connection diagram below.

The LEDs are connected to the Arduino Nano ESP32 via 100Ω resistors to limit the current that passes through them and avoid burning them (and burning the digital outputs to which they are connected).

The LED has two terminals (called anode and cathode) and, like all diodes, it is a component that has its own polarity: it passes the current when it is forward polarized (i.e. the voltage at the anode is greater than that at the cathode) and it blocks current when it is reverse polarized (i.e. the anode voltage is lower than the cathode voltage). The voltage between the anode and cathode, which we will indicate with Vd, varies according to the color of the light emitted. In particular we have that:

  • Vd = 1.8 V for red LEDs
  • Vd = 1.9 V for yellow LEDs
  • Vd = 2 V for green LEDs
  • Vd = 2 V for orange LEDs
  • Vd = 3 V for blue LEDs
  • Vd = 3 V for white LEDs

Below is the assembly diagram created with Fritzing:

Complete circuit diagram of the dimmable LED project and environmental measurements
Complete electrical diagram

How do we identify the anode and cathode of the LED? We do this by looking at its terminals. The longest corresponds to the anode. Also, the LED body has a flattening at one point on the edge indicating that the nearby terminal is the cathode.

So if an LED doesn’t light up it’s possible that it’s wired upside down. In this case, to make it work, simply reverse the connections.

How do you calculate the resistance to connect to the LED?

Please note: this paragraph deals with the calculation of the limiting resistance in a theoretical way and requires a minimum knowledge of the basics of Electrotechnics. Therefore it is not essential for understanding the rest of the project and can be skipped by the reader not interested in such theoretical aspects.

As we have already said, the resistor between the generic GPIO and the LED serves to limit the current flowing through the LED. But how can we calculate its resistance value? Ohm’s Law comes to our aid which says that the potential difference across a resistor (i.e. the voltage measured at the ends of the resistor) is proportional to the current I flowing through it and the constant of proportionality is precisely the resistance value of the resistor R:

V2 - V1 = RI

Please note: for the sake of precision it must be pointed out that while the resistor is the physical component (the actual object), the resistance is its value. So it is improper (even if it happens frequently) to call the resistor with the term resistance.

We can see Ohm’s Law on a simple circuit consisting of a voltage source (the circle on the left) and a resistor:

Representation of Ohm's Law
Representation of Ohm’s Law

The voltage (or potential difference) V2 – V1 impressed by the voltage source on the resistor is equal to the product of R by I.

Now let’s see a slightly more complex scheme where the usual voltage generator, the resistor and a red LED are present:

Circuit for calculating the current limiting resistor on the LED
Circuit for calculating the current limiting resistor on the LED

In our case the Vg represents the voltage present at the digital output of the Arduino Nano ESP32 when it is HIGH and is therefore equal to 3.3V.

Vd is the voltage across the diode (between anode and cathode) when it is forward biased (ie when it is carrying current). Having chosen a red LED, we know from the previous table that Vd = 1.8V.

We need to determine the R-value of the resistor. We still have one unknown: the value of the current I which must flow in the circuit when the pin is in the HIGH state.

Please note: when the digital pin is in the LOW state its voltage (ie Vg) is zero, it follows that also the current I in the circuit is zero.

LEDs generally cannot withstand currents greater than 20mA, so we impose a maximum current of 15mA to be on the safe side.

By Kirchhoff’s voltage law we have that:

Vg - Vr - Vd = 0

From which we derive that:

Vr = Vg - Vd 

Passing to the real values, we have that:

Vr = 3.3V - 1.8V

It follows that:

Vr = 1.5V

But, by Ohm’s Law, we have that:

Vr = RI

from which:

R = Vr / I

Substituting the real values:

R = 1.5V / 0.015A

The result is a value of R equal to 100Ω.

Preparing the environment on the Cloud

At this point the device is ready. We now need to prepare the entire environment on the Arduino Cloud. If you haven’t already done so, create an account on the platform. In this regard you can follow the following video step by step:

Once logged in, you need to connect the Arduino Nano ESP32 to the computer’s USB, add the Arduino type device and wait for the automatic recognition procedure to be completed.

In this video we created:

  • the object (thing) called Arduino_Nano_ESP32_Thing with its ledOnOff variables (both as Name and Declaration) of type boolean, Read & Write and with periodicity of 1 second, ledPWM (both as Name and as Declaration) of type integer, Read & Write and with periodicity of 1 second, temperatures (both as Name and as Declaration) of type float, Read Only and with periodicity of 1 second, humidity (both as Name and as Declaration) of type float, Read Only and with periodicity of 1 second
  • the device named Arduino_Nano_ESP32_Device of type Arduino Nano ESP32;
  • the dashboard called Arduino_Nano_ESP32_Dashboard with a switch that controls the ON/OFF LED, a slider that controls the PWM LED and two indicators, one for the temperature and the other for the humidity.

PLEASE NOTE: it is important to note that in the video, at minute 1:30, I downloaded a pdf which contains the connection parameters to the device. They are called Device ID and Secret Key and we will need them later. So download this pdf too and keep it somewhere.

Obviously the Device ID and Secret Key parameters are specific to each device, therefore they change as the device changes.

The Arduino Cloud has created the empty structure of the sketch that we will take and transfer to PlatformIO in order to be able to fill it with the functions we need. In particular, he created the actual sketch which is a file with the .ino extension and a file called thingProperties.h.

The sketch

Let’s create the PlatformIO project

We have already seen the procedure for creating a PlatformIO project in the article How to create a project for NodeMCU ESP8266 with PlatformIO. You can follow the guide but when choosing the platform you will have to choose Arduino Nano ESP32 in the Board field of the wizard, as in the image below:

The Project Wizard compiled for Arduino Nano ESP32
The Project Wizard compiled for Arduino Nano ESP32

Do not install the libraries indicated in that article but install, always following the usual procedure, the Arduino_ConnectionHandler library:

Installing the Arduino_ConnectionHandler library
Installing the Arduino_ConnectionHandler library

and the ArduinoIoTCloud library:

Installing the ArduinoIoTCloud library
Installing the ArduinoIoTCloud library

Then install the DHT sensor library by Adafruit library:

Installing the DHT sensor library by Adafruit library
Installing the DHT sensor library by Adafruit library

the Adafruit Unified Sensor by Adafruit library:

Installing the Adafruit Unified Sensor by Adafruit library
Installing the Adafruit Unified Sensor by Adafruit library

and the Arduino_ESP32_OTA by Arduino library:

Installing the Arduino_ESP32_OTA by Arduino library
Installing the Arduino_ESP32_OTA by Arduino library

Now edit the platformio.ini file to add these two lines:

monitor_speed = 115200
upload_speed = 921600

and add the WIFI line between the lib_deps so it looks like this:

platform = espressif32
board = arduino_nano_esp32
framework = arduino
monitor_speed = 115200
upload_speed = 921600
lib_deps = 
	adafruit/DHT sensor library@^1.4.6
	adafruit/Adafruit Unified Sensor@^1.1.14

Now download the project from the link below:

Unzip the project you just downloaded and overwrite the main.cpp file in the src folder of the project created before.

Then, from the include folder of the project you just downloaded and unzipped, take the thingProperties.h file and copy it to the include folder of the project created before.

At this point you will have to edit this file in order to connect it to the cloud:


const char SSID[]               = SECRET_SSID;    // Network SSID (name)
const char PASS[]               = SECRET_OPTIONAL_PASS;    // Network password (use for WPA, or use as key for WEP)
const char DEVICE_KEY[]  = SECRET_DEVICE_KEY;    // Secret device password

As you can see, in this section there are some parameters to set.

The first parameter (DEVICE_LOGIN_NAME) can be found in the pdf you downloaded when you created the object (you can find the reference in the previous video). In the pdf the parameter is called Device ID.

The SECRET_SSID and SECRET_OPTIONAL_PASS parameters are, respectively, the name and password of your WiFi network. So, instead of SECRET_SSID you will put the name of your network in double quotes (“) and instead of SECRET_OPTIONAL_PASS you will put your network password (always in double quotes).

The last parameter, SECRET_DEVICE_KEY, can always be found in the pdf you downloaded from the platform with the name Secret Key.

So the section in question should look like this:

const char DEVICE_LOGIN_NAME[]  = "Device ID from the downloaded pdf";
const char SSID[]               = "my_wifi_ssid";    // Network SSID (name)
const char PASS[]               = "my_wifi_password";    // Network password (use for WPA, or use as key for WEP)
const char DEVICE_KEY[]  = "Secret Key from the downloaded pdf";    // Secret device password

As you can see, in the DEVICE_LOGIN_NAME field I put the value taken from the pdf under Device ID (in this case Device ID from the downloaded pdf), in the SSID field the SSID of my WiFi network (in this case my_wifi_ssid), in the PASS field the password of my WiFi network (in this case my_wifi_password) and in the DEVICE_KEY field the value taken from the PDF under Secret Key.

Let’s now analyze the sketch. At the beginning we find the inclusion of the necessary libraries (including the thingProperties.h file which contains information on our Cloud setup):

#include <Arduino.h>
#include "thingProperties.h"
#include "Update.h"
#include <DHT.h>

The GPIO to which the sensor is connected is then defined, the type of sensor (DHT22) and the dht object that manages it is instantiated:

#define DHTPIN  D7
#define DHTTYPE DHT22


The GPIOs for driving the two LEDs are then defined:

const int led1Pin = D2;  // LED 1 connected to pin D2
const int led2Pin = D5;  // LED 2 connected to pin D5

and the variables that time the measurements by the DHT22:

unsigned long measureDelay = 3000;                //    NOT LESS THAN 2000!!!!!   
unsigned long lastTimeRan;

The measurement time of the DHT22 is 2 seconds so it is better not to go below this time.

We then encounter the setup function:

// Initialize serial and wait for port to open:
// This delay gives the chance to wait for a Serial Monitor without blocking if none is found

//start dht sensor:

// Set LED pins as output
pinMode(led1Pin, OUTPUT);
pinMode(led2Pin, OUTPUT);

// Defined in thingProperties.h

// Connect to Arduino IoT Cloud

    The following function allows you to obtain more information
    related to the state of network and IoT Cloud connection and errors
    the higher number the more granular information you’ll get.
    The default is 0 (only errors).
    Maximum is 4

This function initializes the serial port, initializes the sensor, sets the GPIOs of the LEDs as OUTPUT, initializes the part linked to the Arduino Cloud.

We then encounter the loop function. It contains the instruction that updates the Arduino Cloud and a block that, every measureDelay seconds reads the temperature and humidity values ​​from the DHT22:

  // measurements every measureDelay ms
  if (millis() > lastTimeRan + measureDelay)  {
    humidity = dht.readHumidity();
    temperature = dht.readTemperature();
    lastTimeRan = millis();

The sketch ends with the two functions onPwmLEDChange and onOnoffLEDChange which manage the behavior of the two LEDs (the first varies the brightness of one of the two LEDs, the second turns the other LED on or off) based on how we act on the controls (switch and slider) present on the Cloud dashboard:

void onPwmLEDChange()  {
  // Add your code here to act upon PwmLED change
  analogWrite(led2Pin, ledPWM);

void onOnoffLEDChange()  {
  // Add your code here to act upon OnoffLED change
  digitalWrite(led1Pin, ledOnOff);

At this point all you have to do is upload the sketch to the board and go to the Dashboard to control the LEDs and read the values ​​measured by the sensor.

IMPORTANT NOTICE: it can happen, at least as it happened to me for the first upload, to receive an error of this type:

dfu-util: Cannot open DFU device 2341:0364 found on devnum 10 (LIBUSB_ERROR_ACCESS) 

dfu-util: No DFU capable USB device available

I use a Linux distribution (specifically a Fedora) and therefore I had to look for a solution for my system.

If you are using Linux and the aforementioned error appears, you need to create a file called 99-platformio-udev.rules in the /etc/udev/rules.d/ folder by giving the command:

sudo touch /etc/udev/rules.d/99-platformio-udev.rules

and then, still in the terminal, give the command:

curl -fsSL https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/system/99-platformio-udev.rules | sudo tee /etc/udev/rules.d/99-platformio-udev.rules

Once this is done you need to restart udev (or restart your PC) with one of these two alternative methods:

sudo service udev restart


sudo udevadm control --reload-rules
sudo udevadm trigger

For further information I invite you to consult the page https://docs.platformio.org/en/latest/core/installation/udev-rules.html#platformio-udev-rules

If the problem occurs on Windows, you need to install the appropriate drivers as shown in this link https://docs.espressif.com/projects/esp-idf/en/stable/esp32s2/api-guides/dfu.html#:~:text=The%20reason%20for%20No%20DFU,is%20not%20in%20bootloader%20mode. in the USB Drivers (Windows Only) paragraph.

Video of the operation

Below is a video demonstrating how the device works:


If you want to be informed about the release of new articles, subscribe to the newsletter. Before subscribing to the newsletter read the page Privacy Policy (UE)

If you want to unsubscribe from the newsletter, click on the link that you will find in the newsletter email.

Enter your name
Enter your email
0 0 votes
Article Rating
Inline Feedbacks
View all comments
Would love your thoughts, please comment.x
Scroll to Top