← Back to Hub

Student Portal

AI & IoT Training Camp | Resource Center & Interactive Guides

📥 Required Software & Downloads

Before starting the training, ensure you have downloaded and installed the following tools based on your operating system.

Arduino IDE

The core software for writing C++ code to the ESP32 boards.

USB Drivers (CH340 & CP210x)

Essential drivers so your computer can recognize the ESP32 board.

Blynk IoT App

The IoT cloud app for your phone. Required for remote control and monitoring of your ESP32 projects.

🛠️ Initial Arduino IDE Setup

Configure Arduino IDE to communicate with ESP IoT boards.

  1. Open Arduino IDE. Go to File → Preferences.
  2. In the Additional Board Manager URLs field, paste this configuration URL:
https://dl.espressif.com/dl/package_esp32_index.json
  1. Go to Tools → Board → Boards Manager. Search for esp32 and click Install.
  2. Go to Sketch → Include Library → Manage Libraries. Search for Blynk and install "Blynk by Volodymyr Shymanskyy".
  3. Plug your board in. Select ESP32 Dev Module from Tools → Board. Then select the correct COM Port.

☁️ Day 3: ESP32 & Blynk IoT Cloud

Session 3.1: Wi-Fi Provisioning & Cloud Connection

Before coding, we must create a virtual bridge (Template) on Blynk to communicate with our ESP board.

Blynk Cloud Setup:
  1. Go to blynk.cloud and log in. Navigate to Templates.
  2. Click + New Template. Name it "SmartGreenhouse", select ESP32, and choose WiFi as the connection type.
  3. Click on Devices → + New Device → From Template. Select your "SmartGreenhouse" template and name your device (e.g., "Group-1-ESP").
  4. In the device info page, copy the BLYNK_TEMPLATE_ID, BLYNK_TEMPLATE_NAME, and BLYNK_AUTH_TOKEN into the code below.
🤖 AI Generation Prompt:

"Write a C++ code for an ESP32 using the BlynkSimpleEsp32 library to connect to Wi-Fi. It should define BLYNK_TEMPLATE_ID, BLYNK_TEMPLATE_NAME, and BLYNK_AUTH_TOKEN at the top. Setup should include Serial.begin(115200) and Blynk.begin(). The void loop should just run Blynk.run()."

💻 Base Connectivity Code
#define BLYNK_TEMPLATE_ID "TMPLxxxxxx"
#define BLYNK_TEMPLATE_NAME "Device"
#define BLYNK_AUTH_TOKEN "YourAuthToken"

#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>

char ssid[] = "NetworkName";
char pass[] = "Password";

void setup() {
  Serial.begin(115200);
  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
}

void loop() {
  Blynk.run();
}

Change your Wi-Fi credentials in ssid and pass, then upload. Open the Serial Monitor (115200 baud) and you should see "Ready (ping: ...)".

Session 3.2: Level 1 Remote Control (Relays & Pumps)

Now we will control a physical 5V Relay (GPIO 5) using a Virtual Pin (V0) triggered from your phone.

⚠️ Power Warning

Never power motors or relays directly from the ESP's 3.3V pin. Output pins must receive power from the VIN (5V) pin to avoid burning out the microcontroller.

ComponentPinESP32 PinNotes
5V Relay ModuleVCCVIN (5V)Requires 5V external power
5V Relay ModuleGNDGND-
5V Relay ModuleIN (Signal)GPIO 5digitalWrite(5, HIGH)
🤖 AI Generation Prompt:

"Extend the previous ESP32 Blynk code. Add a BLYNK_WRITE function for Virtual Pin V0. When V0 receives a '1' from the mobile app, it should turn a 5V Relay connected to GPIO 5 ON (digitalWrite HIGH). When it receives '0', turn it OFF. Remember to set pinMode to OUTPUT in setup()."

💻 BLYNK_WRITE Code for Motor Control
#define BLYNK_TEMPLATE_ID "TMPLxxxxxx"
#define BLYNK_TEMPLATE_NAME "Device"
#define BLYNK_AUTH_TOKEN "YourAuthToken"

#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>

char ssid[] = "NetworkName";
char pass[] = "Password";

#define RELAY_PIN 5 // GPIO 5 on ESP32

// This function triggers instantly when the V0 switch on your phone is pressed
BLYNK_WRITE(V0) {
  int buttonState = param.asInt(); // Get value from phone (0 or 1)
  
  if (buttonState == 1) {
    digitalWrite(RELAY_PIN, HIGH); // Turn Relay ON
  } else {
    digitalWrite(RELAY_PIN, LOW);  // Turn Relay OFF
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW); // Safe default state: OFF
  
  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
}

void loop() {
  Blynk.run();
}
  • Go to Templates → Datastreams in Blynk Web. Create a new Virtual Pin (V0). Set type to Integer (0-1).
  • Go to Web Dashboard, drag a Switch widget, and assign it to Datastream V0.
  • Now you can turn the water pump on and off from anywhere in the world!

Session 3.3: Level 2 Analog Data & Visualization (BlynkTimer)

Now we'll read Soil Moisture or Gas Sensor data and visualize it on a Gauge widget on the app. We MUST use BlynkTimer instead of delay() to prevent our device from disconnecting from the cloud.

ComponentPinESP32 PinNotes
Soil Moisture SensorVCC3.3V
Soil Moisture SensorGNDGND
Soil Moisture SensorAnalog OutGPIO 34 (ADC1)12-bit: 0–4095
🤖 AI Generation Prompt:

"I am using an ESP32 with BlynkSimpleEsp32. I want to read an analog soil moisture sensor connected to GPIO 34. Since I cannot use delay(), write a code using BlynkTimer that reads the analog sensor every 2 seconds using a custom function, and sends that value to Virtual Pin V1 using Blynk.virtualWrite. Include all necessary SSID, Wifi, and Blynk setup."

💻 Code: Sending Sensor Data to Cloud
#define BLYNK_TEMPLATE_ID "TMPLxxxxxx"
#define BLYNK_TEMPLATE_NAME "Device"
#define BLYNK_AUTH_TOKEN "YourAuthToken"

#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>

char ssid[] = "NetworkName";
char pass[] = "Password";

#define SENSOR_PIN 34 // GPIO 34 (ADC) 
BlynkTimer timer;

void sendSoilData() {
  int moistureLevel = analogRead(SENSOR_PIN); // Read 0-4095
  Blynk.virtualWrite(V1, moistureLevel);      // Send to V1 Channel
}

void setup() {
  Serial.begin(115200);
  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
  
  // Timer runs the function every 2000 milliseconds (2 seconds)
  // NEVER use delay(2000) inside loop(), it will disconnect Blynk!
  timer.setInterval(2000L, sendSoilData);
}

void loop() {
  Blynk.run();
  timer.run(); // Keeps the timer ticking
}
  • Go to Templates → Datastreams. Create a Virtual Pin (V1) named "Soil Moisture", type Integer, Min/Max 0-4095 .
  • On the Web Dashboard, drag a Gauge widget and assign it to V1. Put the sensor in dry and wet soil to see the needle move live!

Session 3.4: Level 3 Sensors & Push Notifications

Read from DHT11 (Temp/Humidity) and Flame sensors. Create logic (If/Else) to trigger a physical Buzzer and send a Push Notification to your phone in case of fire or extreme heat.

ComponentPinESP PinNotes
DHT11 Temp ModuleDATAGPIO 4Code: #define DHTPIN 4
Flame SensorDOGPIO 14Returns LOW when flame detected
Active Buzzer+ (Long Leg)GPIO 12Code: #define BUZZER_PIN 12Note: GPIO 12 is a bootstrap pin. Starts LOW so no boot issues; GPIO 13 is a safe alternative.
Sensors/BuzzerVCC/GND3.3V/GNDProvide common grounding
🤖 AI Generation Prompt:

"Can you create an ESP32 Blynk code that acts as a fire alarm? It should use a DHT11 sensor on GPIO 4 to read temperature and a Flame sensor on GPIO 14 (returns LOW on fire). Use a BlynkTimer running every 2 seconds. In the timer function, if temperature > 35.0 OR flame is LOW, turn ON a buzzer on GPIO 12 and push a notification using Blynk.logEvent('fire_alert', 'Fire!'). Send the temperature to Virtual Pin V2. Include the full Blynk C++ setup."

💻 Code: Conditional Logic & Push Alerts
#define BLYNK_TEMPLATE_ID "TMPLxxxxxx"
#define BLYNK_TEMPLATE_NAME "Device"
#define BLYNK_AUTH_TOKEN "YourAuthToken"

#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <DHT.h>

char ssid[] = "NetworkName";
char pass[] = "Password";

#define DHTPIN 4      // GPIO 4
#define DHTTYPE DHT11
#define FLAME_PIN 14  // GPIO 14 (Digital Input)
#define BUZZER_PIN 12 // GPIO 12 (Digital Output)

DHT dht(DHTPIN, DHTTYPE);
BlynkTimer timer;

void sensorAlgorithm() {
  float temp = dht.readTemperature();
  int flameStatus = digitalRead(FLAME_PIN); // LOW means FIRE
  
  Blynk.virtualWrite(V2, temp); // Send Temp to V2 channel on dashboard
  
  // If temp > 35 OR flame is detected:
  if (temp > 35.0 || flameStatus == LOW) { 
    digitalWrite(BUZZER_PIN, HIGH); // Sound Alarm!
    Blynk.logEvent("fire_alert", "Warning! Fire or Extreme Heat!"); // Phone Notification
  } else {
    digitalWrite(BUZZER_PIN, LOW); // Safe
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(FLAME_PIN, INPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  dht.begin();
  
  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
  timer.setInterval(2000L, sensorAlgorithm);
}

void loop() {
  Blynk.run(); 
  timer.run();
}
  • Create a V2 Datastream (Double, 0-60 Min/Max) for Temperature and show it on a Labeled Value widget.
  • Go to Templates → Events. Create a new event. Name: Fire Alert, Event Code: fire_alert, Type: Warning. Enable Push notifications.
  • Rate Limit: Blynk Free plan allows max 100 events/day. Each Blynk.logEvent() call consumes 1 event. Our 2-second timer means the alarm fires repeatedly — in production you should add a cooldown flag.

🌿 Day 4: Autonomous IoT Systems

Session 4.1 & 4.2: Smart Greenhouse & Autonomous Logic

Combine DHT11, Soil Moisture, LDR, Relay, and Pump into one system. We will code an "Auto/Manual" state machine. If on Auto, the ESP decides when to water the plant based on soil readings. If Manual, you control it from the phone. All data is logged in a SuperChart.

ComponentPinESP32 PinNotes
DHT11 DataDATAGPIO 4Temp + Humidity
Soil MoistureAnalog OutGPIO 34Analog Reading
5V RelayINGPIO 5Pump trigger
5V Relay PowerVCCVIN (5V)NEVER power from 3.3V
🤖 AI Generation Prompt:

"Write an advanced ESP32 Blynk code for an autonomous greenhouse. It must use a 5V relay (Pump/GPIO 5) and an analog soil moisture sensor (GPIO 34). Implement an Auto/Manual state machine using Blynk Virtual Pin V2 as a mode switch. When V2=1 (Auto Mode), check soil every 3 seconds using BlynkTimer; if moisture < 1500, turn pump ON, else OFF. When V2=0 (Manual Mode), the pump is only controlled by a button on Virtual Pin V0. Send soil moisture to Virtual Pin V1."

💻 Code: Auto/Manual Decision Tree
#define BLYNK_TEMPLATE_ID "TMPLxxxxxx"
#define BLYNK_TEMPLATE_NAME "Device"
#define BLYNK_AUTH_TOKEN "YourAuthToken"

#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>

char ssid[] = "NetworkName";
char pass[] = "Password";

#define PUMP_PIN 5 // GPIO 5
BlynkTimer timer;

int modeStatus = 0; // 0=Manual, 1=Auto
int dryThreshold = 1500;

// V2 Switch (Auto/Manual Mode Selector)
BLYNK_WRITE(V2) {
  modeStatus = param.asInt();
}

// V0 Manual Watering Button
BLYNK_WRITE(V0) {
  if (modeStatus == 0) { // ONLY works in Manual mode
    digitalWrite(PUMP_PIN, param.asInt());
  }
}

void autoGreenhouseLogic() {
  int soilMoisture = analogRead(34);
  Blynk.virtualWrite(V1, soilMoisture); // Send data to SuperChart on V1
  
  if (modeStatus == 1) { // If system is in AUTO mode, let the code decide
    if (soilMoisture < dryThreshold) {
      digitalWrite(PUMP_PIN, HIGH); // Soil is dry: Turn pump ON
    } else {
      digitalWrite(PUMP_PIN, LOW);  // Soil is wet: Turn pump OFF
    }
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(PUMP_PIN, OUTPUT);
  digitalWrite(PUMP_PIN, LOW);
  
  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
  timer.setInterval(3000L, autoGreenhouseLogic);
}

void loop() {
  Blynk.run(); 
  timer.run();
}
  • Create a V2 Datastream (Integer, 0-1) named "Mode Selector". Put a Switch widget on it. (On = AUTO, Off = MANUAL).
  • Add a SuperChart widget and add Datastreams V1, V3, V4 into it to log history.

Session 4.3: Edge Cases - The Connection Watchdog

What happens if your WiFi router dies while the relay is ON? The pump will run forever and flood your greenhouse. We must build fail-safes.

🤖 AI Generation Prompt:

"Add a fail-safe 'connection watchdog' function to my ESP32 Blynk code. Create a BlynkTimer running every 10 seconds. If Blynk.connected() is false (WiFi routing failed), immediately turn the water pump (GPIO 5) OFF so it doesn't flood the greenhouse while offline, then attempt Blynk.connect()."

💻 Code: Fail-Safe Logic
void connectionWatchdog() {
  if(!Blynk.connected()){
    // CRITICAL: WiFi dropped, cannot receive commands from phone.
    // Turn off dangerous hardware (pumps, heaters) to prevent disasters.
    digitalWrite(PUMP_PIN, LOW);
    
    Serial.println("Connection lost, motors stopped! Reconnecting...");
    Blynk.connect(); 
  }
}

// Inside your main setup():
void setup() {
  // ... other setups ...
  timer.setInterval(10000L, connectionWatchdog);
}