Introduction to Blynk 

ICT 360: Introduction to IoT

Mr. Seng Theara

Learning Objective

Learning Objectives

  • Build a basic IoT application using ESP32 and Blynk

  • Control hardware remotely via a smartphone

  • Monitor real-time temperature data from a sensor

  • Apply MicroPython for cloud-connected embedded systems

Introduction to Blynk

Expansion Board or External Shield

Blynk is an IoT platform that lets you:

Introduction to Blynk

  • Control hardware remotely (LEDs, motors, relays)

  • Monitor sensor data (temperature, humidity, voltage)

  • Build mobile dashboards without mobile app coding

Blynk Server

Signal

Signal

Vcc/5V

Vcc/5V

GND

GND

The Blynk Server is the central cloud system that connects:

  • 📱 Mobile App (User)

  • 🌍 Internet

  • 🔌 ESP32 Device

It acts as a bridge between the smartphone and the hardware.

Role of the Blynk Server

  • Authenticates devices

  • Routes commands

  • Stores widget data

  • Manages real-time communication

Network Communication Flow with LED

Signal

Signal

Vcc/5V

GND

Phone taps Button Widget

App sends data to Blynk Server

 Server forwards data to ESP32

ESP32 executes code

 LED turns ON/OFF

Network Communication Flow with DHT11

Signal

Signal

Vcc/5V

GND

ESP32 reads DHT11

ESP32 sends temperature to server

 Server updates Gauge

 Phone displays value

Blynk Setup

Sign up and Log In with your Email

Blynk Setup

Go to Developer Zone 

Then choose New Template

In Developer Zone, choose Web Dashboard

Drag and Drop Switch & Gauge from Widget Box to Dashboard

Give a Template Name

Switch Setup

On Switch, Click the setting. Then, Click on Create DataStream and choose Virtual Pin

Gauge Setup

On Gauge, Click the setting. Then, Click on Create DataStream and choose Virtual Pin

Virtual Pin 

A Virtual Pin is a software-only pin used by Blynk to exchange data between:

  •  Blynk App widgets

  •  ESP32 firmware

Why Do We Need Virtual Pins?

  • Phone does not know ESP32 pin numbers
  • A virtual pin is NOT a physical ESP32 GPIO. It exists only in software and the cloud. So, We need them to map value between the virtual pin and the esp32 GPIO 

Virtual pin V0 for LED

Virtual pin V1 for Temperature

Create New Device

Choose Devices

Click New Device and choose From Template

Choose the Template from what you create on the developer Zone

Token

After your create a new device, you will see the token here. Click to copy it.

Blynk with LED & DHT11 Example

from machine import Pin
import time

# Initialize relay pin (GPIO15 / D15)
relay = Pin(15, Pin.OUT)

print("Relay control started...")

while True:
    # Turn relay ON
    relay.value(1)
    print("Relay ON")
    time.sleep(2)

    # Turn relay OFF
    relay.value(0)
    print("Relay OFF")
    time.sleep(2)
import network
import time
import machine
import dht
import urequests as requests

# ---------- CONFIG ----------
WIFI_SSID = "project"
WIFI_PASS = "1234567890"

BLYNK_TOKEN = "XJcAwhsvd_35cracrDAOclFTOUyy5h6f"
BLYNK_API   = "http://blynk.cloud/external/api"

LED_PIN = 2
DHT_PIN = 4

# ---------- HARDWARE ----------
led = machine.Pin(LED_PIN, machine.Pin.OUT)
sensor = dht.DHT11(machine.Pin(DHT_PIN))

# ---------- WIFI ----------
wifi = network.WLAN(network.STA_IF)
wifi.active(True)
wifi.connect(WIFI_SSID, WIFI_PASS)

print("Connecting to WiFi...")
while not wifi.isconnected():
    time.sleep(1)
print("WiFi connected!")

# ---------- BLYNK ----------
def read_button_v0():
    r = requests.get(f"{BLYNK_API}/get?token={BLYNK_TOKEN}&V0")
    value = int(str(r.text).strip('[]"{}'))
    r.close()
    return value

def send_temperature_v1(temp):
    url = f"{BLYNK_API}/update?token={BLYNK_TOKEN}&V1={temp}"
    r = requests.get(url)
    r.close()

# ---------- MAIN ----------
print("Running Blynk control...")

while True:
    # Button → LED
    if read_button_v0() == 1:
        led.on()
    else:
        led.off()

    # Temperature → Gauge
    sensor.measure()
    temp = sensor.temperature()
    print("Temperature:", temp)
    send_temperature_v1(temp)

    time.sleep(2)

How Virtual Pins Work with LED 

from machine import Pin
import time

# Initialize relay pin (GPIO15 / D15)
relay = Pin(15, Pin.OUT)

print("Relay control started...")

while True:
    # Turn relay ON
    relay.value(1)
    print("Relay ON")
    time.sleep(2)

    # Turn relay OFF
    relay.value(0)
    print("Relay OFF")
    time.sleep(2)

Code executes (LED ON)

def read_button_v0():
    r = requests.get(f"{BLYNK_API}/get?token={BLYNK_TOKEN}&V0")
    value = int(str(r.text).strip('[]"{}'))
    r.close()
    return value

User presses Button

App sends {V0:1} to server

Server forwards {V0:1} to ESP32

ESP32 triggers V0 callback function

How Virtual Pins Work with DHT11

from machine import Pin
import time

# Initialize relay pin (GPIO15 / D15)
relay = Pin(15, Pin.OUT)

print("Relay control started...")

while True:
    # Turn relay ON
    relay.value(1)
    print("Relay ON")
    time.sleep(2)

    # Turn relay OFF
    relay.value(0)
    print("Relay OFF")
    time.sleep(2)

Code update temp

def send_temperature_v1(temp):
    url = f"{BLYNK_API}/update?token={BLYNK_TOKEN}&V1={temp}"
    r = requests.get(url)
    r.close()

Reading the Temp from DHT11

esp32 sends {V1:temp} to server

Server update{V1:temp}

Gauge update the temp value

Testing

IR Sensor

from machine import Pin
import time

# Initialize relay pin (GPIO15 / D15)
relay = Pin(15, Pin.OUT)

print("Relay control started...")

while True:
    # Turn relay ON
    relay.value(1)
    print("Relay ON")
    time.sleep(2)

    # Turn relay OFF
    relay.value(0)
    print("Relay OFF")
    time.sleep(2)

IR Sensor is an electronic device, that emits the light in order to sense some object of the surrounding. An IR sensor can measure the heat of an object as well as detects the motion.

Usually, in the infrared spectrum, all the objects radiate some form of thermal radiation. These types of radiations are invisible to our eyes, but infrared sensor can detect these radiations.

IR Sensor Working Principle

from machine import Pin
import time

# Initialize relay pin (GPIO15 / D15)
relay = Pin(15, Pin.OUT)

print("Relay control started...")

while True:
    # Turn relay ON
    relay.value(1)
    print("Relay ON")
    time.sleep(2)

    # Turn relay OFF
    relay.value(0)
    print("Relay OFF")
    time.sleep(2)

There are different types of infrared transmitters depending on their wavelengths, output power and response time. An IR sensor consists of an IR LED and an IR Photodiode, together they are called as PhotoCoupler or OptoCoupler.

IR Transmitter or IR LED

Infrared Transmitter is a light emitting diode (LED) which emits infrared radiations called as IR LED’s. Even though an IR LED looks like a normal LED, the radiation emitted by it is invisible to the human eye.

IR Receiver or Photodiode

Infrared receivers or infrared sensors detect the radiation from an IR transmitter. IR receivers come in the form of photodiodes and phototransistors. Infrared Photodiodes are different from normal photo diodes as they detect only infrared radiation.

IR Sensor Working Principle

from machine import Pin
import time

# Initialize relay pin (GPIO15 / D15)
relay = Pin(15, Pin.OUT)

print("Relay control started...")

while True:
    # Turn relay ON
    relay.value(1)
    print("Relay ON")
    time.sleep(2)

    # Turn relay OFF
    relay.value(0)
    print("Relay OFF")
    time.sleep(2)

When the IR transmitter emits radiation, it reaches the object and some of the radiation reflects back to the IR receiver. Based on the intensity of the reception by the IR receiver, the output of the sensor defines.

Applications of IR Sensor

from machine import Pin
import time

# Initialize relay pin (GPIO15 / D15)
relay = Pin(15, Pin.OUT)

print("Relay control started...")

while True:
    # Turn relay ON
    relay.value(1)
    print("Relay ON")
    time.sleep(2)

    # Turn relay OFF
    relay.value(0)
    print("Relay OFF")
    time.sleep(2)

IR sensors use in various projects and also in various electronic devices. They all are as follow,

An Infrared technology implemented in night vision equipment if there is not enough visible light available to see

Night Vision Devices

Radiation Thermometers

IR sensos uses in radiation thermometers to measure the temperature depend upon the temperature and the material of the object

Infrared Tracking

An Infrared tracking or Infrared homing, is a missile guidance system which operates using the infrared electromagnetic radiation emitted from a target to track it.

Connection of IR Sensor with ESP32

from machine import Pin
import time

# Initialize relay pin (GPIO15 / D15)
relay = Pin(15, Pin.OUT)

print("Relay control started...")

while True:
    # Turn relay ON
    relay.value(1)
    print("Relay ON")
    time.sleep(2)

    # Turn relay OFF
    relay.value(0)
    print("Relay OFF")
    time.sleep(2)

Note*

The IR sensor is active-LOW, which means that when it detects an obstacle, the output is 0. When no obstacle is detected, the output is 1.

Connection of IR Sensor with ESP32

from machine import Pin
import time

# Initialize relay pin (GPIO15 / D15)
relay = Pin(15, Pin.OUT)

print("Relay control started...")

while True:
    # Turn relay ON
    relay.value(1)
    print("Relay ON")
    time.sleep(2)

    # Turn relay OFF
    relay.value(0)
    print("Relay OFF")
    time.sleep(2)

Note*

The IR sensor is active-LOW, which means that when it detects an obstacle, the output is 0. When no obstacle is detected, the output is 1.

from machine import Pin
import time

ir = Pin(12, Pin.IN)

while True:
    value = ir.value()
    
    if value == 0:
        print("Obstacle detected")
    else:
        print("No obstacle")
    
    time.sleep(0.2)

Code

Testing with IR Sensor

from machine import Pin
import time

# Initialize relay pin (GPIO15 / D15)
relay = Pin(15, Pin.OUT)

print("Relay control started...")

while True:
    # Turn relay ON
    relay.value(1)
    print("Relay ON")
    time.sleep(2)

    # Turn relay OFF
    relay.value(0)
    print("Relay OFF")
    time.sleep(2)

Introduction to Servo Motor

from machine import Pin
import time

# Initialize relay pin (GPIO15 / D15)
relay = Pin(15, Pin.OUT)

print("Relay control started...")

while True:
    # Turn relay ON
    relay.value(1)
    print("Relay ON")
    time.sleep(2)

    # Turn relay OFF
    relay.value(0)
    print("Relay OFF")
    time.sleep(2)

A servo motor is a precision motor that uses a servo motor working principle based on closed-loop feedback control, which can rotate to specific angles with exceptional accuracy

If you want to rotate an object to specific angles or distances, servo motors are the ideal choice due to their servo mechanism with built-in position feedback.

Servo motors are usually rated in kg/cm. For example, a 6kg/cm servo can lift 6kg when the load is 1cm from the motor shaft.

How to control Servo Motor

from machine import Pin
import time

# Initialize relay pin (GPIO15 / D15)
relay = Pin(15, Pin.OUT)

print("Relay control started...")

while True:
    # Turn relay ON
    relay.value(1)
    print("Relay ON")
    time.sleep(2)

    # Turn relay OFF
    relay.value(0)
    print("Relay OFF")
    time.sleep(2)

PWM Control Signal Specifications

  • Pulse Period: 20ms (50Hz frequency)

  • 0.5 ms pulse width: Servo rotates to 0° position

  • 1.5ms pulse width: Servo moves to 90° (neutral position)

  • 2.5ms pulse width: Servo rotates to 180° position

Connection of Servo Motor with ESP32

from machine import Pin
import time

# Initialize relay pin (GPIO15 / D15)
relay = Pin(15, Pin.OUT)

print("Relay control started...")

while True:
    # Turn relay ON
    relay.value(1)
    print("Relay ON")
    time.sleep(2)

    # Turn relay OFF
    relay.value(0)
    print("Relay OFF")
    time.sleep(2)

Coding

from machine import Pin
import time

# Initialize relay pin (GPIO15 / D15)
relay = Pin(15, Pin.OUT)

print("Relay control started...")

while True:
    # Turn relay ON
    relay.value(1)
    print("Relay ON")
    time.sleep(2)

    # Turn relay OFF
    relay.value(0)
    print("Relay OFF")
    time.sleep(2)
from machine import Pin, PWM
from time import sleep

servo = PWM(Pin(13), freq=50)

while True:
    servo.duty(26)  # set servo to 0 degree
    sleep(2)
    servo.duty(77) # set servo to 90 degree
    sleep(2)

Why servo.duty(26), the servo move to 0 degree?

We know that 0.5ms pwm servo move to 0 degree.

 

PWM Period 50Hz =20ms

PWM value 0->1023

\begin{aligned} \text{duty} &= \frac{t_{\text{pulse}}}{T_{\text{period}}} \times \text{PWM}_{\max} \\ &= \frac{0.5\,\text{ms}}{20\,\text{ms}} \times 1023 \\ &= 25.575 \approx 26 \end{aligned}

Introduction to TM1637

from machine import Pin
import time

# Initialize relay pin (GPIO15 / D15)
relay = Pin(15, Pin.OUT)

print("Relay control started...")

while True:
    # Turn relay ON
    relay.value(1)
    print("Relay ON")
    time.sleep(2)

    # Turn relay OFF
    relay.value(0)
    print("Relay OFF")
    time.sleep(2)

The TM1637 4-Digit LED 7-Segment display is a display module that combines four 7-segment digits on a single display that can be controlled via the TM1637 driver.

Connection

from machine import Pin
import time

# Initialize relay pin (GPIO15 / D15)
relay = Pin(15, Pin.OUT)

print("Relay control started...")

while True:
    # Turn relay ON
    relay.value(1)
    print("Relay ON")
    time.sleep(2)

    # Turn relay OFF
    relay.value(0)
    print("Relay OFF")
    time.sleep(2)

Library Code TM1637

from machine import Pin
import time

# Initialize relay pin (GPIO15 / D15)
relay = Pin(15, Pin.OUT)

print("Relay control started...")

while True:
    # Turn relay ON
    relay.value(1)
    print("Relay ON")
    time.sleep(2)

    # Turn relay OFF
    relay.value(0)
    print("Relay OFF")
    time.sleep(2)
from machine import Pin
from time import sleep_us

# TM1637 commands
CMD_DATA = 0x40      # auto increment
CMD_ADDR = 0xC0      # start address
CMD_CTRL = 0x80      # display control

# Digit to 7-segment mapping (0–9)
SEGMENTS = [
    0x3F,  # 0
    0x06,  # 1
    0x5B,  # 2
    0x4F,  # 3
    0x66,  # 4
    0x6D,  # 5
    0x7D,  # 6
    0x07,  # 7
    0x7F,  # 8
    0x6F   # 9
]

class TM1637:
    def __init__(self, clk_pin, dio_pin, brightness=7):
        self.clk = Pin(clk_pin, Pin.OUT, value=1)
        self.dio = Pin(dio_pin, Pin.OUT, value=1)
        self.brightness = brightness
        self._update_display()

    # ---------- Low-level protocol ----------
    def _start(self):
        self.dio.value(0)
        sleep_us(10)
        self.clk.value(0)

    def _stop(self):
        self.clk.value(1)
        sleep_us(10)
        self.dio.value(1)

    def _write_byte(self, data):
        for i in range(8):
            self.dio.value(data & 0x01)
            data >>= 1
            self.clk.value(1)
            sleep_us(10)
            self.clk.value(0)
        # ignore ACK
        self.clk.value(1)
        sleep_us(10)
        self.clk.value(0)

    # ---------- Display control ----------
    def _update_display(self):
        self._start()
        self._write_byte(CMD_CTRL | 0x08 | self.brightness)
        self._stop()

    def set_brightness(self, value):
        self.brightness = max(0, min(value, 7))
        self._update_display()

    # ---------- High-level function ----------
    def show_number(self, num):
        num = max(0, min(num, 9999))
        digits = [
            num // 1000 % 10,
            num // 100 % 10,
            num // 10 % 10,
            num % 10
        ]

        self._start()
        self._write_byte(CMD_DATA)
        self._stop()

        self._start()
        self._write_byte(CMD_ADDR)
        for d in digits:
            self._write_byte(SEGMENTS[d])
        self._stop()

        self._update_display()
    def show_digit(self, num):
        """
        Display number (0–9999) with NO leading zeros.
        Unused digits are blank.
        Examples:
          show_digit(4)    ->    '   4'
          show_digit(12)   ->    '  12'
          show_digit(123)  ->    ' 123'
          show_digit(1234) ->    '1234'
        """
        if not 0 <= num <= 9999:
            return

        s = str(num)                  # convert number to string
        data = [0x00, 0x00, 0x00, 0x00]  # blank display

        start = 4 - len(s)            # right alignment
        for i, ch in enumerate(s):
            data[start + i] = SEGMENTS[int(ch)]

        # send data to TM1637
        self._start()
        self._write_byte(CMD_DATA)
        self._stop()

        self._start()
        self._write_byte(CMD_ADDR)
        for seg in data:
            self._write_byte(seg)
        self._stop()

        self._update_display()

save this code in micropython device with tm1637.py

Testing

from machine import Pin
import time

# Initialize relay pin (GPIO15 / D15)
relay = Pin(15, Pin.OUT)

print("Relay control started...")

while True:
    # Turn relay ON
    relay.value(1)
    print("Relay ON")
    time.sleep(2)

    # Turn relay OFF
    relay.value(0)
    print("Relay OFF")
    time.sleep(2)
from tm1637 import TM1637
import time

tm = TM1637(clk_pin=17, dio_pin=16, brightness=5)

count = 0
while True:
    tm.show_number(count)
    count += 1
    time.sleep(1)
from tm1637 import TM1637
import time

tm = TM1637(clk_pin=17, dio_pin=16, brightness=5)

while True:
    tm.show_digit(4)
    time.sleep(1)

    tm.show_digit(12)
    time.sleep(1)

    tm.show_digit(123)
    time.sleep(1)

    tm.show_digit(1234)
    time.sleep(1)

Using show_number

Using show_number