#Làm quen với bộ kit phần cứng
- Danh sách trang thiết bị trong bộ kit
Mạch phát triển MKE-K01 ESP32-S3 Dev Kit

- Thông số kỹ thuật
- Nguồn hoạt động: 5VDC từ cổng USB
- Module trung tâm: ESP32-S3-WROOM-1 (Wi-Fi + BLE5) chính hãng Espressif
- CPU: Xtensa® Dual-core LX7, up to 240 MHz
- Bộ nhớ Flash & PSRAM tùy chọn:
- 16 MB Flash + 8 MB PSRAM (N16R8)
- 4 MB Flash không PSRAM (N4)
- 16 MB Flash không PSRAM (N16)
- Kết nối không dây:
- Wi-Fi 802.11 b/g/n (2.4 GHz)
- Bluetooth Low Energy BLE5
- IC giao tiếp USB-UART: High-speed Serial UART CH343P chính hãng có tốc độ truyền tối đa lên đến 6Mbp tương thích chuẩn USB 2.0, tự nhận Driver trên hầu hết các hệ điều hành.
- Cổng USB
- Cổng USB-to-UART (MicroUSB/USB-C tùy phiên bản) dùng để cấp nguồn, nạp chương trình và giao tiếp debug
- Cổng USB OTG full-speed (USB 1.1) trên chip ESP32-S3 hỗ trợ giao tiếp USB thiết bị/giao diện nếu phần mềm hỗ trợ
- GPIO và giao tiếp
- Hầu hết chân GPIO của ESP32-S3 module được breakout ra header 2 bên, dễ dàng dùng cho các cảm biến/peripherals
- Các chuẩn giao tiếp bao gồm: UART, SPI, I2C, I2S, PWM, ADC
- Lưu ý: Một số chân (GPIO35/36/37) bị dùng bởi kết nối Flash/PSRAM trên module nên không dùng được ngoài
- Nút chức năng
- RESET – khởi động lại MCU
- BOOT (Download) – đưa board vào chế độ nạp firmware
- LED chỉ báo
- LED RGB addressable nằm trên board, được điều khiển qua GPIO48 giúp hiển thị trạng thái, debugging hoặc ánh sáng tùy chỉnh
- LED Power 3.3 V bật khi board được cấp nguồn qua USB
Mạch đế kết nối MKE-B01 ESP32-S3 DK IO Shield

Mạch LED đơn MKE-M01 1-LED

Mạch nút nhấn MKE-M02 Button

Cảm biến ánh sáng quang trở MKE-S02 LDR Light Sensor

Cảm biến độ ẩm nhiệt độ MKE-S14 DHT11 Temperature Humidity Sensor

Mạch LED đổi màu MKE-M22 WS2812B RGB LED Module

Cảm biến độ ẩm đất điện dung MKE-S13 Capacitive Soil Moisture Sensor

- ESP32-S3 Pin-out quick reference

#Cài đặt phần mềm Thonny và cấu hình cho ESP32 lập trình bằng microPython
Cài đặt phần mềm Thonny: thonny.org
Hướng dẫn nạp firmware microPython cho ESP32 trên Thonny:
Hướng dẫn nạp firmware microPython lên ESP32 (Vietduino ESP32) bằng phần mềm Thonny
#Lập trình microPython
#Tín hiệu số (Digital Signal)
Tín hiệu số (digital signal) là một loại tín hiệu mà giá trị của nó chỉ có thể nằm ở một trong hai trạng thái: "bật" hoặc "tắt", "1" hoặc "0", "cao" hoặc "thấp". Trong thực tế, tín hiệu số thường được biểu diễn bằng điện áp, với một mức điện áp cao (ví dụ, 3.3V hoặc 5V) đại diện cho trạng thái "1" và một mức điện áp thấp (ví dụ, 0V) đại diện cho trạng thái "0".


(nguồn ảnh: https://collegedunia.com/exams/differences-between-analog-and-digital-signals-physics-articleid-1490)

- Lập trình xuất tín hiệu số
Khi lập trình cho một chân tín hiệu xuất tín hiệu số, bạn có thể điều khiển cho chân tín hiệu đó tạo ra 1 điện áp mức cao (với ESP32 là 3.3V) hoặc mức thấp (0V). Khi ở mức cao, điện áp từ chân tín hiệu có thể làm sáng (bật) đèn, còi (buzzer)… và ngược lại khi ở mức thấp thì sẽ tắt đèn.
1.1 Điều khiển chớp - tắt đèn LED
Các câu lệnh:
>
- import: gọi thư viện để sử dụng thư viện đó trong chương trình
-led = Pin(13, Pin.OUT): tạo 1 object (đối tượng) led sử dụng chân tín hiệu (Pin, GPIO). Ở đây khởi tạo đối tượng led sử dụng chân tín hiệu số13, ở chế độOUT(xuất tín hiệu Digital)
- .on(): bật tín hiệu
- .off(): tắt tín hiệu
-.sleep(số giây): dừng chương trình trongsố giây
from machine import Pin
import time
#Cài đặt chân GPIO 13 làm output
led = Pin(13, Pin.OUT)
led.on() # Bật LED
time.sleep(1) #dừng chương trình 1 giây
led.off() # Tắt LED
time.sleep(1)1.2 Chương trình Blink - Điều khiển chớp tắt đèn LED liên tục vô hạn
Các câu lệnh:
>
- while True: câu lệnh vòng lặp vô hạn. Câu lệnh while bình thường sẽ thực hiện các câu lệnh bên trong khi phần điều kiện (phía sau while) vẫn đúng (True). Ở đây while True có nghĩa là miễn là phần điều kiện vẫn bằng True (True = True) thì các câu lệnh bên trong sẽ được thực hiện. Vì thế nên các câu lệnh bên trong while True sẽ được thực hiện lặp lại vô hạn (infinite loop).
- .value(): thay đổi giá trị của tín hiệu xuất ra là 0 hoặc 1, tương đương với lệnh .off() hoặc .on()
import machine
import time
led = machine.Pin(13, machine.Pin.OUT)
while True:
led.value(1)
time.sleep(1)
led.value(0)
time.sleep(1)
- Lập trình đọc tín hiệu số
Khi lập trình cho 1 chân tín hiệu đọc tín hiệu số, chân tín hiệu đó có thể “phát hiện” ra điện áp cấp vào chân tín hiệu đó (ví dụ như bạn nối chân tín hiệu đó với nút bấm). Vì đây là dạng tín hiệu số, chỉ có 2 trạng thái “tắt” và “bật”, nên ở trường hợp mặc định “tắt” sẽ tương ứng với 0V và các điện áp lớn hơn 0V đều sẽ là “bật”. Chúng ta có thể cấu hình cho chân tín hiệu vào này sao cho phù hợp với mục đích sử dụng.
1.3 Đọc trạng thái (nhấn/thả) của nút nhấn (Digital Read)
Các câu lệnh
>
-Pin(5, Pin.IN, Pin.PULL_UP): tạo 1 object (đối tượng)buttonsử dụng chân tín hiệu (Pin). Ở đây khởi tạo đối tượng led sử dụng chân tín hiệu số 5, ở chế độIN(đọc tín hiệu Digital) và chế độPULL_UP.
-PULL_UP, PULL_DOWN: ESP32 có 2 cấu hình đọc tín hiệu số là PULL_UP và PULL_DOWN. Ở chế độPULL_UP, mặc định chân tín hiệu đó sẽ được nối với 1 điện trở vào áp cao, vậy nên khi không nhấn nút giá trị đọc được sẽ là ‘1’. Ngược lại, ở chế độPULL_DOWN, khi không nhấn nút giá trị đọc được sẽ là ‘0’.
- print: in văn bản lên Shell
from machine import Pin
import time
#Cài đặt chân GPIO 5 làm input cho nút nhấn
button = Pin(5, Pin.IN, Pin.PULL_UP)
# Đọc trạng thái của nút nhấn
while True:
if button.value() == 1: # Nút được nhấn
print("Button pressed")
else:
print("Button released")
time.sleep(0.5)
- Lập trình câu lệnh điều kiện
Câu lệnh điều kiện (condition) là một dạng cấu trúc chương trình cơ bản dùng để thực hiện các công việc dựa vào các điều kiện cho trước (nếu - thì). Câu lệnh điều kiện thường có 3 phần: phần điều kiện if(expression), phần lệnh thực thi thuận (khi điều kiện đúng - True) và phần lệnh thực thi nghịch (khi điều kiện sai - False). Sơ đồ khối (flowchart) của khối lệnh điều kiện như bên dưới.

1.4 Điều khiển LED bằng nút nhấn
Các câu lệnh
>
-if button.value() == 0:: Kiểm tra điều kiện để xác định xem nút nhấn có được nhấn hay không. Trong trường hợp này,button.value()trả về giá trị0khi nút nhấn được nhấn (vì chân GPIO được cấu hình vớiPin.PULL_UP). Nếu điều kiệnbutton.value() == 0đúng, có nghĩa là nút đã được nhấn. Và ngược lại.
-else:: Nếu điều kiệnifkhông đúng (nút nhấn không được nhấn), thực hiện các câu lệnh trong khốielse.
from machine import Pin
import time
#Cài đặt chân GPIO 13 làm output cho LED
led = Pin(13, Pin.OUT)
# Cài đặt chân GPIO 5 làm input cho nút nhấn
button = Pin(5, Pin.IN, Pin.PULL_UP)
while True:
# Kiểm tra điều kiện: nút được nhấn
if button.value() == 1: # Nút được nhấn
led.on() # nếu đúng, bật đèn LED
else:
led.off() # nếu sai, tắt đèn LED
time.sleep(0.5)1.5 Chớp - tắt đèn dựa vào thời gian (số giây chẵn, lẻ)
Các câu lệnh
>
-utime: Thư việnutimetrong MicroPython cung cấp các hàm để làm việc với thời gian. Thư viện này cho phép bạn lấy thời gian hiện tại, thực hiện các phép toán thời gian, và làm việc với các khoảng thời gian.
- utime.time(): Lấy giá trị thời gian hiện tại từ hệ thống. Hàm này trả về số giây đã trôi qua kể từ một thời điểm cụ thể (epoch time), thường là thời điểm 1970-01-01 00:00:00 UTC. Giá trị này được sử dụng để kiểm tra thời gian hiện tại hoặc thực hiện các thao tác liên quan đến thời gian.
-if (current_time % 2) == 0:: Kiểm tra điều kiện để xác định xem giá trị thời gian hiện tại (current_time) có phải là số chẵn không. Câu lệnhcurrent_time % 2tính toán phần dư khi chiacurrent_timecho 2. Nếu phần dư bằng0, có nghĩa làcurrent_timelà số chẵn.
- Xem thêm về các phép toán trong Python
>
Chương trình dưới đây là ví dụ minh họa cho các phép toán trong Python. Các phép toán so sánh và logic rất hữu ích khi sử dụng câu lệnh điều kiện.
>
```python
from machine import Pin
>
# Khởi tạo biến
a = 10
b = 3
c = 5
>
# Thực hiện phép toán số học
sum_result = a + b # Cộng
difference_result = a - b # Trừ
product_result = a * b # Nhân
quotient_result = a / b # Chia
remainder_result = a % b # Chia lấy dư
power_result = a ** b # Lũy thừa
>
# In kết quả phép toán số học
print("Tổng:", sum_result)
print("Hiệu:", difference_result)
print("Tích:", product_result)
print("Thương:", quotient_result)
print("Dư:", remainder_result)
print("Lũy thừa:", power_result)
>
# Thực hiện phép toán so sánh
is_equal = (a == b) # Bằng
is_not_equal = (a != c) # Khác
is_greater = (a > c) # Lớn hơn
is_less = (a < c) # Nhỏ hơn
is_greater_equal = (a >= c) # Lớn hơn hoặc bằng
is_less_equal = (a <= b) # Nhỏ hơn hoặc bằng
>
# In kết quả phép toán so sánh
print("Bằng nhau:", is_equal)
print("Khác nhau:", is_not_equal)
print("Lớn hơn:", is_greater)
print("Nhỏ hơn:", is_less)
print("Lớn hơn hoặc bằng:", is_greater_equal)
print("Nhỏ hơn hoặc bằng:", is_less_equal)
>
# Thực hiện phép toán logic
logical_and = (a > b) and (b < c) # Và
logical_or = (a > c) or (b < c) # Hoặc
logical_not = not (a == b) # Không
>
# In kết quả phép toán logic
print("Và:", logical_and)
print("Hoặc:", logical_or)
print("Không:", logical_not)
```
>
from machine import Pin
import time
import utime
led = Pin(13, Pin.OUT)
while True:
# Lấy giá trị thời gian từ hệ thống (đơn vị là giây)
current_time = utime.time()
# Kiểm tra điều kiện: thời gian là số chẵn
if (current_time % 2) == 0:
led.on() # nếu đúng (là số chẵn), bật đèn
else:
led.off() # nếu sai, tắt đèn
#Tín hiệu tương tự (Analog Signal)
Tín hiệu tương tự (analog signal) là một loại tín hiệu mà giá trị của nó có thể thay đổi liên tục và có thể ở bất kỳ điểm nào trong một khoảng giá trị nhất định. Khác với tín hiệu số, tín hiệu tương tự không bị giới hạn trong hai trạng thái mà có thể biểu diễn một dãy liên tục các giá trị.
Trong thực tế, tín hiệu tương tự thường được biểu diễn bằng điện áp hoặc dòng điện, và mức điện áp có thể thay đổi mượt mà trong một phạm vi nhất định. Ví dụ, một tín hiệu tương tự có thể là điện áp từ 0V đến 3.3V, nơi các giá trị điện áp trung gian (như 1.5V, 2.7V, v.v.) đều có thể được đo và xử lý.



(nguồn ảnh: https://docs.arduino.cc/micropython/micropython-course/course/analog/)
Tín hiệu tương tự thường được sử dụng để biểu diễn các thông số liên tục như âm thanh, ánh sáng, nhiệt độ, hoặc bất kỳ yếu tố nào có thể thay đổi một cách liên tục. Ví dụ, cảm biến nhiệt độ có thể cung cấp một điện áp tỷ lệ với nhiệt độ đo được, và điện áp này có thể thay đổi liên tục theo nhiệt độ thực tế. Như biểu đồ bên dưới thể hiện mối quan hệ tuyến tính giữa trở kháng của nhiệt điện trở (thermistor) và nhiệt độ.

(nguồn ảnh: https://www.researchgate.net/figure/NTC-Thermistor-characteristic-curve-Resistance-R-vs-Temperature-T_fig6_329896189)
- Lập trình đọc tín hiệu tương tự
1.6 Đọc giá trị cảm biến ánh sáng
Các câu lệnh
>
-light_sensor = ADC(Pin(34)): Tạo một đối tượnglight_sensorsử dụng chân GPIO34. Trong đoạn mã này, chân GPIO 34 được cấu hình để đọc tín hiệu analog từ cảm biến ánh sáng.ADClà lớp dùng để thiết lập và đọc các giá trị từ chân analog.
-.atten(ADC.ATTN_11DB): Thiết lập mức giảm độ phân giải (attenuation) cho cảm biến ánh sáng.ADC.ATTN_11DBcho phép cảm biến đọc giá trị từ 0V đến 3.3V. Điều này giúp tăng phạm vi giá trị có thể đọc được từ cảm biến, phù hợp với điện áp tối đa của cảm biến ánh sáng.
- .read(): Đọc giá trị từ cảm biến ánh sáng. Câu lệnh này trả về giá trị là mức điện áp đo được ở chân tín hiệu sử dụng (ở đây là chân 34), tương đương với mức ánh sáng hiện tại mà cảm biến đo được. Giá trị này nằm trong khoảng từ 0 đến 4095 (12 bit), tùy thuộc vào mức độ ánh sáng mà cảm biến tiếp nhận từ môi trường.
from machine import ADC, Pin
import time
# Cài đặt chân GPIO 34 làm input cho cảm biến ánh sáng (analog)
light_sensor = ADC(Pin(34))
light_sensor.atten(ADC.ATTN_11DB) # Tăng độ phân giải đến 0-3.3V
# Đọc giá trị cảm biến ánh sáng
while True:
light_value = light_sensor.read() # Đọc giá trị ADC (0-4095)
# Chuyển đổi giá trị ADC thành Volt
voltage = (light_value / 4095) * 3.3 # Tương ứng với điện áp 0-3.3V
print("Light Sensor Value:", light_value)
print("Voltage:", voltage, "V")
time.sleep(0.3)
- Lập trình xuất xung PWM giả lập tín hiệu tương tự
PWM (Pulse Width Modulation) là một kỹ thuật sử dụng tín hiệu số (digital) để giả lập tín hiệu tương tự (analog). Thay vì gửi một dòng điện liên tục, PWM bật và tắt tín hiệu điện rất nhanh, tạo ra một chuỗi các xung điện. Bằng cách điều chỉnh thời gian tín hiệu "bật" so với thời gian tín hiệu "tắt" trong mỗi chu kỳ, ta có thể kiểm soát lượng năng lượng trung bình truyền đến thiết bị, như đèn LED hoặc động cơ.
Thời gian “bật” càng nhiều trong chu kỳ tương đương mức truyền cao hơn. Ví dụ như truyền 50% chu kỳ của điện áp 5V thì có thể tương đương với truyền một điện áp 2.5V. Điều này giúp điều chỉnh độ sáng của đèn hoặc tốc độ của động cơ, giống như cách mà tín hiệu analog hoạt động.

(nguồn ảnh: https://docs.arduino.cc/micropython/micropython-course/course/analog/)
/f
1.7 Thay đổi độ sáng của đèn LED (tăng dần rồi giảm dần)
Các câu lệnh:
>
-PWM(Pin(13), freq=5000): Khởi tạo đối tượngPWMsử dụng chân tín hiệu số13. Tần sốfreq=5000thiết lập tần số PWM là 5000 Hz (số xung mỗi giây).
-.duty(100): Thiết lập chu kỳ làm việc của xung (duty cycle) ở mức100/1023. Chu kỳ làm việc quy định thời gian xung điện ở trạng thái "bật" trong một chu kỳ, với giá trị1023tương ứng với 100% và0là 0%. Trong ví dụ này,100/1023tương ứng với khoảng 10% độ sáng tối đa của đèn LED.
from machine import Pin, PWM
import time #thư viện của các hàm thời gian
#Cài đặt chân GPIO 13 làm output cho LED với PWM
led = PWM(Pin(13), freq=5000)
#Thay đổi độ sáng đèn LED
led.duty(100) #Độ sáng ở mức 100/1023 (~10%)
time.sleep(1) #dừng chương trình 1 giây
led.duty(300) #Độ sáng ở mức 300/1023
time.sleep(1)
led.duty(1000)
time.sleep(1)
led.duty(500)
time.sleep(1)
led.duty(100)
time.sleep(1)
led.duty(0)
time.sleep(1) #tắt đèn- Lập trình vòng lặp
Vòng lặp (loop) là các câu lệnh được thực hiện lặp đi lặp lại. Vòng lặp có thể được thiết kế để lặp lại một số lần cụ thể (thường dùng for), lặp lại đến khi một điều kiện nào đó đúng (thường dùng while) hoặc lặp lại vô hạn (while True).
# Lặp số lần cố định với `for`
print("Vòng lặp số lần cố định, bắt đầu từ 0")
for i in range(5): # Lặp 5 lần từ 0 đến 4
print("Lần lặp thứ:", i)
print("Vòng lặp số lần cố định trong 1 khoảng cho trước")
for i in range(1,7): # Lặp 6 lần từ 1 đến 7
print("Lần lặp thứ:", i)
# Lặp theo điều kiện với `while`
print("Vòng lặp theo điều kiện")
count = 0
while count < 5: # Tiếp tục lặp khi `count` nhỏ hơn 5
print("Lần lặp thứ:", count)
count += 1 # Tăng giá trị của `count` mỗi lần lặp
#vòng lặp dừng lại khi count =5
1.8 Dùng vòng lặp thay đổi độ sáng của đèn
Các câu lệnh
>
-for duty in range(0, 1024, 10):: Câu lệnhfornày tạo ra một vòng lặp để thay đổi giá trị của biếndutytừ0đến1023, với bước nhảy là10. Tức là, biếndutysẽ lần lượt nhận các giá trị0,10,20, ... cho đến1023.
from machine import Pin, PWM
import time
# Cài đặt chân GPIO 13 làm output cho LED với PWM
led = PWM(Pin(13), freq=5000)
# Hiệu ứng tăng và giảm độ sáng đèn LED
while True:
# Tăng độ sáng
for duty in range(0, 1023, 10):
led.duty(duty)
time.sleep(0.01)
# Giảm độ sáng
for duty in range(1023, 0, -10):
led.duty(duty)
time.sleep(0.01)
#Giao tiếp giữa phần cứng - giao thức (Communication - Protocol)
- Giao tiếp với cảm biến
Tùy thuộc vào từng loại cảm biến, ta sẽ có những cách sử dụng riêng, đi kèm là các thư viện hỗ trợ. Cảm biến DHT11 là loại cảm biến có thể cho ta biết giá trị của nhiệt độ và độ ẩm trong không khí. DHT11 dễ sử dụng, giá thành rẻ, độ chính xác tương đối.
Cảm biến DHT11 giao tiếp với vi xử lý sử dụng giao thức One Wire. Ngoài ra, còn có các loại cảm biến sử dụng các giao thức khác, phổ biến như là I2C, SPI, UART, RS485, RS323…
1.9 Đọc giá trị nhiệt độ - độ ẩm từ cảm biến DHT11
Các câu lệnh:
>
- while True: câu lệnh vòng lặp vô hạn. Câu lệnh while bình thường sẽ thực hiện các câu lệnh bên trong khi phần điều kiện (phía sau while) vẫn đúng (True). Ở đây while True có nghĩa là miễn là phần điều kiện vẫn bằng True (True = True) thì các câu lệnh bên trong sẽ được thực hiện. Vì thế nên các câu lệnh bên trong while True sẽ được thực hiện lặp lại vô hạn (infinite loop).
import machine
import dht
import time
# Initialize DHT11 sensor on GPIO5 (you can change the GPIO pin as needed)
sensor = dht.DHT11(machine.Pin(5))
while True:
sensor.measure()
temp = sensor.temperature() # Read temperature in Celsius
hum = sensor.humidity() # Read humidity in percentage
# Print the values
print("Temperature:",temp,"°C")
print("Humidity: {}%".format(hum))
time.sleep(1)
- Giao tiếp với máy tính - giao thức UART
Giao thức UART (Universal Asynchronous Receiver/Transmitter) là một phương thức truyền thông nối tiếp được sử dụng rộng rãi để trao đổi dữ liệu giữa các thiết bị, chẳng hạn như giữa máy tính và cảm biến.
- Máy tính: Máy tính có thể giao tiếp với các thiết bị ngoại vi như cảm biến thông qua cổng UART, thường là cổng USB với một bộ chuyển đổi USB-to-UART. Khi kết nối, dữ liệu từ cảm biến có thể được truyền về máy tính để xử lý hoặc lưu trữ.
- Cảm biến: Nhiều cảm biến sử dụng giao thức UART để gửi dữ liệu đến vi điều khiển hoặc máy tính. Các loại cảm biến này thường có các giá trị trả về phức tạp hơn các cảm biến thông thường (chỉ thay đổi giá trị điện áp hoặc các tín hiệu đơn giản) hoặc đi kèm bộ chuyển đổi các giao tiếp khác (phổ biến là các cảm biến công nghiệp theo chuẩn RS485).
1.10 Giao tiếp với ESP32 qua máy tính
[Cách 1] “Nói chuyện” với ESP32. Bạn nhập vào các chuỗi “hello”, “name”để xem ESP32 trả lời như thế nào nhé. Cách này chỉ dành riêng cho giao tiếp với máy tính thông qua cổng USB, rất đơn giản và dễ hiểu.
Các câu lệnh:
>
-input("Enter a command: "): Tạo câu lệnh để người dùng nhập vào một chuỗi ký tự từ bàn phím. Khi câu lệnh này được thực thi, chương trình sẽ dừng lại và chờ người dùng nhập vào một chuỗi ký tự rồi nhấn Enter. Chuỗi ký tự này sẽ được lưu vào biếnuser_input.
while True:
# Tạo câu lệnh để nhập vào
user_input = input("Enter a command: ")
# In đoạn lệnh bạn vừa nhập vào
print("You entered:", user_input)
if user_input.lower() == "hi":
print("Hello!")
elif user_input.lower() == "name":
print("My name is ESP32.")
else:
print("Invalid input")
[Cách 2] “Nói chuyện” với ESP32. Bạn nhập vào các chuỗi “hello”, “name”, "language" hoặc "bye" để xem ESP32 trả lời như thế nào nhé. Cách này sẽ giống với giao thức UART nguyên bản nhất, các câu lệnh sẽ giống với khi các bạn giao tiếp với các cảm biến, phần cứng khác trực tiếp qua cổng UART trên bo mạch.
Các câu lệnh:
>
- uart = UART(1, baudrate=115200, tx=1, rx=3):
- UART(1, ...): Tạo một đối tượng UART trên kênh 1 của ESP32.
- baudrate=115200: Cấu hình tốc độ truyền thông (baud rate) là 115200 bps (bit per second).
- tx=1, rx=3: Chỉ định chân GPIO1 là TX (truyền dữ liệu) và chân GPIO3 là RX (nhận dữ liệu).
- Lưu ý: với chân UART1, thì bắt buộc chân tx=1 và rx=3.
-.any(): Kiểm tra xem có dữ liệu nào sẵn sàng để đọc từ UART không. Trả về số lượng byte có sẵn để đọc. Nếu không có dữ liệu nào, trả về0.
-.read(): Đọc dữ liệu từ bộ đệm UART. Dữ liệu trả về là một chuỗi byte (bytes). Nếu không có dữ liệu, nó trả vềNone.
-.decode('utf-8'): Giải mã chuỗi byte vừa đọc từ bộ đệm UART thành chuỗi ký tự (string) theo chuẩn mã hóa UTF-8.
- .strip(): Loại bỏ các ký tự khoảng trắng (như dấu cách, dấu tab, dấu xuống dòng) ở đầu và cuối chuỗi ký tự đã giải mã.
-.write(): Gửi chuỗi ký tự"nội dung"từ ESP32 qua cổng UART.
from machine import UART
import time
# Initialize UART with default pins (TX=GPIO1, RX=GPIO3)
uart = UART(1, baudrate=115200, tx=1, rx=3)
def check_input():
if uart.any(): # Check if there's any data available to read
received_data = uart.read().decode('utf-8').strip() # Read and decode the data
if received_data.lower() == "hello":
uart.write("hi\n")
if received_data.lower() == "name":
uart.write("my name is ESP32\n")
if received_data.lower() == "language":
uart.write("my language is Python\n")
if received_data.lower() == "bye":
uart.write("goodbye!\n")
time.sleep(0.01) # Small delay to prevent overloading the CPU
while True:
check_input()Sau khi nạp chương trình trên, bạn có thể nhập các đoạn lệnh vào phần Shell trên Thonny để xem các phản hồi từ ESP32 nhé.

#Hàm (Function)
Trong lập trình, hàm (function) là một khối các câu lệnh được quy định và đặt tên trước. Các câu lệnh này sẽ thực hiện các công việc cụ thể. Các hàm có thể được gọi lại trong chương trình để sử dụng.
Cấu trúc của 1 hàm bao gồm
#tạo hàm, bao gồm tên hàm (tham số 1, tham số 2,...)
def function_name(param1, param2, param3):
#các câu lệnh
return result # giá trị trả về của hàm
Tùy vào mục đích sử dụng và thiết kế của hàm, các hàm được chi thành 2 dạng là hàm thực thi và hàm có trả về giá trị.
- Hàm thực thi
Hàm thực thi là hàm thực hiện các công việc cụ thể và không trả về giá trị (không có lệnh return. Các hàm này khi được gọi lại chỉ cần gọi tên_hàm(các tham số)
1.13 Hàm điều khiển LED theo giá trị của cảm biến ánh sáng
from machine import ADC, Pin, PWM
import time
# Cài đặt chân GPIO 34 cho cảm biến ánh sáng (analog)
light_sensor = ADC(Pin(34))
light_sensor.atten(ADC.ATTN_11DB) # Phạm vi đọc giá trị từ 0 đến 3.3V
# Cài đặt chân GPIO 13 cho LED với PWM
led = PWM(Pin(13), freq=5000)
def led_control():
light_value = light_sensor.read() # Đọc giá trị cảm biến ánh sáng trong khoảng từ 0 - 40
led_brightness = int(light_value / 4) # Chia cho 4 để giá trị trong khoảng 0-1023
led.duty(led_brightness) # Điều chỉnh độ sáng đèn LED
time.sleep(0.1) # Thêm độ trễ nhỏ để tránh làm quá tải CPU
# Gọi hàm để bắt đầu điều khiển độ sáng đèn LED
while True:
led_control()
- Hàm trả về giá trị
Hàm có trả về giá trị là hàm thực hiện các công việc cụ thể và có trả về giá trị. Các hàm này khi sử dụng sẽ giống như một “giá trị”, có thể dùng để gán vào biến, so sánh, tính toán hoặc in ra màn hình.
1.14 Hàm đọc giá trị nhiệt độ từ cảm biến theo thang Celsius (độ C) và đổi sang hệ Fahrenheit (độ F)
import machine
import dht
import time
# Initialize DHT11 sensor on GPIO5 (you can change the GPIO pin as needed)
sensor = dht.DHT11(machine.Pin(5))
def celsius_to_fahrenheit(celsius):
fahrenheit = (celsius * 9/5) + 32
return fahrenheit
while True:
sensor.measure() # Đọc giá trị từ cảm biến DHT
temp_celsius = sensor.temperature()
temp_fahrenheit = celsius_to_fahrenheit(temp_celsius) # đổi giá trị nhiệt độ từ C sang F
print("Temperature in Celsius:",temp_celsius,"°C")
print("Temperature in Fahrenheit:",temp_fahrenheit,"°F")
time.sleep(1)
#Hệ thống tệp tin (File system)
ESP32 có bộ nhớ để lưu trữ các thư mục và tệp tin. Các tệp tin có thể được lưu trữ dưới nhiều định dạng khác nhau (thường là các file dạng văn bản hoặc dạng script dành cho các ngôn ngữ như html, css, js, python…) và có thể được sử dụng lại trong các chương trình. Khi lập trình Python trên ESP32, bạn có thể lưu các chương trình lại, đặt tên và sử dụng khi cần thiết dưới dạng các file .py trực tiếp trên bộ nhớ của ESP32 và có thể sao chép lại các chương trình này vào máy..
Hệ thống tệp tin của microPython trên ESP32 có 2 file mặc định, bao gồm:
boot.py: File này sẽ chạy đầu tiên khi ESP32 được cấp điện. Thường dùng để nạp các thư viện quan trọng hoặc thiết đặt ban đầu (như kết nối wifi, đăng nhập thiết bị…).
main.py: File chương trình chính, file này sẽ chạy ngay sau file boot và thường sẽ là nơi chứa chương trình mà bạn muốn ESP32 thực hiện chính.
Lưu ý: nếu bạn muốn ESP32 của mình thực hiện tự động chạy chương trình khi cấp điện (mà không cần điều khiển trên máy tính qua Thonny) thì các bạn PHẢI LƯU chương trình của mình sau khi lập trình xong với tên main.py lên bộ nhớ của ESP32.

Kiến trúc máy tính JVM
Khi sử dụng Thonny để lập trình cho phần cứng ESP32, bạn có thể dễ dàng lưu chương trình, copy các file từ máy lên bo mạch và ngược lại, tạo và sắp xếp các thư mục trên bo mạch… Video bên dưới sẽ hướng dẫn chi tiết các thao tác từ máy tính với hệ thống tệp tin trên bo mạch ESP32
Thonny File Transfer: How to Easily Move Files Between Device and Local Computer (Beginner Tutorial)
- Chạy một file chương trình khác (câu lệnh exec)
Ví dụ dưới đây là cho việc đọc và thực thi một chương trình trong một file .py khác bằng lệnh Python
Đầu tiên bạn tạo 1 file khác và lưu lại trên ESP32 với tên script.py
from machine import Pin
import time
# Set up GPIO 13 for the LED
led = Pin(13, Pin.OUT)
print("running script.py")
# Blink the LED 5 times
for i in range(5):
led.on() # Turn the LED on
time.sleep(0.5) # Wait 0.5 seconds
led.off() # Turn the LED off
time.sleep(0.5) # Wait 0.5 seconds
Sau đó bạn mở một file mới và nhập đoạn code này
with open('script.py', 'r') as file:
code = file.read() # Read the contents of the file
exec(code) Bạn sẽ thấy phần code bên trong script.py được chạy. Đây là một cách đơn giản để gọi lại một chương trình khác trong Python. Ngoài ra còn một số cách khác như đóng gói chương trình Python lại thành một package và gọi lại như các thư viện khác trong Python.
#Bài tập
Tạo 1 trang Notion cá nhân và publish trang Notion. Đây sẽ là trang Notion để chứa các bài tập của bạn. Các bạn tự điền link đến trang Notion của mình vào bảng này: https://docs.google.com/spreadsheets/d/1hL7HubaNWLuZLgsl1U_ivcy24e1EZTMo6OacILEbbz8/edit?usp=sharing

Tạo tài khoản trên Kaggle và hoàn thành 2 khóa học này. Nhận chứng chỉ và upload 2 chứng chỉ đấy lên trang Notion bài tập.
Learn Intro to Programming Tutorials
#Video ghi lại
https://www.youtube.com/watch?v=1Ky3rZb9gPo
Bài tập tặng kèm:
Bên dưới là danh sách các Cảm biến và Module chức năng của MakerEDU tương thích với bộ kit lập trình của khóa học:
https://hshop.vn/makeredu-module
https://hshop.vn/makeredu-sensor
Các bạn hãy vào xem và tra cứu thông tin để hoàn thành 2 cột còn trống (Loại tín hiệu và Hình ảnh) của các thiết bị này. Các bạn có thể thực hiện bài tập trên Excel hoặc chỉnh sửa trên Notion của các bạn (bằng cách duplicate trang Notion này).
*nâng cao: các bạn có thể nghĩ đến 1 dự án sáng tạo sử dụng các thiết bị này và chia sẻ với lớp trong buổi học sau
| Tên Module/Cảm Biến | Loại tín hiệu | Mô tả ngắn | Hình ảnh |
|---|---|---|---|
| Cảm biến siêu âm MKE-S01 | Đo khoảng cách bằng sóng siêu âm, dùng cho robot tránh vật cản. | ||
| Cảm biến ánh sáng MKE-S02 (LDR) | Phát hiện cường độ ánh sáng môi trường. | ||
| Cảm biến lửa MKE-S04 (Flame IR) | Phát hiện ngọn lửa hoặc nguồn nhiệt. | ||
| Cảm biến âm thanh MKE-S06 | Nhận diện âm thanh, có ngưỡng kích hoạt. | ||
| Cảm biến khí gas MKE-S08 (MQ-2) | Phát hiện khí gas như LPG, CO, CH4. | ||
| Cảm biến chất lượng không khí MQ-135 | Đo chất lượng không khí, phát hiện khí độc. | ||
| Cảm biến dò đường MKE-S10 (CNY70) | Robot dò đường, nhận diện vạch đen/trắng. | ||
| Cảm biến vật cản hồng ngoại MKE-S11 | Phát hiện vật cản bằng tia hồng ngoại. | ||
| Cảm biến mưa MKE-S12 | Phát hiện nước mưa, ứng dụng tự động đóng cửa sổ. | ||
| Cảm biến độ ẩm đất MKE-S13 | Đo độ ẩm đất, dùng cho hệ thống tưới tự động. | ||
| Cảm biến nhiệt độ và độ ẩm DHT11 | Đo nhiệt độ và độ ẩm, giao tiếp 1-Wire. | ||
| Cảm biến nhiệt độ DS18B20 | Đầu dò chống nước, đo nhiệt độ chất lỏng. |