#Module 1: Lập trình Python cơ bản
#1. 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:
- Kết nối không dây:
- 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
- GPIO và giao tiếp
- 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
16 MB Flash + 8 MB PSRAM (N16R8) 4 MB Flash không PSRAM (N4) 16 MB Flash không PSRAM (N16)
Wi-Fi 802.11 b/g/n (2.4 GHz) Bluetooth Low Energy BLE5
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ợ
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
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

#2. 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
#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
#3. Lập trình microPython
#3.1. 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".



#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)ledsử dụng chân tín hiệu (Pin, GPIO). Ở đây khởi tạo đối tượngledsử 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 trong số giây.
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 (infinite loop).
Câu lệnh while bình thường sẽ thực hiện các câu lệnh bên trong khi điều kiện (phía sau while) vẫn đúng (True). Ở đây, while True có nghĩa là điều kiện luôn bằng True, nên các câu lệnh bên trong sẽ được thực hiện lặp lại vô hạn.
.value(): Thay đổi giá trị của tín hiệu xuất ra thành0hoặc1, tương đương với lệnh.off()hoặc.on().
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 một object (đối tượng)buttonsử dụng chân tín hiệu (Pin). Ở đây, khởi tạo đối tượngbuttonsử 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_UPvàPULL_DOWN.- Ở chế độ
PULL_UP, mặc định chân tín hiệu sẽ được nối với điện áp cao thông qua một điện trở, 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 hoặc giá trị lên Shell để theo dõi kết quả khi chương trình chạy.
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.
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 lấy thời gian hiện tại, thực hiện các phép toán về 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à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 hay không.
Câu lệnh current_time % 2 tính phần dư khi chia current_time cho 2. Nếu phần dư bằng 0, có nghĩa là current_time là 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.
[updating]
#3.2. 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 GPIO34đượ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ị trong khoảng từ0Vđến3.3V. Điều này giúp tăng phạm vi điện áp có thể đọc được, 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ị tín hiệu analog đo được tại chân tín hiệu (ở đây là chân34), tương ứng với mức ánh sáng mà cảm biến nhận được từ môi trường. Giá trị thường nằm trong khoảng từ0đến4095(12 bit), tùy thuộc vào mức độ ánh sáng mà cảm biến tiếp nhận.
[updating]
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/)
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(5000 xung mỗi giây).
.duty(100): Thiết lập chu kỳ làm việc (duty cycle) của xung ở mức100/1023. Chu kỳ làm việc quy định tỷ lệ 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ới100%và0tương ứng với0%. Trong ví dụ này,100/1023tương ứng với khoảng10%độ sáng tối đa của đèn LED.
[updating]
Lập trình vòng lặp
Vòng lặp (Loop)
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). - Lặp lại vô hạn (
while True).
Ví dụ:
- Điện áp từ 0V đến 3.3V
- Các giá trị trung gian như 1.5V, 2.7V,... đều có thể được đo và xử lý.
