Σε αυτό το σεμινάριο, θα μάθουμε πώς να χρησιμοποιούμε έναν αισθητήρα κίνησης RIR με το Raspberry Pi Pico και να διαμορφώνουμε εξωτερικές διακοπές του Raspberry Pi Pico χρησιμοποιώντας MicroPython. Θα δείξουμε τη χρήση εξωτερικών διακοπών μέσω ενός παραδείγματος με αισθητήρα κίνησης PIR και LED.
Εισαγωγή στα Αιτήματα Διακοπής (interrupt request, IRQ)
Οι διακοπές χρησιμοποιούνται για το χειρισμό συμβάντων που δεν συμβαίνουν κατά τη διαδοχική εκτέλεση ενός προγράμματος. Για παράδειγμα, θέλουμε να εκτελέσουμε ορισμένες εργασίες και αυτές οι εργασίες εκτελούνται διαδοχικά στο πρόγραμμα MicroPython σας. Αλλά υπάρχουν μερικές εργασίες που εκτελούνται μόνο όταν συμβαίνει ένα ειδικό γεγονός, όπως ένα εξωτερικό σήμα στην ακίδα εισόδου ενός μικροελεγκτή. Μια εξωτερική διακοπή ή μια «διακοπή υλικού» προκαλείται από την εξωτερική μονάδα υλικού. Για παράδειγμα, υπάρχει μια διακοπή όταν πιέζεται ένα πλήκτρο σε μία είσοδο GPIO.
Διαφορά μεταξύ διαδοχικής εκτέλεσης και εκτέλεσης βάσει συμβάντων;
στη Διαδοχική εκτέλεση (pulling), πρέπει να παρακολουθούμε συνεχώς την κατάσταση μία ή περισσότερων εισόδων συνεχώς για να ανταποκρινόμενοι σε μία αλλαγή κατάστασής τους. Αλλά ένα κύριο μειονέκτημα αυτής της μεθόδου ήταν ότι πρέπει να ελέγχουμε την κατάσταση της ψηφιακής εισόδου κάθε φορά κατά τη διαδοχική εκτέλεση, ακόμη και αν ο χρήστης δεν πατήσει το κουμπί. Είναι σπατάλη επεξεργαστικής ισχύος και πόρων των μικροελεγκτών.
Τι συμβαίνει όταν συμβαίνει μια διακοπή;
Με τη διακοπή, δεν χρειάζεται να ελέγχουμε συνεχώς την κατάσταση μία ή περισσότερων εισόδων. Όταν παρουσιαστεί μια διακοπή (εντοπιστεί μια αλλαγή), ο μικροελεγκτής διακόπτει την εκτέλεση του κύριου προγράμματος και καλείται μια λειτουργία γνωστή ως Ρουτίνα Εξυπηρέτησης Διακοπής (Interrupt Service Routine, ISR). Στη συνέχεια, εργάζεται προσωρινά σε μια διαφορετική εργασία (ISR) και, στη συνέχεια, επιστρέφει στο κύριο πρόγραμμα μετά τη λήξη της ρουτίνας χειρισμού. Αυτό φαίνεται στο παρακάτω σχήμα.

Ένα παράδειγμα μπορεί να είναι το πάτημα ενός κουμπιού ή η ανίχνευση κίνησης με έναν αισθητήρα PIR. Και στις δύο περιπτώσεις, μπορεί να χρησιμοποιηθεί ένα κουμπί ή ένας αισθητήρας κίνησης PIR για να προκαλέσει μια διακοπή. Επομένως, όταν συμβαίνει ένα εξωτερικό συμβάν, ο επεξεργαστής σταματά αυτό που κάνει και εκτελεί τη ρουτίνα εξυπηρέτησης διακοπής που ορίζουμε για το αντίστοιχο συμβάν. Μετά από αυτό, επιστρέφει στο τρέχον πρόγραμμα. Οι εξωτερικές διακοπές είναι εξαιρετικά χρήσιμες γιατί με τη βοήθειά τους δεν χρειάζεται να παρακολουθούμε συνεχώς την κατάσταση μία ή περισσότερων εισόδων.
Ακίδες διακοπής στο Raspberry Pi Pico
Όλες οι ακίδες GPIO μπορούν να ρυθμιστούν ως εξωτερικός ακίδες διακοπής στις ακόλουθες τέσσερις αλλαγές στην κατάσταση των ακίδων GPIO:
- Υψηλό επίπεδο, HIGH
- Επίπεδο Χαμηλό, LOW
- Θετικό άκρο (μετάβαση από ενεργό χαμηλό σε ενεργό υψηλό), LOW –> HIGH
- Αρνητική ακμή (μετάβαση από ενεργό υψηλό σε ενεργό χαμηλό), HIGH –> LOW
Το παρακάτω διάγραμμα δείχνει τις ακίδες GPIO του Raspberry Pi Pico.
Διαμόρφωση εξωτερικών διακοπών στο Pi Pico
Τώρα ας δούμε πώς να ρυθμίσουμε εξωτερικές διακοπές στο Raspberry Pi Pico χρησιμοποιώντας τη MicroPython. Πρέπει να ακολουθήσετε τα ακόλουθα βήματα.
Ορισμός λειτουργίας χειρισμού διακοπών
def handle_interrupt(pin):
Η λειτουργία χειρισμού διακοπών ορίζεται με εξαιρετικά εύκολο τρόπο. Πρέπει να είναι απλό, καθώς ο επεξεργαστής είναι σε θέση να επιστρέψει γρήγορα στο κύριο πρόγραμμα. Αυτό μπορεί να επιτευχθεί δημιουργώντας μια καθολική μεταβλητή στην οποία μπορούν να έχουν πρόσβαση όλοι, στην περίπτωσή μας θα χρησιμοποιήσουμε τη μεταβλητή «Pin». Η μεταβλητή pin θα λειτουργήσει ως παράμετρος μέσα στη λειτουργία χειρισμού διακοπών ως εξής: handle_interrupt(pin). Αυτή η γραμμή δείχνει το GPIO που σχετίζεται με την ακίδα που προκάλεσε την εμφάνιση διακοπής.
Ρύθμιση του GPIO ως εισόδου που θα λειτουργεί ως ακίδα διακοπής
input=Pin(2,Pin.IN)
Για να λάβουμε την τιμή ενός GPIO, θα δημιουργήσουμε ένα αντικείμενο Pin και θα το ορίσουμε ως είσοδο χρησιμοποιώντας το ‘Pin.IN’ ως δεύτερο όρισμα στην κλάση Pin(). Στο παραπάνω παράδειγμα, η είσοδος είναι στο GPIO2, το οποίο καθορίσαμε στο πρώτο όρισμα. Αυτό αποθηκεύεται στο αντικείμενο ‘input’. Μπορείτε να επιλέξετε όποιο όνομα αντικειμένου θέλετε.
Επισύναψη διακοπής στο pin
input.irq(trigger=Pin.IRQ_RISING, handler=handle_interrupt)
Σε αυτό το βήμα θα συνδέσουμε τη διακοπή στην ακίδα που καθορίσαμε πριν χρησιμοποιώντας τη μέθοδο irq(). Σε αυτή τη μέθοδο περνάμε δύο ορίσματα, δηλαδή το έναυσμα και το χειριστή:
- έναυσμα (trigger): Υπάρχουν τρεις διαφορετικές συνθήκες από τις οποίες μπορούμε να επιλέξουμε.
Pin.IRQ_RISING: Αυτό χρησιμοποιείται για την ενεργοποίηση της διακοπής όταν ο ακροδέκτης πηγαίνει από LOW σε HIGH.

Pin.IRQ_FALLING: Αυτό χρησιμοποιείται για την ενεργοποίηση της διακοπής όταν ο ακροδέκτης πηγαίνει από HIGH σε LOW.

Pin.IRQ_FALLING|Pin.IRQ_RISING: Αυτό χρησιμοποιείται για να ενεργοποιήσει τη διακοπή όταν εντοπιστεί οποιαδήποτε αλλαγή, πράγμα που σημαίνει ότι μπορεί να είναι τόσο HIGH-LOW όσο και LOW-HIGH.

Η MicroPython υποστηρίζει επίσης συμβάντα ενεργοποίησης σε χαμηλό ή υψηλό επίπεδο χρησιμοποιώντας Pin.IRQ_LOW_LEVEL και Pin.IRQ_HIGH_LEVEL, αντίστοιχα.
- χειριστής (handle): Η συνάρτηση handle_interrupt() μεταβιβάζεται ως η δεύτερη παράμετρος στη μέθοδο IRQ(). Αυτή η λειτουργία καλείται κάθε φορά που εντοπίζεται μια διακοπή.
Αισθητήρας κίνησης PIR με Raspberry Pi Pico
Τώρα θα μάθουμε πώς να χειριζόμαστε τις διακοπές στο Raspberry Pi Pico χρησιμοποιώντας έναν αισθητήρα PIR και ένα LED. Για σκοπούς επίδειξης, θα χρησιμοποιήσουμε έναν αισθητήρα ανιχνευτή κίνησης PIR. Όταν ένας αισθητήρας PIR ανιχνεύσει κίνηση, θα ανάψουμε το LED για 5 δευτερόλεπτα όπως φαίνεται στο παρακάτω σχήμα:
Απαιτούνται τα ακόλουθα στοιχεία:
- Rasmperry Pi Pico
- Ένας αισθητήρας PIR
- Ένα LED 5mm
- Μία αντίσταση 220 ohm
- πλακέτα δοκιμών (Breadboard)
- Καλώδια σύνδεσης
Συναρμολογήστε το κύκλωμα σας όπως φαίνεται στο παρακάτω διάγραμμα:

Στο παραπάνω σχήμα, μπορούμε να δούμε ότι το GPIO14 συνδέεται με τον πείρο ανόδου του LED μέσω της αντίστασης 220 ohm και ο πείρος καθόδου συνδέεται με το κοινό έδαφος.
Ο αισθητήρας PIR που χρησιμοποιούμε σε αυτό το σεμινάριο αποτελείται από τρεις ακίδες. Δύο από αυτά είναι ακίδες τροφοδοσίας όπως VCC και ακίδες γείωσης. Μπορούμε να τροφοδοτήσουμε τον αισθητήρα κίνησης PIR απευθείας από την ακίδα τάσης Raspberry Pi Pico 3.3V όπως φαίνεται στο παραπάνω σχηματικό διάγραμμα. Ο κεντρικός ακροδέκτης είναι η ψηφιακή έξοδος που παρέχει έναν ενεργό υψηλό παλμό κάθε φορά που ανιχνεύεται κίνηση. Διαφορετικά, αυτή η ακίδα παραμένει χαμηλά. Αυτό σημαίνει ότι ένα ανερχόμενο άκρο συμβαίνει όταν ένας αισθητήρας PIR ανιχνεύει κίνηση. Μπορούμε να ανιχνεύσουμε αυτό το ανερχόμενο άκρο με τη βοήθεια ακίδων διακοπής του Raspberry Pi Pico.

Πώς λειτουργεί ο αισθητήρας PIR με την εξωτερική διακοπή;
Ο αισθητήρας PIR λειτουργεί ως πηγή για την εξωτερική διακοπή. Αυτό σημαίνει ότι συνδέουμε την έξοδο του αισθητήρα PIR με την ακίδα διακοπής του Raspberry Pi Pico. Επιπλέον, συνδέουμε την ανερχόμενη άκρη που ενεργοποιείται διακοπή σε αυτήν την ακίδα GPIO. Αυτό σημαίνει ότι αυτός ο ακροδέκτης GPIO θα ενεργοποιεί τη διακοπή κάθε φορά που θα ανιχνεύει άνοδο στην είσοδό του.

Αρχικά, η λυχνία LED κατάστασης θα αναβοσβήνει μετά από καθυστέρηση 1 δευτερολέπτου. Όταν ένας αισθητήρας PIR ανιχνεύσει κίνηση, προκαλείται εξωτερική διακοπή, η λυχνία LED θα παραμείνει αναμμένη για 10 δευτερόλεπτα και στη συνέχεια θα επιστρέψει στο κανονικό στάδιο που αναβοσβήνει (ενεργοποίηση/απενεργοποίηση με καθυστέρηση 1 δευτερολέπτου).
Αιτήματα Διακοπής στο Raspberry Pi Pico με σενάριο MicroPython και αισθητήρα κίνησης PIR
Δημιουργήστε ένα νέο αρχείο στο Thonny IDE και αντιγράψτε αυτόν τον κώδικα στο αρχείο που μόλις δημιουργήσατε. Μετά από αυτό, κατεβάστε και εκτελέστε αυτό το σενάριο MicroPython στο Raspberry Pi Pico.
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(10)
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 second
Πώς λειτουργεί ο κώδικας;
Εισαγωγή βιβλιοθηκών MicroPython
Τώρα, ας δούμε τη λειτουργία ενός σεναρίου MicroPython. Για να χρησιμοποιήσουμε διακοπές στη MicroPython, θα πρέπει να εισαγάγουμε την κλάση GPIO από τη μονάδα μηχανής. Επειδή η κλάση GPIO περιέχει μεθόδους για τη διαμόρφωση διακοπών για το Raspberry Pi Pico. Θα πρέπει επίσης να εισαγάγουμε τη μονάδα ύπνου για να εισαγάγουμε καθυστέρηση στο σενάριο MicroPython.
from machine import Pin
from time import sleep
Δημιουργία καθολικής μεταβλητής MicroPython
Στη συνέχεια, δημιουργήστε μια καθολική μεταβλητή με οποιοδήποτε όνομα για να υποδείξετε την κατάσταση του αισθητήρα κίνησης PIR. Έχουμε ορίσει μια καθολική μεταβλητή με όνομα “Motion_Detected” και η τιμή αυτής της καθολικής μεταβλητής μπορεί να είναι είτε True είτε False. Για να υποδείξουμε την κατάσταση του αισθητήρα PIR, θα ορίσουμε την τιμή της καθολικής μεταβλητής σε True κάθε φορά που συμβαίνει διακοπή λόγω κίνησης που ανιχνεύεται από τον αισθητήρα PIR. Αρχικά ορίστε την τιμή αυτής της μεταβλητής σε False.
Motion_Detected = False #Global variable to hold the state of motion sensor
Ορισμός λειτουργίας χειρισμού διακοπών
Στη συνέχεια, ορίζουμε τη λειτουργία χειρισμού διακοπών για την οποία μάθαμε στην ενότητα χειρισμού διακοπών. Η παράμετρος pin στη λειτουργία χειρισμού διακοπών όπως handle_interrupt(), είναι μια παρουσία της κλάσης pin. Αυτή η παρουσία δείχνει ποια καρφίτσα GPIO προκάλεσε διακοπή.
def handle_interrupt(Pin): #defining interrupt handling function
global Motion_Detected
Motion_Detected = True
Μέσα στη συνάρτηση χειρισμού διακοπών, ορίζουμε την καθολική μεταβλητή “Motion_Detected” σε μια λογική τιμή True και θα χρησιμοποιήσουμε αυτήν την τιμή μέσα στον βρόχο while για να εκτελέσουμε κώδικα που εκτελείται μόνο όταν συμβαίνει διακοπή. Πρέπει να αναρωτιέστε γιατί δεν εκτελούμε τον κώδικα που σχετίζεται με τον αισθητήρα PIR μέσα στη λειτουργία handle_interrupt() αντί να τον εκτελούμε μέσα στον βρόχο while(). Αυτό συμβαίνει επειδή συνιστάται να διατηρείτε τις ρουτίνες διακοπής σέρβις όσο το δυνατόν συντομότερες για να βελτιώσετε τον λανθάνοντα χρόνο διακοπής.
Αυτό σημαίνει ότι θα πρέπει να εκτελέσουμε τον ελάχιστο δυνατό αριθμό εντολών μέσα στη λειτουργία επιστροφής κλήσης διακοπής. Αυτός είναι ο λόγος για τον οποίο αλλάξαμε μόνο την κατάσταση της μεταβλητής “Motion_Detected” μέσα στο ISR και θα εκτελέσουμε την υπόλοιπη λειτουργικότητα μέσα στον κύριο κώδικα.
Σημείωση: Το “Motion_Detected” είναι μια καθολική μεταβλητή. Επομένως, μπορούμε να το χρησιμοποιήσουμε καθ ‘όλη τη διάρκεια εκτέλεσης του προγράμματος.
Δημιουργία στιγμιότυπου ακίδας
Δημιουργήστε δύο στιγμιότυπα κατηγορίας καρφίτσας, μία για το LED εξόδου και μία δεύτερη για εξωτερικές ακίδες εισόδου διακοπής.
Για να θέσουμε ένα GPIO ON ή OFF, θα το ορίσουμε ως έξοδο. Το πρώτο όρισμα στην κλάση Pin() είναι ο αριθμός pin στον οποίο ρυθμίζουμε την έξοδο. Η έξοδος είναι στο GPIO14 που είναι συνδεδεμένο με το LED. Το δεύτερο όρισμα δείχνει τη λειτουργία ακίδων, π.χ. ψηφιακή είσοδο ή λειτουργία ψηφιακής εξόδου. Καθώς διαμορφώνουμε το pin 14 ως ψηφιακή έξοδο που δώσαμε, το καθορίζει ως ‘Pin.Out’. Αυτό αποθηκεύεται στο αντικείμενο ‘led’
led=Pin(14,Pin.OUT) //setting GPIO14 led as output
Για να ενεργοποιήσετε την εξωτερική διακοπή στο GPIO13, δημιουργήστε ένα αντικείμενο Pin (PIR_Interrupt ) και ορίστε το ως ψηφιακή καρφίτσα εισόδου χρησιμοποιώντας το ‘Pin.IN’ ως δεύτερο όρισμα στη μέθοδο Pin(). Η είσοδος είναι στο GPIO13 που καθορίσαμε στο πρώτο όρισμα και συνδέεται με τον αισθητήρα PIR.
PIR_Interrupt=Pin(13,Pin.IN) # setting GPIO13 PIR_Interrupt as input
Επισύναψη διακοπής στο GPIO pin
Τώρα, όπως έχουμε ορίσει GPIO, εισόδου/εξόδου. Το επόμενο βήμα είναι να συνδέσετε τη διακοπή στην ακίδα GPIO13. Καθώς θέλουμε ο παλμός ανερχόμενης ακμής του αισθητήρα PIR να ενεργοποιεί τη διακοπή που λειτουργεί ως είσοδος στο GPIO13 ως εξής:
#Attach external interrupt to GPIO13 and rising edge as an external event source
PIR_Interrupt.irq(trigger=Pin.IRQ_RISING, handler=handle_interrupt)
Αυτή η μέθοδος irq() χρησιμοποιείται για τη ρύθμιση του προγράμματος χειρισμού διακοπών που θα κληθεί όταν συμβεί το συμβάν ενεργοποίησης για τη συγκεκριμένη διακοπή. Στην περίπτωσή μας, αυτό το συμβάν σκανδάλης είναι ένα εξωτερικό ανερχόμενο άκρο στον ακροδέκτη GPIO13.
Ορίζουμε το πρώτο όρισμα της μεθόδου irq() ως ‘trigger=Pin.IRQ_RISING’. Αυτό σημαίνει ότι θέλουμε η διακοπή να συμβεί όταν η μετάβαση του σήματος συμβαίνει από ΧΑΜΗΛΗ σε ΥΨΗΛΗ κατάσταση, δηλαδή ανερχόμενη άκρη του σήματος.
Κωδικός ανίχνευσης κίνησης
Μέσα στον βρόχο, ελέγχουμε αν η καθολική μεταβλητή είναι True. Εάν είναι αλήθεια, ανάβουμε το LED για 10 δευτερόλεπτα και μετά σβήνουμε το LED.
if Motion_Detected:
print('Motion is detected!')
led.value(1)
sleep(10)
led.value(0)
print('Motion is stopped!')
Motion_Detected = False
Εάν η καθολική μεταβλητή “Motion_Detected” είναι False. Η λυχνία LED παραμένει αναμμένη για ένα δευτερόλεπτο και σβήνει ξανά για ένα δευτερόλεπτο. Αυτό δείχνει μια σταθερή επίδραση αναβοσβήνει του led μετά από κάθε 1 δευτερόλεπτο.
led.value(1) #led is on
sleep(1) #delay of 1 second
led.value(0) #led is off
sleep(1) #delay of 1 second
Σημείωση: Η μεταβλητή “Motion_Detected” θα γίνει Ture μόνο όταν ανιχνευθεί κίνηση και εκτελεστεί η λειτουργία χειρισμού διακοπής απόκρισης, η οποία θα ορίσει αυτήν την τιμή μεταβλητής σε True.
Τώρα δημιουργήστε ένα νέο αρχείο στο Thonny IDE και ανεβάστε αυτό το σενάριο MicroPython στο Raspberry Pi Pico. Θα δείτε ότι η λυχνία LED αναβοσβήνει με ρυθμό ενός δευτερολέπτου όταν δεν ανιχνεύεται κίνηση και όταν ο αισθητήρας PIR ανιχνεύει κίνηση, η λυχνία LED παραμένει αναμμένη για 10 δευτερόλεπτα.
καλή επιτυχία!!!