Makerlab.vn
PROJECT
PROJECT / MAKERLAB.VN

mardown test 2

2 Column 1 Content Column 2 Content 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 image.png Thông số kỹ thuật Nguồn h

#Column 1

Content

#Column 2

Content

#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

![image.png](Module%201%20L%E1%BA%ADp%20tr%C3%ACnh%20Python%20c%C6%A1%20b%E1%BA%A3n/image.png)

  • 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

![image.png](Module%201%20L%E1%BA%ADp%20tr%C3%ACnh%20Python%20c%C6%A1%20b%E1%BA%A3n/image%201.png)

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

![image.png](Module%201%20L%E1%BA%ADp%20tr%C3%ACnh%20Python%20c%C6%A1%20b%E1%BA%A3n/image%202.png)

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

![image.png](Module%201%20L%E1%BA%ADp%20tr%C3%ACnh%20Python%20c%C6%A1%20b%E1%BA%A3n/image%203.png)

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

![image.png](Module%201%20L%E1%BA%ADp%20tr%C3%ACnh%20Python%20c%C6%A1%20b%E1%BA%A3n/image%204.png)

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

![image.png](Module%201%20L%E1%BA%ADp%20tr%C3%ACnh%20Python%20c%C6%A1%20b%E1%BA%A3n/image%205.png)

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

![image.png](Module%201%20L%E1%BA%ADp%20tr%C3%ACnh%20Python%20c%C6%A1%20b%E1%BA%A3n/image%206.png)

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

![image.png](Module%201%20L%E1%BA%ADp%20tr%C3%ACnh%20Python%20c%C6%A1%20b%E1%BA%A3n/image%207.png)

  • ESP32-S3 Pin-out quick reference

![image.png](Module%201%20L%E1%BA%ADp%20tr%C3%ACnh%20Python%20c%C6%A1%20b%E1%BA%A3n/image%208.png)

#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".

![digi1.gif](Module%201%20L%E1%BA%ADp%20tr%C3%ACnh%20Python%20c%C6%A1%20b%E1%BA%A3n/digi1.gif)

![Screenshot 2024-08-31 at 23.42.50.png](Module%201%20L%E1%BA%ADp%20tr%C3%ACnh%20Python%20c%C6%A1%20b%E1%BA%A3n/Screenshot_2024-08-31_at_23.42.50.png)

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

![giphy.gif](Module%201%20L%E1%BA%ADp%20tr%C3%ACnh%20Python%20c%C6%A1%20b%E1%BA%A3n/giphy.gif)

  • 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 trong số giây
PYTHON
    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()
PYTHON
    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) button sử 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
PYTHON
    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.

![image.png](Module%201%20L%E1%BA%ADp%20tr%C3%ACnh%20Python%20c%C6%A1%20b%E1%BA%A3n/image%209.png)

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ị 0 khi nút nhấn được nhấn (vì chân GPIO được cấu hình với Pin.PULL_UP). Nếu điều kiện button.value() == 0 đúng, có nghĩa là nút đã được nhấn. Và ngược lại.
- else:: Nếu điều kiện if không đúng (nút nhấn không được nhấn), thực hiện các câu lệnh trong khối else.
PYTHON
    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ện utime trong 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ệnh current_time % 2 tính toán 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.

>

```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)
```

>

PYTHON
    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ý.

![torch ana.gif](Module%201%20L%E1%BA%ADp%20tr%C3%ACnh%20Python%20c%C6%A1%20b%E1%BA%A3n/torch_ana.gif)

![analog1a.gif](Module%201%20L%E1%BA%ADp%20tr%C3%ACnh%20Python%20c%C6%A1%20b%E1%BA%A3n/analog1a.gif)

![analog.gif](Module%201%20L%E1%BA%ADp%20tr%C3%ACnh%20Python%20c%C6%A1%20b%E1%BA%A3n/analog.gif)

(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 độ.

![image.png](Module%201%20L%E1%BA%ADp%20tr%C3%ACnh%20Python%20c%C6%A1%20b%E1%BA%A3n/image%2010.png)

(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ượng light_sensor sử dụng chân GPIO 34. 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. ADC là 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_11DB cho 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.
PYTHON
    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.

![pwm.gif](Module%201%20L%E1%BA%ADp%20tr%C3%ACnh%20Python%20c%C6%A1%20b%E1%BA%A3n/pwm.gif)

(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ượng PWM sử dụng chân tín hiệu số 13. Tần số freq=5000 thiế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ức 100/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ị 1023 tương ứng với 100% và 0 là 0%. Trong ví dụ này, 100/1023 tương ứng với khoảng 10% độ sáng tối đa của đèn LED.
PYTHON
    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).

PYTHON
    # 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ệnh for này tạo ra một vòng lặp để thay đổi giá trị của biến duty từ 0 đến 1023, với bước nhảy là 10. Tức là, biến duty sẽ lần lượt nhận các giá trị 0, 10, 20, ... cho đến 1023.
PYTHON
    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).
PYTHON
    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ến user_input.
PYTHON
    
    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.
PYTHON
    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é.

![Screenshot 2024-09-01 at 05.10.26.png](Module%201%20L%E1%BA%ADp%20tr%C3%ACnh%20Python%20c%C6%A1%20b%E1%BA%A3n/Screenshot_2024-09-01_at_05.10.26.png)

#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

PYTHON
#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

PYTHON
    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)

PYTHON
    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](Module%201%20L%E1%BA%ADp%20tr%C3%ACnh%20Python%20c%C6%A1%20b%E1%BA%A3n/image%2011.png)

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

PYTHON
    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

PYTHON
    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

![Screenshot 2024-09-06 at 18.29.07.png](Module%201%20L%E1%BA%ADp%20tr%C3%ACnh%20Python%20c%C6%A1%20b%E1%BA%A3n/Screenshot_2024-09-06_at_18.29.07.png)

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

Learn Python 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ếnLoại tín hiệuMô tả ngắnHì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-S06Nhậ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-S11Phát hiện vật cản bằng tia hồng ngoại.
Cảm biến mưa MKE-S12Phá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.