ICT 360: Introduction to IoT
Mr. Seng Theara
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
Expansion Board or External Shield
Blynk is an IoT platform that lets you:
Control hardware remotely (LEDs, motors, relays)
Monitor sensor data (temperature, humidity, voltage)
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
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
Signal
Signal
Vcc/5V
GND
ESP32 reads DHT11
ESP32 sends temperature to server
Server updates Gauge
Phone displays value
Sign up and Log In with your Email
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
On Switch, Click the setting. Then, Click on Create DataStream and choose Virtual Pin
On Gauge, Click the setting. Then, Click on Create DataStream and choose 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?
Virtual pin V0 for LED
Virtual pin V1 for Temperature
Choose Devices
Click New Device and choose From Template
Choose the Template from what you create on the developer Zone
After your create a new device, you will see the token here. Click to copy it.
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)
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
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
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.
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.
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.
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
IR sensos uses in radiation thermometers to measure the temperature depend upon the temperature and the material of the object
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.
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
# 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
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
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.
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)
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
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
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
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.
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
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
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