Guides · 17 min read

Blynk ESP32 Tutorial: Control LEDs, Relays and Sensors by Phone

Blynk ESP32 tutorial: create a template and datastreams (V0, V1), get the auth token, control an LED and relay, chart sensor data, send alerts, use BlynkTimer.

Blynk and the ESP32 are the fastest way to control a board from anywhere in the world without writing your own phone app. Blynk IoT gives you a cloud server the ESP32 connects to (Blynk.Cloud), a mobile app where you build a dashboard by drag and drop, and a web dashboard. When you tap a switch on your phone, the command goes to the cloud first and from there to the ESP32; the temperature the ESP32 measures travels back the same way and shows up on your phone as a number and a chart. Your phone and the board don't have to be in the same house: it even works when your phone is on mobile data.

In this guide you'll build a working project from scratch: you'll open a Blynk.Cloud account, define a template and datastreams (V0, V1, V2, V3), get the device's auth token, install the library, control an LED and a relay from your phone, chart DHT11 sensor data and get a notification on your phone when the temperature rises. You'll also learn why you shouldn't use delay() and what BlynkTimer does instead, how to work out the free plan's message limit, why code left over from the old Blynk doesn't compile, and how to fix the most common connection errors.

ESP32 development board controlled from a phone with Blynk IoT
Thanks to its built-in Wi-Fi, the ESP32 connects straight to Blynk.Cloud; it doesn't need any extra wireless module.

What is Blynk IoT and how does it work?

With Blynk, the ESP32 and your phone never connect to each other directly; both connect to Blynk.Cloud and the server carries the messages. When the ESP32 starts, it joins Wi-Fi, then connects to the Blynk server and identifies itself with its auth token. Data flows through virtual pins (V0–V255): a virtual pin is not a real leg of the ESP32 but a numbered data channel between your code and the app. The switch in the app writes 1 to V1, the BLYNK_WRITE(V1) function in your code catches it and energizes the relay; when your code runs Blynk.virtualWrite(V2, 24.5), the gauge on your phone updates. These are the building blocks:

ConceptWhat it doesExample in this guide
TemplateThe shared recipe for devices of the same kind: datastreams, dashboards and eventsESP32 Home
DatastreamA data channel tied to a virtual pin, with a fixed type and rangeV2: Temperature, Double, 0–50 °C
DeviceA real board created from the template; each one has its own dataThe ESP32 in the living room
Auth tokenThe device's secret identity key; your code uses it to connect to the cloudThe BLYNK_AUTH_TOKEN line
WidgetDashboard elements such as switches, gauges and chartsButton, Gauge, SuperChart
EventAn alert that sends notifications and is logged on the timelineyuksek_sicaklik

Differences between the old Blynk and the new Blynk IoT

Most Blynk videos and sketches on the internet were made for the old version (Blynk Legacy), which no longer works. The new platform launched in May 2021; the old app was pulled from the stores in June 2022 and the old cloud servers were shut down for good on December 31, 2022. So a token from an old project, energy points you once bought, or the blynk-cloud.com address are useless today; you need to rebuild the project on the new platform. The good news: most of the ESP32 code (BLYNK_WRITE, virtualWrite, BlynkTimer) stayed the same.

FeatureOld Blynk (Legacy)Blynk IoT (new)
Where is the project set up?Everything in a project inside the phone appTemplates and datastreams in Blynk.Console (web), dashboards on phone and web
Auth tokenOne per project, sent by emailOne per device, shown on the device page
Pricing modelWidgets were bought with energy pointsMonthly plans with device, message and feature limits
Top of the sketchJust a char auth[] lineBLYNK_TEMPLATE_ID, BLYNK_TEMPLATE_NAME and BLYNK_AUTH_TOKEN are required
NotificationsBlynk.notify() and Blynk.email()An event is defined in the template and triggered with Blynk.logEvent()
Serverblynk-cloud.com, port 80 or 8080 (shut down)blynk.cloud, port 80 or 443 with SSL
Web dashboardNoneYes (Blynk.Console)
Local serverAn open-source Java server could be self-hostedNo personal local server; the old server is no longer updated
When you compile an old example with the new library, you'll hit three typical problems: sketches that use BLYNK_DEVICE_NAME fail with "Please specify your BLYNK_TEMPLATE_ID and BLYNK_TEMPLATE_NAME", sketches containing Blynk.notify() stop with "'class BlynkWifi' has no member named 'notify'", and sketches that name blynk-cloud.com (usually with port 8080) in Blynk.begin() may compile but will never connect.

Parts list and wiring

For this project you'll use an ESP32 development board, a 5 V relay module, a DHT11 temperature and humidity sensor, an optional LED with a 220 Ω resistor, a breadboard and jumper wires. For the LED, the board's built-in blue LED on GPIO 2 is enough; if you add an external LED, you can find the resistor value with the LED resistor calculator. Check your board's pin layout in the Pinout tool too; on some boards the 5 V pin is labeled VIN, on others 5V.

ESP32
ESP32
Röle modülü
Röle modülü
DHT11
DHT11
LED
LED
Breadboard
Breadboard
Jumper kablo
Jumper kablo
PartPart pinESP32 pinNote
LED (optional)Long leg (+)GPIO 2Through a 220 Ω resistor; short leg to GND
Relay moduleVCCVIN / 5VAbout 5 V is present on this pin when powered over USB
Relay moduleGNDGNDCommon ground
Relay moduleINGPIO 26For an active-LOW module set ROLE_AKTIF_LOW = true in the code
DHT11VCC3V3Works from 3.3–5.5 V
DHT11DATAGPIO 4A bare sensor needs a 10 kΩ pull-up; modules have it on board
DHT11GNDGNDCommon ground
The ESP32's pins output 3.3 V. Most 5 V relay modules switch with this signal, but on an active-LOW module a 3.3 V HIGH may not always release the relay fully; if the relay never turns off, use a 3.3 V trigger module or an NPN transistor in between. If you switch a 230 V mains load with the relay, always wire it with the plug pulled, leave no exposed conductors and get help from an adult; details in What Is a Relay Module?

Step 1: Create a Blynk.Cloud account and a template

  1. On your computer go to blynk.cloud, sign up for a free account with your email address and set your password using the link in the email you receive.
  2. In the left menu go to Developer Zone > My Templates and click + New Template.
  3. Give the template a name (for example ESP32 Home), choose ESP32 as the hardware and WiFi as the connection type, and create the template.
  4. The BLYNK_TEMPLATE_ID and BLYNK_TEMPLATE_NAME values shown on the template page will go into your code; for now just note where they are.
  5. If a Quickstart wizard pops up when you sign up, you can skip it; in this guide we'll do every step by hand so you see what each setting is for.

Step 2: Define the datastreams (V0, V1, V2, V3)

A datastream is a virtual pin's ID card: it sets which pin it is, the data type (Integer for whole numbers, Double for decimals, String for text), the minimum and maximum value, the unit and how many decimals are shown. Open the template in edit mode, go to the Datastreams tab, choose + New Datastream > Virtual Pin and create these four channels:

Virtual pinNameData typeMin – MaxUnit and decimalsWidget
V0LEDInteger0 – 1NoneButton / Switch
V1RelayInteger0 – 1NoneButton / Switch
V2TemperatureDouble0 – 50°C, #.#Gauge, SuperChart
V3HumidityDouble0 – 100%, #Gauge, SuperChart
The Min and Max fields aren't decoration: Blynk clamps out-of-range values to the limit. If you leave the temperature datastream's Max at 1, you'll see 1 on the dashboard even when the sensor reads 24.5 °C. If you want switches to return to their last state when the board restarts, use Blynk.syncVirtual() inside BLYNK_CONNECTED() in your code; alternatively, turn on Sync with latest server value in the datastream's advanced settings and call Blynk.syncAll(). Don't forget to click Save on the template after every change.

Step 3: Create a device and get the auth token

The template is a recipe, the device is the real board made from it. In the left menu open Devices, click + New Device, pick the ESP32 Home template with From template and give the device a name. Once the device is created, a three-line configuration appears: BLYNK_TEMPLATE_ID, BLYNK_TEMPLATE_NAME and BLYNK_AUTH_TOKEN. Copy these lines; you can also find them later in the Device Info section of the device page (called Developer Tools in some versions of the interface).

The auth token is your device's password. Don't post code containing the token on forums or in a public GitHub repository; anyone who gets the token can switch your relay on and off. If the token leaks, delete the device and create it again to get a new token. Every board needs its own device and its own token: if you flash the same token onto two ESP32s, they'll keep kicking each other offline.

Step 4: Install the Blynk library in the Arduino IDE

  1. If the ESP32 board package isn't installed in the Arduino IDE yet, install it first; the steps are in What Is the ESP32?
  2. Open the Library Manager, type Blynk in the search box and install the official Blynk library by Volodymyr Shymanskyy. If asked about dependencies, choose Install all.
  3. For the sensor, install Adafruit's DHT sensor library and the Adafruit Unified Sensor library it requires from the same place. If you run into trouble, see the How to Add an Arduino Library guide.
  4. Select ESP32 Dev Module under Tools > Board, connect the board with a USB cable that carries data and choose the right port.
  5. The library comes with ready-made examples: File > Examples > Blynk > Boards_WiFi > ESP32_WiFi is the simplest form of the first sketch below.

First sketch: turn an LED on and off from your phone (V0)

In the code below, replace the top three lines with the ones you copied from your device page, and the Wi-Fi name and password with your own. These three #define lines must come before the #include lines; the library looks for these values while compiling and throws a compile error if it can't find them.

Arduino (C++)
1// Bu üç satırı Blynk.Console'daki cihaz sayfasından kopyala / copy these three lines from the device page in Blynk.Console
2#define BLYNK_TEMPLATE_ID   "TMPLxxxxxxxx"
3#define BLYNK_TEMPLATE_NAME "ESP32 Ev"
4#define BLYNK_AUTH_TOKEN    "CihazTokeniniBurayaYapistir"
5
6#define BLYNK_PRINT Serial          // bağlantı günlüğünü Seri Monitör'e yaz / print the connection log to the Serial Monitor
7
8#include <WiFi.h>
9#include <WiFiClient.h>
10#include <BlynkSimpleEsp32.h>
11
12char ssid[] = "AgAdi";              // Wi-Fi adın (yalnız 2,4 GHz) / your Wi-Fi name (2.4 GHz only)
13char pass[] = "Sifre123";           // Wi-Fi şifren / your Wi-Fi password
14
15const int LED_PIN = 2;              // çoğu DevKit'te dahili LED / onboard LED on most DevKits
16
17// Uygulama V0'a her değer yazdığında çalışır / runs every time the app writes a value to V0
18BLYNK_WRITE(V0) {
19  int deger = param.asInt();        // anahtar: 0 ya da 1 / switch: 0 or 1
20  digitalWrite(LED_PIN, deger);
21  Serial.print("V0 = ");
22  Serial.println(deger);
23}
24
25// Buluta her bağlanışta son V0 değerini iste / ask for the last V0 value on every connection
26BLYNK_CONNECTED() {
27  Blynk.syncVirtual(V0);
28}
29
30void setup() {
31  Serial.begin(115200);
32  pinMode(LED_PIN, OUTPUT);
33  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);   // Wi-Fi'ye ve Blynk.Cloud'a bağlan / connect to Wi-Fi and Blynk.Cloud
34}
35
36void loop() {
37  Blynk.run();                      // gelen komutları işler, bağlantıyı canlı tutar / handles commands, keeps the link alive
38}
LineWhat it does
BLYNK_PRINT SerialMakes the library print its connection steps to the Serial Monitor; very handy when troubleshooting
BLYNK_WRITE(V0)A function that runs automatically when the app or web dashboard sends a value to V0
param.asInt()Converts the incoming value to an integer; use asFloat() for decimals and asStr() for text
BLYNK_CONNECTED()Runs once after every successful connection
Blynk.syncVirtual(V0)Asks the server for the last value of V0, so the LED returns to its previous state even after a restart
Blynk.begin(...)Connects to Wi-Fi and Blynk.Cloud; waits until connected
Blynk.run()Processes incoming commands and keeps the connection alive; it must be called in loop without any waiting

After uploading the code and opening the Serial Monitor at 115200 baud, you should see lines like "Connecting to AgAdi", "Connected to WiFi", the IP address, "Connecting to blynk.cloud:80" and finally "Ready (ping: 45ms)." in that order. Once the Ready line appears, the device shows as Online in Blynk.Console. On the first connection you may also see a line starting with "Redirecting to"; the library automatically switches to the regional server your account lives on, which is normal.

Setting up the phone and web dashboards

The code is ready, so let's place the buttons. In Blynk, the mobile dashboard and the web dashboard are designed separately; since both use the same datastreams, a change you make from one shows up instantly on the other.

  1. Install the Blynk IoT app on your phone (not the old Blynk or Blynk Legacy) and log in with the same account.
  2. Turn on Developer Mode on your profile page, then tap the ESP32 Home template in the Developer Zone.
  3. Tap the empty canvas to add widgets: a Button or Switch each for V0 and V1, a Gauge or Labeled Value for V2 and V3, and a SuperChart for history.
  4. Tap each widget and select the matching datastream in its settings; you can add V2 and V3 to the SuperChart together. Changes are saved automatically.
  5. For the web dashboard, edit the template in Blynk.Console, drag and drop widgets on the Web Dashboard tab, pick the datastream from each widget's gear icon and click Save.
  6. In the app, tap your device's name and try the switch: the LED on GPIO 2 should light up instantly and the Serial Monitor should print "V0 = 1".
The Button widget has two modes: in Switch mode it toggles between 1 and 0 with every tap, in Push mode it sends 1 while you hold it and 0 when you let go. Use Switch for lamps and sockets, and Push for jobs that need a short pulse, like a doorbell or a garage door.

Relay and sensor: reading without delay() using BlynkTimer

The golden rule of Blynk is: loop() should contain only Blynk.run() and timer.run(). If you put delay(2000) in loop, the ESP32 can't see commands from your phone during that time and the switch responds late; very long waits make the server consider the device offline. Worse, if you put Blynk.virtualWrite() straight into loop, the ESP32 tries to send hundreds of messages per second; the server throttles the device and your monthly message quota runs out fast. The fix is BlynkTimer, which works on the millis() principle: it calls the function you choose at the interval you choose, and loop stays free in between. We explain this idea in detail in Arduino millis() vs delay().

The code below controls the relay with V1, sends the temperature read from the DHT11 to V2 and the humidity to V3 every 60 seconds, and triggers a notification event when the temperature goes above 30 °C. For how the sensor works, see DHT11 Temperature and Humidity Sensor.

Arduino (C++)
1#define BLYNK_TEMPLATE_ID   "TMPLxxxxxxxx"
2#define BLYNK_TEMPLATE_NAME "ESP32 Ev"
3#define BLYNK_AUTH_TOKEN    "CihazTokeniniBurayaYapistir"
4#define BLYNK_PRINT Serial
5
6#include <WiFi.h>
7#include <WiFiClient.h>
8#include <BlynkSimpleEsp32.h>
9#include <DHT.h>
10
11char ssid[] = "AgAdi";
12char pass[] = "Sifre123";
13
14const int ROLE_PIN = 26;            // röle modülünün IN pini / relay module IN pin
15const int DHT_PIN  = 4;             // DHT11 veri pini / DHT11 data pin
16const bool ROLE_AKTIF_LOW = true;   // çoğu modül LOW'da çeker / most modules switch on with LOW
17
18DHT dht(DHT_PIN, DHT11);            // DHT22 kullanıyorsan DHT22 yaz / write DHT22 if you use a DHT22
19BlynkTimer timer;                   // delay() yerine zamanlayıcı / a timer instead of delay()
20bool alarmGitti = false;            // aynı bildirimin tekrarını önler / stops the same alert repeating
21
22void roleYaz(bool acik) {
23  if (ROLE_AKTIF_LOW) digitalWrite(ROLE_PIN, acik ? LOW : HIGH);
24  else                digitalWrite(ROLE_PIN, acik ? HIGH : LOW);
25}
26
27// V1: uygulamadaki röle anahtarı / relay switch in the app
28BLYNK_WRITE(V1) {
29  roleYaz(param.asInt() == 1);
30}
31
32// Elektrik gidip gelince rölenin son durumunu geri al / restore the relay state after a power cut
33BLYNK_CONNECTED() {
34  Blynk.syncVirtual(V1);
35}
36
37// Zamanlayıcının çağırdığı fonksiyon / the function called by the timer
38void sensorGonder() {
39  float sicaklik = dht.readTemperature();
40  float nem = dht.readHumidity();
41  if (isnan(sicaklik) || isnan(nem)) {
42    Serial.println("DHT okunamadi / DHT read failed");
43    return;
44  }
45  Blynk.virtualWrite(V2, sicaklik);   // V2: sıcaklık (°C) / temperature (°C)
46  Blynk.virtualWrite(V3, nem);        // V3: nem (%) / humidity (%)
47
48  // 30 °C'yi geçince tek bildirim, 28 °C'nin altında yeniden kur / one alert above 30 °C, re-arm below 28 °C
49  if (sicaklik > 30.0 && !alarmGitti) {
50    Blynk.logEvent("yuksek_sicaklik", String("Sicaklik / Temp: ") + sicaklik + " C");
51    alarmGitti = true;
52  } else if (sicaklik < 28.0) {
53    alarmGitti = false;
54  }
55}
56
57void setup() {
58  Serial.begin(115200);
59  pinMode(ROLE_PIN, OUTPUT);
60  roleYaz(false);                   // açılışta röle kapalı / relay off at boot
61  dht.begin();
62  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
63  timer.setInterval(60000L, sensorGonder);   // 60 saniyede bir ölç ve gönder / measure and send every 60 seconds
64}
65
66void loop() {
67  Blynk.run();
68  timer.run();                      // loop'ta delay() ya da virtualWrite olmasın / no delay() or virtualWrite in loop
69}

The line timer.setInterval(60000L, sensorGonder) calls the function every 60,000 milliseconds; the L at the end marks the number as a long. For one-off jobs use timer.setTimeout(), for example to switch the relay on and turn it off 5 seconds later. One BlynkTimer object holds up to 16 timers, which is more than enough for most projects. The isnan() check stops a meaningless NaN value from reaching the cloud when the sensor can't be read. The alarmGitti flag and the gap between the 30 and 28 °C thresholds (hysteresis) prevent a new notification on every reading while the temperature hovers around 30 °C.

Showing sensor data on a chart

Two things are needed for the chart to fill up: the ESP32 has to send data with virtualWrite, and the datastream has to keep history. If Last Value is selected for history in the datastream settings, the server stores only the latest value and no chart is drawn; the per-minute average (1 Minute AVG) option is enough for charts. On the free plan, history is kept for 1 week, and raw (RAW) data storage is reserved for paid plans. In SuperChart you can switch between time ranges such as hours, days and weeks and see temperature and humidity in two colors on the same chart. Since data arrives every 60 seconds, the first points take a few minutes to appear; don't get impatient and drop the interval to 1 second, you'll see why in the free plan section.

Sending notifications: events and Blynk.logEvent()

In the new Blynk, notifications work through events. You first define the event in the template, then trigger it in code with Blynk.logEvent(); Blynk writes the event to the device's timeline and, depending on its settings, sends a push notification or an email to your phone. An event description can be up to 300 characters, but since the library's send buffer is small, it's best to keep it short.

  1. Open the template in edit mode and switch to the Events & Notifications tab.
  2. Click + Create Event, give the event a name such as "High temperature" and set its event code to yuksek_sicaklik. The code may only contain letters, digits and underscores and must match the text in your sketch exactly.
  3. Choose Warning as the event type; Info, Warning and Critical set how serious the alert is. Make sure the timeline option is on so the event shows up in the app.
  4. On the Notifications tab turn notifications on, pick your own account as the recipient and push and email as channels; if you like, limit notifications to one per hour.
  5. Click Save on the template and confirm updating the device. Don't forget to allow notifications for the Blynk IoT app on your phone.
LimitValue
Events per device per day (logEvent)100
Between two events of the same typeAt least 1 second
Between two notifications (push, email)At least 5 seconds
Event descriptionUp to 300 characters
Request rate per deviceUp to 50 per second
String value lengthUp to 1024 bytes
Never put Blynk.logEvent() inside loop() or inside a condition without a flag that runs on every reading. Code that sends an event every 60 seconds while the temperature is above the threshold uses up the 100-events-per-day limit in about 100 minutes, and you won't get any other notification that day. Use a flag like the one in the code above, or turn on the limiting options on the Notifications tab.

Free plan limits: how to do the message maths

Blynk's free plan is enough for learning and small projects, but a project built without knowing its limits can go silent mid-month. As of October 2026, Blynk's pricing page lists these values for the free plan: 5 devices, 1 user, 100,000 device messages per month, 1 week of data history, 10 templates, 5 events per template, 1 webhook and 5 automations. These limits have changed several times in recent years; before building a long-term project, check the current values on Blynk's pricing page or in your account's plan settings. What counts most toward the quota are the virtualWrite, syncVirtual and logEvent commands your device sends, and every single virtualWrite is one message. A month has about 2,592,000 seconds, so the maths is simple:

Send interval1 datastream (30 days)2 datastreams (30 days)Fits the 100,000 limit?
2 seconds1,296,0002,592,000No
10 seconds259,200518,400No
30 seconds86,400172,800One value fits, two don't
60 seconds43,20086,400Fits, but with two values there's little headroom
5 minutes8,64017,280Fits easily
There are three ways to save messages: make the measurement interval as long as you really need (checking room temperature every 5 minutes is enough), send a value only when it changes by a set amount (for example when the temperature changes by 0.5 °C), and don't send data to datastreams you don't use. The library's own examples also advise against sending more than 10 values per second.

A connection that doesn't hang without Wi-Fi

Blynk.begin() is easy but has a drawback: if Wi-Fi or the Blynk connection can't be established, it waits forever inside setup() and the rest of the board never runs. In projects that must keep working when the internet drops, like a thermostat or an irrigation system, you should manage the connection yourself. The skeleton below starts Wi-Fi without waiting, only applies the settings with Blynk.config() and checks the connection every 10 seconds; meanwhile the local jobs you add to the timer keep running regardless of the internet.

Arduino (C++)
1#define BLYNK_TEMPLATE_ID   "TMPLxxxxxxxx"
2#define BLYNK_TEMPLATE_NAME "ESP32 Ev"
3#define BLYNK_AUTH_TOKEN    "CihazTokeniniBurayaYapistir"
4#define BLYNK_PRINT Serial
5
6#include <WiFi.h>
7#include <WiFiClient.h>
8#include <BlynkSimpleEsp32.h>
9
10char ssid[] = "AgAdi";
11char pass[] = "Sifre123";
12
13BlynkTimer timer;
14
15// Wi-Fi varsa ama Blynk bağlı değilse yeniden dene / retry Blynk when Wi-Fi is up but Blynk is not
16void baglantiKontrol() {
17  if (WiFi.status() == WL_CONNECTED && !Blynk.connected()) {
18    Serial.println("Blynk'e yeniden baglaniliyor / reconnecting to Blynk");
19    Blynk.connect(3000);            // en fazla 3 saniye bekle / wait at most 3 seconds
20  }
21}
22
23void setup() {
24  Serial.begin(115200);
25  WiFi.mode(WIFI_STA);
26  WiFi.begin(ssid, pass);           // beklemeden başlat / start without waiting
27  Blynk.config(BLYNK_AUTH_TOKEN);   // yalnız ayarla, bağlanmayı bekleme / configure only, don't block
28  timer.setInterval(10000L, baglantiKontrol);   // 10 saniyede bir kontrol / check every 10 seconds
29}
30
31void loop() {
32  if (Blynk.connected()) {
33    Blynk.run();
34  }
35  timer.run();                      // yerel işler internet yokken de çalışır / local tasks keep running offline
36}

The ESP32 tries to reconnect to Wi-Fi on its own when the link drops; the code only reconnects to Blynk once Wi-Fi is back. If you want your data encrypted, just include BlynkSimpleEsp32_SSL.h instead of BlynkSimpleEsp32.h; the connection then uses TLS on port 443 instead of 80 and also gets past port blocks on some school or company networks. If you don't want to hard-code your Wi-Fi details, the library's Blynk.Edgent > Edgent_ESP32 example lets you enter the network name and password from the Blynk IoT app on your phone; with this method the auth token is assigned automatically when the device is added and the code can be updated over the air (OTA). The same code also runs on ESP8266 boards: for a NodeMCU, just use ESP8266WiFi.h and BlynkSimpleEsp8266.h.

Blynk with the Raspberry Pi Pico W and MicroPython

Blynk isn't just for the ESP32. If you use MicroPython on a Raspberry Pi Pico W, all you need is to copy the single-file BlynkLib.py from Blynk's Python library to the Pico with Thonny. Be aware that this library is no longer actively developed and that Blynk recommends its MQTT API for new projects; still, it does the job for learning and simple projects. The code below controls the Pico W's onboard LED with V0 and sends the on-chip temperature sensor's reading to V2 once a minute. Create a separate device for the Pico W in Blynk.Console and use its token. If you're new to MicroPython, MicroPython Basics is a good place to start.

MicroPython
1import network, time
2from machine import Pin, ADC
3import BlynkLib                      # BlynkLib.py Pico'da olmalı / BlynkLib.py must be on the Pico
4
5WIFI_SSID = "AgAdi"
6WIFI_PASS = "Sifre123"
7BLYNK_AUTH = "PicoTokeniniBurayaYapistir"
8
9led = Pin("LED", Pin.OUT)            # Pico W dahili LED / Pico W onboard LED
10sensor = ADC(4)                      # yongadaki sıcaklık sensörü / on-chip temperature sensor
11
12wlan = network.WLAN(network.STA_IF)
13wlan.active(True)
14wlan.connect(WIFI_SSID, WIFI_PASS)
15while not wlan.isconnected():
16    time.sleep(0.5)
17print("IP:", wlan.ifconfig()[0])
18
19blynk = BlynkLib.Blynk(BLYNK_AUTH, insecure=True)   # 80 portu, TLS'siz / port 80, no TLS
20
21@blynk.on("V0")
22def v0_yazildi(value):               # uygulamadaki anahtar / switch in the app
23    led.value(int(value[0]))
24
25@blynk.on("connected")
26def baglandi(ping):
27    print("Blynk hazir / ready, ping:", ping, "ms")
28    blynk.sync_virtual(0)            # son V0 değerini iste / ask for the last V0 value
29
30son = time.ticks_ms()
31while True:
32    blynk.run()
33    if time.ticks_diff(time.ticks_ms(), son) >= 60000:   # 60 saniyede bir / every 60 seconds
34        son = time.ticks_ms()
35        volt = sensor.read_u16() * 3.3 / 65535
36        sicaklik = 27 - (volt - 0.706) / 0.001721
37        blynk.virtual_write(2, round(sicaklik, 1))      # V2: sıcaklık / temperature

In this example the connection is made unencrypted on port 80 with insecure=True; this is the option that uses the least memory and it's on the same level as BlynkSimpleEsp32.h on the ESP32. If you remove this parameter, the library tries to use TLS on port 443. The reason we measure time with ticks_ms in the loop instead of time.sleep() is the same as on the Arduino side: if blynk.run() isn't called often, commands lag and the connection drops. The on-chip temperature sensor can be a few degrees off from room temperature; connect a DHT11 or DS18B20 for real measurements.

Project ideas with Blynk

  • Smart plug: switch a desk lamp or a fan on and off from anywhere in the world with a relay; for relay wiring see What Is a Relay Module?
  • Remote plant watering: run the pump when the soil moisture sensor reports dry soil and follow the moisture level on a chart.
  • Smart greenhouse: switch on a fan when temperature and humidity rise and get a notification when values cross a threshold; details in Smart Greenhouse Project.
  • Burglar alarm: send a critical notification to your phone with logEvent when the PIR motion sensor detects someone.
  • Gas leak alert: when the MQ-2 gas sensor crosses its threshold, sound a buzzer and make your phone buzz too.
  • Weather station: compare temperature, humidity and pressure from a BME280 on a weekly chart.
  • Door and window monitor: see in the app whether a door was left open with a reed switch.

Common errors and fixes

Symptom or messageCauseFix
"Please specify your BLYNK_TEMPLATE_ID and BLYNK_TEMPLATE_NAME" when compilingLines missing, written after the #include, or the old BLYNK_DEVICE_NAME usedPut the three #define lines at the very top, before the includes; change DEVICE_NAME to TEMPLATE_NAME
"'class BlynkWifi' has no member named 'notify'" when compilingThe Blynk.notify() command from old Blynk codeCreate an event in the template and use Blynk.logEvent()
"Invalid auth token" in the Serial MonitorToken missing or copied wrong, device deleted, or an old Blynk token in useCopy the token again from the device page with no spaces at the start or end
Nothing after the "Connecting to AgAdi" lineThe board can't join Wi-Fi: 5 GHz network, wrong password or weak signalUse a 2.4 GHz network; see the ESP32 Wi-Fi guide for details
"Connecting to blynk.cloud:80" repeats or "Login timeout"No internet on the network, or a school or company network blocks the connectionTry a phone hotspot; use port 443 with BlynkSimpleEsp32_SSL.h
"Heartbeat timeout", device often OfflineLong delay() or a blocking loop in loop, weak power supplyMove waits into BlynkTimer, use a good cable and power adapter
Nothing happens when you press the switchThe widget is bound to another datastream or the pin in BLYNK_WRITE is differentThe pin in the widget settings must match the Vx in your code
Gauge always shows 1 or the chart is emptyThe datastream's Max was left at 1 or history is set to Last ValueFix Min and Max to the sensor's range and change the history setting
After a while no data arrives at allThe monthly message quota is used upLengthen the send interval and send only on change
Relay works the wrong way round or never releasesActive-LOW module or the 3.3 V signal isn't enoughFlip ROLE_AKTIF_LOW and use a 3.3 V compatible module
Keep to an order when troubleshooting: first check the Wi-Fi connection in the Serial Monitor, then look for the "Ready" line, and only then check that widgets match datastreams. If you're stuck at the Wi-Fi stage, see ESP32 Not Connecting to Wi-Fi; if the board restarts when Wi-Fi turns on, read ESP32 Brownout and Guru Meditation.

Blynk, your own web server or MQTT?

MethodProsConsWhen to choose it
Blynk IoTReady-made dashboard without writing an app, access from outside your home, notificationsFree plan limits, depends on the cloudFast prototypes and remote monitoring
ESP32 web serverCompletely free, works without internetUsually reachable only from the same network, you write the interfaceIn-home control panel
MQTT and Home AssistantUnlimited messages, runs locally, powerful automationLonger setup, needs an always-on serverA permanent smart home system
Telegram botFree, ideal for alerts and commandsNo charts or dashboardAlarms and simple commands

In short, Blynk is the easiest way to get quick results with a ready-made, good-looking dashboard and to reach your project from outside your home. If you want an unlimited, fully local system, read ESP32 Web Server and WebSocket or ESP32 MQTT and Home Assistant; if you just want to send alerts to your phone, check out the ESP32 Telegram Bot guide.

Once you understand the template, datastream and auth token trio, connecting a new ESP32 project to your phone with Blynk takes just a few minutes. Combine the LED, relay and sensor examples here and you have the start of your own smart home system. In the BlueGrays app you can also find ESP32 projects such as blinking an LED, connecting to Wi-Fi, measuring temperature with a DHT22, smart lighting, plant watering and a motion alarm with Telegram, each with a step-by-step circuit diagram and code.

Frequently asked questions

Is Blynk free?

Yes, Blynk has a free plan for personal use. As of October 2026 it offers 5 devices, 100,000 device messages per month and 1 week of data history. For more devices, unlimited messages and longer data storage you need to move to a paid monthly plan.

Where do I find the Blynk auth token?

In Blynk.Console, open your device from the Devices section; in Device Info you'll see the BLYNK_TEMPLATE_ID, BLYNK_TEMPLATE_NAME and BLYNK_AUTH_TOKEN lines ready to paste into your code. In the new Blynk the token is no longer sent by email, and every device has its own token.

Does the old Blynk app still work?

No. The old Blynk (Legacy) app was removed from the stores in 2022 and its cloud servers were shut down on December 31, 2022. You need to rebuild old projects on the new Blynk IoT platform with templates and datastreams; most of the ESP32 code can be reused with small changes.

What is a virtual pin in Blynk?

A virtual pin is a numbered data channel between the app and your code, and it doesn't correspond to a physical leg of the board. They are numbered from V0 to V255; values from the app are read with BLYNK_WRITE(Vx), and values from the board are sent to the app with Blynk.virtualWrite(Vx, value). This lets you process incoming values however you like and bring sensor data to the dashboard.

Why does my ESP32 show as offline in Blynk?

The most common causes are a wrong or missing auth token, the ESP32 trying to join a 5 GHz network, long delay() calls in loop() and a weak power supply. If the "Ready" line doesn't appear in the Serial Monitor, the problem is the connection; if it does, make sure you're looking at the right device in the app.

Does Blynk work without internet?

No. In Blynk IoT, commands and data travel through Blynk.Cloud, so both the ESP32 and your phone need internet access. For control without internet, you can use the ESP32's own web server, ESP-NOW or Bluetooth.

See all projects
LED Blink with ESP32
#103Beginner

LED Blink with ESP32

Teaches basic GPIO output usage with ESP32. We achieve a blinking effect by turning an LED on and off from a digital pin. ESP32 version of the classic blink project on Arduino UNO; the basic blink commands in the Arduino environment are the same, but the ESP32's pin layout and 3.3 V GPIO levels differ from those of the Arduino UNO.

4.7(36)
96
ESP32 Built-in LED Blink
#106Beginner

ESP32 Built-in LED Blink

Blinking the built-in blue LED on the ESP32 DevKit V1. No external components required! The first project you should try when you buy an ESP32. GPIO 2 is connected to the built-in LED.

4.8(29)
53
Reading Light Intensity with the ESP32 LDR Module
#113Beginner

Reading Light Intensity with the ESP32 LDR Module

Real-time monitoring of the LDR module's raw ADC value and relative light percentage calculated from dark and light reference values in the Serial Monitor. This percentage is not a lux measurement. Teaches the module’s calibration logic. It is ideal to complete this before Project 10, as it is used to determine the threshold value.

4.6(36)
55
ESP32 Wi-Fi STA Connection (with LCD Screen)
#127Advanced
Premium

ESP32 Wi-Fi STA Connection (with LCD Screen)

In this project, we connect the ESP32 to the home Wi-Fi network in Station (STA) mode in a secure, fault-tolerant manner. We store the SSID and password in a separate `secrets.h` file to prevent leaking to Git, set up an auto-reconnect mechanism, and display the RSSI signal level and IP address on an I2C LCD screen. The internal LED works as a status indicator. It is a production-grade connection manager.

4.4(21)
33
ESP32 DHT22 Temperature and Humidity (with LCD Display)
#117Intermediate

ESP32 DHT22 Temperature and Humidity (with LCD Display)

This project measures ambient temperature and humidity using a DHT22 sensor and displays the data in real time on a 16x2 I2C LCD. Data is read from the sensor using the one-wire protocol via the Adafruit DHT library. This project serves as the foundation for IoT weather stations, smart home automation, or environmental monitoring systems in greenhouses. Communication with the DHT22 is established via the ESP32's GPIO 4 pin.

4.8(38)
54
ESP32 Smart Lighting (PIR + LDR + Relay + OLED)
#141Advanced
Premium

ESP32 Smart Lighting (PIR + LDR + Relay + OLED)

Turn your hallway, bathroom, or pantry into smart lighting with ESP32! Using a PIR motion sensor, LDR light sensor, and a relay module, we build the classic "light turns on when motion is detected in the dark" scenario — if the environment is already bright, motion does NOT trigger the light, saving energy during the day. The light stays on for 30 seconds; if motion continues, the timer resets and the light stays on longer. The SSD1306 OLED shows large-font status (ON / DAYTIME / WAITING), a cou

4.3(6)
11
ESP 32 Smart Plant Watering System
#139Advanced
Premium

ESP 32 Smart Plant Watering System

In this project, an automatic plant watering system was developed using an ESP32 and a soil moisture sensor. The sensor continuously measures the soil’s moisture level. When the moisture level drops below a specified threshold, the ESP32 activates the relay to turn on the water pump and water the plant. When the soil is sufficiently moist, the pump automatically stops. Thanks to this project, plants can be watered regularly, and water can be conserved. _______________________________ Connections

4.7(10)
14
ESP32 Motion Alarm System (PIR + Buzzer + LED + Telegram)
#145Advanced
Premium

ESP32 Motion Alarm System (PIR + Buzzer + LED + Telegram)

A smart security alarm system that activates the buzzer and LED when the PIR sensor detects motion, while simultaneously sending an instant notification to the owner via Telegram. It includes a 30-second cooldown to limit the frequency of repeated alarms; this mechanism does not validate PIR detections or eliminate false triggers. Suitable for home security, garage monitoring, warehouses, or workrooms. With ESP32-CAM, photo notifications can be added; with the classic ESP32 DevKit V1, text notif

0.0(0)
8