Trong hướng dẫn này, chúng ta sẽ tìm hiểu cách định cấu hình và xử lý các ngắt trong bảng phát triển ESP32 và ESP8266 bằng MicroPython. Chúng tôi sẽ chứng minh điều này thông qua một ví dụ với cảm biến PIR và đèn LED
điều kiện tiên quyết
Để hiểu hoàn toàn hướng dẫn này, bạn nên biết cách sử dụng bảng ESP32 và ESP8266 với MicroPython bằng cách sử dụng bất kỳ IDE nào được MicroPython hỗ trợ như uPyCraft IDE và Thonny IDE. Nếu bạn chưa có hiểu biết trước về các IDE này, bạn nên đọc các hướng dẫn bắt đầu này
- Bắt đầu với MicroPython bằng uPyCraft IDE và ESP32/ESP8266
Nếu bạn đang sử dụng Thonny IDE, bạn có thể xem hướng dẫn bắt đầu này
- Bắt đầu với Thonny MicroPython IDE cho ESP32 và ESP8266
Đầu tiên chúng ta hãy xem phần giới thiệu về ngắt và ứng dụng của ngắt là gì, đặc biệt là trong các hệ thống nhúng
Ngắt giới thiệu?
Ngắt được sử dụng để xử lý các sự kiện không xảy ra trong quá trình thực hiện tuần tự chương trình. Ví dụ: chúng tôi muốn thực hiện một số tác vụ nhất định và các tác vụ này thực hiện tuần tự trong chương trình MicroPython của bạn. Nhưng có một số tác vụ chỉ thực thi khi một sự kiện đặc biệt xảy ra, chẳng hạn như tín hiệu kích hoạt bên ngoài đến chân đầu vào kỹ thuật số của vi điều khiển
Ngắt bên ngoài hoặc 'ngắt phần cứng' là do mô-đun phần cứng bên ngoài gây ra. Ví dụ: có Ngắt cảm ứng xảy ra khi phát hiện cảm ứng và ngắt GPIO khi nhấn một phím
Khác nhau giữa thực thi theo hướng tuần tự và theo sự kiện?
Trong hướng dẫn trước của chúng tôi, nơi chúng tôi điều khiển đèn LED được kết nối với một trong các chân GPIO của ESP32 và ESP8266 với sự trợ giúp của nút ấn. Nút nhấn này được kết nối với chân đầu vào kỹ thuật số của ESP32/ESP8266. Trong mã MicroPython đó, chúng ta phải liên tục theo dõi trạng thái của chân đầu vào kỹ thuật số mà nút nhấn được kết nối. Để đáp ứng với trạng thái của đầu vào kỹ thuật số, chúng tôi đã điều khiển đèn LED. Nhưng một nhược điểm chính của phương pháp này là chúng ta phải kiểm tra trạng thái của đầu vào kỹ thuật số mỗi lần trong quá trình thực hiện tuần tự ngay cả khi người dùng không nhấn nút. Đó là một sự lãng phí năng lượng và tài nguyên xử lý của vi điều khiển
Điều gì xảy ra khi xảy ra gián đoạn?
Với ngắt, chúng ta không cần kiểm tra mà kiểm tra liên tục trạng thái của chân đầu vào kỹ thuật số. Khi xảy ra ngắt (phát hiện thay đổi), bộ xử lý dừng thực thi chương trình chính và một chức năng được gọi là ISR hoặc Quy trình dịch vụ ngắt. Sau đó, bộ xử lý tạm thời làm việc trên một tác vụ khác (ISR) và sau đó quay lại chương trình chính sau khi quy trình xử lý kết thúc. Điều này được thể hiện trong hình bên dưới
Một ví dụ có thể là nhấn nút ấn hoặc phát hiện chuyển động bằng Cảm biến PIR. Trong cả hai trường hợp, có thể sử dụng nút ấn hoặc cảm biến chuyển động PIR để kích hoạt ngắt. Do đó, khi một sự kiện bên ngoài xảy ra, bộ xử lý sẽ dừng công việc đang làm và thực hiện quy trình dịch vụ ngắt mà chúng ta xác định cho sự kiện tương ứng. Sau đó, nó quay trở lại chương trình hiện tại. Ngắt ngoài cực kỳ hữu ích vì với sự trợ giúp của chúng, chúng tôi không phải liên tục theo dõi trạng thái chân đầu vào kỹ thuật số
Chân ngắt ESP32 và ESP8266
Chân ngắt ESP32
Đối với ESP32, chúng ta có thể sử dụng tất cả các chân GPIO cho ngắt ngoài ngoại trừ GPIO6, GPIO7, GPIO8, GPIO9, GPIO10 và GPIO11. Sơ đồ bên dưới cho thấy chân ra khỏi chân GPIO trong ESP32 có thể được sử dụng
Chân ngắt ESP8266
Đối với ESP8266, chúng ta có thể sử dụng tất cả các chân GPIO ngoại trừ GPIO16 để tạo ngắt ngoài. Hình dưới đây cho thấy các chân GPIO có thể được sử dụng
Định cấu hình ngắt trong MicroPython
Bây giờ chúng ta hãy xem cách thiết lập các ngắt bên ngoài trong bảng phát triển ESP32 và ESP8266 của chúng tôi bằng MicroPython. Cần tuân theo các bước sau
Xác định chức năng xử lý ngắt
def handle_interrupt(pin):Chức năng xử lý ngắt được xác định một cách cực kỳ dễ dàng. Nó cần đơn giản để bộ xử lý có thể nhanh chóng quay lại chương trình chính. Điều này có thể đạt được bằng cách tạo một biến toàn cục có thể được truy cập bởi tất cả mọi người trong trường hợp của chúng tôi, chúng tôi sẽ sử dụng biến 'Pin'. Biến pin sẽ hoạt động như một tham số bên trong hàm xử lý ngắt của chúng ta như sau handle_interrupt(pin). Dòng này hiển thị GPIO được liên kết với chân gây ra gián đoạn
Đặt GPIO làm đầu vào sẽ hoạt động như một chân ngắt
input=Pin(2,Pin.IN)Để lấy giá trị của một GPIO, chúng ta sẽ tạo một đối tượng Pin và đặt nó làm đầu vào bằng cách sử dụng 'Pin'. IN' làm đối số thứ hai trong lớp Pin() của chúng tôi. Trong ví dụ trên, đầu vào là GPIO2 mà chúng tôi đã chỉ định trong đối số đầu tiên. Điều này được lưu trữ trong đối tượng 'đầu vào'. Bạn có thể chọn bất kỳ tên đối tượng nào bạn muốn
Gắn ngắt vào chốt
đầu vào. irq(kích hoạt=Pin. IRQ_RISING, handler=handle_interrupt)
Trong bước này, chúng ta sẽ gắn ngắt vào chân mà chúng ta đã chỉ định trước đó bằng cách sử dụng phương thức irq(). Trong phương thức này, chúng tôi chuyển hai đối số là trình kích hoạt và trình xử lý
- cò súng. Có ba điều kiện khác nhau mà chúng ta có thể chọn
Ghim. IRQ_RISING. Điều này được sử dụng để kích hoạt ngắt khi chân đi từ THẤP lên CAO
Ghim. IRQ_FALLING. Điều này được sử dụng để kích hoạt ngắt khi chân chuyển từ CAO xuống THẤP
Ghim. IRQ_FALLING. Ghim. IRQ_RISING. Điều này được sử dụng để kích hoạt ngắt khi phát hiện bất kỳ thay đổi nào, nghĩa là nó có thể ở mức CAO-THẤP hoặc THẤP-CAO
MicroPython cũng hỗ trợ sự kiện kích hoạt ở mức thấp hoặc cao bằng Pin. IRQ_LOW_LEVEL và Ghim. IRQ_HIGH_LEVEL tương ứng
- xử lý. hàm handle_interrupt() được truyền dưới dạng tham số thứ hai trong phương thức irq(). Chức năng này được gọi bất cứ khi nào một ngắt được phát hiện
Ngắt bên ngoài sử dụng Cảm biến PIR trong ESP32 và ESP8266
Bây giờ chúng ta sẽ tìm hiểu cách xử lý các ngắt trong bảng ESP32 và ESP8266 bằng Cảm biến PIR và đèn LED. Đối với mục đích trình diễn, chúng tôi sẽ sử dụng cảm biến phát hiện chuyển động PIR. Khi cảm biến PIR phát hiện chuyển động, chúng ta sẽ bật đèn LED trong 5 giây như hình bên dưới
Các thành phần sau đây được yêu cầu
- Ban phát triển ESP32/ESP8266
- Một cảm biến PIR
- Một đèn LED 5 mm
- Một điện trở 220 ohm
- Một điện trở 10k ohm
- bánh mì
- kết nối dây
Cảm biến chuyển động PIR với ESP32 và ESP8266
Chúng tôi sẽ sử dụng cùng một chân GPIO cho cả hai mô-đun ESP32/ESP8266. Lắp ráp mạch của bạn như trong sơ đồ bên dưới cho ESP8266 và ESP32 tương ứng
Sơ đồ nguyên lý ESP32 và ESP8266 với cảm biến PIR
Trong sơ đồ trên, chúng ta có thể thấy rằng GPIO14 được kết nối với chân cực dương của đèn LED và chân cực âm được kết nối với điểm chung thông qua điện trở 220 ohm
Cảm biến PIR mà chúng tôi đang sử dụng trong hướng dẫn này bao gồm ba chân. Hai trong số đó là các chân cấp nguồn như Vcc và chân nối đất. Chúng ta có thể cấp nguồn cho cảm biến chuyển động PIR trực tiếp từ các chân nguồn ESP32 và ESP8266 như trong sơ đồ trên. Chân trung tâm là chân đầu ra cung cấp xung cao hoạt động bất cứ khi nào phát hiện chuyển động. Mặt khác, chân này vẫn hoạt động ở mức thấp. Điều đó có nghĩa là cạnh tăng lên xảy ra khi cảm biến PIR phát hiện chuyển động. Chúng ta có thể phát hiện cạnh tăng này với sự trợ giúp của các chân ngắt của ESP32 và ESP8266
Cảm biến PIR hoạt động như thế nào với Ngắt ngoài?
Cảm biến PIR hoạt động như một nguồn cho ngắt ngoài. Nghĩa là ta nối ngõ ra của cảm biến PIR với chân GPIO của ESP32 và ESP8266. Hơn nữa, chúng tôi gắn ngắt kích hoạt cạnh lên vào chân GPIO này. Điều đó có nghĩa là chân GPIO này sẽ kích hoạt ngắt bất cứ khi nào nó cảm nhận được cạnh tăng trên đầu vào của nó
Ban đầu, đèn LED trạng thái sẽ nhấp nháy sau 1 giây. Khi cảm biến PIR phát hiện chuyển động, gây ra ngắt bên ngoài, đèn LED sẽ sáng trong 10 giây rồi quay trở lại trạng thái nhấp nháy bình thường (bật/tắt với độ trễ 1 giây). Hình dưới đây cho thấy quá trình
Ngắt Tập lệnh MicroPython
Tạo một tệp mới trong uPyCraft hoặc Thonny IDE và sao chép mã này vào tệp mới tạo của bạn. Sau đó tải xuống và chạy tập lệnh MicroPython này trên ESP32 và ESP8266
from machine import Pin #importing classes from time import sleep #Import sleep from time class Motion_Detected = False #Global variable to hold the state of motion sensor def handle_interrupt(Pin): #defining interrupt handling function global Motion_Detected Motion_Detected = True led=Pin(14,Pin.OUT) #setting GPIO14 led as output PIR_Interrupt=Pin(13,Pin.IN) # setting GPIO13 PIR_Interrupt as input #Attach external interrupt to GPIO13 and rising edge as an external event source PIR_Interrupt.irq(trigger=Pin.IRQ_RISING, handler=handle_interrupt) while True: if Motion_Detected: print('Motion is detected!') led.value(1) sleep(20) led.value(0) print('Motion is stopped!') Motion_Detected = False else: led.value(1) #led is on sleep(1) #delay of 1 second led.value(0) #led is off sleep(1) #delay of 1 secondMã hoạt động như thế nào?
Nhập thư viện MicroPython
Bây giờ, hãy xem hoạt động của một tập lệnh MicroPython. Để sử dụng ngắt trong MicroPython, Chúng ta nên nhập lớp GPIO từ mô-đun máy. Vì lớp GPIO chứa các phương thức cấu hình ngắt cho ESP32 và ESP8266. Chúng ta cũng nên nhập mô-đun ngủ để chèn độ trễ trong tập lệnh MicroPython của mình
from machine import Pin from time import sleepTạo biến toàn cầu MicroPython
Tiếp theo, tạo một biến toàn cục với bất kỳ tên nào để chỉ trạng thái của cảm biến chuyển động PIR. Chúng tôi đã xác định một biến toàn cục có tên là “Motion_Detected” và giá trị của biến toàn cục này có thể là True hoặc False. Để biểu thị trạng thái của cảm biến PIR, chúng ta sẽ đặt giá trị biến toàn cục thành True mỗi khi xảy ra ngắt do cảm biến PIR phát hiện chuyển động. Ban đầu đặt giá trị của biến này thành Sai
Motion_Detected = False #Global variable to hold the state of motion sensorXác định hàm xử lý ngắt
Tiếp theo, chúng ta xác định chức năng xử lý ngắt mà chúng ta đã học trong phần xử lý ngắt. Tham số pin cho chức năng xử lý ngắt chẳng hạn như handle_interrupt(), là một thể hiện của lớp pin. Trường hợp này cho biết chân GPIO nào đã gây ra ngắt
def handle_interrupt(Pin): #defining interrupt handling function global Motion_Detected Motion_Detected = TrueBên trong hàm xử lý ngắt, chúng tôi đặt biến toàn cục “Motion_Detected” thành giá trị logic True và chúng tôi sẽ sử dụng giá trị này bên trong vòng lặp while để thực thi mã chỉ thực thi khi xảy ra ngắt. Chắc hẳn bạn đang thắc mắc tại sao chúng ta không thực thi mã liên quan đến cảm biến PIR bên trong hàm handle_interrupt() thay vì thực thi nó bên trong vòng lặp while(). Điều này là do nên giữ các quy trình dịch vụ ngắt càng ngắn càng tốt để cải thiện độ trễ ngắt
Điều đó có nghĩa là chúng ta nên thực hiện số lệnh tối thiểu có thể bên trong hàm gọi lại ngắt. Đó là lý do tại sao chúng tôi chỉ thay đổi trạng thái của biến “Motion_Detected” bên trong ISR và sẽ thực hiện các chức năng còn lại bên trong mã chính
Ghi chú. “Motion_Detected” là một biến toàn cầu. Do đó, chúng ta có thể sử dụng nó trong suốt quá trình thực hiện chương trình
Tạo phiên bản ghim
Tạo hai phiên bản của lớp Pin một cho đèn LED đầu ra và phiên bản thứ hai cho các chân đầu vào ngắt bên ngoài
Để bật hoặc tắt GPIO, chúng tôi sẽ đặt nó làm đầu ra. Đối số đầu tiên trong lớp Pin() là số pin mà chúng tôi đang định cấu hình đầu ra. Đầu ra là trên GPIO14 được kết nối với đèn LED. Đối số thứ hai cho thấy chế độ pin e. g. chế độ đầu vào kỹ thuật số hoặc đầu ra kỹ thuật số. Vì chúng tôi đang định cấu hình chân 14 làm đầu ra kỹ thuật số mà chúng tôi đã cung cấp, hãy chỉ định nó là 'Pin. Ngoài'. Điều này được lưu trữ trong đối tượng 'led'
led=Pin(14,Pin.OUT) //setting GPIO14 led as outputĐể bật ngắt bên ngoài trên GPIO13, hãy tạo một đối tượng Pin (PIR_Interrupt ) và đặt nó làm chân đầu vào kỹ thuật số bằng cách sử dụng 'Pin. IN' làm đối số thứ hai trong phương thức Pin() của chúng tôi. Đầu vào trên GPIO13 mà chúng tôi đã chỉ định trong đối số đầu tiên và được kết nối với Cảm biến PIR
PIR_Interrupt=Pin(13,Pin.IN) # setting GPIO13 PIR_Interrupt as inputĐính kèm ngắt vào chân GPIO
Bây giờ khi chúng tôi đã xác định GPIO đầu vào/đầu ra của mình. Bước tiếp theo là gắn ngắt vào chân GPIO13. Vì chúng tôi muốn xung cạnh tăng của Cảm biến PIR kích hoạt ngắt hoạt động như một đầu vào cho GPIO13 như sau
________số 8_______Phương thức irq() này được sử dụng để định cấu hình trình xử lý ngắt sẽ được gọi khi sự kiện kích hoạt cho ngắt cụ thể đó xảy ra. Trong trường hợp của chúng tôi, sự kiện kích hoạt này là một cạnh tăng bên ngoài trên chân GPIO13
Chúng tôi đặt đối số đầu tiên của phương thức irq() là 'trigger=Pin. IRQ_RISING. ' Điều này có nghĩa là chúng tôi muốn ngắt xảy ra khi quá trình chuyển đổi tín hiệu xảy ra từ trạng thái THẤP sang CAO, cụ thể là cạnh tăng của tín hiệu
Mã phát hiện chuyển động
Trong vòng lặp, chúng tôi kiểm tra xem biến toàn cục có đúng không. Nếu là True, chúng ta bật đèn LED trong 10 giây và sau đó tắt đèn LED
if Motion_Detected: print('Motion is detected!') led.value(1) sleep(20) led.value(0) print('Motion is stopped!') Motion_Detected = FalseNếu biến toàn cục “Motion_Detected” là Sai. Đèn LED BẬT trong một giây và TẮT lại trong một giây. Điều này cho thấy hiệu ứng nhấp nháy liên tục của đèn led cứ sau 1 giây
input=Pin(2,Pin.IN)0Ghi chú. Biến “Motion_Detected” sẽ trở thành Ture chỉ khi chuyển động được phát hiện và chức năng xử lý ngắt đáp ứng được thực thi sẽ đặt giá trị biến này thành True
Bây giờ hãy tạo một tệp mới trong uPyCraft IDE hoặc Thonny IDE và tải xuống Tập lệnh MicroPython này cho ESP32 hoặc ESP8266. Bạn sẽ thấy đèn LED nhấp nháy với tốc độ một giây khi không phát hiện chuyển động và khi cảm biến PIR phát hiện chuyển động, đèn LED sẽ sáng trong 10 giây như sau
Video giới thiệu
Trong hướng dẫn này, chúng ta đã tìm hiểu về cách xử lý các ngắt bên ngoài trong ESP32/ESP8266 trong Micro python bằng Cảm biến PIR