Motion Detection with ESP32 & PIR Sensor

Hello readers, we hope you all are doing great. Welcome to the 4th lecture of Section 5(ESP32 Sensor) in the ESP32 Programming Series. So far, we have discussed the ESP32 built-in sensors in this section. Today, we are going to interface an external embedded sensor(i.e. PIR Sensor) with the ESP32 Microcontroller board. At the start, we will discuss the basics of a PIR Sensor(HC-SR501) i.e. its pinout and working. After that, we will design a simple project to detect the motion with a PIR sensor and ESP32. Finally, we will display the motion detection results on the ESP32 WebServer.

We will use ESP32 interrupts to detect the motion. Interrupts are used when a microcontroller needs to continuously monitor an event while executing other tasks at the same time. We have already posted a tutorial on ESP32 Interrupts, which includes both software and hardware interrupts. In this tutorial, we are implementing the hardware interrupt(Hardware interrupts are the external interrupts that are caused by an external event). In our project, the hardware interrupt will be generated by the PIR sensor.

PIR motion sensor is mostly used in home automation & security projects, used to enable the system to respond automatically over human presence. Appliances connected to ESP32 will respond automatically(as per the instructions provided) whenever an interrupt is triggered by the PIR motion sensor. Let's first have a look at the working of PIR Sensor:

Where To Buy?
No.ComponentsDistributorLink To Buy
1ESP32AmazonBuy Now

What is a PIR Motion Sensor?

In today's project, we will use the HC-SR501 PIR Sensor to detect the motion. PIR stands for Passive Infrared sensors. It uses a pair of pyroelectric sensors to detect heat energy in the surrounding environment. Both the sensors sit beside each other, and when a motion is detected or the signal differential between the two sensors changes the PIR motion sensor will return a LOW result (logic zero volts). It means that you must wait for the pin to go low in the code. When the pin goes low, the desired function can be called.

PIR Sensor Calibration

PIR Sensor has two variable resistors on its back side, used to adjust the Sensitivity and Detection Range, explained below:

  • Low sensitivity ignores the small motions i.e. a moving leaf or a small mouse. The sensitivity can be adjusted based on the installation location and project requirements.
  • The second resistor is used to specify how long the detection output should be active. It can be set to turn on for as little as a few seconds or as long as a few minutes.

PIR Sensor Applications

Thermal sensing applications, such as security and motion detection, make use of PIR sensors. They're frequently used in security alarms, motion detection alarms, and automatic lighting applications.

Now let's interface the PIR Sensor with ESP32:

Interfacing PIR Sensor with ESP32

As I mentioned earlier, in today's project, we will design a motion detection project with ESP32 and PIR Sensor. In the first example, we will turn "ON" the LED on motion detection, while in the second project, we will display the results in the ESP32 WebServer.

Here's the list of the components for today's project:

Components Required

  • ESP32 Development Board
  • PIR motion sensor (HC-SR501)
  • LED
  • 1k Ohm resistor
  • Jumper Wires
  • Breadboard

Circuit Diagram

Here's the circuit diagram for motion detection with ESP32 and PIR Sensor:

Now let's design the programming code for motion detection:

ESP32 Motion Detection Code

We are using Arduino IDE to compile and upload code into the ESP32 module. You need to first Install ESP32 in Arduino IDE to get started. Here's the code for motion detection:

//----Set GPIOs for LED and PIR Motion Sensor
const int led = 23;
const int PIRSensor = 4;

// -----Timer: Auxiliary variables
#define timeSeconds 10
unsigned long now = millis();
unsigned long lastTrigger = 0;
boolean startTimer = false;

//---Checks if motion was detected, sets LED HIGH and starts a timer
void IRAM_ATTR detectsMovement()
{
    Serial.println( " MOTION DETECTED " );
    Serial.println("Turning ON the LED");
    digitalWrite(led, HIGH);
    startTimer = true;
    lastTrigger = millis();
}

void setup()
{
    Serial.begin( 115200 ); // Serial port for debugging purposes
    pinMode( PIRSensor, INPUT_PULLUP ); // PIR Motion Sensor mode INPUT_PULLUP
    pinMode( led, OUTPUT );
    digitalWrite( led, LOW );
    attachInterrupt( digitalPinToInterrupt( PIRSensor ), detectsMovement, FALLING ); // Set PIRSensor pin as interrupt, assign interrupt function and set RISING mode
}

void loop()
{
    now = millis();
    if( startTimer && (now - lastTrigger > ( timeSeconds*500)))
    {
        Serial.println(" Turning OFF the LED " );
        digitalWrite( led, LOW );
        startTimer = false;
    }
}

Variables Declaration

  • The first step is to set up the GPIO pins for the LED and motion sensor(PIR).
  • LED is connected to GPIO23 and PIR sensor to GPIO4, as shown in the below code:
//----Set GPIOs for LED and PIR Motion Sensor
const int led = 23;
const int PIRSensor = 4;
  • Next, we need variables to set the timer to count the time, after the interrupt is detected.
  • The variable "now" defines the current time
  • The variable "lastTrigger" defines the time when the interrupt is detected.
  • The variable "startTimer" is used to start the time when an interrupt is detected.
//-----Timer: Auxiliary variables
#define timeSeconds 10
unsigned long now = millis();
unsigned long lastTrigger = 0;
boolean startTimer = false;

ESP32 Interrupt Function "IRAM_ATTR"

  • The Function with the attribute "IRAM_ATTR" is executed inside the internal RAM.
  • We are assigning this attribute to our interrupt function because RAM (random access memory) operates faster than flash memory.
  • After the execution of the interrupt code or ISR, the normal code will be executed inside the flash memory.
  • It is recommended that the interrupt service routine should have the minimum possible execution time because it halts or blocks the normal program execution.
//---Checks if motion was detected, sets LED HIGH and starts a timer
void IRAM_ATTR detectsMovement()
{
    Serial.println( " MOTION DETECTED " );
    Serial.println("Turning ON the LED");
    digitalWrite(led, HIGH);
    startTimer = true;
    lastTrigger = millis();
}

Setup() Function

  • Inside the setup() function we are initializing the serial communication with a baud rate of 115200.
  • Set the mode of pin GPIO23 (LED) as output.
  • Set the initial state of the LED as LOW.
  • Assigned the digital pin(connected to the PIR Sensor) to hardware interrupt using the attachInterrupt function.
  • The detectMovement function is passed as an argument inside this function.
void setup()
{
    Serial.begin( 115200 ); // Serial port for debugging purposes
    pinMode( PIRSensor, INPUT_PULLUP ); // PIR Motion Sensor mode INPUT_PULLUP
    pinMode( led, OUTPUT );
    digitalWrite( led, LOW );
    attachInterrupt( digitalPinToInterrupt( PIRSensor ), detectsMovement, FALLING ); // Set PIRSensor pin as interrupt, assign interrupt function and set RISING mode
}

Loop() Function

We have activated the interrupt in the Setup Function, so when the PIR Sensor detects the motion, it will automatically execute the interrupt function, which will turn the LED ON and start the timer.

  • In the loop function, we are comparing the current time with the last triggered time.
  • LED will turn off after a delay of 5sec (once an interrupt is detected).
  • The variable “now” will be updated with the current time in each iteration.
void loop()
{
    now = millis();
    if( startTimer && (now - lastTrigger > ( timeSeconds*500)))
    {
        Serial.println(" Turning OFF the LED " );
        digitalWrite( led, LOW );
        startTimer = false;
    }
}

Motion Detection Results/Testing

  • Select the right development board from Tools >> Boards >> DOIT ESP32 DevKit V1 in Arduino IDE.
  • Compile and upload the code into ESP32 using Arduino IDE.
  • Open the serial monitor with a 115200 baud rate as defined in the Arduino code.
  • Press the EN button on the ESP32 development board.

This concludes the tutorial. I hope you find this tutorial helpful. Thanks for reading. See you soon with a new tutorial on ESP32. Take care !!!

Servo Motor Control with ESP32 WebServer

Hello readers, we hope you all are doing great. In this tutorial, we are going to demonstrate how to interface and control a servo motor using an ESP32 board. After that, we will demonstrate how to create a webserver to control the servo motor’s shaft position with the ESP32 board.

Servo Motors are among the most important actuators in robotics, with applications ranging from RC planes to automated door locks.

Where To Buy?
No.ComponentsDistributorLink To Buy
1ESP32AmazonBuy Now

Hardware components required

  • A servo motor
  • ESP32 development board
  • Connecting wires
  • Breadboard

Servo Motor

There are several specific types of electric motor applications in which the motor must rotate only at a specific angle. For such applications, we need a special type of motor with such a special arrangement that causes the motor to rotate at a specific angle for a given electric signal (input). The servo motor comes into effect for this purpose.

A servo motor is a linear or rotary actuator that enables accurate control of linear or angular position, acceleration, and velocity. It is made up of a motor and a sensor for position feedback. It also necessitates a fairly sophisticated controller, which is frequently a dedicated module designed specifically for use with servo motors.

Fig. Servo Motor

The primary reason to use a servo motor is that it offers angular precision, which means that it will only rotate as far as we want it to before stopping and waiting for the next signal to take action. The servo motor, unlike a standard electric motor, begins to turn as soon as we apply input power to it and continues to rotate until we turn off the power. We cannot restrict the rotational progress of an electric motor, but we can control its speed and turn it on and off. Small servo motors are included in numerous beginner Arduino launcher kits since they are simple to use in small electronic projects and applications.

Interfacing Servo Motor with ESP32

 

Fig. Interfacing Servo motor with ESP32

When compared to an Arduino, interfacing a servo motor to the ESP32 is extremely difficult because it does not support analogWrite(). However, it employs a variety of frequencies and timers, allowing all digital pins to be used as PWM pins and to send signals much faster than any Arduino.

Connections:

Servo motor consists of three wires;

Table 1 ESP32 and servo motor interfacing

Controlling servo motor

A servo motor is controlled by sending a PWM or pulse width modulated signal. A servo motor can only turn for a total of 180-degree movement (90 degrees in either direction).

The PWM signal sent to the motor specifies the position of the shaft, and the rotor will turn to the desired position depending on the duration of the pulse sent through the control wire.

Arduino IDE programming

We are using Arduino IDE to compile and upload code into the ESP32 module. To know more about Arduino IDE and how to use it, follow our previous tutorial i.e., on the ESP32 programming series.

  • Installing Required Libraries
  • Download the library from the given link:

https://github.com/RoboticsBrno/ServoESP32

  • Open the Arduino IDE.
  • Go to Sketch >> Include Library >> Add .ZIP library.
  • Select the zip file you have downloaded from the above link.

Fig. Adding Library file

Arduino IDE Code

  • We are using the example code that comes with the library file we have downloaded for the above link.
  • To access the example code, go to Files >> Examples >> Servo ESP32 and select the required example code.
  • In this tutorial, we are using a simple servo example code.

#include <Servo.h>

static const int servoPin = 4;

Servo servo1;

void setup()

{

Serial.begin( 115200 );

servo1.attach( servoPin);

}

void loop() {

for(int posDegrees = 0;

posDegrees <= 180;

posDegrees++)

{

servo1.write( posDegrees );

Serial.println( posDegrees );

delay( 20);

}

for(int posDegrees = 180;

posDegrees >= 0;

posDegrees--)

{

servo1.write( posDegrees);

Serial.println( posDegrees);

delay(20);

}

}

Code Description

    • The first task is adding the required library files or header files.

Fig. header file

  • Define the GPIO pin which you are going to use for controlling the servo motor.

Fig. Defining Variables

  • Create an object Servo, which is called

Setup()

  • Inside the setup() function, the first task is to initialize the serial monitor with a 115200 baud rate for debugging purposes.
  • Attach the GPIO pin you have assigned to the variable servoPin (in the global declaration) to the servo object.

Fig. setup function

Loop()

  • As we mentioned earlier, a servo motor can only rotate between 0 to 180 degrees. So in this code, we are changing the position of the servo motor from 0 degree to 180 degrees and then back to 0 degree from 180 degrees.
  • We have defined a variable postDegree to store the position or angle of the servo motor.
  • We are using the for() loop, which will change the position of servo motor from 0 to 180 degrees.

Fig.

  • Another for() loop is used to change the position back to 0 degrees from 180 degrees.

Testing

  • Select the right development board from Tools >> Boards >> DOIT ESP32 DevKit V1 in Arduino IDE.
  • Compile and upload the code into ESP32 using Arduino IDE.
  • Open the serial monitor with a 115200 baud rate as defined in the Arduino code.
  • Press the EN button from the ESP32 development board.
  • Now you should see the servo motor’s shaft rotating as per the instructions provided.
  • You can observe the variation on shaft’s angle on the serial monitor as well, as shown below:

Fig. Serial monitor output

Fig. ESP32 and servo motor

Creating a web server to control servo motor with ESP32

Let’s create a web server to control the position of the servo motor. We will create a web page containing a slider to control the angle/position of the servo motor’s shaft.

We have also created a tutorial on creating a simple web server with ESP32.

Arduino IDE Code

#include <WiFi.h>

#include <Servo.h>

Servo servo1; // create servo object to control a servo

// twelve servo objects can be created on most boards

// GPIO the servo is attached to

static const int servoPin = 13;

// Replace with your network credentials

const char* ssid = "SSID";

const char* password = "PASSWORD";

// Set web server port number to 80

WiFiServer server(80);

// Variable to store the HTTP request

String header;

String valueString = String(5);

int angle_x = 0;

int angle_y = 0;

// Current time

unsigned long currentTime = millis();

// Previous time

unsigned long previousTime = 0;

// Define timeout time in milliseconds (example: 2000ms = 2s)

const long timeoutTime = 2000;

void setup() {

Serial.begin(115200);

servo1.attach(servoPin); // attaches the servo on the servoPin to the servo object

// Connect to Wi-Fi network with SSID and password

Serial.print("Connecting to ");

Serial.println(ssid);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {

delay(500);

Serial.print(".");

}

// Print local IP address and start web server

Serial.println("");

Serial.println("WiFi connected.");

Serial.println("IP address: ");

Serial.println(WiFi.localIP());

server.begin();

}

 

void loop(){

WiFiClient client = server.available(); // Listen for incoming clients

if (client) { // If a new client connects,

currentTime = millis();

previousTime = currentTime;

Serial.println("New Client."); // print a message out in the serial port

String currentLine = ""; // make a String to hold incoming data from the client

while (client.connected() && currentTime - previousTime <= timeoutTime) { // loop while the client's connected

currentTime = millis();

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

header += c;

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("Connection: close");

client.println();

// Display the HTML web page

 

client.println("<!DOCTYPE html><html>");

client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");

client.println("<link rel=\"icon\" href=\"data:,\">");

// CSS to style the slider

// Feel free to change the background-color and font-size attributes to fit your preferences

client.println("<style>body { text-align: justify; font-family: \"Trebuchet MS\", Arial; margin-left:auto; margin-right:auto;}");

client.println(".slider { width: 600px; }</style>");

client.println("<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\"></script>");

// Styling Web Page

client.println("</head><body><h1>Control Servo via ESP32</h1>");

client.println("<p>Angle: <span id=\"servoPos\"></span></p>");

client.println("<input type=\"range\" min=\"0\" max=\"180\" class=\"slider\" id=\"servoSlider\" onchange=\"servo(this.value)\" value=\""+valueString+"\"/>");

client.println("<script>var slider = document.getElementById(\"servoSlider\");");

client.println("var servoP = document.getElementById(\"servoPos\"); servoP.innerHTML = slider.value;");

client.println("slider.oninput = function() { slider.value = this.value; servoP.innerHTML = this.value; }");

client.println("$.ajaxSetup({timeout:2000}); function servo(pos) { ");

client.println("$.get(\"/?value=\" + pos + \"&\"); {Connection: close};}</script>");

client.println("</body></html>");

//GET /?value=180& HTTP/1.1

if(header.indexOf("GET /?value=")>=0) {

angle_x = header.indexOf('=');

angle_y = header.indexOf('&');

valueString = header.substring(angle_x+1, angle_y);

//Rotate the servo

servo1.write(valueString.toInt());

Serial.println(valueString);

}

// 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

}

}

}

// Clear the header variable

header = "";

// Close the connection

client.stop();

Serial.println("Client disconnected.");

Serial.println(" ");

}

}

Code Description

  • Replace SSID and PASSWORD with your network credentials.

Fig. Variables to store Network credentials

  • As we are creating a web server, we need to assign a port to it and normally we use port 80 for a local webserver.
  • So, in the below code, we have assigned port 80 to the web server and then initialized a few variables:

Fig.

  • header variable is used to store the HTTP requests.
  • Variables angle_x and angle_y are used to store the position/angle of servo motor’s shaft.

Fig.

  • Variables to store timer values for a delay of 2sec or 2000ms.

Fig.

Setup()

  • Inside the setup() function, servoPin is being attached to the servo1 object.

Fig.

  • Wi-Fi.begin() is used to initialize the ESP32’s wi-fi module.
  • IP address of the device will be fetched once ESP32 is successfully connected to the wi-fi network.
  • begin() function is used to initialize the webserver mode in ESP32.

Loop()

  • After the webserver has been initialized successfully, the ESP32 server will be continuously waiting for the client connection.

Fig

  • Once the connection is established between the access point and the client device, the access point will wait for the data input.
  • A string type variable called currentLine has been defined to hold the incoming data from the client.
  • If there is a byte to be read from the client, then it will be stored inside the char type variable

HTML to display a web page

  • The ESP32 will respond to your browser with HTML (hypertext markup language) code that will be used to construct the web page.
  • HTTP header always starts with a response code e.g.: HTTP/1.1 200 ok
  • An HTML page will be created on the client’s browser, from where the client device can control the position of the servo motor.

Fig.

  • The next line, which signals that we are transmitting HTML, should always be the first thing we send.
  • Make the web page responsive in any web browser.
 

Fig.

  • The next task is styling the webpage and the slider.
  • The maximum and minimum angles are 180 and 0 degrees respectively.
  • valueString variable is containing the current angle/position of the slider, fetched from the HTTP request.

Fig.

  • Close the web connection and clear the header that was used to store the HTTP request header.
  • Print information about the closed web connection on the serial monitor.

Fig. Close the connection

Testing

  • Enter the Wi-Fi or network credentials in the code.
  • Compile and upload the code into ESP32 using Arduino IDE.
  • Make sure you have selected the right development board and com port before uploading the code.
  • Open the serial monitor with a 115200 baud rate as defined in the Arduino code.
  • Press the EN button from the ESP32 development board.

Fig. Serial Monitor

  • Copy the IP address from the serial monitor.
  • Open the web browser.
  • Paste the IP address. A webpage to control the position/angle of servo motor will be displayed, as shown below:

Fig. Web Page

This concludes the tutorial. I hope you found this of some help and also to see you soon with a new tutorial on ESP32.

Accessing ESP32 Dual Core

We are familiar with multiple features of the ESP32 module. Like Wi-Fi capabilities, classic Bluetooth, Bluetooth low energy (BLE), inbuilt sensors etc.

Hello readers, I hope you all are doing great. We have already mentioned in our previous tutorials that, ESP32 is also featured with a Dual-Core Processor. Which provides better performance and efficiency.

In this tutorial, we will learn how to use ESP32’s dual cores. ESP32 has two (32-bit each) Tensilica Xtensa LX6 microprocessors namely, core0 and core1 which makes it a powerful dual-core microcontroller and hence stands apart from its predecessors.

When we compile and upload a code using Arduino IDE, we do not have to worry about which core executes the code. It just runs.

Fig. 1 ESP32 dual-core processor

Features of Dual-Core processor

  • Power Efficiency: A single-core processor can rapidly hit 100% of its workload. On the other hand, a dual-core processor allows the efficient allocation of resources with a multitasking environment.
  • Increased Performance to Multithread Programs: Aside from being able to run multiple programs at the same time, dual-core processors can also collaborate to make a single program faster and more efficient. Multithreading allows programmers to send different instructions from the same program into two processing paths. On a single processor with hyper-threading, the program is still limited to the single core's maximum processing speed. However, on a dual-core, this effectively doubles the speed available to that program.
  • Two programs running simultaneously: Two cores allow two programs to run at the same time. The many complex calculations that a computer must perform to create the average browsing experience are difficult to quantify; however, single-core processors only create the illusion of multitasking through technologies such as hyper-threading.
Where To Buy?
No.ComponentsDistributorLink To Buy
1ESP32AmazonBuy Now

FreeRTOS in ESP32

A FreeRTOS (real-time operating system) firmware is already available in the ESP32 module. FreeRTOS is helpful in improving the system performance and managing the resources of the module. FreeRTOS allows users to handle several tasks like measuring sensor readings, making a network request, controlling motor speed etc. all of them run simultaneously and independently.

FreeRTOS offers multiple APIs for different applications. Those APIs can be used to create tasks and make them run on different cores. You need to create tasks to assign a particular part of code to a specific core. You can also prioritize that on which core the code will run. Priority value starts with level_0.

Accessing ESP32’s both cores using Ardui1no IDE

Whenever we run a code on Arduino IDE, it runs on core_1 by default.

  • How to check on which core the code is running?

There is a function you can use to check on which core the code is running on.

xPortGetCoreID()

Run the following code in Arduino IDE:

void setup()

{

Serial.begin(115200);

Serial.print( " setup() is running on: Core_" );

Serial.println( xPortGetCoreID() );

delay(1000);

}

void loop()

{

Serial.print( " loop() is running on: Core_" );

Serial.println( xPortGetCoreID() );

delay(1000);

}

  • Open the serial monitor with a 115200 baud rate.
  • Press the EN button from the ESP32 development board.

Fig. 2 Serial Monitor

From the results on the serial monitor, you can see that both setup() function and loop() function are running on core_1.

Steps to be followed to create a task are:

  • Create a task handle to keep a track of the task created. For example, a task handle named task is created below:

Fig. 3

  • Inside setup() function, create a task assigned to a specific core. xTaskCreatedPinnedToCore() function is used to create a task assigned to a specific core.

This function takes seven arguments:

  1. Name of the function to implement the task
  2. Name of the task
  3. Stack size assigned to the task in words (where 1 word = 2 Bytes)
  4. Task Input parameter
  5. Priority of the task
  6. Task handler
  7. Core where the task should run

Fig. 4

  • Create a function that contains the code for the task you have been created.

For example, we have created a function named task_code(). Inside the task_code() function a for(;;) loop is used which will create an infinite loop. All the instructions to be given for a particular core to perform a particular task like led blinking, sensor readings etc. will be written inside this for(;;) loop.

Fig. 5

  • How to delete the created task, during the code execution?

You can use the function vTaskDelete() during the code execution to delete a task. This function takes the task handle (task) as an argument.

  • Code for creating and assigning the separate task to each core

In this code we will use two LEDs to be processed by different core.

TaskHandle_t task1;

TaskHandle_t task2;

// Assign GPIOs pins to LEDs

const int led1 = LED_BUILTIN;

const int led2 = 25;

void setup() {

Serial.begin(115200 );

pinMode( led1, OUTPUT );

pinMode( led2, OUTPUT );

//create a task that will be executed in the Task1code() function, with priority 1 and executed on core 0

xTaskCreatePinnedToCore(task_1code, // Task function.

"Task1", // name of task.

10000, // Stack size of task

NULL, // parameter of the task

1, // priority of the task

&task1, // Task handle to keep track of created task

1); // pin task to core 1

delay(1000);

//create a task that will be executed in the Task2code() function, with priority 1 and executed on core 1

xTaskCreatePinnedToCore(task_2code, //Task function.

"task2", //name of task.

10000, //Stack size of task

NULL, //parameter of the task

1, //priority of the task

&task2, //Task handle to keep track of created task

0); //pin task to core 0

delay(1000);

}

//task_1code: blinks an LED every 1000 ms

void task_1code( void * pvParameters ){

Serial.print( "task1 running on: core " );

Serial.println( xPortGetCoreID() );

for(;;)

{

digitalWrite( led1, HIGH);

delay(1000);

digitalWrite(led1, LOW);

delay(1000);

}

}

//task_2code: blinks an LED every 500 ms

void task_2code( void * pvParameters )

{

Serial.print( "task2 running on: core " );

Serial.println(xPortGetCoreID() );

for(;;){

digitalWrite(led2, HIGH );

delay(500);

digitalWrite(led2, LOW );

delay(500);

}

}

void loop()

{

Serial.print( " loop() is running on: Core " );

Serial.println( xPortGetCoreID() );

delay(1000);

}

Code Description

  • We have created two task handle to keep track of two different tasks created for each core. Task1 is for core_1 and task2 is for core_0.
  • Although we do not need to create a new task and a task handle for core_1 because the void loop() function be default run on core_1 but for better understanding we are creating a different task for each core.

Fig. 6

  • Allocate GPIOs to the LEDs. Led1 is the inbuilt one that is connected with GPIO2 (internally) and another one is led2 to be connected with GPIO 25.

Fig. 7

Setup()

  • Initialize the serial monitor with a 115200 baud rate for debugging purposes.
  • Set the mode of LEDs as OUTPUT.

Fig. 8 setup() function

  • Create a task (task1) using xTaskCreatePinnedToCore() This task will take seven parameters which include; the task function namely task_1code(), name of the task, stack size of the task, priority level, task handle (if created), core to which you want to assign the task.

Fig. 9

  • Create a similar task for another core. We will create a different function for this task namely task_2code() and will pass task_2 as a task handle and the core selected is

Fig. 10

  • The next step is to create functions to execute the above task for each core.
  • task_1code() function is passed as a parameter in
  • xPortGetCoreID() function is used to fetch the core number on which the current function is running on.
  • This function will make the inbuilt LED (GPIO2) or led1 blink with a delay of 1 second or 1000msec.
  • This for(;;) loop will make led1 blink continuously which is similar to the instructions executed inside loop() function.
  • print() function is used to print the results on the serial monitor for debugging purposes.

Fig. 11

  • task_2code() function is called for task2.
  • This code will be executed in core0.
  • Led2 (GPIO25) will blink continuously with a delay of 0.5sec.

Fig. 12

  • Inside the loop function we called the xPortGetCoreID() function to get the core number which is responsible to execute the instructions written inside loop() function

Fig. 13 loop function

Testing

Components required:

  • ESP32 development board
  • Breadboard
  • 2*Jumper wires
  • 1*LED
  • 1*resistor(330 ohms)

Steps for testing:

  • Connect the LED with ESP32 as shown below:

Fig. 14 connecting LED with ESP32

  • Upload the code into the ESP32 development board.
  • Open the serial monitor with a 115200 baud rate.
  • Press the EN from the ESP32 development board.
  • Results observed from the serial monitor are shown below:

Fig. 15 Results on the serial monitor

  • On the serial monitor, we can see that task1 functions are processed by core 1 and task2 is processed by core 0.
  • We have already mentioned that core1 is the default processing core so instructions inside the loop() function are processed by core1.

This concludes the tutorial. We hope you found this helpful and also hope to see you soon with a new tutorial on ESP32.

Sending Sensor Readings to Google Sheet Through IFTTT using ESP32

Hello readers, I hope you all are doing great. In our previous tutorial, we learnt how to make HTTP POST from ESP32 to the IFTTT server.

In this tutorial, we will learn about another application of the ESP32 module in the field of IoT (Internet of Things). We can publish multiple sensor readings from ESP32 to Google sheets via the IFTTT web service.

IFTTT is used as a third-party web service to integrate Google sheets with ESP32.

Fig. 1

Where To Buy?
No.ComponentsDistributorLink To Buy
1ESP32AmazonBuy Now

Creating an IFTTT Account for Integrating ESP32 with Google Sheets

We are going to create an applet (on the IFTTT server) that is responsible to integrate the Webhooks and Google Sheets services.

While operating with the IFTTT server there are some services/utilities that we are going to deal with like Applets and Webhooks. Before getting started with the project, let’s first introduce you to those terms:

Applet

An Applet is a small application or a utility program, which is used for one or a few simple functions. It connects two or more devices or apps together. An applet provides integration between two devices or services to enable some functionality that those devices or services cannot do alone or on their own. An applet consists of actions and triggers.

Fig. 2

Webhooks

  • Webhooks are hypertext transfer protocol (HTTP) callbacks that are defined by the user. They are data and executable commands sent from one app to another over HTTP rather than through the computer's command line. Essentially, it is a method for apps to send automated messages or information to other apps.
  • When an event occurs on the "trigger" application, the app serializes the data and sends it to a webhook URL from the "action" application (the app that processes the data from the "trigger" application). After that, the active application can send a callback message.

Getting Started with IFTTT:

  1. Enter the following link in the web browser: https://ifttt.com
  2. Login with your Gmail or Facebook accounts for free.
  3. Click on Create icon (top left menu) to create an

Fig. 3: Creating an Applet

  1. Click on the ”if This” icon.

Fig. 4: “If This”

  1. Select a service. Search for the Webhooks service and select the respective icon.

Fig. 5: Search and Select Webhooks

  1. Click on the Receive a web request option to select a trigger option. The trigger will fire every time the maker service receives a web request to notify it of an event.

Fig. 6: Receive a Web Request

  1. Assign a name to the trigger event and click on Create trigger We have assigned ESP32_GoogleSheets.

Fig. 7: Create Trigger

  1. Next, click on the “Then That”

Fig. 8:  Then That

  1. To select the service, search for the Google Sheets service and click on the respective icon.

Fig. 9:  Google Sheets

 
  1. The next step is selecting an action, click on Add row to the spreadsheet

Fig. 10: Select an Action

  1. Click on the connect button to connect with the Google Sheet service, if you haven’t connected to it yet.

Fig. 11: Connect to Google Sheets Service

  1. A new window will pop up, where you need to log in with your Gmail account.
  2. Enter your Gmail account address and password.
  3. Click on Allow icon, (as shown below) to allow the IFTTT web service to access files from your Google drive. So that IFTTT can create new folders or update details in the existing Google drive folders with new sensor readings.

Fig. 12: Allow IFTTT Service to Access Files of your Google Drive

  1. Finally, complete the action field by assigning the name to the spreadsheet and path the folder in Google drive. Leave the Formatted row as it is (default).
  2. A folder named IFTTT will be created by default if you leave the above fields empty.

Fig. 13: Complete Action Fields

  1. Click on the finish

Fig. 14: Applet Successfully Created

Testing the Applet

Before interfacing the IFTTT service (applet) with ESP32, let us test the applet whether it is created successfully or not.

  1. Open the following link: https://ifttt.com/maker_webhooks
  2. Click on the Documentation

Fig. 15

  • A new window will open containing your key (API).
  • Enter the details in To trigger an Event and click on Test it.

Fig. 16: Test your Applet

  • Open your Google drive.
  • You should see a folder (named IFTTT ) in your Google drive.
  • Open the folder to see the values received from the IFTTT server.

Fig. 17:  IFTTT Folder in Google Drive

 

Components Required:

  • ESP32 development board.
  • USB cable to connect to ESP32 development board with the computer.

No external components are required as we are using the ESP32’s inbuilt sensors to take the readings.

 

Arduino IDE code

Let’s have an overview of the project before writing the Arduino code:

  • To access the internet, the ESP connects to the local Wi-Fi network.
  • Then, the Hall sensor will take the readings;
  • Your ESP32 will communicate with the IFTTT Webhooks service that publishes the readings to a spreadsheet on Google Sheets that is saved in your Google Drive’s folder.
  • After publishing the readings, the ESP goes into deep sleep mode for 15 minutes;
  • After 15 minutes the ESP wakes up;
  • After waking up, the ESP connects to Wi-Fi, and the process repeats.
  • We are using Arduino IDE to compile and upload into the ESP32 module. To know more about Arduino IDE and how to use it, follow our previous tutorial i.e., on ESP32 programming series.

#include <WiFi.h>

// Replace with your SSID and Password

const char* ssid = "SSID";

const char* password = "Password";

// Replace with your unique IFTTT URL resource

const char* serverName = "https://maker.ifttt.com/trigger/replace_this_with_eventName/with/key/replace_this_with_your_unique_key ";

// Maker Webhooks IFTTT

const char* server="maker.ifttt.com";

//----Timer for sleep

uint64_t uS_TO_S_FACTOR = 1000000; // Conversion factor for micro seconds to seconds

uint64_t TIME_TO_SLEEP = 900; //sleep for 15 minutes

 

void setup()

{

Serial.begin(115200);

delay(100);

Serial.print("Connecting to: ");

Serial.print(ssid);

WiFi.begin(ssid, password);

int timeout = 10 * 4; // 10 seconds

while( WiFi.status() != WL_CONNECTED && ( timeout-- > 0) )

{

delay(200);

Serial.print(".");

}

Serial.println(" ");

if(WiFi.status() != WL_CONNECTED )

{

Serial.println(" Failed to connect, going back to sleep ");

}

Serial.print("WiFi connected in: ");

Serial.print(millis());

Serial.print(", IP address: ");

Serial.println(WiFi.localIP());

makeIFTTTRequest();

// enable timer deep sleep

esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);

Serial.println("Going to sleep now");

esp_deep_sleep_start(); // start deep sleep for 900 seconds (15 minutes)

}

 

void loop()

{

// sleeping so wont get here

}

void makeIFTTTRequest()

{

Serial.print("Connecting to ");

Serial.print(server);

WiFiClient client;

int retries = 5;

while(!!!client.connect(server, 80) && (retries-- > 0))

{

Serial.print(".");

}

Serial.println();

if(!!!client.connected())

{

Serial.println(" Failed to connect... ");

}

Serial.print(" Request server: ");

Serial.println( serverName );

// Hall sensor values

String jsonObject = String("{\"value1\":\"") +

hallRead() +

"\",\"value2\":\"" + hallRead()

+ "\",\"value3\":\"" +

hallRead() + "\"}";

client.println(String("POST ") + serverName + " HTTP/1.1");

client.println(String("Host: ") + server);

client.println("Connection: close\r\nContent-Type: application/json");

client.print("Content-Length: ");

client.println(jsonObject.length());

client.println();

client.println(jsonObject);

int timeout = 5 * 10; // 5 seconds

while(!!!client.available() && (timeout-- > 0)){

delay(100);

}

if(!!!client.available()) {

Serial.println("No response...");

}

while(client.available()){

Serial.write(client.read());

}

Serial.println("\nclosing connection");

client.stop();

}

Code Description

  • Add the required header files.
  • WiFi.h header file is used to enable the Wi-Fi module and its respective functions.

Fig. 18:  Library Files

  • Enter the network credentials, SSID and Password.

Fig. 19:  Network Credentials

  • Add the IFTT domain name, the event name (you have created) and the API key. The event name we have created is ESP32_test.

Fig. 20

  • IFTTT Server URL.

Fig. 21

  • Time_To_Sleep variable is used to set a timer (sleep time) of 15 minutes (900 sec). ESP32 processor will wake up from sleep mode after every 15 minutes to take the sensor readings and publish them to Google Sheets.
  • uS_To_S_Factor is used to store the conversion value for converting the timer unit from microseconds to seconds.

Note: The ESP32 sleep time should not be very short. A very short sleep time can result in the exceeded limit of requests imposed by the IFTTT service.

Fig. 22: Timer

 

Setup()

    • Initialize the Serial monitor with a 115200 baud rate for debugging purposes.

Fig. 23:  Serial Monitor

  • Enable ESP32’s Wi-Fi module using begin() function which is using SSID and password as arguments.
  • Wait until the ESP32 is not connected to the Wi-Fi network.
  • Fetch the IP address using WiFi.localIP() function.

Fig. 24:  Wi-Fi

  • makeIFTTTRequest() function is used to connect ESP32 with the client server.

Fig. 25

  • esp_sleep_enable_timer_wakeup() function is used to enable the timer for sleep mode.
  • The duration of sleep mode is passed as an argument inside the timer function.
  • Esp_deep_sleep_start() function is used to start the sleep mode.

Fig. 26

  • The below code represents the process happening inside the makeIFTTTRequest()

Fig. 27

  • ESP32 connects to IFTTT serve and then communicates with the server (IFTTT) through port 80.
  • ESP32 tries 5 times to connect to the server and if it couldn’t then it will enter the sleep mode.

Fig. 28

  • jsonObject variable is used to store the sensor data to be shared to the Google Sheets via the IFTTT server.
  • We are using ESP32’s inbuilt Hall sensor to take the readings.
  • This variable will take three sensor values and ESP32 will communicate the readings to Google Sheets.

Fig. 29

  • Connection with the server will be closed once the data is shared successfully and ESP32 will enter to sleep mode form next 15 minutes.

Fig. 30

Testing

  • Select the right development board in Tools >> Boards >> DOIT ESP32 DevKit V1 in Arduino IDE.
  • Compile and upload the code into ESP32 using Arduino IDE.
  • Make sure that you have entered the right Wi-Fi credentials, API key and event name before uploading the code.
  • Open the serial monitor with a 115200 baud rate as defined in the Arduino code.
  • Press the EN button from the ESP32 development board.
  • Go to your Google drive.
  • You should see a folder (named IFTTT ) in your Google drive.
  • Another folder will be there inside the IFTTT folder (named as ESP32_hall sensor readings, in our case)
  • Open the folder to see the values received from the IFTTT server.
  • The spreadsheet will be updated after every 15 minutes. If you press the EN button before completing the sleep duration(15 minutes), the spreadsheet will be updated automatically with new sensor data, as shown below:

Fig. 31: Hall Sensor Readings on Google Sheets

Fig. 32: Serial Monitor

This concludes the tutorial. I hope you found this of some help and also to see you soon with the new tutorial on ESP32.

ESP32 HTTP Post with ThingSpeak and IFTTT

ESP32 is a powerful chip for Internet of Things applications. This tutorial is also based on another ESP32 application in the field of IoT.

Hello readers, I hope you all are doing great. In the previous tutorial, we learned how to send sensor readings from ESP32 to the cloud (ThingSpeak webserver).

In this tutorial, we will learn to send HTTP POST requests from the ESP32 board to ThingSpeak and IFTTT APIs.

Where To Buy?
No.ComponentsDistributorLink To Buy
1ESP32AmazonBuy Now

What is HTTP?

Fig. 1 Hypertext Transfer Protocol

HTTP stands for hypertext transfer control and it is a protocol for transferring data between a web client and a web server. Hyper text transfer protocol was invented alongside HTML (Hypertext markup language) to create the first interactive, text-based web browser: the original www or World Wide Web.

Server and client communication process over HTTP:

  • The ESP32 (client) sends an HTTP request to a server ( for example ThingSpeak or IFTTT.com)
  • The server responds to the ESP32 ( client ).
  • Finally, the response contains request status information as well as the requested content.

HTTP POST Request

Fig. 2 HTTP POST Request

Hypertext transfer protocol uses particular request methods to execute various tasks. Two mostly used HTTP request methods are: HTTP GET request and HTTP POST request.

HTTP GET request is generated to request data from a specific resource and the HTTP POST request method is used to send data from the client device to the server to create or update resources.

In this tutorial, we will demonstrate only the HTTP POST method with ThingSpeak and IFTTT web services.

Features of the HTTP POST request:

  • Unlimited data length: Data is submitted through the body of HTTP so there is no limit/restriction on data length.
  • Secure: Data does not get saved on the web browser hence, this method of data communication is secure.
  • Allows different data types.
  • Data privacy.

What is IFTTT?

IFTT stands for If This Then That. It is a free web service for making different services like email, weather services, Twitter etc to connect.

IFTTT means if a service is triggered, other IFTTT services will take action.

 

Fig. 3 IFTTT

IFTTT and ESP32

IFTTT acts as a bridge between ESP32 and other web services. Some of the tasks the ESP32 board can perform with the IFTTT API service are:

  • Sending Emails and SMSs
  • Controlling ESP32 with Google Assistant
  • Communicating data or information with smartphones.
  • Scheduling events for ESP32.

IFTTT comprises Applets and Applets further contains two IFTTT services namely trigger and action.

You can use the applets created by a company or can also create your own applet. To use the IFTTT applet with ESP32, we need to create an applet by ourselves. Such applet will contain Webhooks service to interact directly with ESP32 and other services that you want to use like email, Twitter service etc.

There are cases while using ESP32 with the IFTTT: either ESP32 will trigger the IFTTT to do some task or the IFTTT triggers ESP32 to do some task.

Steps to trigger IFTTT via ESP32

  • Create an IFTTT account
  • Create an Applet to connect Webhooks to the desired service.
  • Sending HTTP POST request from ESP32 board to IFTTT
  1. Creating an IFTTT account:

Enter the following link in the web browser: https://ifttt.com

  1. Login with your Gmail or Facebook accounts for free.
  2. Click on Create icon (top left menu) to create an Applet.
 

Fig. 4 Creating an Applet

 
  1. Click on the ”if This” icon.

Fig. 5 ” If This”

 
  • Select a service. Search for the Webhooks service and select the respective icon.

Fig. 6 Search and Select Webhooks

 
  • Click on the Receive a web request option to select a trigger option. The trigger will fire every time the maker service receives a web request to notify it to an event.

Fig. 7 Receive a Web Request

 
  • Assign a name to the trigger event and click on Create trigger We have assigned ESP32_test.
 

Fig. 8 Create Trigger

  • Next, click on the “Then That”

Fig. 9 Then that

  • Select a service. We are selecting an Email service.

Fig. 10 Selecting a Service

  • Next, define what will happen whenever the event is triggered (the event that we have created earlier) and click on the Finish

Fig. 11

  • Testing the Applet
  1. Open the following link: https://ifttt.com/maker_webhooks
  2. Click on the Documentation A new window will open containing your key (API).
  3. Enter the details in To trigger an Event and click on Test it.
 

Fig. 12 To Trigger an Event

Fig. 13 Event Successfully Triggered

 
  • Open the email account, you have used while creating an IFTTT account.
  • You should receive an email from IFTTT.

Arduino Code

#include <WiFi.h>

#include <HTTPClient.h>

//---------Netwrok Credentials

const char* ssid = "SSID";

const char* password = "Password";

const char* serverName = "http://maker.ifttt.com/trigger/ESP32_test/with/key/Enter you API key";

unsigned long lastTime = 0;

unsigned long timerDelay = 15000;

void setup()

{

Serial.begin(115200);

WiFi.begin(ssid, password);

Serial.println("Connecting");

while(WiFi.status() != WL_CONNECTED)

{

delay(500);

Serial.print(".");

}

Serial.println("");

Serial.print("Connected to WiFi network with IP Address: ");

Serial.println(WiFi.localIP());

// Random seed is a number used to initialize a pseudorandom number generator

randomSeed(hallRead());

}

Void Loop()

//Send an HTTP POST request after every 15 seconds

if ((millis() - lastTime) > timerDelay)

{

//Check WiFi connection status

if(WiFi.status()== WL_CONNECTED)

{

WiFiClient client;

HTTPClient http;

// Your Domain name with URL path or IP address with path

http.begin(client, serverName);

// Specify content-type header

http.addHeader("Content-Type", "application/x-www-form-urlencoded");

// Data to send with HTTP POST

String httpRequestData = "value1=" + String(random(25)) + "&value2=" + String(random(25))+ "&value3=" + String(random(25));

// Send HTTP POST request

int httpResponseCode = http.POST(httpRequestData);

/*

// If you need an HTTP request with a content type: application/json, use the following:

http.addHeader("Content-Type", "application/json");

// JSON data to send with HTTP POST

String httpRequestData = "{\"value1\":\"" + String(random(40)) + "\",\"value2\":\"" + String(random(40)) + "\",\"value3\":\"" + String(random(40)) + "\"}";

// Send HTTP POST request

int httpResponseCode = http.POST(httpRequestData);

*/

Serial.print("HTTP Response code: ");

Serial.println(httpResponseCode);

Serial.println("successfully conected to host");

// Free resources

http.end();

}

else

{

Serial.println("WiFi Disconnected");

}

lastTime = millis();

}

}

Code Description

  • Add the required header files.
  • WiFi.h header file is used to enable the Wi-Fi module and its respective functions.
  • HTTPClient.h header file is used to let the server and client pass information with HTTP response or request.

Fig. Libraries

  • Enter the network credentials, SSID and Password.

Fig. Network Credentials

  • Add the IFTT domain name, the event name (you have created) and the API key. The event name we have created is ESP32_test.

Fig.

Setup()

  • Initialize the Serial monitor with a 115200 baud rate for debugging purposes.

Fig.

  • Enable ESP32’s Wi-Fi module using begin() function which is using SSID and password as arguments.
  • Wait until the ESP32 is not connected to the Wi-Fi network.
  • Fetch the IP address using WiFi.localIP() function.

Fig.

  • randomSeed() function is used to generated a pseudorandom number. We are using Hall sensor to take hall readings and share them to IFTTT server (host).

Fig.

Loop()

  • If the ESP32 board is successfully connected to the Wi-Fi network, HTTP POST requests will be generated automatically after every 15 seconds.
  • Some random values (hall readings) will be sent through value1, value1, value3

Fig

  • Send HTTP POST request.
  • Print the HTTP POST response with the response code.
  • Response code 200 is for successful communication and 402 code will be printed if some error is detected during HTTP post request.

Fig.

  • Following lines are used when you want to make a request with some JSON

Fig.

  • End the HTTP request.

Fig.

Testing

  • Select the right development board in Tools >> Boards >> DOIT ESP32 DevKit V1 in Arduino IDE.
  • Compile and upload the code into ESP32 using Arduino IDE.
  • Make sure that you have entered the right Wi-Fi credentials, API key and event name before uploading the code.
  • Open the serial monitor with a 115200 baud rate as defined in the Arduino code.
  • Press the EN button from the ESP32 development board.
  • On the serial monitor, we can check whether ESP32 is successfully connected to the network or not and whether the HTTP POST request is generated successfully or not.

Fig. 14 Serial Monitor

  • Open your IFTTT account and click on My
  • Next, click on View Activity.

Fig. 15 View Activity

  • A screenshot of the latest activity is shown below:

Fig. 16 Received data.

 
  • Check your registered email. You should receive an email from IFTTT.

Fig. 17 Email Received from IFTTT Server

 

Making an HTTP POST Request (JSON data) from ESP32 to ThingSpeak with Arduino IDE

We have already posted an article on sending sensor readings from ESP32 to ThingSpeak. In this article, we will learn how to send HTTP POST requests from ESP32 to send JSON data to the ThigSpeak server.

ThingSpeak is a web service operated by MathWorks where we can send sensor readings/data to the cloud. We can also visualize and act on the data (calculate the data) posted by the devices to ThingSpeak. The data can be stored in either private or public channels.

Steps to be followed to access ThingSpeak API:

  • First, you need to create a MathWorks Account.
  • To create an account or log in to ThingSpeak (operated by MathWorks) server follow the link: https://thingspeak.com/
  • Click on Get Started for free.

Fig. 18 Getting Started for Free

  • Enter your details to create a MathWorks account as shown below:

Fig. 19 Create New Account

  • If you have already created a MathWorks account, then click on Sign in.

Fig. 20 MathWorks Sign in

  • Create a channel by clicking on the New Channel

Fig. 21 New Channel

  • Enter the respective details in the channel.

Fig. 22 Create a New Channel

 

Arduino Code

//-----------Libraries

#include <WiFi.h>

#include <HTTPClient.h>

//-----------Network Credentials

const char* ssid = "replace with your network SSID";

const char* password = "replace with netwrok password";

// Domain Name with full URL Path for HTTP POST Request

const char* serverName = "http://api.thingspeak.com/update";

// Service API Key

String apiKey = "Write API Key";

unsigned long lastTime = 0;

unsigned long timerDelay = 5000; //to add delay of 5sec

void setup()

{

Serial.begin(115200);

WiFi.begin(ssid, password); //initialize ESP32 wifi module

Serial.println("Connecting");

while(WiFi.status() != WL_CONNECTED)

{

delay(500);

Serial.print(".");

}

Serial.println("");

Serial.print("Connected to WiFi network with IP Address: ");

Serial.println(WiFi.localIP());

Serial.println("Timer set to 10 seconds (timerDelay variable), it will take 10 seconds before publishing the first reading.");

// Random seed is a number used to initialize a pseudorandom number generator

randomSeed(analogRead(25));

}

void loop()

{

//Send an HTTP POST request after every 5 seconds

if ((millis() - lastTime) > timerDelay)

{

//Check the WiFi connection status

if(WiFi.status()== WL_CONNECTED)

{

WiFiClient client;

HTTPClient http;

http.begin( client, serverName );

http.addHeader("Content-Type", "application/json");

String httpRequestData = "{\"api_key\":\"" + apiKey +

"\",\"field1\":\"" +

String(random(30)) + "\"}";

int httpResponseCode = http.POST(httpRequestData);

Serial.print("HTTP Response code: ");

Serial.println(httpResponseCode);

// Free resources

http.end();

}

else {

Serial.println("WiFi Disconnected");

}

lastTime = millis();

}

}

Code Description

  • Add the server address and API (Write) Key.

Fig.

Setup()

  • Inside setup() function, initialize the serial monitor with a 115200 baud rate for debugging purposes. Also initialize the Wi-Fi module using WiFi.begin() function.
  • randomSeed() function is used to generate pseudorandom numbers.
  • Inside the randomSeed() function, the data you want to share will be passed as an argument.
  • The data could be a sensor reading or some analog values.

Loop()

    • Inside the loop function, once the ESP32 board is successfully connected with Wi-Fi, ESP32 will make an HTTP POST request for JSON data.
    • The request will be made after every 5 seconds.
    • In this code, we will share JSON data.

Fig.

  • Print the HTTP POST response with the response code.
  • Response code 200 is for successful communication and 402 code will be printed if some error is detected during HTTP post request.

Fig.

Testing

  • Select the right development board in Tools >> Boards >> DOIT ESP32 DevKit V1 in Arduino IDE.
  • Compile and upload the code into ESP32 using Arduino IDE.
  • Make sure that you have entered the right Wi-Fi credentials, and write the API key before uploading the code.
  • Open the serial monitor with a 115200 baud rate to check whether ESP32 is connected to Wi-Fi or not.
  • Open the ThingSpeak account and check the Channel Stats.

Fig. : data (JSON) Chart on ThingSpeak

 

This concludes the tutorial. I hope you found this of some help and also to see you soon with the new tutorial on ESP32.

Sending Data to Cloud with ESP32 and ThingSpeak

The Internet of Things ( or IoT) is a network of interconnected computing devices such as digital machines, automobiles with built-in sensors, or humans with unique identifiers and the ability to communicate data over a network without human intervention.

Hello readers, I hope you all are doing great. In this tutorial, we will learn how to send sensor readings from ESP32 to the ThingSpeak cloud. Here we will use the ESP32’s internal sensor like hall-effect sensor and temperature sensor to observe the data and then will share that data cloud.

Where To Buy?
No.ComponentsDistributorLink To Buy
1ESP32AmazonBuy Now

What is ThingSpeak?

Fig. 1: ESP32 ThingSpeak

It is an open data platform for IoT (Internet of Things). ThingSpeak is a web service operated by MathWorks where we can send sensor readings/data to the cloud. We can also visualize and act on the data (calculate the data) posted by the devices to ThingSpeak. The data can be stored in either private or public channels.

ThingSpeak is frequently used for internet of things prototyping and proof of concept systems that require analytics.

Features of ThingSpeak

  • ThingSpeak service enables users to share analyzed data through public channels: Users can view multiple options on their channels via the settings panel. The tab displays sharing options, allowing the user to make their channel private, public or shared with specific users. Professionals can import and export data through their channels as well.
  • ThingSpeak allows professionals to prepare and analyze data for their businesses: Weather forecasters use the MATLAB Analysis app to prepare, analyze, and filter data, such as estimating average humidity or calculating dew point. Users can use the visualization and analysis applications to perform operations on live or historical data by using template codes. To enable modular coding, industry professionals can add new functions to the software. Companies can use ThingSpeak Analysis to read stored data or write new data to their private channels. They can scrape numbers from various web pages thanks to the URL filter.
  • ThingSpeak updates various ThingSpeak channels using MQTT and REST APIs: Professionals in the industry also use the platform to analyze and chart numerical data sent from smart devices and stored on various channels. Business owners can update their feeds, clear, or delete their channels entirely by using REST API calls like POST, GET, DELETE, or PUT. MQTT Publish methods allow users to update their feeds, whereas MQTT Subscribe methods allow them to receive messages.

Preparing Arduino IDE for ESP32 and ThingSpeak

  • We are using Arduino IDE to compile and upload code into the ESP32 module. To know more about Arduino IDE and how to use it, follow our previous tutorial i.e., on the ESP32 programming series.

Downloading and installing the required Library file:

  • Follow the link attached below to download theThingSpeak Arduino library:

https://github.com/mathworks/thingspeak-arduino

  • Open the Arduino IDE.
  • Go to Sketch >> Include Library >> Add .ZIP Library and select the downloaded zip file.

Fig. 2: Adding ThingSpeak Library

To check whether the library is successfully added or not:

  • Go to Sketch >> Include Library >> Manage Libraries

Fig. 3

  • Type thingspeak in the search bar.

Fig. 4: Arduino IDE Library Manager

  • The ThingSpeak library by MathWorks has been successfully downloaded.

This library comes with multiple example codes. You can use any of the example codes as per your requirements ad also modify the example code.

Fig. 5: Example Codes

Getting Started with ThingSpeak

  • To create an account or log in to ThingSpeak (operated by MathWorks) server follow the link: https://thingspeak.com/
  • Click on Get Started for free.

Fig. 6: Getting Started For Free

  • Enter your details to create a MathWorks account as shown below:

Fig. 7: Create New Account

  • If you have already created a MathWorks account, then click on Sign in.

Fig. 8: MathWorks Sign in

  • Create a channel by clicking on the New Channel

Fig. 9: New Channel

  • Enter the respective details in the channel.
  • As we already mentioned, we will use ESP32’s inbuilt sensors, Hall and temperature sensor to take the readings and then publish them to the ThingSpeak server.
  • So we are using two files, field1 and field2 for temperature and hall readings respectively.
  • You can use/enable more than two fields as per your requirements.

Fig. 10: Enter the Details in Channel

  • Click o the save button to save the channel details.

Fig. 11: Save the channel

  • After successfully saving the channel, a new window will open containing the channel details and Channel Stats.

Fig. 12: Channel Stats

  • In the same window, go to API Keys which contains the Write API keys and Read API keys.
  • Copy the Write API key and paste this in ESP32 Arduino code to send the sensor values to ThingSpeak.
  • You can also customize the chart in Private View. Click on the icon present at the top-right menu of Field Chart (in red box) to edit the chart.
  • Edit the details as per your requirements and click on the save button to save the details.

Fig. 13: Field Chart Edit

Arduino Code

We have already published a tutorial on the ESP32 hall sensor and internal temperature sensor.

// ------style guard ----

#ifdef __cplusplus

extern "C"

{

#endif

uint8_t temprature_sens_read();

#ifdef __cplusplus

}

#endif

uint8_t temprature_sens_read();

// ------header files----

#include <WiFi.h>

#include "ThingSpeak.h"

// -----netwrok credentials

const char* ssid = "SSID"; // your network SSID (name)

const char* password = "PASSWORD"; // your network password

WiFiClient client;

// -----ThingSpeak channel details

unsigned long myChannelNumber = 1;

const char * myWriteAPIKey = "API Key";

// ----- Timer variables

unsigned long lastTime = 0;

unsigned long timerDelay = 1000;

void setup()

{

Serial.begin(115200); // Initialize serial

WiFi.mode(WIFI_STA);

if(WiFi.status() != WL_CONNECTED)

{

Serial.print("Attempting to connect");

while(WiFi.status() != WL_CONNECTED )

{

WiFi.begin(ssid, password);

delay(1000);

}

Serial.println("\nConnected. ");

}

ThingSpeak.begin(client); // Initialize ThingSpeak

}

void loop()

{

if ((millis() - lastTime) > timerDelay )

{

int hall_value = 0;

float temperature = 0;

hall_value = hallRead();

// Get a new temperature reading

temperature = ((temprature_sens_read()-32)/1.8 );

Serial.print("Temperature (ºC): " );

Serial.print(temperature);

Serial.println("ºC" );

Serial.print("Hall value:" );

Serial.println(hall_value);

ThingSpeak.setField(1, temperature );

ThingSpeak.setField(2, hall_value );

 

// Write to ThingSpeak. There are up to 8 fields in a channel, allowing you to store up to 8 different

// pieces of information in a channel. Here, we write to field 1.

int x = ThingSpeak.writeFields(myChannelNumber,

myWriteAPIKey );

if(x == 200)

{

Serial.println("Channel update successful." );

}

else

{

Serial.println("Problem updating channel. HTTP error code " + String(x) );

}

lastTime = millis();

}

}

Code Description

  • Style guard is used at the beginning to declare some function to be of “C” linkage, instead of “C++” Basically, to allow C++ code to interface with C code.

Fig. 14: Style Guard

  • Add the required header files.
  • We have already discussed above how to download and add the ThingSpeak library file to Arduino IDE.

Fig. 15: Libraries

  • Enter the network credentials (SSID and Password).

Fig. 16

  • A Wi-Fi client is created to connect with ThingSpeak.

Fig. 17

  • Define timer variables.

Fig. 18

  • Add the channel number and API (Write) Key. If you have created only one channel then the channel number will be ‘1’.

Fig. 19

Setup()

    • Initialize the Serial monitor with a 115200 baud rate for debugging purposes.

Fig. 20

  • Set ESP32 Wi-Fi module in station mode using mode() function.
  • Enable ESP32’s Wi-Fi module using begin() function which is using SSID and password as arguments.
  • Wait until the ESP32 is not connected with the wifi network.

Fig. 21

  • Initialize the ThingSpeak server using begin() function that is passing client (globally created) as an argument.

Fig. 22

Loop()

    • Inside the loop() function, define an integer type variable to store the hall sensor readings.

Fig. 23

  • Define another float type variable to store temperature readings.

Fig. 24

  • Call the hallRead() function to store the hall sensor readings into hall_value

Fig. 25

  • Temperature_sens_read() function is used to read the temperature of ESP32 core.
  • Temperature observed by the internal temperature sensor is in Fahrenheit
  • o convert observed temperature i.e., in Fahrenheit into Celsius :

(F-32) *(5/9) = degree Celsius

Fig. 26

  • Print the temperature in degree Celsius and Hall sensor observations on serial moitor.

Fig. 27

  • Set the number of fields you have created to the thingSpeak server. We are adding only two fields. You can add up to maximum of 8 fields for different readings.

Fig. 28

  • writeFields() function is used to write data to the ThingSpeak server. This function is using the channel number and API key as an argument.

Fig. 29

  • Return the code 200 if the sensor readings are successfully published to ThingSpeak server and print the respective results on the serial monitor.

Fig. 30

Testing

  • Connect the ESP32 module with your laptop using USB cable.
  • Select the right development board in Tools >> Boards >> DOIT ESP32 DevKit V1.
  • Compile and upload the code into ESP32 using Arduino IDE.
  • Make sure that you have entered the right Wi-Fi credentials, API key and channel number before uploading the code.
  • Open the ThingSpeak website where you have created a channel and check the sensor readings.
  • A screenshot of the field chart we have created is show below. Where you can see the temperature and hall sensor values on the chart.

Fig. 31: ThingSpeak Channel Stats

 
  • To see the sensor values on Arduino IDE open the serial monitor with a 115200 baud rate.

Fig. 32: Results on the Serial Monitor

 

This concludes the tutorial. I hope you found this of some help and also to see you soon with new tutorial on ESP32.

ESP-NOW Protocol with ESP32 and ESP8266

Hello readers, I hope you all are doing great. In this tutorial, we will learn about the ESP-NOW protocol and how to communicate data between two ESP modules through ESP-NOW protocol and that is too without Wi-Fi connectivity.

Where To Buy?
No.ComponentsDistributorLink To Buy
1ESP32AmazonBuy Now

What is ESP-NOW Protocol?

Fig. 1: ESP-NOW Protocol

ESP–NOW is a connectionless communication protocol that is used for sharing small data packets between two ESP boards. This protocol is developed by Espressif.

Features of ESP-NOW Protocol:

  • It is a low-power wireless protocol, which makes two or more ESP devices communicate directly with each other without using Wi-Fi.
  • ESP-NOW protocol does not require a handshake for establishing a connection but, they require pairing and once the devices are paired they can exchange data.
  • ESP-NOW offers a persistent connection between ESP nodes. This means, once two ESP nodes are connected with each other (wirelessly) and suddenly one of the ESP devices loses power or restarted, the device will again (automatically) establish a connection with the other node to which it was connected before the power reset.
  • ESP- NOW protocol offers encrypted communication and hence, it is a secure method of wireless communication.
  • To check the success and failure of message delivery a callback function is used to send the information regarding the communication status. Before initializing the ESP-NOW, we need to enable the Wi-Fi for wireless connectivity but it is now required to connect the ESP devices with the internet.

ESP-NOW Protocol Limitations:

  • This protocol is only supported by ESP devices.
  • Only 10 (maximum) encrypted peers are supported in station mode and a maximum of 6 devices in access point mode.
  • The maximum payload size supported by ESP-NOW protocol is 250 bytes only.

Although, ESP-NOW protocol can communicate only small data packets ( maximum 250 bytes), but it is a high-speed protocol for wireless communication.

ESP devices can communicate over ESP-NOW protocol in different network topologies which makes it a very versatile protocol. The communication can be a point to point or point to multipoint (broadcast).

Different Scenarios in Which ESP Devices Can Communicate

Peer to peer or one to one communication

Fig. 2: Point to Point Communication

In peer-to-peer communication, only two ESP (either ESP32 or ESP8266) devices can connect with each other for data exchange. Each ESP device can act as a master device, a slave device or both master and slave at the same time.

Broadcast or one to many (master and slave)

Fig. 3: ESP32 Broadcasting with ESP-NOW protocol

In broadcast one ESP device (known as a broadcaster) act as a master device and broadcast the data to ESP devices acting as slave devices. Data is shared with all the slave devices simultaneously.

This communication method is used when users want to control multiple slave devices at a time.

Many to one. (Gateway)

Fig. 4: Many to One Communication

In many to one communication scenarios, there will be a central node or gateway which collects all the data from its nearby connected ESP devices.

This scenario can be applied when you need to collect sensor data from various sensor nodes to a single collector or central device, which is connected to all the nearby sensors.

Application of ESP-NOW Protocol

  • ESP-NOW protocol is used when users need to communicate data between two or more ESP devices without using a Wi-Fi router (whether it is ESP32 or ESP8266).
  • This protocol can be used for industrial or residential automation applications. Where we need to transmit small data or instructions like to turn ON and OFF equipment without using Wi-Fi. For example smart lights, sensors, remote control devices etc.

MAC Address to Identify The Receiver

MAC address or Media Access Control address is a six-byte hexadecimal address, that is used to track or connect with devices in a network. It provides the user with a secure way to identify senders and receivers in a network and avoid unwanted network access.

Fig. 5: MAC Address

Each ESP device has a unique MAC address.

So, before sharing the data between two or more ESP devices the MAC address of the receiver device should be known to the sender device.

Implementing ESP-NOW protocol with ESP32 in Arduino IDE

Both, the ESP32 and ESP8266 modules support the ESP-NOW protocol.

In this tutorial, we will connect the ESP32 and ESP8266 using the ESP-NOW protocol.

  • We are using Arduino IDE as a compiler and upload into the ESP32 module. To know more about Arduino IDE and how to use it, follow our previous tutorial i.e., on the ESP32 programming series.

Fig. 6: ESP-NOW Example Code in Arduino IDE

Library file Required to implement ESP-NOW Protocol:

  • Download the library from the given link: https://github.com/yoursunny/WifiEspNow
  • In this example, we are using two ESP devices where one is ESP32 and another is ESP8266.
  • We will make ESP32 to act as a Master device and ESp8266 as slave device.

Sender (ESP32) Source Code

#include <esp_now.h>

#include <WiFi.h>

// REPLACE WITH YOUR RECEIVER MAC Address

uint8_t broadcastAddress[] = {0xEE, 0xFA, 0xBC, 0xC5, 0xA4, 0xBF};

typedef struct struct_message {

char a[32];

int b;

float c;

bool d;

} struct_message;

// Create a struct_message called myData

struct_message myData;

// callback when data is sent

void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {

Serial.print("\r\nLast Packet Send Status:\t");

Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");

}

void setup() {

// Init Serial Monitor

Serial.begin(115200);

// Set device as a Wi-Fi Station

WiFi.mode(WIFI_STA);

// Init ESP-NOW

if (esp_now_init() != ESP_OK) {

Serial.println("Error initializing ESP-NOW");

return;

}

// get the status of Trasnmitted packet

esp_now_register_send_cb(OnDataSent);

// Register peer

esp_now_peer_info_t peerInfo;

memcpy(peerInfo.peer_addr, broadcastAddress, 6);

peerInfo.channel = 0;

peerInfo.encrypt = false;

// Add peer

if (esp_now_add_peer(&peerInfo) != ESP_OK){

Serial.println("Failed to add peer");

return;

}

}

void loop()

{ strcpy(myData.a, "THIS IS A CHAR");   // Send message via ESP-NOW esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));   if (result == ESP_OK) { Serial.println("Sent with success"); } else { Serial.println("Error sending the data"); } delay(2000); }

Code Description

  • The first step is including the required libraries or header files.

Fig. 7: Library Files

  • Replace the string with the MAC address of the receiver ESP device.

Fig. 8: MAC Address

  • The next step is creating a structure that contains the type of data you want to share with the receiver node or device. We are using four different data variables which include char, int, float, and bool. You can the data type according to your requirements.

Fig. 9: Variables

  • Create a variable of struct_message type to store the variable values. We created myData

Fig.10

  • onDataSent() function is a callback function which will be executed when a message is sent. This function will print a string on serial monitor to show that the message is successfully sent.

Fig. 11

Setup()

    • Inside the setup function, the first task is the usual one i.e., initializing the serial monitor for debugging purpose.
    • Set the ESP device in STA mode or in Wi-Fi station mode before initializing ESP-NOW.

Fig. 12: Serial monitor and Wi-Fi Initialization

  • Next step is, initializing ESP-NOW.

Fig. 13

  • A callback function is registered which will be called when a message is send (after initializing the ESP-NOW successfully).

Fig. 14

  • The next thing is pairing with another ESP-NOW device to communicate data.

Fig. 15: Pairing with the ESP8266 Receiver

  • esp_now_add_peer () function is used to pair with the receiver.
  • This function is passing a parameter called This parameter contains the MAC address of the receiver (ESP8266) to which the sender want to connect and communicate data.
  • If somehow the sender is not able to pair with the receiver ESP device, the result will be printed on the serial monitor.

Fig. 16

Loop()

  • In the loop() function, the message will be sent.
  • We have globally declared a structure variable myData.
  • In the loop function values or message that we want to share with the receiver ESP device (ESP8266) is assigned to the variables.

Fig. 17: Data to Be Shared

  • If the ESP32 (or sender) is successfully connected/paired with the receiver (ESP8266) send the message and once the message is sent, print the result on the Serial monitor.

Fig. 18

  • Esp_now_send() function is used to send data to receiver (i.e., ESP8266) over ESP-NOW protocol.
  • This function is passing two parameters. First is the broadcastAddress i.e. the MAC address of the receiver and another is the data stored in the variables.

Fig. 19: Send The Message

  • If there is some error in message sending then print the respective details on the serial monitor.
  • The next message will be sent with a delay of 2 sec (or 2000ms).

Fig. 20

ESP8266 (Receiver) Code

#include <WifiEspNow.h>

#if defined(ARDUINO_ARCH_ESP8266)

#include <ESP8266WiFi.h>

#elif defined(ARDUINO_ARCH_ESP32)

#include <WiFi.h>

#endif

// The recipient MAC address. It must be modified for each device.

static uint8_t PEER[]{0x02, 0x00, 0x00, 0x45, 0x53, 0x50};

void printReceivedMessage(const uint8_t mac[WIFIESPNOW_ALEN],

const uint8_t* buf, size_t count, void* arg)

{

Serial.printf("Message from %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3],

mac[4], mac[5]);

for (int i = 0; i < static_cast<int>(count); ++i) {

Serial.print(static_cast<char>(buf[i]));

}

Serial.println();

}

 

void setup()

{

Serial.begin(115200);

Serial.println();

WiFi.persistent(false);

WiFi.mode(WIFI_AP);

WiFi.disconnect();

WiFi.softAP("ESPNOW", nullptr, 3);

WiFi.softAPdisconnect(false);

Serial.print("MAC address of this node is ");

Serial.println(WiFi.softAPmacAddress());

uint8_t mac[6];

WiFi.softAPmacAddress(mac);

Serial.println();

Serial.println("You can paste the following into the program for the other device:");

Serial.printf("static uint8_t PEER[]{0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X};\n", mac[0],

mac[1], mac[2], mac[3], mac[4], mac[5]);

Serial.println();

bool ok = WifiEspNow.begin();

if (!ok) {

Serial.println("WifiEspNow.begin() failed");

ESP.restart();

}

WifiEspNow.onReceive(printReceivedMessage, nullptr);

ok = WifiEspNow.addPeer(PEER);

if (!ok) {

Serial.println("WifiEspNow.addPeer() failed");

ESP.restart();

}

}

loop()

{

char msg[60];

int len = snprintf(msg, sizeof(msg), "hello ESP-NOW from %s at %lu",

WiFi.softAPmacAddress().c_str(), millis());

WifiEspNow.send(PEER, reinterpret_cast<const uint8_t*>(msg), len);

delay(1000);

}

Code Description

  • This code can be used for both ESP8266 as well as ESP32 receivers.
  • The first task is adding the required libraries.
  • h is for enabling wireless connectivity in ESP8266 and WiFi.h is for ESP32 module (if you are using this device).
  • h is to enable the ESP-NOW protocol and its respective function is the ESP device.

Fig. 21: Header files in Receiver Code

  • printReceivedMessay() function is used to fetch the message details transmitted by ESP32 (sender node), and the MAC address of the transmitter.
  • If you are receiving data from multiple sender nodes then a unique MAC address will be fetched from multiple sender nodes along with the message received.

Fig. 22

Setup()

  • Initialize the serial monitor with a 115200 baud rate for debugging purposes.
  • Wi-Fi should be enabled to implement the ESP-NOW protocol and wireless connectivity. It could be either AP or STA mode and does not require to be connected.

Fig. 23: Serial Monitor Wi-Fi Initialization

  • Print the MAC address of the sender on the serial monitor.

Fig. 24

  • Initialize the ESP-NOW using begin() function.
  • If somehow the ESP device is unable to initialize the ESP then print the respective details on the serial monitor.

Fig. 25

  • Once ESP-NOW and Wi-Fi are successfully initialized, the ESP receiver (ESP8266) is ready to receive the data packets from sender.

Fig. 26

  • Testing (Receiving a message in ESP8266 from ESP32 )
  • Select the ESP8266 development board you are using in Arduino IDE.
  • For that, go to Tools >> Boards and select the right development board.
  • We are using the ESP8266 Generic module as shown below:

Fig. 27: Selecting The ESP 8266 Development Board

  • Upload the Receiver code in the ESP8266 module.
  • Open the serial monitor with a baud rate of 115200.
  • Press the reset (Rst) button from the ESP8266 development board.
  • MAC address of the receiver will be printed on the serial monitor as shown below:

Fig. 28: MAC Address of Receiver

  • Copy the MAC address of the receiver and paste into the sender (ESP32) code.
  • Again change the development board from ESP8266 to ESP32.

Fig. 29: Selecting ESP32 Board in Arduino IDE

  • Upload the code into sender (ESP32).
  • Open the serial monitor with a 115200 baud rate.
  • Press the enable (EN) button from the ESP32 development board.
  • Results are shown below:

Fig. 30: Message Sent

  • If you want to read the data received at ESP8266, remove the ESP32 and power it with a different power source.
  • Connected the ESP8266 with a laptop.
  • Again select the ESP8266 development board on Arduino IDE’s Tools >> Boards
  • Open the serial monitor with a 115200 baud rate.
  • Press the reset (RST) button from the ESP8266 developments board.
  • Results are shown below:

Fig. 31: Message Received

This concludes the tutorial. I hope, you found this helpful and I hope to see you soon for the new ESP32 tutorial.

ESP32 Internal Temperature Sensor

Hello friends, I hope you all are doing great. Welcome to the 3rd lecture of Section 5(ESP32 Sensors) in the ESP32 Programming Series. We have already discussed the two built-in ESP32 sensors i.e. Hall Effect Sensor and Capacitive Touch Sensor. Today, we are going to discuss the 3rd and final built-in ESP32 sensor i.e. Internal Temperature Sensor.

ESP32 Internal Temperature Sensor is used to calculate the temperature of the ESP32 core. So, we can't use it to measure the ambient temperature (the temperature of the atmosphere), for that, we need to use embedded temperature sensors i.e. DS18B20, DHT11, BMP280 etc. We will first discuss the basics of this Internal Temperature Sensor and then will design a code to monitor the change in temperature by changing the frequency of the ESP32 CPU.

Note:

  • Internal Temperature Sensor is not present in all ESP32 variants.
  • So, if ESP32 lacks the sensor, it sends an invalid temperature reading of 53.33oC(equivalent to 128 in decimal).

Important specs of the ESP32 Temperature Sensor are given in the below table:

ESP32 Temperature Sensor Features
Parameter Value
Converter Types ADC (Analog-to-Digital Converter), DAC (Digital-to-Analog Converter)
Accurate Temperature Sensing Range -40 °C to 125 °C
Suitability Good
Most Accurate Range -10 °C to 80 °C
Temperature Fluctuation Measurement High resolution
Potential Performance & Accuracy Issues Voltage fluctuations, Noise, Environmental factors, Nearby heat sources
Where To Buy?
No.ComponentsDistributorLink To Buy
1ESP32AmazonBuy Now

ESP32 Internal Temperature Sensor

ESP32’s on-chip temperature sensor cannot be used for monitoring external temperature. It can only be used to monitor the temperature of the core. This temperature sensor is available on some selective ESP32 boards and obsolete on most ESP32 variants. It has a high-temperature sensing range of -40 to 125 °C.

ESP32 boards are normally used in real-time IoT Projects i.e. home automation, back security etc. Such projects need to run 24/7 to get live updates and may heat up the motherboard. Thus, to get a stable performance in continuous operations, these internal temperature sensors are introduced to monitor the ESP32 Core.

ESP32 Boards with Built-in Temperature Sensor

Most of the modern ESP32 variants are equipped with the Internal Temperature Sensor. I have created a list of the ESP32 boards by taking the ESP-IDF documentation that caters to the built-in temperature sensor. Here's the list:

  • ESP32-C2
  • ESP32-C3
  • ESP32-C6
  • ESP32-H2
  • ESP32-S2
  • ESP32-S3

As you can see, most of the newer versions have a temperature sensor, but some older versions may also have one.

How does this temperature sensor work?

ESP32 temperature sensor consists of 2 converters:

  1. 8-bit Sigma-Delta analog-to-digital converter(ADC)
  2. digital-to-analog converter(DAC)

8-bit Sigma-Delta analog-to-digital converter (ADC)

Sigma-delta ADCs are widely favored for their exceptional accuracy and remarkable resolution, enabling them to deliver precise measurements. This ADC takes the analog signal from the temperature sensor, converts it to a digital signal and feeds it to the microcontroller for processing.

Digital-to-analog converter (DAC)

The DAC is responsible for the accuracy of the temperature measurements. It is embedded within the ESP32 and converts the digital values(converted by the Sigma-Delta ADC) again into analog values to offset any temperature-induced variation. As a result, it ensures accurate readings from the sensor.

Measuring Errors in Temperature Sensor

The accuracy of this temperature sensor changes according to the range group of the temperature values. Among different groups, the range of -10 ~ 80 is the most accurate. The reading errors along with their measuring ranges are shown in the below table:

Measuring Errors in ESP32 Temperature Sensor
No. Offset Predefined Range (°C) Error (°C) Operating Range (°C)
1 -2
50 ~ 125 < 3 Not recommended(Error)
2
-1
20 ~ 100 < 2 Ideal range for best accuracy
3
0 -10 ~ 80 < 1 Acceptable range with moderate accuracy
4
1
-30 ~ 50 < 2 Usable range with increased error at extremes
5
2
-40 ~ 20 < 3 Not recommended (error)

Different factors, including voltage fluctuations, noise, environmental factors, and nearby heat sources, can affect the performance and accuracy of this sensor.

Formula to convert observed temperature i.e. Fahrenheit to Celsius:

(F-32) *(5/9) = degree Celsius

ESP32 Temperature Sensor Applications

Here are the main applications of the ESP32 built-in temperature sensor:

Improve Chip Performance

A designer can easily monitor the internal chip’s temperature through the temperature sensor, identify bottleneck conditions, and conduct performance evaluations under extreme circumstances. So, the sensor helps in optimizing the chip's temperature and, thus, the performance.

Avoid Overheating

Electronic components/modules are sensitive, and if they are designed to work for prolonged operation, temperature management is one of the most crucial points to be considered. The built-in temperature sensor is a useful way to measure the operating temperature of the components connected to its peripherals and the whole system. These values are then utilized to set the threshold value so the system can trigger the safety mechanism when a certain heat level is passed. This can be done using the ESP32 code and surely prevent overheating to maintain the performance.

Energy Monitoring

The built-in temperature sensor helps to maintain the energy monitoring that, in turn, allows the energy monitoring of the project. The careful observation of the built-in temperature sensor output helps the user understand the relationship between temperature change and energy consumption. Using this approach, designers can target an optimized energy consumption.

Programming ESP32 to measure Core temperature in Arduino IDE

  • We are using the Arduino IDE as a compiler, we have already installed ESP32 in it, if you haven't, please read out How to Install ESP32 in Arduino IDE.
#ifdef __cplusplus
extern "C" {
    #endif
    uint8_t temprature_sens_read();
    #ifdef __cplusplus
}
#endif
uint8_t temprature_sens_read();

void setup()
{
    Serial.begin(115200);
}

void loop()
{
    Serial.print("Temperature: ");
    Serial.print(temprature_sens_read() );
    Serial.print(" F");
    Serial.print("______");

    // Convert raw temperature in F to Celsius degrees
    Serial.print((temprature_sens_read() - 32) / 1.8);
    Serial.println(" C");
    delay(1000);
}

Code Description

  • Style guard is used at the beginning to declare some function to be of “C” linkage, instead of “C++” Basically, to allow C++ code to interface with C code.
#ifdef __cplusplus
extern "C" {
    #endif
    uint8_t temprature_sens_read();
    #ifdef __cplusplus
}
#endif
uint8_t temprature_sens_read();

Setup() Function

  • Initialize the Serial monitor with a 115200 baud rate for debugging purposes.
void setup()
{
    Serial.begin(115200);
}

Loop() Function

  • Temperature_sens_read() function is used to read the temperature of the core.
  • Print the observer temperature on the serial monitor.
void loop()
{
    Serial.print("Temperature: ");
    Serial.print(temprature_sens_read() );
    Serial.print("______");
}
  • Convert the temperature from Fahrenheit to degrees Celsius and print on the serial monitor.
  • The result will be printed with a delay of 1 sec.
// Convert raw temperature in F to Celsius degrees
    Serial.print((temprature_sens_read() - 32) / 1.8);
    Serial.println(" C");
    delay(1000);

Testing/Results

  • Upload the code into the ESP32 board.
  • Open the serial monitor with a 115200 baud rate.
  • Press the EN button from the ESP32 development board.
  • See the result on the serial monitor as shown below:

This concludes the tutorial. I hope you found this of some help and also to see you soon with the new tutorial on ESP32.

Receiving Emails with ESP32 using IMAP Server

Hello readers, I hope you all are doing great. In our previous tutorial, we learned SMTP server and how to implement an SMTP server for sending emails with ESP32. In the previous tutorial, we also demonstrated some examples like sharing raw text, HTML text, images and text files.

So, at the transmitter end, we are using the SMTP server.

But, what about the receiver end?

At the receiver end, we use another protocol called IMAP (or Internet Message Access Protocol) and POP3 (Post office Protocol V3) for receiving the emails.

Fig. IMAP and SMTP

Where To Buy?
No.ComponentsDistributorLink To Buy
1ESP32AmazonBuy Now

What is IMAP Protocol and How does it Work?

IMAP is an application layer (TCP/IP) protocol that is used at the receiver end to receive emails from SMTP server or mail server. IMAP follows the client/server model.

Fig. IMAP Protocol

Features of IMAP protocol:

  • IMAP can operate in three modes:
    1. Online mode
    2. Offline mode
    3. Disconnected mode
  • IMAP uses two ports:
    1. 143 Port – Communication over this port is not secure because this is a non-encrypted IMAP port.
    2. 993 Port – Communication over this port is secure and it is used when the client (IMAP) wants to connect securely through IMAP.
  • Users can access emails from a remote server without deleting the emails from the email server.
  • Setting message flag – The message flag is set to help the user in keeping the track of which message has already been seen.
  • Receivers can create a folder to organize mails in the hierarchy.
  • Users can also download a portion of a message from the mime-multi part in case of large multimedia files.
  • Organizing mail on the server.
  • Check email header – user can check the email header before downloading the mail.

What is POP3?

POP3 stands for Post Office Protocol version 3.

POP3 is another protocol to receive emails. This protocol is used to access the TCP/IP mailbox. The protocol is quite popular due to its offline mail access model.

The offline access model enables the user to access the mails from the mail server on the local machine, and then delete them from the mail server.

Why IMAP is Preferred over the POP3?

  • Being an offline access model, POP3 is not suitable for the ideal world. The biggest drawback of the POP3 model is that emails are permanently deleted from the server, and is it not possible to access the mails in different computers.
  • In POP3 user is not allowed to manage the mails on the server whilst in IMAP protocol the user can delete, create or rename the mails on the server.
  • Another drawback of the protocol is data security and safety.
  • So, a new protocol is developed to overcome the drawback of the POP3 protocol. The protocol was named Internet Message Access Protocol or IMAP. Which is an online protocol and mails received via IMAP protocol can be accessed on different computers.

Though in some applications POP3 protocol is still used, but in most of the email receivers, it is preferred to use IMAP protocol over POP3 protocol.

Setting parameters for different IMAP service provider

IMAP (incoming) setting parameter for Gmail

  • IMAP Server address – imap.gmail.com
  • IMAP username – xyz@gmail.com
  • IMAP password – password
  • IMAP port – 993

IMAP (incoming) setting parameters for Yahoo

  • IMAP Server address – mail.yahoo.com
  • IMAP username – xyz@yahoo.com
  • IMAP password – password
  • IMAP port – 993
  • SSL required – Yes

Similarly, other email service providers like Outlook and Hotmail, have different setting parameters.

  • Components required to send and receive emails using ESP32 over SMTP server are:
  • Recipient’s email address.
  • Sender’s email address.
  • Content to be shared over SMTP server.
  • ESP mail client library.
  • ESP32 module.

ESP mail client Library

To send emails with ESP32 we need to install this ESP Mail Client library. This library, make ESP32 able to send emails over SMTP server.

Step to install ESP Mail Client Library:

  • To download the ESP Mail Client Library click on the link: https://github.com/mobizt/ESP-Mail-Client
  • Open the Arduino IDE.
  • Go to Sketch >> Include Library >> Add .ZIP Library.
  • Select the downloaded ZIP file.
  • Click on

Your Arduino IDE is ready to send email using ESP32.

Create a new Gmail account

It is recommended to create a new email account for sending emails using ESP32 or ESP8266 modules.

If you are using your main (personal) email account (for sending emails) with ESP and by mistake, something goes wrong in the ESP code or programming part, your email service provider can ban or disable your main (personal) email account.

In this tutorial, we are using a Gmail account.

Follow the link to create a new Gmail account: https://accounts.google.com

Access to Less Secure apps

To get access to this new Gmail account, you need to enable Allow less secure apps and this will make you able to send emails. The link is attached below:

https://myaccount.google.com/lesssecureapps?pli=1

Fig.

Arduino IDE Code, for configuring IMAP Protocol in ESP32

  • As we mentioned earlier, we are using Arduino IDE as a compiler and upload into ESP32 module. To know more about Arduino IDE and how to use it, follow our previous tutorial i.e., on the ESP32 programming series.
  • We have already discussed installing the ESP Mail Client Library to make ESP32 able to send emails over the SMTP server.
  • This library includes multiple examples on SMTP like sending text messages, images, HTML code, text files etc. We have attached an image below for your reference.
  • You can use those examples to send emails.

Fig IMAP and SMTP Example Code

Note: You can not use the exact code. Hence, you need to make some changes like replacing SSID and password with your network credentials, email address of sender and receiver, setting IMAP and SMTP parameters for respective email service providers etc, needs to be done before uploading the code. We will also describe these things during code description.

ESP32 IMAP Code

In this code, we will implement both IMAP and SMTP protocols to receive and transmit emails.

Although, we are using SMTP in this tutorial, but we have already discussed and demonstrated the implementation on SMTP protocol in our previous tutorial. So, in this tutorial we will not explain the SMTP part.

Follow our previous tutorial for detailed study of SMTP implementation in ESP32.

#include <Arduino.h>

#include <WiFi.h>

#include <ESP_Mail_Client.h>

//To use only IMAP functions, you can exclude the SMTP from compilation, see ESP_Mail_FS.h.

#define WIFI_SSID "public"

#define WIFI_PASSWORD "ESP32@123"

//-----------setting IMAP parameters------

/* The imap host name e.g. imap.gmail.com for GMail or outlook.office365.com for Outlook */

#define IMAP_HOST "imap.gmail.com"

#define IMAP_PORT 993

#define AUTHOR_EMAIL "techeesp697@gmail.com"

#define AUTHOR_PASSWORD "Tech@ESP123"

#define RECIPIENT_EMAIL "maneesha607ece@gmail.com"

//------------setting SMTP credentials----------

#define SMTP_HOST "smtp.gmail.com"

#define SMTP_PORT 465

//------IMAP Rx emails and their status

/* Callback function to get the Email reading status */

void imapCallback(IMAP_Status status);

void printAllMailboxesInfo(IMAPSession &imap);

void printSelectedMailboxInfo(SelectedFolderInfo sFolder);

void printMessages(std::vector<IMAP_MSG_Item> &msgItems, bool headerOnly);

/* Print all attachments info from the message */

void printAttacements(std::vector<IMAP_Attach_Item> &atts);

/* The IMAP Session object used for Email reading */

IMAPSession imap;

//-------SMTP sending mails and their status----

/* The SMTP Session object used for Email sending */

SMTPSession smtp;

/* Callback function to get the Email sending status */

void smtpCallback(SMTP_Status status);

 

void setup()

{

Serial.begin(115200);

#if defined(ARDUINO_ARCH_SAMD)

while (!Serial)

;

Serial.println();

Serial.println("**** Custom built WiFiNINA firmware need to be installed.****\nTo install firmware, read the instruction here, https://github.com/mobizt/ESP-Mail-Client#install-custom-built-wifinina-firmware");

#endif

Serial.println();

Serial.print("Connecting to AP");

WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

while (WiFi.status() != WL_CONNECTED)

{

Serial.print(".");

delay(200);

}

Serial.println("");

Serial.println("WiFi connected.");

Serial.println("IP address: ");

Serial.println(WiFi.localIP());

Serial.println();

/** Enable the debug via Serial port

* none debug or 0

* basic debug or 1

*

* Debug port can be changed via ESP_MAIL_DEFAULT_DEBUG_PORT in ESP_Mail_FS.h

*/

imap.debug(1);

/* Set the callback function to get the reading results */

imap.callback(imapCallback);

ESP_Mail_Session session;

session.server.host_name = IMAP_HOST;

session.server.port = IMAP_PORT;

session.login.email = AUTHOR_EMAIL;

session.login.password = AUTHOR_PASSWORD;

/* Setup the configuration for searching or fetching operation and its result */

IMAP_Config config;

/* Set seen flag */

//config.fetch.set_seen = true;

/* Search criteria */

config.search.criteria.clear();

/* Also search the unseen message */

config.search.unseen_msg = true;

/* Set the storage to save the downloaded files and attachments */

config.storage.saved_path = "/email_data";

config.storage.type = esp_mail_file_storage_type_flash;

 

config.download.header = true;

config.download.text = true;

config.download.html = true;

config.download.attachment = true;

config.download.inlineImg = true;

config.enable.html = true;

config.enable.text = true;

/* Set to enable the sort the result by message UID in the ascending order */

config.enable.recent_sort = true;

/* Set to report the download progress via the default serial port */

config.enable.download_status = true;

config.limit.search = 5;

config.limit.msg_size = 512;

config.limit.attachment_size = 1024 * 1024 * 5;

/* Connect to server with the session and config */

if (!imap.connect(&session, &config))

return;

/* {Optional} */

printAllMailboxesInfo(imap);

/* Open or select the mailbox folder to read or search the message */

if (!imap.selectFolder("INBOX"))

return;

/* {Optional} */

printSelectedMailboxInfo(imap.selectedFolder());

String uid = String(imap.getUID(imap.selectedFolder().msgCount()));

config.fetch.uid = uid;

/* Read or search the Email and close the session */

//When message was fetched or read, the /Seen flag will not set or message remained in unseen or unread status,

//as this is the purpose of library (not UI application), user can set the message status as read by set \Seen flag

//to message, see the Set_Flags.ino example.

MailClient.readMail(&imap);

/* Clear all stored data in IMAPSession object */

imap.empty();

}

void loop()

{

}

/* Callback function to get the Email reading status */

void imapCallback(IMAP_Status status)

{

/* Print the current status */

Serial.println(status.info());

/* Show the result when reading finished */

if (status.success())

{

/* Print the result */

/* Get the message list from the message list data */

IMAP_MSG_List msgList = imap.data();

printMessages(msgList.msgItems, imap.headerOnly());

/* Clear all stored data in IMAPSession object */

imap.empty();

SMTP_MSG();

}

}

void printAllMailboxesInfo(IMAPSession &imap)

{

/* Declare the folder collection class to get the list of mailbox folders */

FoldersCollection folders;

/* Get the mailbox folders */

if (imap.getFolders(folders))

{

for (size_t i = 0; i < folders.size(); i++)

{

/* Iterate each folder info using the folder info item data */

FolderInfo folderInfo = folders.info(i);

ESP_MAIL_PRINTF("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");

}

}

}

void printSelectedMailboxInfo(SelectedFolderInfo sFolder)

{

/* Show the mailbox info */

ESP_MAIL_PRINTF("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());

ESP_MAIL_PRINTF("Predicted next UID: %d\n", sFolder.nextUID());

for (size_t i = 0; i < sFolder.flagCount(); i++)

ESP_MAIL_PRINTF("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");

}

void printAttacements(std::vector<IMAP_Attach_Item> &atts)

{

ESP_MAIL_PRINTF("Attachment: %d file(s)\n****************************\n", atts.size());

for (size_t j = 0; j < atts.size(); j++)

{

IMAP_Attach_Item att = atts[j];

/** att.type can be

* esp_mail_att_type_none or 0

* esp_mail_att_type_attachment or 1

* esp_mail_att_type_inline or 2

*/

ESP_MAIL_PRINTF("%d. Filename: %s, Name: %s, Size: %d, MIME: %s, Type: %s, Creation Date: %s\n", j + 1, att.filename, att.name, att.size, att.mime, att.type == esp_mail_att_type_attachment ? "attachment" : "inline", att.creationDate);

}

Serial.println();

}

void printMessages(std::vector<IMAP_MSG_Item> &msgItems, bool headerOnly)

{

for (size_t i = 0; i < msgItems.size(); i++)

{

/* Iterate to get each message data through the message item data */

IMAP_MSG_Item msg = msgItems[i];

 

Serial.println("****************************");

ESP_MAIL_PRINTF("Number: %d\n", msg.msgNo);

ESP_MAIL_PRINTF("UID: %d\n", msg.UID);

ESP_MAIL_PRINTF("Messsage-ID: %s\n", msg.ID);

ESP_MAIL_PRINTF("Flags: %s\n", msg.flags);

//The attachment may not detect in search because the multipart/mixed

//was not found in Content-Type header field.

ESP_MAIL_PRINTF("Attachment: %s\n", msg.hasAttachment ? "yes" : "no");

if (strlen(msg.acceptLang))

ESP_MAIL_PRINTF("Accept Language: %s\n", msg.acceptLang);

if (strlen(msg.contentLang))

ESP_MAIL_PRINTF("Content Language: %s\n", msg.contentLang);

if (strlen(msg.from))

ESP_MAIL_PRINTF("From: %s\n", msg.from);

if (strlen(msg.sender))

ESP_MAIL_PRINTF("Sender: %s\n", msg.sender);

if (strlen(msg.to))

ESP_MAIL_PRINTF("To: %s\n", msg.to);

if (strlen(msg.cc))

ESP_MAIL_PRINTF("CC: %s\n", msg.cc);

if (strlen(msg.date))

{

ESP_MAIL_PRINTF("Date: %s\n", msg.date);

ESP_MAIL_PRINTF("Timestamp: %d\n", (int)MailClient.Time.getTimestamp(msg.date));

}

if (strlen(msg.subject))

ESP_MAIL_PRINTF("Subject: %s\n", msg.subject);

if (strlen(msg.reply_to))

ESP_MAIL_PRINTF("Reply-To: %s\n", msg.reply_to);

if (strlen(msg.return_path))

ESP_MAIL_PRINTF("Return-Path: %s\n", msg.return_path);

if (strlen(msg.in_reply_to))

ESP_MAIL_PRINTF("In-Reply-To: %s\n", msg.in_reply_to);

if (strlen(msg.references))

ESP_MAIL_PRINTF("References: %s\n", msg.references);

if (strlen(msg.comments))

ESP_MAIL_PRINTF("Comments: %s\n", msg.comments);

if (strlen(msg.keywords))

ESP_MAIL_PRINTF("Keywords: %s\n", msg.keywords);

/* If the result contains the message info (Fetch mode) */

if (!headerOnly)

{

if (strlen(msg.text.content))

ESP_MAIL_PRINTF("Text Message: %s\n", msg.text.content);

if (strlen(msg.text.charSet))

ESP_MAIL_PRINTF("Text Message Charset: %s\n", msg.text.charSet);

if (strlen(msg.text.transfer_encoding))

ESP_MAIL_PRINTF("Text Message Transfer Encoding: %s\n", msg.text.transfer_encoding);

if (strlen(msg.html.content))

ESP_MAIL_PRINTF("HTML Message: %s\n", msg.html.content);

if (strlen(msg.html.charSet))

ESP_MAIL_PRINTF("HTML Message Charset: %s\n", msg.html.charSet);

if (strlen(msg.html.transfer_encoding))

ESP_MAIL_PRINTF("HTML Message Transfer Encoding: %s\n\n", msg.html.transfer_encoding);

if (msg.rfc822.size() > 0)

{

ESP_MAIL_PRINTF("RFC822 Messages: %d message(s)\n****************************\n", msg.rfc822.size());

printMessages(msg.rfc822, headerOnly);

}

}

Serial.println();

}

}

void SMTP_MSG()

{

smtp.debug(1);

smtp.callback(smtpCallback);

ESP_Mail_Session session;

session.server.host_name = SMTP_HOST;

session.server.port = SMTP_PORT;

session.login.email = AUTHOR_EMAIL;

session.login.password = AUTHOR_PASSWORD;

session.login.user_domain = "";

/* Declare the message class */

SMTP_Message message;

message.sender.name = "The_Engineering_Projects";

message.sender.email = AUTHOR_EMAIL;

message.subject = "Auto_Response";

message.addRecipient("Maneesha", RECIPIENT_EMAIL);

//Send raw text message

String textMsg = "Thanks for contacting us. One of our client will contact you soon. www.theengineeringprojects";

message.text.content = textMsg.c_str();

message.text.charSet = "us-ascii";

message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;

message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;

message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;

/* Connect to server with the session config */

if (!smtp.connect(&session))

return;

/* Start sending Email and close the session */

if (!MailClient.sendMail(&smtp, &message))

Serial.println("Error sending Email, " + smtp.errorReason());

}

//-----------SMTP Status function-----

// Callback function to get the Email sending status

void smtpCallback(SMTP_Status status)

{

/* Print the current status */

Serial.println(status.info());

/* Print the sending result */

if (status.success())

{

Serial.println("----------------");

ESP_MAIL_PRINTF("Message sent success: %d\n", status.completedCount());

ESP_MAIL_PRINTF("Message sent failled: %d\n", status.failedCount());

Serial.println("----------------\n");

struct tm dt;

for (size_t i = 0; i < smtp.sendingResult.size(); i++)

{

/* Get the result item */

SMTP_Result result = smtp.sendingResult.getItem(i);

time_t ts = (time_t)result.timestamp;

localtime_r(&ts, &dt);

ESP_MAIL_PRINTF("Message No: %d\n", i + 1);

ESP_MAIL_PRINTF("Status: %s\n", result.completed ? "success" : "failed");

ESP_MAIL_PRINTF("Date/Time: %d/%d/%d %d:%d:%d\n", dt.tm_year + 1900, dt.tm_mon + 1, dt.tm_mday, dt.tm_hour, dt.tm_min, dt.tm_sec);

ESP_MAIL_PRINTF("Recipient: %s\n", result.recipients);

ESP_MAIL_PRINTF("Subject: %s\n", result.subject);

}

Serial.println("----------------\n");

}

}

Code Description

  • The first task is adding the required header files or libraries.
  • h is used to enable the Wi-Fi module and hence wireless network connectivity.
  • Another library is h to enable email services for receiving and transmitting mails over IMAP and SMTP protocols respectively.
  • Enter the network credentials in place of SSID and PASSWORD.
  • Enter the IMAP server address and port number of the respective email service provider.
  • In this code, we are using the Gmail service.
  • Enter the SMTP server address and port number of respective email service provider.

Fig. SMTP server address and port number

  • Enter your (source) email address and password details to receive and transmit emails.
  • Insert another (destination) email address.
  • imapCallback() function is used to fetch the email reading status.
  • Print the list of mailbox folders.
  • Print the information of the selected mail folder.
  • Print all the messages from the message list.
  • Print the attachment contained in the mail.
  • Call the IMAP session object which is used to read emails.
  • SMTPSession object is used for sending emails.
  • This smtpCallback() function is used to get the email sending status.
  • This function also includes printing the results like success and failure of email sent.

Setup() Code

  • Initialize the serial monitor at a 115200 baud rate for debugging purposes.
  • WiFi.begin() function is used to initialize the Wi-Fi module with Wi-Fi credentials used as arguments.
  • The While loop will continuously run until the ESP32 is connected to the Wi-Fi network.

Fig

  • If the device is connected to a local Wi-Fi network then print the details on the serial monitor.
  • WiFi.localIP() function is used to fetch the IP address.
  • Print the IP address on the serial monitor using println() function.

Fig.

  • Imap.debug(1) function is used for debugging through the serial monitor.
  • Where parameter ‘1’ represents basic debug.

Fig.

  • imap.callback() function is set to get the reading results.

Fig.

  • Declare the session configuring data.

 

  • Some properties of session configuration and imap_configuration accept the pointer to constant char. You can also change them to a string.
  • Set the session configuration which includes the server address of the IMAP service provider, port, and your email address and password.
  • For searching and fetching operation results set the configuration.
  • Configure the searching criteria for available information.
  • Configuration for searching unseen messages.

Fig.

  • Set the storage path to save the downloaded files.

Fig.

  • Configure the flash for storing email files.

Fig.

  • Set the message (download) header which includes text, HTML message, attachments (to store the attachments you need to enable Serial Peripheral Interface Flash File System or SPIFFS).
  • Follow our previous tutorial i.e., on sending emails with ESP32 over SMTP

  • Enable the results for HTML and text messages which are to be stored in IMAPSession object.
  • The IMAPSession object’s size is limited by config.limit.msg_size.
  • Enable.recent_sort is configured to enable the feature of sorting the messages by UID in ascending order.
  • download_status is configured to indicate the download progress on the serial monitor.
  • limit.search is configured to limit the emails in the search result.
  • The size of the message stored is limited to 512 bytes.
  • The size of attachments and images that can be downloaded is limited to 1024*1024*5bytes.
  • Connect to IMAP server with the set session and configurations.

 

  • Open the selected mail folder to read the received information.
  • Fetch UID from the maximum message number in mailbox and write the UID into a string type variable
  • Read the message once it is fetched.
  • Delete/clear all the data stored in the IMAPSession

imapCallback()

  • As we mentioned earlier, imapCallback() function is used to fetch the email reading status.
  • The current status is printed on the serial monitor from info() function.
  • If the email is fetched successfully, print the result and message list.
  • After that clear all the data stored in IMAPSession object.
  • SMTP_MSG() function is called when an email is fetched.
  • SMTP_MSG() function initialize the SMTP server to send an email to the destination client. This function contains all the instructions related to sending email which includes debugging, session object, message header, type of data contained in the email (raw text or HTML text), SMTP server settings, connecting to the server.
  • ESP32 will automatically send an email in reply of the mail received from the client device using this SMTP_MSG function.

Fig.

Note:- We have already discussed the SMTP server in our previous tutorial that is Sending Emails with ESP32 using SMTP server. So, follow our previous tutorial for a detailed study on SMTP protocol and send an email using ESP32.

Testing

  • After making the required changes in the given code like Wi-Fi credentials, email service provider’s details, email address of sender and receiver etc. upload the code into the ESP32 module.
  • Make sure you have turned on the access for less secure apps as discussed earlier.
  • Open the serial monitor with a 115200 baud rate.
  • Send an email to the address login in ESP32 from another email.
  • Make sure ESP32 is connected to the internet.
  • When an email is received by ESP32, the respective results are shown below :

Fig. Email received by ESP32 over IMAP

  • Once the email is fetched completely, SMTP will be initialized and an auto-response email will be sent to the destination email address.

Fig. Email successfully sent from ESP32 over SMTP

 

Fig. Response from ESP32

This concludes the tutorial. I hope you found this helpful and also hope to see you soon with a new tutorial on ESP32.

Sending Email with ESP32 using SMTP Protocol

Hello readers, I hope you all are doing great. In this tutorial, we will learn how to send an email using ESP32 module. We will also learn to send text files, images or some sensor readings using the SMTP server using the ESP32 module.

In IoT (Internet of things), there are various applications where we need to send emails carrying information like sending some sensor readings, altering emails, images, text files and much more.

Where To Buy?
No.ComponentsDistributorLink To Buy
1ESP32AmazonBuy Now

What is SMTP?

SMTP or simple mail transfer protocol is an internet standard for sending and receiving electronic mail (or email) where an SMTP server receives emails from the email client.

SMTP is also used for setting communication between servers.

Various email providers like Gmail, Hotmail, Yahoo, etc. have unique SMTP addresses and port numbers.

How does SMTP work?

SMTP protocol which is also known as a push protocol is used to send emails and IMAP that is Internet Message Access Protocol (or post office protocol or POP) is used to receive emails at the receiver end.

SMTP protocol operates at the application layer of TCP/IP protocol.

When a client wants to send emails, a TCP connection will be open for the SMTP server and emails will be sent across the connection.

SMTP commands:

  • HELO – This command is sent only once per session and is used to identify the qualified domain names and the client to the server.
  • MAIL – used to initiate a message
  • RCPT – Identifies the address
  • DATA – share the data line by line

SMTP parameters for different email providers

SMTP parameters for Gmail

Gmail is the email service provided by Google and Gmail SMTP server is free to access and anyone can access this service, who has a Gmail account.

  • SMTP server: smtp.gmail.com
  • SMTP Port: 465
  • SMTP sender’s address: Gmail address
  • SMTP sender's password: Gmail Password

SMTP parameters for Yahoo

  • SMTP server: smtp.mail.yahoo.com
  • SMTP Port: 465 (with SSL)
  • Another Port number: 587 (with TLS)
  • SMTP sender’s address: email address
  • SMTP sender’s password: password

SMTP parameters for Hotmail

  • SMTP server: smtp-mail.outlook.com
  • SMTP port: 587
  • SMTP sender’s address: Hotmail email address
  • SMTP sender’s password: Hotmail password
  • SMTP TLS/SSL required : YES

SMTP parameters for Outlook

  • SMTP server: smtp-mail.office.com
  • SMTP server port for incoming mail: 993
  • SMTP server port for outgoing mail: 587
  • SMTP sender’s address: Outlook email address
  • SMTP sender’s password: Outlook password
  • SMTP TLS/SSL required : YES

Sending emails over SMTP using ESP32 in Arduino IDE

  • In this tutorial, we will demonstrate sending raw text messages and HTML messages, images, text files, etc. to the client over the SMTP server.

Components required to send and receive emails using ESP32 over SMTP server are:

  • Recipient’s email address.
  • Sender’s email address.
  • Content to be shared over SMTP server.
  • ESP mail client library.
  • ESP32 module.

ESP mail client Library

To send emails with ESP32 we need to install this ESP Mail Client library. This library, make ESP32 able to send emails over an SMTP server.

Step to install ESP Mail Client Library:

  • To download the ESP Mail Client Library click on the link given below: https://github.com/mobizt/ESP-Mail-Client
  • Open the Arduino IDE.
  • Go to Sketch >> Include Library >> Add .ZIP Library.
  • Select the downloaded ZIP file. Click on

Your Arduino IDE is ready to send email using ESP32.

Create a new Gmail account (Sender)

It is recommended to create a new email account for sending emails using ESP32 or ESP8266 modules.

If you are using your main (personal) email account (for sending emails) with ESP and by mistake, something goes wrong in the ESP code or programming part, your email service provider can ban or disable your main (personal) email account.

In this tutorial, we are using a Gmail account.

Follow the link to create a new Gmail account: https://accounts.google.com

 

Access to Less Secure apps

To get access to this new Gmail account, you need to enable Allow less secure apps and this will make you able to send emails. The link is: https://myaccount.google.com/lesssecureapps?pli=1

Arduino IDE Code, for sharing raw text and HTML text with ESP32 and SMTP server:
  • As we mentioned earlier, we are using Arduino IDE as a compiler and upload into the ESP32 module. To know more about Arduino IDE and how to use it, follow our previous tutorial Introduction to ESP32 Programming Series.
  • We have already discussed installing the ESP Mail Client Library to make ESP32 able to send emails over the SMTP server.
  • This library includes multiple examples on SMTP like sending text messages, images, HTML code, text files etc. We have attached an image below for your reference.
  • You can use those examples to send emails.

Fig SMTP example code

  • Note: You can not use the exact code. Hence, you need to make some changes like replacing SSID and password with your network credentials, email address of sender and receiver, SMTP setting parameters for respective email service providers etc, which need to be done before uploading the code. We will also describe these things during code description.

#include <WiFi.h>

#include <ESP_Mail_Client.h>

#define WIFI_SSID "SSID"

#define WIFI_PASSWORD "PASSWORD"

#define SMTP_HOST "smtp.gmail.com"

#define SMTP_PORT 465

/* The sign in credentials */

#define AUTHOR_EMAIL "email address"

#define AUTHOR_PASSWORD "email password"

/* Recipient's email*/

#define RECIPIENT_EMAIL "email address_Rx"

/* The SMTP Session object used for Email sending */

SMTPSession smtp;

/* Callback function to get the Email sending status */

void smtpCallback(SMTP_Status status);

void setup(){ Serial.begin(115200);

Serial.println();

Serial.print("Connecting to AP");

WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

while (WiFi.status() != WL_CONNECTED){

Serial.print(".");

delay(200);

}

Serial.println("");

Serial.println("WiFi connected.");

Serial.println("IP address: ");

Serial.println(WiFi.localIP());

Serial.println();

/** Enable the debug via Serial port

none debug or 0 basic debug or 1

*/

smtp.debug(1);

/* Set the callback function to get the sending results */

smtp.callback(smtpCallback);

/* Declare the session config data */

ESP_Mail_Session session;

/* Set the session config */

session.server.host_name = SMTP_HOST; session.server.port = SMTP_PORT; session.login.email = AUTHOR_EMAIL; session.login.password = AUTHOR_PASSWORD;

session.login.user_domain = "";

/* Declare the message class */

SMTP_Message message; message.sender.name = "ESP32"; message.sender.email = AUTHOR_EMAIL; message.subject = "ESP32 Test Email";

message.addRecipient("Sara", RECIPIENT_EMAIL);

/*Send HTML message*/

String htmlMsg = "<div style=\"color:#2f4468;\"><h1>Hello CLient!</h1><p>- Sent from ESP board</p></div>"; message.html.content = htmlMsg.c_str(); message.html.content = htmlMsg.c_str(); message.text.charSet = "us-ascii";

message.html.transfer_encoding = Content_Transfer_Encoding::enc_7bit;

//Send raw text message

/* String textMsg = "Hello Client! - you have a message from ESP32 board"; message.text.content = textMsg.c_str(); message.text.charSet = "us-ascii";

message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;*/

message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;

message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;

/* Set the custom message header */

//message.addHeader("Message-ID: <abcde.fghij@gmail.com>");

/* Connect to server with the session config */ if (!smtp.connect(&session))

return;

/* Start sending Email and close the session */ if (!MailClient.sendMail(&smtp, &message))

Serial.println("Error sending Email, " + smtp.errorReason());

}

void loop(){

}

/* Callback function to get the Email sending status */

void smtpCallback(SMTP_Status status){

/* Print the current status */

Serial.println(status.info());

/* Print the sending result */ if (status.success()){

Serial.println("----------------");

ESP_MAIL_PRINTF("Message sent success: %d\n", status.completedCount());

ESP_MAIL_PRINTF("Message sent failled: %d\n", status.failedCount());

Serial.println("----------------\n"); struct tm dt;

for (size_t i = 0; i < smtp.sendingResult.size(); i++){

/* Get the result item */

SMTP_Result result = smtp.sendingResult.getItem(i);

time_t ts = (time_t)result.timestamp; localtime_r(&ts, &dt);

ESP_MAIL_PRINTF("Message No: %d\n", i + 1);

ESP_MAIL_PRINTF("Status: %s\n", result.completed ? "success" : "failed"); ESP_MAIL_PRINTF("Date/Time: %d/%d/%d %d:%d:%d\n", dt.tm_year + 1900,

dt.tm_mon + 1, dt.tm_mday, dt.tm_hour, dt.tm_min, dt.tm_sec); ESP_MAIL_PRINTF("Recipient: %s\n", result.recipients); ESP_MAIL_PRINTF("Subject: %s\n", result.subject);

}

Serial.println("----------------\n");

}

}

Code Description

  • The first task is adding the required header files or libraries.
  • Wifi.h is used to enable the Wi-Fi module and hence wireless network connectivity.
  • Another library is ESP_Mail_Client.h to enable email service over SMTP (simple mail transfer protocol).
  • Enter the network credentials in place of SSID and PASSWORD.
  • Insert SMTP parameter of the respective email service provider.
  • The parameters used below are for Gmail.
  • Enter the sender’s email address and password details.
  • Insert recipient’s email address.
  • SMTPSession object is used for sending emails.
  • This smtpCallback() function is used to get the email sending status.
  • This function also includes printing the results like success and failure of email sent.

Setup()

  • Initialize the serial monitor at a 115200 baud rate for debugging purposes.
  • WiFi.begin() function is used to initialize the Wi-Fi module with Wi-Fi credentials used as arguments.
  • The While loop will continuously run until the ESP32 is connected to the Wi-Fi network.

  • If the device is connected to a local Wi-Fi network then print the details on the serial monitor.
  • WiFi.localIP() function is used to fetch the IP address.
  • Print the IP address on the serial monitor using Serial.println() function.

  • Serial.debug() is used to enable the debug via Serial port where ‘0’ and ‘1’ are used as arguments where;
    • - none debug
    • - basic debug
  • Inside ESP_Mail_FS.h header file, ESP_MAIL_DEFAULT_DEBUG_PORT can be used to change the Debug port.
  • Set the smtp.callback() function to get sending results.

  • Next step is setting the message header.
  • Message header will be set inside the setup() function which includes, sender’s name, subject, sender’s email address, receiver’s email address and name.

Sending raw text message

Write the message content (raw text) in the textMsg variable which you want to share over email.

Sending HTML text

To send HTML text write the respective content in the htmlMsg variable.

  • Connect to server with session configuration using smtp.connect() function.
  • Next thing to do is, send an email to the client for that MailClient.sendMail() function is used and if mail transmission is failed then that will be printed on the serial monitor along with the reason.
  • Loop() function will remain empty.

Testing

  • Upload the Arduino IDE code in the ESP32 module.
  • Make sure the Wi-Fi network is ON to which your ESP32’s Wi-Fi module is supposed to connect.
  • Open Serial monitor with 115200 baud rate.
  • Also, make sure that you have turned ON the permission for less secure apps.

Otherwise, you won’t be able to send emails and an error will be printed on the serial monitor.

  • Press the EN button from the ESP32 development board.

  • Check receiver email inbox.

Arduino IDE code, for sending images and text files using ESP32 and SMTP server:

In this example code, we will demonstrate how to share text files and images through emails using ESP32 over the SMTP server.

But, before sharing attachments (text files or images) you need to save those files on the ESP32 filesystem (SPIFFS).

Uploading files to ESP32 Filesystem (SPIFFS)

SPIFFS stands for Serial Peripheral Interface Flash File System, which is built into the ESP32 module. This is a lightweight filesystem designed for microcontrollers with flash chips connected via SPI bus, such as the ESP32 flash memory. In this flash memory, we can write, delete, read, and close files.

  • Text files and images will be saved on ESP32 filesystem (SPIFFS) using ESP32 filesystem uploader plugin for Arduino IDE.

Installing Arduino ESP32 Filesystem Uploader:

Fig.

  • Restart the Arduino IDE.

Check if the plugin is successfully uploaded or not:

  • Open Arduino IDE. Select ESP32 development board.
  • Go to
  • Check whether this ESP32 Sketch Data Upload option is available or not. If it is available that means plugin is uploaded successfully and it is ready to upload files.

Fig.

Finally, uploading files using SPIFFS or filesystem upload:

  • In Arduino IDE, create a new Arduino sketch.
  • Save the project.
  • Go to Sketch >> Show Sketch Folder. As shown in the image below:

Fig.

  • Create a new folder named as

Fig.

  • Inside that data folder add the respective text files or images you want to share over email as shown in the image below:

Fig.

  • If you are using the example code from ESP mail-client library then the images should be named as png and text files as text_file.text.
  • After saving files inside data folder, open the Arduino IDE then go to Tools >> ESP32 Sketch Data Upload to upload the SPIFFS Image.

Fig.

A message “SPIFFS Image Uploaded” will be displayed at the bottom of Arduino IDE, once the SPIFFS image is uploaded successfully.

Fig.

Arduino IDE Code

Code is already available in ESP Mail Client Library. As shown below:

Fig.

  • You can not use the exact code.
  • Some changes like Wi-Fi credentials, email address of sender and receiver, SMTP setting parameters for respective email service providers etc, need to be done before uploading the code.

// To use send Email for Gmail to port 465 (SSL), less secure app option should be enabled. https://myaccount.google.com/lesssecureapps?pli=1

// The file systems for flash and sd memory can be changed in ESP_Mail_FS.h.

#include <Arduino.h>

#include <WiFi.h>

#include <ESP_Mail_Client.h>

#define WIFI_SSID "SSID"

#define WIFI_PASSWORD "PASSWORD"

// server address for Gmail account

#define SMTP_HOST "smtp.gmail.com"

/** The smtp port e.g.

25 or esp_mail_smtp_port_25 465 or esp_mail_smtp_port_465 587 or esp_mail_smtp_port_587

*/

#define SMTP_PORT 465

/* The log in credentials */

#define AUTHOR_EMAIL "Sender's email address"

#define AUTHOR_PASSWORD "password"

/* Recipient's email*/

#define RECIPIENT_EMAIL "receiver's email address"

/* The SMTP Session object used for Email sending */

SMTPSession smtp;

/* Callback function to get the Email sending status */

void smtpCallback(SMTP_Status status);

void setup(){

Serial.begin(115200);

Serial.println();

Serial.print("Connecting to AP");

WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

while (WiFi.status() != WL_CONNECTED){

Serial.print(".");

delay(200);

}

Serial.println("");

Serial.println("WiFi connected.");

Serial.println("IP address: ");

Serial.println(WiFi.localIP());

Serial.println();

if (!SPIFFS.begin(true)) {

Serial.println("An error has occurred while mounting SPIFFS");

}

else{

Serial.println("SPIFFS mounted successfully");

}

/** Enable the debug via Serial port

  • none debug or 0
  • basic debug or 1

*/

smtp.debug(1);

/* Set the callback function to get the sending results */

smtp.callback(smtpCallback);

/* Declare the session config data */

ESP_Mail_Session session;

/* Set the session config */ session.server.host_name = SMTP_HOST; session.server.port = SMTP_PORT; session.login.email = AUTHOR_EMAIL; session.login.password = AUTHOR_PASSWORD;

session.login.user_domain = "mydomain.net";

/* Declare the message class */

SMTP_Message message;

/* Enable the chunked data transfer with pipelining for large message if server supported

*/

message.enable.chunking = true;

/* Set the message headers */ message.sender.name = "ESP Mail";

message.sender.email = AUTHOR_EMAIL;

message.subject = "Test sending Email with attachments and inline images from SD card and Flash";

message.addRecipient("Sara", RECIPIENT_EMAIL);

/** Two alternative content versions are sending in this example e.g. plain text and html */

String htmlMsg = "This message contains attachments: image and text file."; message.html.content = htmlMsg.c_str(); message.html.charSet = "utf-8";

message.html.transfer_encoding = Content_Transfer_Encoding::enc_qp;

message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_normal; message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;

/* The attachment data item */

SMTP_Attachment att;

/** Set the attachment info e.g.

  • file name, MIME type, file path, file storage type,
  • transfer encoding and content encoding

*/

att.descr.filename = "image.png"; att.descr.mime = "image/png"; //binary data

att.file.path = "/image.png";

att.file.storage_type = esp_mail_file_storage_type_flash;

att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;

/* Add attachment to the message */

message.addAttachment(att);

message.resetAttachItem(att);

att.descr.filename = "text_file.txt"; att.descr.mime = "text/plain"; att.file.path = "/text_file.txt";

att.file.storage_type = esp_mail_file_storage_type_flash;

att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;

/* Add attachment to the message */

message.addAttachment(att);

/* Connect to server with the session config */ if (!smtp.connect(&session))

return;

/* Start sending the Email and close the session */ if (!MailClient.sendMail(&smtp, &message, true))

Serial.println("Error sending Email, " + smtp.errorReason());

}

void loop()

{

}

/* Callback function to get the Email sending status */

void smtpCallback(SMTP_Status status){

/* Print the current status */

Serial.println(status.info());

/* Print the sending result */ if (status.success()){

Serial.println("----------------");

ESP_MAIL_PRINTF("Message sent success: %d\n", status.completedCount());

ESP_MAIL_PRINTF("Message sent failled: %d\n", status.failedCount());

Serial.println("----------------\n"); struct tm dt;

for (size_t i = 0; i < smtp.sendingResult.size(); i++){

/* Get the result item */

SMTP_Result result = smtp.sendingResult.getItem(i); time_t ts = (time_t)result.timestamp;

localtime_r(&ts, &dt);

ESP_MAIL_PRINTF("Message No: %d\n", i + 1);

ESP_MAIL_PRINTF("Status: %s\n", result.completed ? "success" : "failed"); ESP_MAIL_PRINTF("Date/Time: %d/%d/%d %d:%d:%d\n", dt.tm_year + 1900,

dt.tm_mon + 1, dt.tm_mday, dt.tm_hour, dt.tm_min, dt.tm_sec);

ESP_MAIL_PRINTF("Recipient: %s\n", result.recipients);

ESP_MAIL_PRINTF("Subject: %s\n", result.subject);

}

Serial.println("----------------\n");

}

}

Code Description:

Most part of the code is similar to the previous one (that is sending raw text and HTML text), including libraries, network credentials, enabling Wi-Fi and the serial monitor, setting the email parameters of the respective email service provided. So we not explaining the complete code but, we will explain the programming part which is different than the previous one.

Setup()

  • We are initializing the SPIFFS, inside the setup() function to sore files which are to be shared over the SMTP server.
  • begin() function is used to for initializing SPIFFS.

Fig.

  • If the server supports, enable chunked data transfer with pipelining for large messages.

Fig.

  • Next, you need to create data attachments.

Fig.

  • The next thing is sending the image, for that you need to add the attachment details: filename, path, mime type, type of storage, encoding technique.
 

Fig.

  • After adding the details of the image, add the attachment to the message.

Fig.

  • To send a text file you also need to add similar details: name of the file, path, storage type, mime type and encoding technique.

Fig.

  • Add this attachment too to the message.

Testing

  • Upload the code into the ESP32 board.
  • Make sure you have selected the correct ESP32 development board and COM port.
  • Also, make sure that you have turned on the access for less secure apps for the sender’s email account as discussed earlier. Otherwise, the ESP32 will face an authentication error.
  • Turn ON the Wi-Fi with which your device is supposed to connect with.
  • Once the device is connected with the access point, it will automatically send the attachment to the receiver's email account.

Fig.

Fig.

Fig. Email Received

This concludes the tutorial; I hope you found this helpful and also hope to see you again with a new tutorial on ESP32.

Syed Zain Nasir

I am Syed Zain Nasir, the founder of <a href=https://www.TheEngineeringProjects.com/>The Engineering Projects</a> (TEP). I am a programmer since 2009 before that I just search things, make small projects and now I am sharing my knowledge through this platform.I also work as a freelancer and did many projects related to programming and electrical circuitry. <a href=https://plus.google.com/+SyedZainNasir/>My Google Profile+</a>

Share
Published by
Syed Zain Nasir