ESP32 Over The Air (OTA) Web Updater

Hello readers, I hope you are all doing great. In this tutorial, we are going to discuss the OTA web updater on the ESP32.

We already covered the fundamentals of OTA programming in ESP32, in our previous tutorial where we used the Arduino IDE to upload OTA code into the ESP32 module using the network port.

In the OTA web updater, you need to create a web server page for OTA programming.

[caption id="attachment_166886" align="aligncenter" width="1920"] ESP32 OTA web updater[/caption]

Fig.1 ESP32 OTA web updater

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

Over the Air Web Updater

  • "Over-the-air" refers to the ability to wirelessly download an application, configuration, or firmware to internet-enabled devices, also known as IoT. (OTA). It functions similarly to our computers, laptops, tablets, and phones.
  • Instead of using a serial port and a wired medium to upload a code, the OTA web updater allows the user to update the code or firmware wirelessly via a web server.
  • When sensor nodes are frequently placed in remote or difficult-to-reach locations, OTA programming can be used.

Steps to implement an OTA web updater using ESP32

  • Using the serial communication port, upload the code containing the instructions to enable the OTA web updater (so that in the future you can update the code using a browser instead of a wired medium).
  • The code uploaded via the serial port will launch a web server, allowing you to upload new code over the air.
  • The new code, which has been uploaded using a web server, should contain instructions to keep the OTA web updater enabled on the ESP32 board so that you can use the OTA programming feature in future applications as well.
  • Create a .bin using Arduino IDE compiler and upload the file on the server.

Fig. 2

Code for OTA web updater implementation in ESP32

In this tutorial, we will discuss only the OTA web updater method using Arduino IDE and ESP32 dev-Kit V1 module.

If you want to know more about the basics of ESP32 and how to get started with Arduino IDE, then read Introduction to ESP32 Programming Series.

  • You can find the code through File> Examples> ArduinoOTA> BasicOTA.
  • An image has been attached below for reference:

Fig. 3

  • This code should be uploaded serially through a serial communication port only then you can access the OTA web updater feature.

Code

#include <WiFi.h> #include <WiFiClient.h> #include <WebServer.h> #include <ESPmDNS.h> #include <Update.h>   const char* host = "esp32"; const char* ssid = "SSID"; const char* password = "password";   WebServer server(80);   /* * Login page */   const char* loginIndex = "<form name='loginForm'>" "<table width='20%' bgcolor='A09F9F' align='center'>" "<tr>" "<td colspan=2>" "<center><font size=4><b>ESP32 Login Page</b></font></center>" "<br>" "</td>" "<br>" "<br>" "</tr>" "<td>Username:</td>" "<td><input type='text' size=25 name='userid'><br></td>" "</tr>" "<br>" "<br>" "<tr>" "<td>Password:</td>" "<td><input type='Password' size=25 name='pwd'><br></td>" "<br>" "<br>" "</tr>" "<tr>" "<td><input type='submit' onclick='check(this.form)' value='Login'></td>" "</tr>" "</table>" "</form>" "<script>" "function check(form)" "{" "if(form.userid.value=='admin' && form.pwd.value=='admin')" "{" "window.open('/serverIndex')" "}" "else" "{" " alert('Error Password or Username')/*displays error message*/" "}" "}" "</script>";   /* * Server Index Page */   const char* serverIndex = "<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>" "<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>" "<input type='file' name='update'>" "<input type='submit' value='Update'>" "</form>" "<div id='prg'>progress: 0%</div>" "<script>" "$('form').submit(function(e){" "e.preventDefault();" "var form = $('#upload_form')[0];" "var data = new FormData(form);" " $.ajax({" "url: '/update'," "type: 'POST'," "data: data," "contentType: false," "processData:false," "xhr: function() {" "var xhr = new window.XMLHttpRequest();" "xhr.upload.addEventListener('progress', function(evt) {" "if (evt.lengthComputable) {" "var per = evt.loaded / evt.total;" "$('#prg').html('progress: ' + Math.round(per*100) + '%');" "}" "}, false);" "return xhr;" "}," "success:function(d, s) {" "console.log('success!')" "}," "error: function (a, b, c) {" "}" "});" "});" "</script>";   /* * setup function */ void setup(void) { Serial.begin(115200);   // Connect to WiFi network WiFi.begin(ssid, password); Serial.println("");   // Wait for connection while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.print("Connected to "); Serial.println(ssid); Serial.print("IP address: "); Serial.println(WiFi.localIP());   /*use mdns for host name resolution*/ if (!MDNS.begin(host)) { //http://esp32.local Serial.println("Error setting up MDNS responder!"); while (1) { delay(1000); } } Serial.println("mDNS responder started"); server.on("/", HTTP_GET, []() { server.sendHeader("Connection", "close"); server.send(200, "text/html", loginIndex); }); server.on("/serverIndex", HTTP_GET, []() { server.sendHeader("Connection", "close"); server.send(200, "text/html", serverIndex); });   /*handling uploading firmware file */ server.on("/update", HTTP_POST, []() { server.sendHeader("Connection", "close"); server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK"); ESP.restart(); }, []() { HTTPUpload& upload = server.upload(); if (upload.status == UPLOAD_FILE_START) { Serial.printf("Update: %s\n", upload.filename.c_str()); if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max available size Update.printError(Serial); } } else if (upload.status == UPLOAD_FILE_WRITE) { /* flashing firmware to ESP*/ if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) { Update.printError(Serial); } } else if (upload.status == UPLOAD_FILE_END) { if (Update.end(true)) { //true to set the size to the current progress Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize); } else { Update.printError(Serial); } } }); server.begin(); }   void loop(void) { server.handleClient(); delay(1); }

Code Description

The first task is to add the header files, required to perform over the air (OTA) web updates using the ESP32 module.
  • WiFi.h : This header file allows the ESP32 board to connect to the internet. It can serve either as a server or a client.
  • ESPmDNS.h : This library is used to implement multicast DNS query support for the ESP32 chip. A multicast UDP service is used to provide local network service.
  • WiFiClient.h : It is used to create a client that can connect to a specific port and IP address.

Fig. 4

  • Enter the SSID and password.

Fig. 5

  • You can style the HTML page anytime as per your requirements or use the default style given in the example code.

Setup()

  • Initialize the serial monitor at a 115200 baud rate.
  • WiFi.begin() function is used to initialize the Wi-Fi module with Wi-Fi credentials used as arguments.

Fig. 6

  • Wait until the ESP32 is connected to the Wi-Fi network.

Fig. 7

  • 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.

Fig. 8

  • Use multicast Domain Name System (mDNS) for hostname resolution.
  • Hostname has been defined as a global variable at the beginning of code.
  • Start the mDNS responder for esp32 or host using MDNS.begin() function.

Fig. 9

  • Return the index page which is stored in serverIndex.
  • Send the status OK (200 represents ‘OK’) to inform the client.

Fig. 10

  • Handling the uploading of firmware files.

Fig. 11

  • Start uploading the new firmware into the ESP32 board.

Fig. 12

  • Server.begin() function will start the server to listen for incoming connections.

Fig. 13

Loop()

  • Server.handleCLient() function is used to handle the client devices.
  • It will monitor the client devices and provide the requested HTML page.

Fig. 14

  • After successfully uploading the code into ESP32 board using serial communication port, open the serial monitor with 115200 baud rate.
  • Press EN or enable button from the ESP32 board.
  • You can see the IP address printed on the serial monitor, once the ESP32’s Wi-Fi module is connected to wi-fi network.
  • We have attached a screenshot below for your reference:

Fig. 15 Serial monitor

Testing

  • Now the ESP32 module is ready for over the air (OTA) programming.
  • For testing the OTA web updater, remove the ESP32 module from your computer and power the ESP32 board using another power source.
  • Open the browser and enter the IP address from the Serial Monitor as shown in the above image.
  • A web page with an IP address of 168.43.223 is shown below:

Fig. 16

  • Enter the username and password on the login page. As per the example code:
Username: admin Password: admin
  • You can change the username and password details if you wish to.
  • Click on Login.
  • A new browser page with URL 192.168.43.223/serverIndex will be displayed on the screen, as shown below:

Fig. 17

  • You can style the browser page as per your requirements.

Test code

  • Write a new code in Arduino IDE.
  • The code should contain two sections:
  1. The instructions to keep OTA web updater feature enabled
  2. Instructions to blink the LED (you can replace the LED code with another code as per your requirements).
#include <WiFi.h> #include <WiFiClient.h> #include <WebServer.h> #include <ESPmDNS.h> #include <Update.h>   const char* host = "esp32"; const char* ssid = "SSID"; const char* password = "password";   //variabls to blink without delay: const int led = 2; unsigned long previousMillis = 0; // will store last time LED was updated const long interval = 1000; // interval at which to blink (milliseconds) int ledState = LOW; // ledState used to set the LED   WebServer server(80);   /* * Login page */   const char* loginIndex = "<form name='loginForm'>" "<table width='20%' bgcolor='A09F9F' align='center'>" "<tr>" "<td colspan=2>" "<center><font size=4><b>ESP32 Login Page</b></font></center>" "<br>" "</td>" "<br>" "<br>" "</tr>" "<td>Username:</td>" "<td><input type='text' size=25 name='userid'><br></td>" "</tr>" "<br>" "<br>" "<tr>" "<td>Password:</td>" "<td><input type='Password' size=25 name='pwd'><br></td>" "<br>" "<br>" "</tr>" "<tr>" "<td><input type='submit' onclick='check(this.form)' value='Login'></td>" "</tr>" "</table>" "</form>" "<script>" "function check(form)" "{" "if(form.userid.value=='admin' && form.pwd.value=='admin')" "{" "window.open('/serverIndex')" "}" "else" "{" " alert('Error Password or Username')/*displays error message*/" "}" "}" "</script>";   /* * Server Index Page */   const char* serverIndex = "<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>" "<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>" "<input type='file' name='update'>" "<input type='submit' value='Update'>" "</form>" "<div id='prg'>progress: 0%</div>" "<script>" "$('form').submit(function(e){" "e.preventDefault();" "var form = $('#upload_form')[0];" "var data = new FormData(form);" " $.ajax({" "url: '/update'," "type: 'POST'," "data: data," "contentType: false," "processData:false," "xhr: function() {" "var xhr = new window.XMLHttpRequest();" "xhr.upload.addEventListener('progress', function(evt) {" "if (evt.lengthComputable) {" "var per = evt.loaded / evt.total;" "$('#prg').html('progress: ' + Math.round(per*100) + '%');" "}" "}, false);" "return xhr;" "}," "success:function(d, s) {" "console.log('success!')" "}," "error: function (a, b, c) {" "}" "});" "});" "</script>";   /* * setup function */ void setup(void) { pinMode(led, OUTPUT);   Serial.begin(115200);   // Connect to WiFi network WiFi.begin(ssid, password); Serial.println("");   // Wait for connection while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.print("Connected to "); Serial.println(ssid); Serial.print("IP address: "); Serial.println(WiFi.localIP());   /*use mdns for host name resolution*/ if (!MDNS.begin(host)) { //http://esp32.local Serial.println("Error setting up MDNS responder!"); while (1) { delay(1000); } } Serial.println("mDNS responder started"); /*return index page which is stored in serverIndex */ server.on("/", HTTP_GET, []() { server.sendHeader("Connection", "close"); server.send(200, "text/html", loginIndex); }); server.on("/serverIndex", HTTP_GET, []() { server.sendHeader("Connection", "close"); server.send(200, "text/html", serverIndex); }); /*handling uploading firmware file */ server.on("/update", HTTP_POST, []() { server.sendHeader("Connection", "close"); server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK"); ESP.restart(); }, []() { HTTPUpload& upload = server.upload(); if (upload.status == UPLOAD_FILE_START) { Serial.printf("Update: %s\n", upload.filename.c_str()); if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max available size Update.printError(Serial); } } else if (upload.status == UPLOAD_FILE_WRITE) { /* flashing firmware to ESP*/ if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) { Update.printError(Serial); } } else if (upload.status == UPLOAD_FILE_END) { if (Update.end(true)) { //true to set the size to the current progress Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize); } else { Update.printError(Serial); } } }); server.begin(); }   void loop(void) { server.handleClient(); delay(1);   //loop to blink without delay unsigned long currentMillis = millis();   if (currentMillis - previousMillis >= interval) { // save the last time you blinked the LED previousMillis = currentMillis;   // if the LED is off turn it on and vice-versa: ledState = not(ledState);   // set the LED with the ledState of the variable: digitalWrite(led, ledState); } }

Test Code Description

  • We are using the same old code with an additional LED blinking part.
  • In this code, we are using inbuilt LED for testing.
  • Define the GPIO pin to which LED is connected.
  • GPIO 2 is connected to the inbuilt LED.
  • To add delay, we are using timers instead of delay() function.
  • The variable interval is defining the time delay.
  • Set LED’s state to low.

Fig. 18

Arduino Loop() Function

  • Blink the LED after every 1000ms or 1sec delay as defined in variable ‘interval’.

Fig. 19

How to generate a bin file

  • Compile the code in Arduino IDE.
  • Go to Sketch > Export compiled Binary or press Crl+Alt+S to generate .bin file.

Fig. 20

Fig. 21 bin file

  • Upload the .bin file on the browser with 192.168.43.223/serverIndex URL and click on update option.
  • At 100% progress the inbuilt LED from the ESP32 board will start blinking.

Fig 22

Fig. 23 LED blink

  • Similarly, you can upload a new code using over the air web updater.

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

PWM with STM32

PWM stands for Pulse-Width Modulation. Once the switching frequency (fsw) has been chosen, the ratio between the switch-on time (TON) and the switch-off time (TOFF) is varied. This is commonly called duty-cycle (D). The duty cycle can be between 0 and 1 and is generally expressed as a percentage (%).

D = TON / (TON + TOFF) = TON x fsw

The variation of the pulse width, made at a high frequency (kHz), is perceived as continuous and can be translated into a variation of the rotation speed of a motor, dimming a LED, driving an encoder, driving power conversion, and etc. The use of PWM is also widely used in the automotive sector in electronic control units (ECU - Electronic Control Unit) to manage the energy to be supplied to some actuators, both fixed and variable frequency. Among the various actuators used in a vehicle and controlled by PWM i.e. diesel pressure regulator, EGR valve actuator, voltage regulator in modern alternators, turbocharger variable geometry regulation actuator, electric fans, etc.

Where To Buy?
No.ComponentsDistributorLink To Buy
1STM32 NucleoAmazonBuy Now

PWM signal generation through Timer in STM32

Let's see now how it is possible to generate a PWM with STM32. In this case, it can be generated using a timer made available by the microcontroller.

STM32 configuration with STCube

In this article, we will see how to configure and write an application to dim an LED connected to an output pin (GPIO) of the STM32F446RE Nucleo board. First of all, let's see how to configure the initialization code with the STCube tool.

Basic Configurations

GPIO selection and configuration

It is necessary to identify a GPIO to associate a timer to generate the PWM. For example, we choose PB3 associated with Channel 2 of Timer 2 (TIM2_CH2). Note that the pin turns orange to remind us of that timer 2 still needs to be configured.

System Reset and Clock Control (RCC) Initialization

  • To initialize the RCC use the following path: “Pinout & Configuration”-> System Core -> RCC. “High-Speed Clock” (HSE) and “Low-Speed Clock” (LSE) select for both “Crystal/Ceramic Resonators”.

Timer 2 Configuration

Now you need to configure timer two which is hooked to pin PB3.

Clock Configuration

We configure the clock tree so that the clock frequency (HCLK) of the microcontroller is 84 MHz, handling frequency divisor and multiplier of PLLCLK. The bus to which the timers are connected (APB1 timer and APB2 timer clocks) is also at 84 MHz.

Timer Configuration

We now know that timer 2 has a clock source of 84 MHz, so every time the clock switches the timer does a count. If we configure it to count to 84 million (it is a 32-bit timer, the Counter must be between 0 and 4294967295) it will take a second. We can set this number to exactly half so that the LED lights up for half a second and turns it off for another half-second. In practice, we will see at the output a square wave that will have a duty cycle of 50% and a switching frequency of 1Hz (too slow not to notice the switching on and off the LED !!). To do what has been said, the timer must be configured as follows:

  1. Enable PWM Generation on Channel 2;
  1. Set Prescaler to 0
  2. Set Counter Mode to “Up”;
  3. Set Counter Period to 83999999;
  4. Set Internal Clock Division to “No Division”;
  5. Set auto-reload preload to “Disable”;
  6. Set Master-Slave Mode to “Disable”;
  7. Set Trigger Event Selection to “Reset (UG bit from TIMx_EGR”;
  8. Set Mode to “PWM mode 1”;
  9. Set Pulse to 0;
  10. Set Output compare preload to “Enable”;
  11. Set Fast Mode to “Disable”
  12. Set CH Polarity to “High”.

Now we are ready to lunch the initialization code and write our application.

The initialization code

In “Private variables” we find TIM_HandleTypeDef htim2, it is an instance to C struct that needs to manipulate the DAC peripheral. In “Private function prototypes” the function prototype used to initialize and configure the peripherals:
/* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_TIM2_Init(void);/* USER CODE BEGIN PFP */
At the end of main() we find the initialization code of System Clock, Timer 2 and GPIO ( as previously selected in STCube):
void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};   /** Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3); /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLM = 16; RCC_OscInitStruct.PLL.PLLN = 336; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4; RCC_OscInitStruct.PLL.PLLQ = 2; RCC_OscInitStruct.PLL.PLLR = 2; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error_Handler(); } }   /** * @brief TIM2 Initialization Function * @param None * @retval None */ static void MX_TIM2_Init(void) {   /* USER CODE BEGIN TIM2_Init 0 */   /* USER CODE END TIM2_Init 0 */   TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0};   /* USER CODE BEGIN TIM2_Init 1 */   /* USER CODE END TIM2_Init 1 */ htim2.Instance = TIM2; htim2.Init.Prescaler = 0; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 83999999; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_PWM_Init(&htim2) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) { Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 0; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN TIM2_Init 2 */   /* USER CODE END TIM2_Init 2 */ HAL_TIM_MspPostInit(&htim2);   }   /** * @brief GPIO Initialization Function * @param None * @retval None */ static void MX_GPIO_Init(void) {   /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOB_CLK_ENABLE();   }   /* USER CODE BEGIN 4 */   /* USER CODE END 4 */   /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ }

On/Off LED with STM32

Now we are ready to write our code in main() to on/off LED.
int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_TIM2_Init(); /* USER CODE BEGIN 2 */ HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2); __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, 41999999); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }

As mentioned earlier we have set the timer two to count up to 84 million, so we know that counting 84 million a second has elapsed. Now let's use the PWM function to make sure that for half a second the LED stays on and the other half a second off. In practice, to generate a square wave with a duty cycle of 50% and a frequency of one second.

We use the function “HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2)” to enable timer 2 to start in PWM mode and the macro “__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, 41999999)” tells the timer which is the value with which to compare the internal count (in this case 41999999) to decide whether the LED should be off or on.

Now we just must connect a led between pin PB3 and ground through a 220OHm resistor to limit the current (if we want to work with a duty cycle of 100%) and compile our application.

Once this is done, we see that the LED will remain on for 500ms second and off for another 500ms as can be seen from the waveform acquired by the PB3.

Since we have chosen a switching frequency of the PWM that is too low (1Hz), we will only see the LED turn on and off and we do not check its luminosity: we will see in the next paragraph how to increase the switching frequency, adjust the duty cycle in order to increase and decrease the brightness.

Dimming LED using PWM in STM32

First, we declare the following define:

#define D_COUNTER 839

Now, we associate it with the field “htim2.Init.Period” of the structure *htim2:

htim2.Init.Period = D_COUNTER;

In this way, we can quickly the number of counts that the timer must do and therefore manage the frequency and duty cycle of our PWM.

This way our timer will count up to 839 in 10us. Consequently, the switching frequency will be 100kHz (clearly exceeding 1Hz !!). Note that as in the previous example we have subtracted 1 from the count value because the timer starts at zero.

Then, we define an unsigned int variable to set the duty cycle:

unsigned int D; //duty cycle In the main() we write; /* USER CODE BEGIN 2 */ D= 10; //it menas duty cycle of 10% HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2); __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, (D_COUNTER/100)*D); /* USER CODE END 2 */

Where (D_COUNTER/100)*D needs to re-proportion the value of the duty cycle to the count that the timer must perform.

Compiling we will see that now the LED will always be on but with low brightness, in fact, the duty cycle is only 10% as can be seen from the generated waveform and the rms value of the voltage given to the LED is about 1.1 Volt (as you can see in the bottom corner of the RMS figure for the green trace). Furthermore, the figure confirms that the duty cycle is 10% both intuitively by looking at the green trace and by reading the measurement at the bottom center (Dty+ = 10,48%).

If we set D=70, the LED will be brighter, in fact the RMS value is about 2.82 Volt (as you can see in the bottom corner of the RMS figure for the green trace). Furthermore, the figure confirms that the duty cycle is 70% both intuitively by looking at the green trace and by reading the measurement at the bottom center (Dty+ = 69,54%).

If we set D=100, the led will be illuminated with the maximum brightness imposed by the limitation of the 220 Ohm resistor. The rms value at the ends of the LED with the resistance in series will be 3.3 Volts (the maximum generated by the GPIO)

Now if you write the following code on while(), we will see that the LED will change brightness every 100ms (in practice it increases, every 100ms the duty by 1% starting from 1% until it reaches 100% and then starts all over again)

/* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ for(D=1; D<=100; D++){ HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2); __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, (D_COUNTER/100)*D); HAL_Delay(100); } /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */

To do this we include the PWM configuration function ( HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2); __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, (D_COUNTER/100)*Duty) in the following loop for(D=1; D<=100; D++) which increases the value of variable D by 1 every 100 ms through the function HAL_Delay(100).

Now we are ready to effectively manage the PWM to control the brightness of a led, but in a similar way, we can control the speed of a DC motor or various actuators.

Simple 4-Way Traffic Light Control using Arduino

Hello friends, I hope you’re all well and healthy. In today’s tutorial, we will be going through a simple, yet effective practice to design a 4-way traffic light simulation in Proteus software. This project is designed for undergrad engineering students with majors in electronics, electrical and mechatronics engineering. It is also useful for people that want to learn the basics of circuit design and Arduino programming.

Where To Buy?
No.ComponentsDistributorLink To Buy
1LEDsAmazonBuy Now
2Arduino Mega 2560AmazonBuy Now

4-Way Traffic Light Control using Arduino:

Traffic lights are an integral part of the world’s transportation systems. Over the years a number of different algorithms regarding traffic lights have been developed. The algorithm being used at any place for the purpose of controlling traffic takes into account of various factors, such as number of lanes, people that cross a certain road, etc. The most common usage of traffic lights is to control the flow of traffic, which means providing a steady flow for people to go about their daily business on the road. Traffic lights help reduce accidents by a large margin since they allow the flow of vehicles in only one direction at a time. Traffic lights also help in avoiding traffic jams. The most common traffic light pattern being used in the world today is a 4-way traffic control that accounts for pedestrians as well. This sort of pattern is used in main city blocks and squares since these possess both vehicular traffic as well as pedestrian traffic. Traffic lights have a universal color understanding that red light signals for the traffic to stop, yellow light serves as a transition light from going to stop and vice versa.

Software to Install:

Since we are simulating this project instead of designing it using hardware components, you need to fill some requisites so that you can follow our procedure. At first, we need to have the simulating software. For simulation purposes, we will use the Proteus software, if you already have that installed, that is excellent. However, if you don’t, you should Install Proteus Software. Proteus is a circuit simulating software that has an open database that can be customized quite easily, leaving room to add new components along with their libraries. To start working with Proteus for this project, you need to add the following libraries:

  • Arduino Library for Proteus: This library includes all the Arduino boards, giving you options to simulate your circuit exactly according to your needs.

Project Overview:

The main components of a 4-way traffic light are:

  • Arduino Mega: For this circuit, we recommend using Arduino mega, that is because to control 4-way traffic along with pedestrian lights, we need 20 output pins while an Arduino UNO only has 14 digital I/O pins.
  • Traffic light module: This is an inbuilt traffic light module you can find in Proteus, there is no need for any additional libraries for this.
  • Pedestrian Lights: To distinguish pedestrian lights, we will use simple LEDs.

In this certain design, we have used delays to control the ON and OFF time of the traffic lights. There are other ways around this as well but using delays with Arduino is the simplest and most effective way for small projects.

The pedestrian lights are set up so that whenever a certain traffic light is GREEN, its opposing pedestrian light on which there is no traffic is turned ON and signals for the pedestrians to walk.

Components Needed:

  • Arduino Mega
  • Green and Red LEDs
  • Traffic Lights

Component details:

Arduino Mega:

Arduino Mega is a programmable microcontroller board.

Arduino Mega contains ATMegaGA2560 and is based on that microcontroller.

Every Arduino board is equipped with voltage regulators to make sure an excessive input does not burn components on the board.

Arduino Mega has 53 digital I/O pins.

Figure 1: Arduino Mega

Traffic Lights:

This module consists of three lights, namely, Red, Yellow and Green.

All three lights have separate input pins through which each light is controlled independently.

Make sure you connect all three pins to the Arduino, even if you are not using a certain light. This is because Proteus simulation only works when all the pins of traffic light are connected.

Figure 2: Traffic Lights

Proteus Simulation of Traffic Light Control:

We will first make the circuit on our Proteus software, after doing the connections of the circuit, we will work on the Arduino code based upon the circuitry and connections made.

First of all, make sure you have downloaded and installed Proteus software on your system and have downloaded and integrated the required libraries with the downloaded software.

Open Proteus and then open a new project, there is no need to change settings and simply select okay to default selected settings.

Import all the components of this project mentioned above and shown in the figure below:

Figure 3: Required Components

Place the components in the worksheet as illustrated below:

Figure 4: Component Placement

After placing the components in the worksheet, make connections as follows:

  • Connect 0,1 and 2 digital pins of Arduino to red, yellow and green of traffic light 1 respectively.
  • Connect 3,4 and 5 digital pins of Arduino to red, yellow and green of traffic light 2 respectively.
  • Connect 6,7 and 8 digital pins of Arduino to red, yellow and green of traffic light 3 respectively.
  • Connect 9,10 and 11 digital pins of Arduino to red, yellow and green of traffic light 4 respectively.
  • Connect 12and 13 digital pins of Arduino to red and green LEDs of pedestrian light 1 respectively.
  • Connect 14 and 15 digital pins of Arduino to red and green LEDs of pedestrian light 2 respectively.
  • Connect 16 and 17 digital pins of Arduino to red and green LEDs of pedestrian light 3 respectively.
  • Connect 18 and 19 digital pins of Arduino to red and green LEDs of pedestrian light 4 respectively.
  • Ground the negative terminals of all LEDs.

With this, your circuit connections are complete and we will now move on to the firmware setup of this circuit.

Arduino Code:

We have divided the Arduino code into 3 segments:

  • Declaration Code
  • Void setup
  • Void loop

We will look at these sections separately now.

Declaration Code:

The first step in the code is the declaration of variables that we will utilize in our program. At first is the declaration of traffic lights and setting them up with their respective pins of Arduino board. The syntax of this code is as follows.

Figure 5: Arduino Code

The next declaration is of pedestrian lights. The syntax of pedestrian light declaration is illustrated as follows.

Figure 6: Arduino Code

Void Setup:

This part of the code along with the declaration part is run only once, we will use this to define output and input pins. This helps Arduino to understand which pins to take data from and which pins to write data on.

Since there is no input, we will only define traffic lights and pedestrian lights as output pins. The syntax to do this is shown in figure 7.

Figure 7: Arduino code, Void Setup

Void Loop:

This part of the code runs in a loop consistently and is used to write the main section of the code.

In the first section, we will turn on the green light of signal 1 while all other signals are red. The pedestrian lights are red for pedestrian signals 1, 2 and 3. While the pedestrian 4 light is green since it is opposite to traffic signal 1.

Figure 8: Arduino Code

After a delay of 2000ms, we will turn on the yellow light for signal 1 and signal 2 to indicate that a transition from signal 1 to signal 2 will be made shortly. We will also turn all pedestrian lights red in order to ensure pedestrian safety.

Figure 9: Arduino Code

After a delay of 1000ms, all traffic and pedestrian lights will turn off for 100ms.

Figure 10: Arduino Code

For the second signal, we will turn on the green light of signal 2 while all other signals are red. The pedestrian lights are red for pedestrian signals 2, 3 and 4. While the pedestrian 1 light is green since it is opposite to traffic signal 2.

Figure 11: Arduino Code

After a delay of 2000ms, we will turn on the yellow light for signal 2 and signal 3 to indicate that a transition from signal 2 to signal 3 will be made shortly. We will also turn all pedestrian lights red in order to ensure pedestrian safety.

Figure 12: Arduino Code

After a delay of 1000ms, all traffic and pedestrian lights will turn off for 100ms.

Figure 13: Arduino Code

For signal 3, we will turn on the green light of signal 3 while all other signals are red. The pedestrian lights are red for pedestrian signal 1, 3 and 4. While the pedestrian 2 light is green since it is opposite to traffic signal 3.

Figure 14: Arduino Code

After a delay of 2000ms, we will turn on the yellow light for signal 3 and signal 4 to indicate that a transition from signal 3 to signal 4 will be made shortly. We will also turn all pedestrian lights red in order to ensure pedestrian safety.

Figure 15: Arduino Code

After a delay of 1000ms, all traffic and pedestrian lights will turn off for 100ms.

Figure 16: Arduino Code

For the final signal, we will turn on the green light of signal 4 while all other signals are red. The pedestrian lights are red for pedestrian signals 1, 2 and 4. While the pedestrian 3 light is green since it is opposite to traffic signal 4.

Figure 17: Arduino Code

After a delay of 2000ms, we will turn on the yellow light for signal 4 and signal 1 to indicate that a transition from signal 4 to signal 1 will be made shortly. We will also turn all pedestrian lights red in order to ensure pedestrian safety. This will also complete the loop and the sequence will keep running on its own.

Figure 18: Arduino Code

After a delay of 1000ms, all traffic and pedestrian lights will turn off for 100ms.

Figure 19: Arduino Code

With this, the program of the void loop will end and start again from signal 1 on its own.

Results/Working:

Generate a hex file from the Arduino program made above. Be sure to select

Integrate the hex file into your Arduino board on Proteus.

Run the simulation.

The results of the simulation should be something like our simulation results.

The simulation results for each scenario are illustrated in the figure below.

At first, traffic signal 1 is turned ON and the green light is displayed for 2000ms. The green pedestrian light 4 is also turned ON since it is opposite to signal 1.

Figure 20: Signal 1 is ON while Pedestrian 4 is ON.

Then the yellow light of signals 1 and 2 are turned ON showing transition is about to happen. The red pedestrian lights during this are turned ON to ensure pedestrian safety.

Figure 21: Yellow light showing the transition.

Then traffic signal 2 is turned ON and the green light is displayed for 2000ms. The green pedestrian light 1 is also turned ON since it is opposite to signal 2.

Figure 22: Signal 2 is ON while Pedestrian 1 is ON.

Then the yellow light of signal 2 and 3 is turned ON showing transition is about to happen. The red pedestrian lights during this are turned ON to ensure pedestrian safety.

Figure 23: Yellow light showing transition.

Then traffic signal 3 is turned ON and the green light is displayed for 2000ms. The green pedestrian light 2 is also turned ON since it is opposite to signal 3.

Figure 24: Signal 3 is ON and Pedestrian 2 is ON

Then the yellow light of signal 3 and 4 is turned ON showing transition is about to happen. The red pedestrian lights during this are turned ON to ensure pedestrian safety.

Figure 25: Yellow light showing the transition.

Then traffic signal 4 is turned ON and the green light is displayed for 2000ms. The green pedestrian light 3 is also turned ON since it is opposite to signal 4.

Figure 26: Signal 3 is ON and Pedestrian 2 is ON

Then the yellow light of signal 4 and 1 is turned ON showing transition is about to happen. The red pedestrian lights during this are turned ON to ensure pedestrian safety.

Figure 27: Yellow light showing the transition.

That is all for today’s tutorial, I hope you enjoyed learning with us. We wish you have a good day ahead of you. Thanks for reading.

THT vs SMT

Hello everyone, I hope you all are doing great. Today, we are going to share the 9th chapter in the PCB learning series, where we will have a look at the difference between Through-hole and Surface-mount technology.

In our previous lectures, we studied both THT and SMT methods separately and have seen that both are used for components mounting on the PCB board. So, today, we will have a look at the difference between the two techniques. So, let's get started without wasting any time.

Through-Hole vs Surface-Mount

Let us know have a look at these differences and get to know the way forward when it comes to the process of component selection whether SMT or DIP.

Definition - THT vs SMT

  • THT stands for through-hole technology.

In Through-hole technology, components are mounted by the use of holes that are systematically drilled through the layers of printed circuit boards. the components have long leads that are properly fitted in the holes and soldered.

  • SMT method stands for Surface Mount Technology.

In Surface-mount technology, components are mounted on the surface of the printed circuit board. This is the most recent method employed in manufacturing of printed circuit boards.

How to Manufacture?

There are many online PCB Manufacturing companies, where you can place your SMT or THT orders. For example, let's talk about JLCPCB Fabrication House, they offer both THT and SMT fabrication. You can place your order on the official site of JLCPCB. They have an excellent support team, so while placing your order, you can discuss your design with them and they will guide you completely.

JLCPCB offers competitive prices as compared to other PCB houses and delivers quality work within the assigned time limit. They also offer seasonal discounts, so if you are a regular PCB designer, you should subscribe to JLCPCB.

Component Mounting

Through-hole Technology:

  • In Through-hole Technology, DIP components are used having copper leads/wires called lead wire terminals.
  • These leads are used to connect the components with copper tracks on the PCB board.
  • These leads are inserted in the drilled holes on the PCB board and are soldered from the back side.
  • The extra leads are then trimmed off using a cutter.
  • A DIP component having two leads is shown in the below figure:

Surface-mount Technology;

  • In Surface-mountTechnology, SMT components are used having copper flat terminals(called pads) instead of leads/wires.
  • These SMT components are placed on the surface of the PCB board as mentioned in the design files and the flat terminals are soldered with the pads of the PCB board.
  • An SMT component is shown in the below figure:

Manual vs Automatic Process

Through-hole Technology

  • Through-hole PCB boards can be assembled both manually and automatically(with the help of machines).
  • Normally manual assembling is preferred in THT boards.

Surface-mount Technology

  • As the SMT circuits are complex in design, thus it involves the use of sophisticated systems to ensure that the process is accurate and error-prone.
  • Pick-and-place machines and stencils are used in the SMT process.
  • Manufacturing SMT PCB at home is too difficult so automatic processes are recommended in this case.

Stencils

Stencil is a modern technique to place solder paste on a bare circuit board. This paste forms the deposits on the board that is used to hold the components in place.

Through-hole Technology:

  • The through-hole technology does not involve the use of stencils since the components are mounted in holes and are soldered on the other side.

Surface-mount Technology

  • The surface mount technology uses stencils for the process to be smooth.
  • Solder paste is poured through a stencil on the PCB board and then SMT components are placed on it.

Vias

Vias are small drilled holes between the PCB layers to electrically join traces of the circuitry.

[TEPImg11]

Through-hole Technology

  • For the through-hole technology, vias are not that necessary since the components are connected through the holes to the other layers of the boards.

Surface-mount Technology

  • The surface-mount devices employ the use of the vias to connect between layers of the board. Since components are mounted on the same layer, it is very necessary to employ the vias to interconnect between the layers of the PCB board.

Debugging

  • Through-hole technology mounting components and boards are quite easy to debug/repair, that's why, THT is used when a prototype or testing is required.
  • Surface-mount technology components are quite difficult to debug/repair because they are very small in size.

Soldering

Through-hole Technology

  • Wave Soldering is used in THT boards.
  • It's an in-line soldering process that treats the solder with flux.
  • The solder is melted after getting heated and then immersed on the PCB board.
[TEPImg12]

Surface-mount Technology

  • Reflow soldering is used in SMT boards.
  • In reflow soldering, a solder paste is used to mount components temporarily on the board by the use of the pads after which the entire design is preheated.
[TEPImg13]

Component Types

  • Through-hole technology uses lead capacitors and resistors, DIP and GPA components.
  • The surface mount technology uses LCCCP, SPOIC, QFP, BGA, SOT, LCC, chip resistors/capacitors etc.

Assembly Density

  • Through-hole technology is used when a low density of components is required.
  • Surface mount technology is used where a high density of components is required.

Solder Joint

Through-hole Technology

  • For the through-hole technology, the solder joint connects the component lead to the board through a hole drilled on it.
  • The solder is applied on the lower side of the board and the upper side is filled with the flux.

Surface-mount Technology

  • For the surface mount devices, the board is first spread with the solder paste, after that components with pads are placed accordingly on the soldered points and then the solder is melted to fix the components on the board.

Cost of Production

The cost of production for the two methods varies, normally determined by the type of manufacturing process and the components used.

Through-hole Technology

  • Through-hole technology proves to be the most expensive. when it comes to initial production because it involves drilling holes to mount the components.
  • But when it comes to routine maintenance of the THT boards, the cost is relatively low since it is very easy to replace any component on the boards. THT is easily repairable.

Surface-mount Technology

  • Surface-mount devices are cheaper when it comes to initial manufacturing.
  • The process is purely automated hence saving oh human labor costs.
  • Also, the process does not involve the use of holes in the mounting of the components hence reducing costs.
  • The boards are produced in bulk through the process of PCB panelization, this also lowers the cost of production of the boards.
  • Now, there is one challenge with this type of board, the maintenance cost is too demanding. You will need a lot of expertise to change any faulty component. Some of them cannot be changed since they are so tiny. Therefore, in most cases, if the board has a problem, you might end up buying a new one hence it is very expensive when it comes to maintenance and repair.

Applications

Through-hole Technology

  • Through-hole technology is preferred in hobbyists and academic projects, because of simple circuits to design.
  • THT Boards are also used in areas where strong mechanical strength is required such as in military equipment and equipment with high vibrations. This is because their soldered joints are mechanically strong.

Surface-mount Technology

  • Surface-mount devices are preferred in the industry sector where commercial products are designed because SMT is cheap, lightweight and small in size.
  • The manufacturing time of SMT boards is quite low, especially in mass production, because its manufacturing process is purely automated.

So, that was all for today. I hope you have enjoyed today's lecture, let me know if you need any help with it. Thanks for reading.

Introduction to Through Hole Technology(THT)

Greetings and welcome to today’s lecture. It's our 7th tutorial in the PCB learning series. In our previous lectures, we have studied the two main types of PCB i.e. Single-sided and Double-sided PCB. Today is going to be a very interesting and interactive class about Through Hole Technology(THT), which is applied in the process of designing printed circuit boards.

A PCB board has a properly designed circuit on it and it's composed of connecting traces/paths and various electronic components. The electronic components are mounted on the board in two different ways i.e. Through-hole and Surface-mount. We will cover Surface-mount in our next lecture and today, we will discuss how to mount components on PCB boards using though-hole technology.

So, let's get started with Through-hole technology:

Introduction to Through-Hole Technology of PCB Design

  • In Through-Hole Technology(THT), small holes are drilled in the PCB board to mount the components.
  • The normal-sized components(unlike SMD components) have long copper leads/pins and are plugged into these drilled PCB holes and soldered from the other side. The extra leads are trimmed off.
  • In through-hole technology, components are placed on one side of the board and soldered on the other side, where the copper foil is present.
  • Through-hole technology is normally used in single-sided boards.

History of Through-hole Technology

  • THT is the oldest among these PCB components' attachment methods.
  • For quite a long time, it remained the standard method to use in the PCB assembly process.
  • In the 1980s, when the surface mount technology process was introduced in the field of PCB assembly, designers thought that the THT method will become extinct but that is still not the case.

Why do we still need THT?

  • The surface mount technology, being advanced had many advantages over the old Through-hole technology but because of low cost, THT is still operating.
  • Some high-power components that required strong connections could not be fitted by the surface mount process, THT is the only option that could be used in such a process.
  • For example, the connection of the terminal blocks, power jacks and other power connectors can not be done by any other method apart from the THT.
  • Also, equipment working in places with high temperatures and vibrations can only have boards that are connected through the through-hole technology.
  • Therefore, while others thought that, the entry of the surface mount devices was the end of the through-hole technology, their thought was disapproved over time, as of today, through-hole technology remains one of the important mounting processes in the manufacturing of the PCB.

How to place THT PCB Order?

There are many online PCB Fabrication Houses, that provide Through Hole PCB board services. One of them is JLCPCB Manufacturing House, which offers this facility of mounting Through Hole components as well as SMT components, a sister company of EasyEDA. JLCPCB is a top-notch PCB Fabrication House, provides low rates for PCB orders.

JLCPCB has an excellent support team, so you should discuss your PCB order with them first. They will completely guide you and will give you the final price and time to complete it. JLCPCB provides a perfect product as per your requirements, a personal experience.

THT Process

  • Drill holes on the PCB following the clients’ design.
  • Holes have several specifications from location to diameter sizes.
  • In the design folder submitted by the designer, there is a very specific file named drill file. This is the file that will give the location and sizes of the holes to be drilled on the boards accordingly.
  • Select the components, that must have long leads and every component has its own specification. Components are mentioned in the BOM files, schematics and the GERBER files. If you go through the files, you will get the components to be used in the design, whether, THT or SMD components. THT components will be selected in this case.
  • The next phase is to place the components on the board and ensure that their leads are on the holes as defined in the design. This process can be done manually by human hands or can be done by pick-and-place machines that have been designed specifically for this purpose.
  • Ensuring that the components are in the positions described in the design to avoid any errors.
  • Solder the terminals on the board accordingly. Soldering is one of the most important processes in THT PCB design.

  • Soldering is done by use of the soldering gun which is of different varieties as shown below:

Initially, this process was done manually and was time-consuming, but today, due to AI technology, it has become quite simple and automated to design through-hole technology. An automated insertion machine helps in inserting the electrical elements into the drilled holes of the PCB before the soldering process starts.

Classifications of Through Hole Components

We have talked about the electrical components being placed on the PCB boards through the hole.s These components can be classified into two main types:

  1. Radial-leads components.
  2. Axial-leads components.

Radial-leads Components

  • In Radial-leads components, all the leads originate from one side of the component.
  • The components can be mounted either vertically or horizontally.
  • Radial-lead components include capacitors, op-amp, power regulators(LM317, LM7805) etc.

Vertical mounting of Radial THT components

  • In this case, the component is placed perpendicular to the board while the base is placed parallel to the board. Soldering is done on one side of the terminal and the other side is filled with flax.

Horizontal mounting of Radial THT components

  • The component body is fixed horizontally as you can see in the image above.
  • The leads exhibit a very nice bend and spacing. This allows the proper filling of the solder on the component hence forming the strongest bond.
  • The component is free from vibration effects as it is well-fixed on the board.

The Axial leads Components.

  • In axial-leads components, the leads appear from opposite sides of the component package.
  • Axial components are placed horizontally over the PCB board and are strongly attached to the sheet.
  • Common examples are diodes, resistors etc.

Vertical axial mounting method.

  • One side of the mounting lead is long and allows room for its bending to achieve horizontal fixing.
  • It has a strong mechanical joint as it can allow soldering on both sides of the board.

THT Components types

Single-ended

This is mostly used in integrated circuit embedded systems. Those ICs that have terminals on one single side are said to be single-ended THT components. See the attached figure below.

Double ended

Again, it is applied in ICs systems. Some IC for example the 8051 AT89C51 have pins that are arranged in two files each from its side of the length as shown below. The type of THT that will be used to fix them in the PCB is called double-ended THT mounting.

Pin grid arrays THTs

In this type of THT, the components have so many pins that are arranged throughout the component in a grid manner. See the example of such components below.

Applications of THT

  • High voltage areas eg in the medical equipment. When high voltages are involved, there is a possibility of shorts and overheating of the components. Since this type of component mounting provides a strong joint, thus THT comes in handy.
  • High mechanical stress devices eg military equipment. High stress, requires strong joints to avoid breakages. This can only be offered via the THT type of mounting.
  • High power areas eg in the steam boilers. High power is accompanied by vibrations and magnetic forces. This type of mounting is good for such devices.
  • High temperatures operating devices eg in the nuclear plants. High temperature means the possibility of high reliability. Hence, we can use THT as it can be easy to replace components in case of problems.
  • Prototyping and testing of components since it is the most flexible method offering easy ways for replacement of components during the process.

Advantages of THT

  1. The use of the THT method will ensure that you have a very strong mechanical bond between your components and PCB board.
  2. THT-bound components have high resistance to wear and tear and this is made possible by the use of the large soldering deposits at the terminals.
  3. The THT components are very easy to swap/repair, thus, best for prototyping works.
  4. It is best suited for places where strong mechanical applications are needed such as aerospace and military equipment.

Disadvantages of the THT method of PCB components Mounting.

  1. Due to the drilling of the required holes, the production machines have to be very accurate.
  2. Drilling of the holes requires some additional time, hence THT method takes a longer time compared to other methods.
  3. This method limits the available routing paths for the multilayer PCBs because the drilled holes have to go through the given layers.
  4. The technology being used in the industrial mass production of THT is less reliable compared to other methods.

The through-hole technology PCB mounting is the best method to be used when manufacturing large PCB boards. It is best for mechanically strong component mounting and also the cheapest when it comes to doing testing and prototypes. It can't be extinct and it will never.

So, that was all for today. In the next lecture, we will discuss the second method of mounting components on PCB boards named Surface-mount technology. Till then, take care!!!

ESP32 OTA (Over The Air) Programming

Hello readers, hope you all are doing great. In this tutorial, we are going to discuss a mechanism that allows users to update the ESP32 with a new program wirelessly or over the air (without using a USB cable to upload a new program).

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

Over-The-Air (OTA) programming

Fig. 1 ESP32 OTA

  • OTA programming is the mean by which a product manufacturer or product service provider can update the features or functionality of the device wirelessly or over the air, after the device has been deployed in the field where connecting a cable or uploading the code serially is difficult.
  • One key advantage of OTA is that a single central node can send an update to multiple ESPs on the same network.
  • The device must have a provisioning client capable of receiving, processing, and setting parameters in order to receive, process, and set parameters in a mobile device over the air.

Applications of OTA programming

Mobile Phones:

  • In order to improve the compatibility with hardware and enhance the stability of software and applications, software updates are required.
  • OTA updates are intended to improve the underlying operating system, time zone rules, read-only apps installed on the system partition these updates have no effect on user-installed applications.

IoT (internet of things) application:

  • The ability to wirelessly download an application, configuration, or firmware to internet-enabled devices, also known as IoT, is referred to as over-the-air (OTA). It works in the same way that our computers, laptops, tablets, and phones do.
  • Application, where sensor nodes are frequently placed in remote or difficult-to-reach locations OTA programming can be used.

Fig. 2 OTA programming for IoT

 

How does OTA programming work?

There are two methods of OTA implementation.

  • Basic OTA: In the basic OTA method the program is updated into ESP32 over the air using Arduino IDE.
  • OTA web updater: In web updater OTA the program is updated over the air using a web browser.

Implementing OTA Update feature using ESP32

In this tutorial, we will discuss only the basic OTA method using Arduino IDE and ESP32 module.

If you want to know more about the basics of ESP32 and how to get started with Arduino IDE, then follow the tutorial Introduction to ESP32 Programming Series.

  • For Basic OTA programming with ESP32, it is required to install the python 2.7.x version in your system.
  • Follow the link to download python: https://www.python.org/downloads/
  • Install the python into your system.
  • Upload the basic OTA code into ESP32 using the serial port.
  • Upload the new ESP32 test code over the air using the network port into esp32 module.

To implement the Basic OTA method, an example is available is Arduino IDE.

  • You can find the code through File> Examples> ArduinoOTA> BasicOTA.
  • An image has been attached below for reference:

Fig. 3

Arduino IDE Code

  • It is required to first upload the basic OTA code serially (using serial com port).
  • Because in default mode the ESP32 is not ready for OTA updates (as there is no inbuilt OTA firmware available inside the ESP32 board).
  • Only after that you can access the OTA feature
#include <WiFi.h> #include <ESPmDNS.h> #include <WiFiUdp.h> #include <ArduinoOTA.h>   const char* ssid = "SSID"; const char* password = "Password";   void setup() { Serial.begin(115200); Serial.println("Booting"); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (WiFi.waitForConnectResult() != WL_CONNECTED) { Serial.println("Connection Failed! Rebooting..."); delay(5000); ESP.restart(); } ArduinoOTA.onStart([]() { String type; if (ArduinoOTA.getCommand() == U_FLASH) type = "sketch"; else // U_SPIFFS type = "filesystem";   // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end() Serial.println("Start updating " + type); }) .onEnd([]() { Serial.println("\nEnd"); }) .onProgress([](unsigned int progress, unsigned int total) { Serial.printf("Progress: %u%%\r", (progress / (total / 100))); }) .onError([](ota_error_t error) { Serial.printf("Error[%u]: ", error); if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); else if (error == OTA_END_ERROR) Serial.println("End Failed"); }); ArduinoOTA.begin(); Serial.println("Ready"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); } void loop() { ArduinoOTA.handle(); }

Code Description

  • The first step is to add all the necessary header files. Here we are using four header files.
  • WiFi.h: This header file allows the ESP32 board to connect to the internet. It can serve either as a server or a client.
  • ESPmDNS.h: This library is used to implement multicast DNS query support for the ESP32 chip. A multicast UDP service is used to provide local network service.
  • WiFiUdp.h: This is a library for Arduino wifi shield. It is used to send data to a UDP host over a wireless network.
  • ArduinoOTA.h: this library allows users to update the code in the ESP32 board using wifi instead of using the serial port.
  • Next, you need to add your wifi credentials. Enter the SSID and password.

Arduino Setup() Function

  • Inside the setup () function, the first task is to begin the serial monitor at a 115200 baud rate so that, you can print the results and other required details on the serial monitor for verification purposes.
  • Set ESP32 Wi-Fi module in station mode(esp32 will act as a client device) using WiFi.mode() function.
  • Enable ESP32’s Wi-Fi module using WiFi.begin() function which is using SSID and password as arguments.
  • Wait until the ESP32 is not connected with the wifi network.
  • ESP.restart() function will reset the ESP32. ESP.restart() function tells SDK to reboot.
  • If an error occurred in OTA programming, print the error on the serial monitor

  • ArduinoOTA.begin() function is used to initialize the OTA updater.
  • Wi-Fi.lockIP() is used to fetch the IP address.
  • Print the IP address on the serial monitor.

Arduino Loop() Function

  • Inside the loop() function, ArduinoOTA.handle() function is used for updating the ESP32 code over the air using the network port instead of the serial port.
  • Compile the code and upload serially using serial com port.
  • Open the serial monitor, set the baud rate to 115200.
  • You can see the IP address on the serial monitor once the ESP32 is connected to the Wi-Fi network.

Fig. 11 Serial monitor

Uploading new program into ESP32 module Over the Air

Code

#include <WiFi.h> #include <ESPmDNS.h> #include <WiFiUdp.h> #include <ArduinoOTA.h>   const char* ssid = "public"; const char* password = "ESP32@123";   //variabls for blinking an LED with Millis const int led = 2; // ESP32 Pin to which onboard LED is connected unsigned long previousMillis = 0; // will store last time LED was updated const long interval = 1000; // interval at which to blink (milliseconds) int ledState = LOW; // ledState used to set the LED   void setup() {   pinMode(led, OUTPUT);   Serial.begin(115200); Serial.println("Booting"); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (WiFi.waitForConnectResult() != WL_CONNECTED) { Serial.println("Connection Failed! Rebooting..."); delay(5000); ESP.restart(); } ArduinoOTA .onStart([]() { String type; if (ArduinoOTA.getCommand() == U_FLASH) type = "sketch"; else // U_SPIFFS type = "filesystem";   // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end() Serial.println("Start updating " + type); }) .onEnd([]() { Serial.println("\nEnd"); }) .onProgress([](unsigned int progress, unsigned int total) { Serial.printf("Progress: %u%%\r", (progress / (total / 100))); }) .onError([](ota_error_t error) { Serial.printf("Error[%u]: ", error); if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); else if (error == OTA_END_ERROR) Serial.println("End Failed"); });   ArduinoOTA.begin();   Serial.println("Ready"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); }   void loop() { ArduinoOTA.handle();   //loop to blink without delay unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval) { // save the last time you blinked the LED previousMillis = currentMillis; // if the LED is off turn it on and vice-versa: ledState = not(ledState); // set the LED with the ledState of the variable: digitalWrite(led, ledState); } }
  • In the test code, which we are going to upload using a wireless network port over the air, a LED blinking function is added just to test whether the OTA functionality is working fine or not.

Note: It is required to upload the OTA programming handler code every time you upload a new code into ESP32 over the air. So that, OTA programming remains enabled for future use.

Code Description

  • Add the required header files.

  • Enter Wi-FI credentials over which you are going to upload the code wirelessly.
  • Define the GPIO pin to which LED is connected.
  • GPIO 2 is connected to the inbuilt LED.
  • To add delay, we are using timers instead of delay() function.
  • The variable interval is defining the time delay.
  • Set LED’s state to low.

Arduino Setup() Function

  • Although in the example code serial monitor is initialized but it is not required anymore as we are using the network port for communication.
  • Initialize ESP32 Wi-Fi in station mode using WiFi.mode() function.
  • Wait until esp32 is connected to the Wi-Fi network.

  • ArduinoOTA.begin() function is used to initialize the OTA updater.
  • Wi-Fi.lockIP() is used to fetch the IP address.
  • Print the IP address on the serial monitor.

Arduino Loop() Function

  • Blink the LED after every 1000ms or 1sec delay as defined in variable ‘interval’.

  • Compile the above code.
  • Go to the Tools menu, then click on port and select the network port as shown in the image below.

This concludes the tutorial. I hope you found this helpful. In the next tutorial, we will discuss the OTA web updater in ESP32.

Accident Detection System using Arduino

Hello everyone, Welcome to our new project. Our new project plays a very important role in our daily life as it is directly connected to our lives. In this project, we are going to design an Accident Detection module. Accidents are the most common thing we hear about in the news, and in social media. Everyone here or there has seen accidents or has been with one. So when any such incidents happen, we inform respective stations or hospitals in that emergency situation. But what about the accidents that happen at night, or in places where there is very less crowd or you are alone. So, to address this issue and provide a potential solution for that, we are going to learn how to detect an accident automatically and inform nearby aid/help stations.

We can use this useful project for an engineering project’s showcase for electronics, electrical engineering students, and can be used in real-life situations where it can help people in disastrous situations.

According to WHO, research says that in the current scenario, 1.3 million people are the victims of road traffic crashes, and 40% of these accidents of all fatal accidents occur at night. In most cases, the accidents are not reported immediately, or the injured doesn’t receive any help during that time. The time between the accident and the arrival of medical help for the injured can sometimes make the difference between his life or death. In the future, we can interface with the vehicle airbag system. This will optimize the proposed technology to the maximum extent and result in the finest accident detection system possible. In this Modern era, everything is being automated and with this project, we are going to automate this process with some electronic components and Arduino. So Let’s dive in. Here's the video demonstration of this project:

Where To Buy?
No.ComponentsDistributorLink To Buy
1NEO-6MAmazonBuy Now
2SIM900AmazonBuy Now
3Arduino UnoAmazonBuy Now

Software to Install:

Instead of using real components, we will design this project using Proteus Simulation. Working with simulation before attempting to make it with real components is also a smart practice. We can figure out the issue that may arise while working on real components and avoid any kind of damage to our components by simulating it.

Proteus is a very fascinating tool that allows us to simulate and create electronic circuits. Despite the fact that Proteus software contains a large library of electronics components, it still lacks pre-installed modules such as Arduino boards, GPS or GSM modules, and so on.

Let’s install the required libraries which, we are going to use in this project:

You can download this whole project for example Proteus Simulation and Arduino Code, by tapping the below button

Accident Detection System using Arduino

Project Overview:

These are required components for Accident Detection, which are as follows:

  • Arduino Uno: Arduino Uno is a development board from the Arduino family, which is the main component of this project. The Microcontroller i.e., Arduino is responsible for the decisions that are going to be processed in the project.
  • Accelerometer: An accelerometer is a device that measures acceleration, which is the change in speed (velocity) per unit time. By measuring acceleration we can get information like object inclination and vibration which helps in detecting unusual activities/ accidents.
  • GSM: A GSM/GPRS Module is a device that is actually responsible for the wireless communication with the GSM Network, in this case, it is responsible for sending the appropriate information to rescue stations.

Components Needed:

  1. Arduino Uno
  2. GPRS Module
  3. Accelerometer
  4. GSM Module
  5. Bread Board
  6. Jumper Wires

Component details:

Arduino Uno:

  • The Arduino UNO is one of the Arduino family's programmable, open-source microcontroller boards.
  • It includes an Atmel Microchip ATMega328P microcontroller with an 8-bit RISC processing core and 32 KB flash memory from Atmel.
  • It has 14 digital I/O pins, including 6 PWM pins and 6 analog I/O pins with a resolution of 10 bits (0-1024).
  • It comes with one hardware UART, one I2C, and one SPI peripheral.
  • We can use the Arduino UNO with a voltage range of 7-12 volts, but not more than 9 volts is recommended because it may damage the Arduino board
  • To power the Arduino UNO we can use a USB-B cable (the same cable that we use to upload the sketch to Arduino UNO), a DC power jack, or the Vin pin on the board.

GPS Module:

  • The Global Positioning System (GPS) is a space-based global navigation satellite system that gives accurate location and timing in all weather and at all times around the world.
  • It sendLongitude, latitude, height, and time are the four variables that a GPS receiver determines.
  • Data determined by the module will be sent to the microcontroller (Arduino Uno) through the UART protocol.
  • With a USB interface, the GPS module is simple to operate. It operates on a 3.2 to 5V supply range, allowing it to interface with both 3.3V and 5V microcontrollers.
  • It has a default baud rate of 9600 and can be modified as per our requirement.
  • We have used this to get the current location of the user.

Accelerometer:

  • Accelerometer sensors are integrated circuits (ICs) that are used to measure acceleration, inclination, and various parameters regarding the x,y,z axes. It is the main component to detect the accident.
  • Here we used the MEMS (Microelectromechanical Systems) accelerometer. These types of accelerometers are used where we have to measure the vibration or shock without any fixed reference.
  • It monitors changes in the capacitance and converts that value to analog output voltage.
  • Gyro Range of the Accelerometer sensor is ± 250, 500, 1000, 2000 °/s (may vary depending upon the sensor).
  • Accelerometer Range of the sensor module is ± 2 ± 4 ± 8 ± 16 g (may vary depending upon the sensor).

GSM module:

  • This module is used to send the notification to the rescue station or the emergency numbers.
  • It communicates with the Arduino UNO using the UART protocol.
  • It works in a voltage range of 3.5 - 5 volts.
  • There are different types of GSM modules available but in this project, we have used the SIM900D module.
  • We operate them using the AT commands. As there are hundreds of AT commands but we will use some basic only just to send the message.

Proteus Simulation of Accident Detection Circuit:

Now, it is time to start designing the main circuit of Accident detection in Proteus Simulation software.

  • Most importantly, ensure that Proteus is installed on your PC/Laptop and download all the required libraries for Proteus ahead of starting the designing steps.
  • For this project, we are going to use libraries for Arduino Uno, GPRS Module, GSM module.
  • To add the libraries in the Proteus suite we have to go to the C drive then LabCenter Electronics >> Proteus 8 professional >> Data >> Library and paste the downloaded library files here.
  • The download links of all the libraries have been provided to you in the above sections, please go check them out.
  • Let’s start the making of a new project, open the new project in Proteus.
  • After that enter the name of your new project.
  • Now our working area will be open here we will import all the required components which we are going to use.
  • The following components need to be selected from the Proteus component library. We’ll connect the components and make the circuit complete.
  • Now we have imported all the required components for this project, after this, we will start connecting them.

Circuit Diagram and Working:

  • There are two modules GPRS and GSM modules, both communicate using the UART protocol but in the Arduino UNO there is only one hardware UART’s provision. Now, you may have doubts about how we are going to connect them. No worries, we will handle that on the coding side by declaring the different pins as UART pins.
  • We can use different pins for UART using the SoftSerial library of Arduino, which will be discussed in the code.
  • We will use the digital pins for UART connections, digital pins 2 and 3 for communication of the GSM module, which means connecting the Rx and Tx of the GSM module with the D2 and D3 pins of Arduino UNO respectively.
  • Connect the Rx and Tx of the GPRS module with the D10 and D11 pins of Arduino UNO respectively.
  • As modules are connected, now we will connect the accelerometer. As it will not be possible to simulate the accelerometer in Proteus so we have used the potentiometers to change the value of the X-axis, Y-axis and Z-axis.
  • You may have doubts about how we can replace the accelerometer with potentiometers. As we will use the MEMS accelerometer, which sends the analog voltages for each axis, so we can simulate that using the potentiometer because we will receive the same type of data.
  • We need three potentiometers, one for each axis. Potentiometers of the X-axis, Y-axis and Z-axis will be connected to A1, A2 and A3 pins of Arduino respectively.
  • We will connect a serial terminal for debugging purposes.

Arduino code for Accident Detection System

Before going to start the coding, it would be easy if you understood the circuit diagram connections.

  • When we start writing the code(called a sketch in Arduino IDE), we will first include all of the necessary libraries for this project.
  • So, if the essential libraries aren't already installed in the Arduino IDE, our first step would be to get them.
  • Here we use mainly two libraries, one for serial communication and parsing data from the GPS module.
  • By heading to 'Sketch > Include Library > Manage Library' in the Arduino IDE, we can install libraries related to Arduino. We can now search for our essential libraries in the library manager. We can also use zip files to install the libraries.
  • As we've installed all the specified libraries. Let’s include them in our sketch.
  • Now, we are declaring D2 and D3 pins for serial communication with GPRS modules and declaring GPS objects as well, which will pretty much do all the grunt work with the NMEA data.
  • After that, we will declare variables to store the GPS module data.
  • Now, we are declaring pins and variables for the accelerometer which we will use in our project. Here, we are using Analog Pins because we are reading the analog voltages from the potentiometer.
  • We need to declare two threshold values for change in acceleration when an accident is detected.
  • The min and max values can vary. So, it is highly recommended to measure the values by accelerometer for devices using.

Void Setup():

  • It is one of the most important functions which will execute only once in the whole process.
  • As we are using a GPS module in our project, We should first start serial communication between the components and Monitor them through “Serial Monitor” in the Arduino IDE.
  • “Serial.begin” is used to set up the serial configuration for the device which is connected to the Serial Port of the Arduino. Here, we will set the baud rate for that device i.e 9600 in our case.
  • “serial_connection.begin(9600)” is used to set up the UART configuration for the GPS module. As the GPS module communicates to the Arduino at the baud rate of 9600.
  • We are using an Accelerometer in the circuit and it was clearly explained in detail that it will sense the x,y,z coordinates of the device and send them to Arduino.
  • Here, we have initialized a for loop to collect the sample data for x, y, and z coordinates of the device in the ideal state.
  • Afterward, the sample coordinates have been successfully measured by the Accelerometer sensor, but we need an average value for smoothing the sample coordinate values. So here, we will calculate the average of each coordinate and print them in the serial monitor.
  • After the setup, we will write our main application code in the Void loop function.

Void loop():

  • It is the second most important function of Arduino code. It will come to action after the execution of “void setup()”
  • We'll write the code required to run in a continuous loop in this part. So this is where we'll write our primary application code.
  • As a result, when the code gets to the void loop portion, We firstly take the NMEA data from the GPS module and print it in the serial monitor.
  • Wait a minute, NMEA??, I can understand all the questions in your mind. Let us give you a simple explanation regarding NMEA and its applications.
  • The word NMEA stands for the National Marine Electronics Association, which is a mode of communication that existed before inventing GPS. NMEA-format GPS data can be accessed with a wide variety of GPS receivers, instead of creating a new custom interface every time. Thus, it makes our lives easier using the GPS Module.
  • When we are printing the NMEA data into the serial monitor, it will be printed in a specific structure. This NMEA data was output from a GPS receiver:

“$GPGGA,191605.00,4521.7785210,N,07331.7656561,W,2,19,1.00,674.354,M,19.900,M,0.90,0000*60”

  • All NMEA signals start with the ‘ $ ’ character and for every data field such as coordinates, and various parameters are separated by a comma. The data further includes Timestamp, Latitude, Longitude, Quality indicator, Number of satellites involved, Altitude, etc., which is not necessary to remember. Make sure to get the data from the GPS module. If we have succeeded in this step and get the data on the serial monitor, then we are good to go for further processing.
  • The “if” statement is to process the NMEA data and separate the data into the required format if there is any location updated to the GPS receiver.
  • As we have already received NMEA data in the previous step, the data will be separated into Latitude, Longitude and Altitude.
  • In the Loop function, the values of GPS and accelerometer will be continuously tracked.
  • Here, the analog values of x,y,z coordinates are being measured and printed in the serial monitor.
  • These are not the values we measured in the void setup, those were the values to take the readings in the ideal state of the device.
  • But in the loop, the values are the present x,y and z coordinates measured by the accelerometer.
  • This is the condition for accident detection, we have already discussed before that in the void loop the x,y,z coordinate values are continuously extracted and the “if” statement here compares the recent values with fixed min and max values of the coordinates.
  • If the recent values are indistinct or do not match with threshold values i.e., max value and min value, then it indicates that an accident has been detected.
  • When the accident detection condition is satisfied, the GPRS module will be activated and will call to rescue stations for aid/help and their home.
  • Here, we have programmed to give a call 5 times to the appropriate numbers in the “for” loop.
  • And the process also includes a messaging feature along with calling to rescue stations.
  • When the same accident condition is satisfied, the messaging feature will be activated and we are going to send the alerting message including the Location, Latitude, Longitude, and Google map location link by appending latitude and longitude values the to respective numbers.

Results / Working:

We have successfully completed our Accident detection project and it’s ready to test!
  • Before going to start the simulation, we need to import the hex files of Arduino code in the Proteus, to do so click on the Arduino and browse to the hex file of the code and select.
  • Now we need to add the program files for the GPS and GPRS modules.
  • Here we should note that we only need to upload the program files for the modules while we are working in simulation. In the real modules, they come up with pre-installed codes.

Now we have done all the prerequisites of simulation.

  • Let’s power the circuit and start the simulation, firstly the void setup function will run and it will initialize all the required pins and variables and will read the ideal state values of the potentiometer.
  • Now to simulate the accident case, we will change the values from the potentiometer, so when the potentiometer’s value changes and the falls in the Min and Max value range the if condition will be stratified.
  • After this GSM module will call the stored number 5 times and send the GPS location with Google maps link in that.
  • We have used some serial monitors for debug purposes, you can see the current state of the project using them.

I hope you have a good understanding of how our Accident Detection project works and that you have liked it. Although I believe we have covered almost everything, please let us know if you have any questions or suggestions in the comments section.

Thank you very much for reading this project. All the best for your projects!

Using DAC with STM32

A Digital to Analog Converter(DAC) performs the task of converting digital words of n bits into voltages whose amplitude will be proportional to the value of the code expressed by the words themselves. Since the input binary words represent a succession of finite codes, the voltage coming out of a DAC cannot be continuous over time but is made up of as many levels as the converted codes are. This means that the devices to which the analog signal produced by a DAC is sent must filter it with a low-pass characteristic (integrating action). The operating criterion of a DAC is simple: in fact, it is sufficient to have a succession of as many voltages as there are convertible codes, obtained for example by means of a weighted resistance network (i.e. the value proportional to the code implied in the binary word). The conversion consists in sending the voltage corresponding to the code applied to the input to the output of the converter.

One of the simplest and most classic DACs is the R-2R ladder, but today there are more complex objects with optimization in the signal reconstruction. Below is shown a 3bit R-2R ladder DAC.

In practice, the circuit is an inverting adder where the bits (B0, B1, ... Bn) command a switch. The output voltage in the case of the 3-bit DAC is:

Vout= -1/2*B1*Vref - (1/4)*B1*Vref- (1/8)*B1*Vref

If the 3bit string is D and Vref is equal to the logical voltage of 3.3V

Vout= (3.3*D)/2^3

The typical output characteristic is shown in the following figure.

Compared to the weighted resistor DAC, the R-2R scale DAC has the advantage of using only two resistive values. Therefore, it is more easily achievable with integrated circuit technology.

Where To Buy?
No.ComponentsDistributorLink To Buy
1STM32 NucleoAmazonBuy Now

DAC on STM32 platform

Many of the STM32 microcontrollers have on board at least one DAC (generally 12 bit) with the possibility of buffering the output signal (with internal operational amplifier OP-AMP). The use of the DAC finds various applications, for example, it can be used to reconstruct a sampled signal or to generate any waveform (sine wave, square wave, sawtooth, etc.), to generate a reference voltage (for example for a digital comparator).

The DAC peripheral can be controlled in two ways:

  • Manually
  • Using a Data Memory Access (DMA) with a trigger source (can be an internal timer or external source).

DAC in manual mode

In this modality we can drive DAC to on/off a LED, to generate a reference voltage, etc. We will use a NUCLEO STM32L053R8 board to show as configure DAC with STCube. This NUCLEO has available a DAC with only one channel (in general every DAC has one or more channels) with resolution up to 12bit with a maximum bus speed of 32 MHz and a maximum sampling rate of 4 Msps. First, let's see how to initialize the peripherals using STCube Tool:

Configuration of DAC in manual mode

DAC Initialization

  • Select DAC with following path: “Pinout & Configuration”-> Analog -> DAC. Select the Output 1 (OUT1 Configuration):
  • In Configuration->Parameter Setting select Output Buffer= Enable and Trigger = None
  • The GPIO PA4 is associated to DAC Output1. PA4 has been configurated in Analog Mode, No Pull-Up and No Pull-Down.

System Reset and Clock Control (RCC) Initialization

  • Select RCC with following path: “Pinout & Configuration”-> System Core -> RCC. “High Speed Clock” (HSE) and “Low Speed Clock” (LSE) select for both “Crystal/Ceramic Resonator”.

Now we are ready to generate the initialization code.

Diving into the initialization code

At this point, let's look at the generated code:

  • In “Private variables” we find DAC_HandleTypeDef hdac, it is an instance to C struct that need to manipulate the DAC peripheral:
typedef struct { DAC_TypeDef *Instance; /*!< Register base address */   __IO HAL_DAC_StateTypeDef State; /*!< DAC communication state */   HAL_LockTypeDefLock; /*!< DAC locking object */   DMA_HandleTypeDef *DMA_Handle1; /*!< Pointer DMA handler for channel 1 */   #if defined (DAC_CHANNEL2_SUPPORT) DMA_HandleTypeDef *DMA_Handle2; /*!< Pointer DMA handler for channel 2 */ #endif __IO uint32_t ErrorCode; /*!< DAC Error code }DAC_HandleTypeDef;
  • In “Private function prototypes” the function prototype used to initialize and configure the peripherals:
/* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_DAC_Init(void); /* USER CODE BEGIN PFP */
  • Where we find the initialization select in STCube Tool.

Driving DAC to generate a reference voltage

Now, before writing our application, let's see what functions the HAL library makes available to handle the DAC.

  • HAL_DAC_Start(DAC_HandleTypeDef* hdac, uint32_t Channel): need to enable DAC and start conversion of channel.
  • “hdac” is a pointer to DAC structure
  • “Channel” is the selected DAC channel
  • HAL_DAC_Stop(DAC_HandleTypeDef* hdac, uint32_t Channel): need to disable DAC and start the conversion of the channel.
  • “hdac” is a pointer to DAC structure
  • “Channel” is the selected DAC channel
  • HAL_DAC_SetValue(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t Alignment, uint32_t Data): is used to set in DAC channel register the value passed.
  • “hdac” is pointer to DAC structure
  • “Channel” is the selected DAC channel
  • “Alignment” needs to select the data alignment; we can select three configurations, because the DAC wants the data in three integer formats:
  • “DAC_ALIGN_8B_R” to configure 8bit right data alignment;
  • “DAC_ALIGN_12B_L” to configure 12bit left data alignment;
  • “DAC_ALIGN_12B_R” to configure 12bit left data alignment.
  • “Data” is the data loaded in the DAC register.

The voltage output will be:

Vout,DAC = (Vref*data)/2^nb

where nb is a resolution (in our case 12bit), Vref is voltage reference (in our case 2 Volt) and the passed data.

So, to set DAC output to 1 Volt data must be 2047 (in Hexadecimal 0x7FF) so we call the function this way:

HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 0x7FF);

To set the output voltage to 3.3 Volt we call function in this way:

HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 0xFFF);

 

To verify that change the value in our main we write the following code and then we check the output connecting it to the oscilloscope probe.

int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_DAC_Init(); while (1) { /* USER CODE END WHILE */ HAL_DAC_Start(&hdac, DAC_CHANNEL_1); HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 0x7FF); HAL_Delay(1000); HAL_DAC_Stop(&hdac, DAC_CHANNEL_1); HAL_Delay(1000); HAL_DAC_Start(&hdac, DAC_CHANNEL_1); HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 0x7FF); HAL_Delay(1000); HAL_DAC_Stop(&hdac, DAC_CHANNEL_1); HAL_Delay(1000); /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }

We expect the output voltage to change every second by repeating the following sequence: 1V - 0V - 2V – floating (as shown in the figure below)

The signal displayed on the oscilloscope checks the sequence we expected. In the first second the output voltage from the DAC is 1V then in the next second 0V then 2V and in the last second of the sequence, the output is floating.

Using DAC in Data Memory Access (DMA) mode with a Timer

In this modality we can drive DAC to on/off a LED, to generate a reference voltage, etc. We will use a NUCLEO STM32L053R8 board to show as configure DAC with STCube. This NUCLEO has available a DAC with only one channel (in general every DAC has one or more channels) with resolution up to 12bit with a maximum bus speed of 32 MHz and a maximum sampling rate of 4 Msps. First, let's see how to initialize the peripherals using STCube Tool:

Configuration DAC in DMA mode

  • DAC Configuration
  • Select DAC with following path: “Pinout & Configuration”-> Analog -> DAC. Select the Output 1 (OUT1 Configuration):
  • In “Parameter Settings” the Output Buffer is enabled, Timer 6 is selected as Trigger Out Event and Wave generation mode is disabled.
  • Activate DMA to handle DAC using channel 2. The direction is Memory to Peripheral. The buffer mode is “circular”, and the data length is a word.
  • Set interrupt related channel 2 of DMA

TIM 6 Configuration

  • We use TIM6 because is one of two timers used by uP to trigger the DAC output. At the moment we do not change the initial configuration, later we will see what we need.
  • TIM6 -> NVIC Setting: flag “TIM6 interrupt and DAC1/DAC2 underrun error interrupts” to activate interrupts.

Now we are ready to generate the initialization code. Before we need to learn as the waveform can be generated using DAC.

Sinewave generation

Let's see mathematically how to reconstruct a sinewave starting from a given number of samples. The greater the number of samples, the more "faithful" the reconstructed signal will be. So, the sampling step is 2pi / ns where ns is the number of samples in this way, we have to save our samples in a vector of length ns. The values ??of every single element of the vector will be given by the following equation:

S[i] = (sin(i*(2p/ns))+1)

We know that the sinusoidal signal varies between 1 and -1 so it is necessary to shift it upwards to have a positive sinewave (therefore not with a null average value) therefore it must be moved to the middle of the reference voltage. To do this, it is necessary to retouch the previous equation with the following:

S[i] = (sin(i*(2p/ns))+1)*((0xFFF+1)/2)

Where 0xFFF is the maximum digital value of DAC (12bit) when the data format is 12 bits right aligned.

To set the frequency of the signal to be generated, it is necessary to handle the frequency of the timer trigger output (freq.TimerTRGO, in our case we use the TIM6) and the number of samples.

Fsinewave = freq.TimerTRGO/ns

In our case, we define Max_Sample = 1000 ( is uint32_t variable) and let's redefine some values of the timer 6 initialization.

static void MX_TIM6_Init(void) { /* USER CODE BEGIN TIM6_Init 0 */ /* USER CODE END TIM6_Init 0 */ TIM_MasterConfigTypeDef sMasterConfig = {0}; /* USER CODE BEGIN TIM6_Init 1 */ /* USER CODE END TIM6_Init 1 */ htim6.Instance = TIM6; htim6.Init.Prescaler = 1; htim6.Init.CounterMode = TIM_COUNTERMODE_UP; htim6.Init.Period = 100; htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&htim6) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN TIM6_Init 2 */ /* USER CODE END TIM6_Init 2 */ }

We have changed the following parameters:

htim6.Init.Prescaler = 1; htim6.Init.Period = 100;

So with 1000 samples, the output sinewave will be a frequency of 10 Hz. We can change the number of samples (being careful not to use too few samples) or the “Init.Prescaler” and “Init.Period” values of timer 6.

Driving DAC in DMA mode with Timer

Using the DAC in DMA mode the HAL library makes available to handle the DAC another function to set the DAC output.

HAL_DAC_Start_DMA(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t* pData, uint32_t Length, uint32_t Alignment)

Compared to the manual function we find two more parameters:

  • uint32_t* pData is the peripheral buffer address;
  • uint32_t Length is the length of data to be transferred from the memory to DAC peripheral.

As you can see from the following code we first need to include the "math.h" library, define the value of pigreco (pi 3.14155926), and write a function to save the sampled sinewave values in a array (we wrote a function declared as get_sineval () ).

#include "math.h" #define pi 3.14155926 DAC_HandleTypeDef hdac; DMA_HandleTypeDef hdma_dac_ch1; TIM_HandleTypeDef htim6; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_DMA_Init(void); static void MX_DAC_Init(void); static void MX_TIM6_Init(void); uint32_t MAX_SAMPLES =1000; uint32_t sine_val[1000]; void get_sineval() { for (int i =0; i< MAX_SAMPLES; i++) { sine_val[i] = ((sin(i*2*pi/MAX_SAMPLES)+1))*4096/2; } } /* USER CODE END 0 */
  • Once this is done, we can start the DAC by saving the sampled values of the sinewave in the buffer (* pdata) as shown below:
int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_DMA_Init(); MX_DAC_Init(); MX_TIM6_Init(); /* USER CODE BEGIN 2 */ get_sineval(); HAL_TIM_Base_Start(&htim6); HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, sine_val, MAX_SAMPLES, DAC_ALIGN_12B_R); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }

Now we just have to show the acquisition that the oscilloscope:

If we change the number of MAX_SAMPLE to 100 the sinewave will be a frequency of 100 Hz, but as can be seen from the acquisition, the number of samples, in this case, is a bit low.

We can optimize the waveform by acting on timer 6 in order to increase the number of samples. For example by modifying htim6.Init.Period = 400

So, that was all for today. I hope you have enjoyed today's lecture. Let me know if you have any questions. Thanks for reading. Take care !!! :)

How the Use of IoT Has Made Life a Lot Easier for Medical Professionals

IoT – the Internet of Things – has revolutionized the way we use and perceive technology over the last couple of decades. From introducing the world to smart homes and cars to envisioning a more efficient office and work environment, IoT has done it all.

We have integrated IoT in our industrial, tech, and agricultural sectors, as well as our personal lives. However, one of the most fascinating ways IoT has influenced our current society is through its contribution to the health and medical sector.

The healthcare sector managed to get the most out of the Internet of Things technology. Utilizing modern sensors to keep a close eye on their patients’ conditions, these IoT systems are making life easier for medical professionals. And while IoT systems cannot run entire healthcare facilities by themselves, they make life easier for doctors in other ways and provide benefits to patients too. Here is how.

Urgent Care and Walk-In Clinic Services

IoT sensors, especially those that can measure temperature, pulse and heartbeat, breathing rate, etc. are being deployed in medical facilities all over the world right now. Due to COVID-19, urgent care and walk-in clinic services have gained a lot of popularity.

However, for their safety, healthcare professions maintain a considerable distance from patients at times. So whenever possible, the tests are carried out from a distance, and IoT can help in this regard.

Take the MLX90614 IR temperature sensor used in temperature guns. It can take the reading, then send the doctor the results via an IoT network within the healthcare facility. The doctor can then carry out more tests in an unmanned manner (wherever possible), and then write the prescription. All they have to do is note down the readings, explain the situation, and hit their custom signature stamp on the paper.

Thus, during such times of crisis, a doctor only needs to carry a self-inking signature stamp to work. Hitting their custom signature stamps on the prescriptions, mostly containing their qualifications and name, are all that they have to do manually right now. This is, by no means, is demeaning to their work or responsibility. It just goes to show how IoT is making their life a lot easier, and safer.

Remote Health Monitoring And Long Distance Check-Up

In a lot of cases, doctors need not be present at the clinic or hospital to write their patients a prescription or update them about their medical condition. They can do so within the comfort of their homes as well.

Take the AMD-DS-AS0028-1 fingertip sensor as an example here. Pulse oximeters, which are being used all over the world right now to check for dropping oxygen levels in the human body, use these sensors to measure SpO2 levels.

Normally, the measurements are then displayed on a screen on the device or a separate monitor. However, with a proper network connection, this system can be IoT-enabled. That will allow the doctor to receive the pulse oximeter reading at his home, from where they can then advise the patient on what to do next.

A similar case can be carried out for long-distance check-ups. Once the medical devices, like the oximeter or blood pressure machine, get the readings, they can then deliver those numbers to the doctor, who might be living a few hundred miles away. Based on the findings of these devices, the doctor will prescribe a course of action for the patient.

For this system to go fully remote, a high-definition camera is also preferred, because the way a patient looks is also crucial in treatment these days. Thus, a quick look at them can reveal a lot of vital information about their health.

Machine Learning and AI-Driven Treatment Suggestions

Walk-in and remote health services are just two of the areas that IoT contributes to in the healthcare sector. One of the more vital roles it plays is that it can navigate medical professions in the right direction during a difficult treatment procedure. Of course, IoT does not do this by itself. It utilizes machine learning and artificial intelligence for better results.

Take the latest COVID trends as examples. New strains are popping up every once in a while, and it is getting difficult to keep track of them all. So virologists are gathering samples via unmanned drones or bots and then testing them at labs. The results are then run through various ML algorithms to determine the strain’s origin.

A similar approach is being used to predict the next coronavirus. The AI used here can classify the animals based on their chances of forming a new coronavirus.

And as we continue to explore more aspects of IoT, we will keep coming up with newer innovations that can benefit the healthcare sector, as well as other fields.

ESP32 Low Power Modes

Hello readers, hope you all are doing great. In this tutorial, we will discuss low power modes in ESP32, their purpose and their implementation to increase the battery life by reducing power consumption.

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

Purpose of Low Power Modes

Fig.1

Along with multiple wireless and processing features, ESP32 also provides us with a power-saving feature by offering sleep modes. When you are powering the ESP32 module from the live supply using an adaptor or a USB cable, there is nothing to worry about power consumption. But when you are using a battery, as a power source to ESP32, you need to manage the power consumption for longer battery life.

Low Power Modes in ESP32

When ESP32 is in sleep mode, a small amount of power is required to maintain the state of ESP32 in RAM (random access memory) and retain necessary data. Meanwhile, the power supply won’t be consumed by any unnecessary peripheral or inbuilt modules like Wi-Fi and Bluetooth.

ESP32 offers 5 power modes. Each mode is configurable and offers different power-saving capabilities:

  1. Active Mode
  2. Modem Sleep Mode
  3. Light Sleep Mode
  4. Deep Sleep Mode
  5. Hibernation Mode

Fig. 2

Active Mode:

  • In active mode, all the modules and features of ESP32, like processing cores, Wi-Fi, Bluetooth, radio etc. remain active all the time.
  • Most of the power consumption occurs in this power mode which can vary between 160 -240mA and sometimes the maximum consumption could reach up to 790mA (when both Wi-Fi and Bluetooth are enabled or active at the same time).

Modem Sleep Mode:

  • In this mode, radio, Wi-Fi, Bluetooth will be disabled and everything else will remain active. Power consumption in this mode varies from 3 to 20mA.
  • Sleep modes can switch between modem and active modes as per the predefined intervals, by following the associated sleep pattern.

Light Sleep Mode:

  • During this mode, the central processing unit is paused by turning/powering off its clock.
  • ULP- coprocessor and RTC (real-time clock) remain active during light sleep mode and power consumption is 0.8mA.

Deep Sleep mode:

  • In this mode, the Ultra Low Power (ULP) coprocessor remains active while the ESP32 core and other digital peripherals remain inactive.
  • The ULP coprocessor wakes up the core processor when required.
  • The amount of power consumed in this mode is 10uA.

Fig 3

Hibernation Mode:

    • In this mode, the ULP coprocessor and internal oscillator both are disabled.
  • Only a real-time clock (RTC) remains active to wake up the processor and other required modules from hibernation mode and the power consumption in this mode is extremely low that is approximately 2.5uA.

For a better understanding of low power modes in ESP32, we are going to implement deep sleep mode in esp32 and will also discuss how to wake up the device from deep sleep mode.

Deep Sleep mode and Wakeup Using Capacitive Touch-sensitive pins

To implement deep sleep modes we are going to use another ESP32 feature that is Capacitive Touch Sensing pins. These pins can sense the presence of a body that holds an electric charge.

So we are going to use these touch-sensitive pins for waking up ESP32 from deep sleep mode using the Arduino IDE compiler.

In Arduino IDE examples are given for deep sleep mode with various wake-up methods.

  • Follow the image attached below to open the example code:

Fig. 4 Example code.

  • Arduino IDE Code

#define Threshold 40 /* Greater the value, more the sensitivity */ RTC_DATA_ATTR int bootCount = 0; touch_pad_t touchPin; /* Method to print the reason by which ESP32 has been awaken from sleep */ void print_wakeup_reason(){ esp_sleep_wakeup_cause_t wakeup_reason;   wakeup_reason = esp_sleep_get_wakeup_cause();   switch(wakeup_reason) { case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break; case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break; case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break; case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break; case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break; default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break; } }   /* Method to print the touchpad by which ESP32 has been awaken from sleep */ void print_wakeup_touchpad(){ touchPin = esp_sleep_get_touchpad_wakeup_status();   switch(touchPin) { case 0 : Serial.println("Touch detected on GPIO 4"); break; case 1 : Serial.println("Touch detected on GPIO 0"); break; case 2 : Serial.println("Touch detected on GPIO 2"); break; case 3 : Serial.println("Touch detected on GPIO 15"); break; case 4 : Serial.println("Touch detected on GPIO 13"); break; case 5 : Serial.println("Touch detected on GPIO 12"); break; case 6 : Serial.println("Touch detected on GPIO 14"); break; case 7 : Serial.println("Touch detected on GPIO 27"); break; case 8 : Serial.println("Touch detected on GPIO 33"); break; case 9 : Serial.println("Touch detected on GPIO 32"); break; default : Serial.println("Wakeup not by touchpad"); break; } }   void callback(){ //placeholder callback function }   void setup(){ Serial.begin(115200); delay(1000); //Take some time to open up the Serial Monitor   //Increment boot number and print it every reboot ++bootCount; Serial.println("Boot number: " + String(bootCount));   //Print the wakeup reason for ESP32 and touchpad too print_wakeup_reason(); print_wakeup_touchpad();   //Setup interrupt on Touch Pad 3 (GPIO15) touchAttachInterrupt(T3, callback, Threshold);   //Configure Touchpad as wakeup source esp_sleep_enable_touchpad_wakeup();   //Go to sleep now Serial.println("Going to sleep now"); esp_deep_sleep_start(); Serial.println("This will never be printed"); }   void loop(){ //This will never be reached }

Code Description

  • The first step is to set the threshold value for touch-sensitive pins.
  • When a body, containing an electric charge touches a touch-sensitive pin, the threshold value decreases below 40, that decrease in the threshold value will make ESP32 wake up from deep sleep mode. In the example code threshold value is 40.
  • The next task is to store the data into RTC memory (using RTC_DATA_ATTR ) because in deep sleep mode only RTC remains active and all other peripherals, processors, wireless modules will be disabled.
  • ESP32 offers 8kB SRAM on RTC to store the data.
  • But when you press EN/reset button the data stored in RTC memory will also be erased.
  • bootCount an integer type variable is used to count the number of times ESP32 has woken up during sleep mode. The value of bootCount variable is stored in RTC memory.
  • The print_wakeup_reason() function is used to print the reason for ESP32 wakeup from deep sleep whether it is due to an external interrupt, timer, or touch-sensitive pins.
  • The ESP32 has multiple capacitive touch-sensitive GPIO pins which can be used to wake up esp32 from deep sleep mode.
  • Print_wakeup_touchpad() function is used to print the GPIO pin which made ESP32 wake up from sleep mode.
  • When you hold a capacitive sensitive pin for a longer duration the threshold value (initialized globally) decreases from its predefines value i.e., 40 which will cause ESP32 to wake up, at that time the callback() function comes into action.
  • This function will be used as an argument inside the touchAttachInterrupt() function.

Setup()

  • Inside the setup() function the first task is to start the serial monitor with a baud rate of 115200.
  • Next, if there is any increment in boot count due to wake up calls, then print that count on the serial monitor.

Call the respective functions to print the wake-up reason:
  • Print_wakeup_reason() is used to print whether the ESP32 wake-up is caused by an external interrupt, timer or a capacitive sensitive pin.
  • If the wake up is due to a capacitive sensitive pin then the print_wakeup_touchpad() function will print the GPIO pin number which caused the wake-up.
  • The next task is to attach the interrupt using touchAttachInterrupt() function, to capacitive sensitive GPIO pin which you will use to wake up ESP32.
  • In this example we are using GPIO 15 capacitive sensitive pin as a wakeup interrupt pin.
  • esp_sleep_enable_touchpad_wakeup() is used to enable touch sensor feature.
  • esp_deep_sleep_start() function is used to make ESP32 enter to deep sleep mode.
  • Once ESP32 enters the sleep mode no other operation or data communication is possible until it receives a wakeup call.

Fig 12

Loop()

  • In this example code, there is nothing, written inside the loop function. But you can change the code as per your requirements.

Code Testing

  • To test the code, use a connecting wire (male to female) and connect one side to ESP32’s touch-sensitive pin (which you have mentioned in the code as an interrupt).
  • When you touch that pin an interrupt will be generated to wake ESP32 from sleep.
  • You can see the results on a serial monitor or can check the current consumption or can run other functions once it is awake like blinking LED.
  • In this code, we are using GPIO_15 touch-sensitive pin.

Fig. 13 waking up esp32 using capacitive sensitive GPIO pin

We have attached a screenshot from the serial monitor for reference.

Fig. 14

Deep Sleep mode and Wakeup Using Interrupt method

Arduino IDE Code

#define uS_TO_S_FACTOR 1000000ULL /* Conversion factor for micro seconds to seconds */ #define TIME_TO_SLEEP 5 /* Time ESP32 will go to sleep (in seconds) */ RTC_DATA_ATTR int bootCount = 0; /* Method to print the reason by which ESP32 has been awaken from sleep */ void print_wakeup_reason(){ esp_sleep_wakeup_cause_t wakeup_reason; wakeup_reason = esp_sleep_get_wakeup_cause(); switch(wakeup_reason) { case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break; case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break; case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break; case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break; case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break; default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break; } }   void setup(){ Serial.begin(115200); delay(1000); //Take some time to open up the Serial Monitor   //Increment boot number and print it every reboot ++bootCount; Serial.println("Boot number: " + String(bootCount));   //Print the wakeup reason for ESP32 print_wakeup_reason();   /* First we configure the wake up source We set our ESP32 to wake up every 5 seconds */ esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR); Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) + " Seconds");   /* Next we decide what all peripherals to shut down/keep on By default, ESP32 will automatically power down the peripherals not needed by the wakeup source, but if you want to be a poweruser this is for you. Read in detail at the API docs http://esp-idf.readthedocs.io/en/latest/api-reference/system/deep_sleep.html Left the line commented as an example of how to configure peripherals. The line below turns off all RTC peripherals in deep sleep. */ //esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF); //Serial.println("Configured all RTC Peripherals to be powered down in sleep");   /* Now that we have setup a wake cause and if needed setup the peripherals state in deep sleep, we can now start going to deep sleep. In the case that no wake up sources were provided but deep sleep was started, it will sleep forever unless hardware reset occurs. */ Serial.println("Going to sleep now"); Serial.flush(); esp_deep_sleep_start(); Serial.println("This will never be printed"); }   void loop(){ //This is not going to be called }

Code Description

  • The first task is, to define the timer period for which ESP32 will be in deep sleep mode.
  • As we know that ESP32 operates at the MHz frequency range so the timer will be in microseconds. So, it is required to convert the time into seconds.
  • To add a timer of 5sec we need to multiply 5*1000000.
  • bootCount an integer type variable is used to count the number of times ESP32 has woken up during sleep mode. The value of bootCount variable is stored in RTC memory.

Fig 15

  • The print_wakeup_reason() function is used to print the reason for ESP32 wakeup from deep sleep whether it is due to an external interrupt, timer or touch-sensitive pins.

Fig. 16

Setup()

  • As discussed earlier, inside the setup function first we need to initialize the serial monitor at 115200 baud rate and then print the value of bootCount variable which is incrementing every time a wakeup interrupt occurs.

Fig. 17

  • The esp_sleep_enable_wakeup() function is used to enable the timer to generate a timer interrupt by passing time in microsecond as an argument.
  • In the beginning of code we have defined some global variable to add 5 sec timer (or 5000000us) and after every 5 sec ESP32 should wake up from deep sleep till 5 sec.

Fig. 18

  • esp_deep_sleep_start() function is used to make ESP32 enter the deep sleep mode.

Fig. 19

Testing

  • You can see the results of above code on serial monitor as shown is the image attached below.

Fig 20

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

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