آموزش میکروپایتون: وقفه‌ها با ESP32 و ESP8266

در این آموزش نحوه پیکره‌بندی و مدیریت وقفه‌ها را با استفاده از فریمور میکروپایتون و با برد ESP32 و ESP8266 یاد می‌گیرید. برای مثال، یک پروژه با سنسور حرکت PIR خواهیم ساخت.

پیشنیازها

برای دنبال کردن این آموزش، نیاز دارید که فریمور میکروپایتون در برد ESP32 یا ESP8266 فلش شده باشد. همچنین برای نوشتن و آپلود کد در بردتان به یک IDE نیاز دارید. ما پیشنهاد می‌کنیم از Thonny IDE یا uPyCraft IDE استفاده کنید.

معرفی وقفه‌ها

وقفه‌ها برای ایجاد اتفاقات خودکار در برنامه های میکروکنترلر مفید هستند و می‌توانند به حل مشکلات زمان‌بندی کمک کنند. با وجود وقفه‌ها نیازی به بررسی مداوم مقدار پین فعلی نیست. هنگامی که تغییری تشخیص داده می‌شود ، یک رویداد فعال می‌شود.(یک تابع فراخوانی می‌شود)

همان‌طور که در شکل می‌بینید، زمانی که یک وقفه ایجاد می‌شود، پردازنده اجرای برنامه اصلی را برای اجرای یک کار متوقف می‌کند و سپس به برنامه اصلی برمی‌گردد.

اجرای وقفه و برنامه اصلی

وقفه برای شروع یک فرآیند وقتی حرکتی تشخیص داده می‌شود و یا وقتی دکمه فشاری فشار داده می‌شود بدون نیاز به بررسی مداوم وضعیت آن، کارآمد است.

پین‌های وقفه ESP32: تمام GPIOها می‌توانند برای وقفه استفاده شوند به جز GPIO 6 تا GPIO 11.
پین‌های وقفه ESP8266: تمام GPIOها می‌توانند برای وقفه استفاده شوند به جز GPIO 16

تنظیمات یک وقفه در میکروپایتون

برای تنظیمات وقفه در میکروپایتنون، مراحل زیر را طی کنید.

۱- یک تابع مدیریت وقفه را تعریف کنید. تابع مدیریت وقفه باید تا حد ممکن ساده باشد؛ بنابراین پردازنده سریعا به اجرای برنامه اصلی باز می‌گردد. به عنوان مثال، بهترین رویکرد این است که با استفاده از یک متغیر global به کد اصلی که وقفه رخ داده است، سیگنال بدهید. تابع مدیریت وقفه پارامتری از نوع Pin را می‌پذیرد. این پارامتر به تابعی که بازفراخوانی می‌شود، برمی‌گردد و به GPIO که باعث وقفه شده است، اشاره دارد.

def handle_interrupt(pin):

۲- GPIO که به عنوان پین وقفه عمل می‌کند را به عنوان ورودی تنظیم کنید. برای مثال:

pir = Pin(14, Pin.IN)

۳- با فراخوانی تابع ()irq، وقفه را به آن پین اختصاص دهید.

pir.irq(trigger=Pin.IRQ_RISING, handler=handle_interrupt)

تابع ()irq آرگومان‌های زیر را می‌پذیرد:

  • trigger: حالت فعال شدن وقفه را مشخص می‌کند. سه حالت مختلف وجود دارد:
    Pin.IRQ_FALLING: برای فعال کردن وقفه وقتی که پین از HIGH به LOW می‌رود.
    Pin.IRQ_RISING: برای فعال کردن وقفه وقتی که پین از LOW به HIGH می‌رود.
    ۳: برای فعال کردن وقفه در هر دو حالت HIGH به LOW و LOW به HIGH. (یعنی وقتی که تغییری تشخیص داده می‌شود)
  • handler: تابعی است که زمانی که وقفه تشخیص داده می‌شود، فراخوانی می‌شود. در اینجا تابع ()handle_interrupt

مثال پروژه با سنسور PIR

برای نمایش عملی چگونگی مدیریت وقفه‌ها، یک پروژه ساده با سنسور حرکت PIR می‌سازیم. هر وقت که حرکتی تشخیص داده شود، یک LED به مدت ۲۰ ثانیه روشن می‌شود.

عملکرد سنسور حرکت PIR

قطعات مورد نیاز

لیستی از قطعاتی که برای ساخت مدار نیاز دارید:

ESP32 یا ESP8266
LED 5 mm
مقاوت ۳۳۰ اهم
سنسور حرکت (AM312) Mini PIR یا سنسور حرکت PIR (HC-SR501)
بردبرد
سیم جامپر

شماتیک – ESP32

اگر از برد ESP32 استفاده می‌کنید، از دیاگرام شماتیک زیر استفاده کنید.

ESP32 و سنسور حرکت

شماتیک – ESP8266

اگر از برد ESP8266 استفاده می‌کنید، از دیاگرام شماتیک زیر استفاده کنید.

ESP8266 و سنسور حرکت

توجه: در این پروژه ما از سنسور حرکت Mini AM312 PIR استفاده می‌کنیم که در ۳.۳ ولت عمل می‌کند. اگر شما از سنسور حرکت دیگری مانند HC-SR501 استفاده می‌کنید، در ۵ ولت عمل می‌کند. شما می‌توانید عملکرد آن را به ۳.۳ ولت هم تغییر دهید و یا به سادگی از پین Vin تغذیه بگیرید.

در شکل زیر، ما pinout سنسور حرکت Mini AM312 PIR را نشان می‌دهیم. اگر از سنسور حرکت دیگری استفاده می‌کنید، پیش از بستن مدار pinout آن را چک کنید.

Mini PIR – pinout

کد

اسکریپت زیر حرکت را تشخیص می‌دهد و زمانی که حرکت تشخیص داده شود، یک LED روشن می‌شود. این کد با هر دو برد ESP32 و ESP8266 سازگار است.

from machine import Pin
from time import sleep

motion = False

def handle_interrupt(pin):
  global motion
  motion = True
  global interrupt_pin
  interrupt_pin = pin 

led = Pin(12, Pin.OUT)
pir = Pin(14, Pin.IN)

pir.irq(trigger=Pin.IRQ_RISING, handler=handle_interrupt)

while True:
  if motion:
    print('Motion detected! Interrupt caused by:', interrupt_pin)
    led.value(1)
    sleep(20)
    led.value(0)
    print('Motion stopped!')
    motion = False

کد چگونه کار می‌کند

برای استفاده از وقفه‌ها، کلاس Pin از ماژول machine را وارد کنید. همچنین برای اضافه کردن تاخیر، متد sleep از ماژول time را وارد کنید.

from machine import Pin
from time import sleep

یک متغیر با نام motion بسازید که می‌تواند True یا False باشد. این متغیر نشان می‌دهد که حرکتی تشخیص داده شده است یا خیر.( این متغیر global است و در تابع مدیریت تابع تغییر خواهد کرد)

motion = False

سپس، یک تابع با نام handle_interrupt بسازید.

def handle_interrupt(pin):
  global motion
  motion = True
  global interrupt_pin
  interrupt_pin = pin 

این تابع زمانی فراخوانی می‌شود که حرکتی تشخیص داده شود. تابع handle_interrupt یک پارامتر ورودی (pin) که یک شی از کلاس Pin است دارد و وقتی ارسال می‌شود که وقفه رخ دهد.(مشخص می‌کند کدام پین باعث وقفه شده است)

ما پینی که باعث وقفه شده است را در متغیر interrupt_pin ذخیره می‌کنیم. در اینجا خیلی کارآمد نیست چون ما فقط یک پین وقفه داریم. با این حال اگر چندین وقفه داشته باشیم که تابع وقفه یکسانی را فعال کنند و بخواهیم بدانیم کدام GPIO باعث وقفه شده است، مفید است.

در مثال ما، تابع handle_interrupt به سادگی متغیر motion را به True تغییر می‌دهد و پین وقفه را ذخیره می‌کند. تابع مدیریت وقفه شما باید تا حد امکان کوتاه باشد و داخل آن از تابع ()print استفاده نکنید. سپس، کد اصلی باید همه مواری که می‌خواهیم هنگام وقفه رخ دهد را داشته باشد.

توجه: اگر شما می‌خواهید متغیر motion داخل تابع و در تمام کد قابل استفاده باشد، نیاز است که به صورت global (سراسری) تعریف شود. در غیر این صورت، وقتی حرکتی تشخیص داده می‌شود، هیچ اتفاقی نمی‌افتد؛ چون متغیر motion فقط داخل تابع تغییر می‌کند، نه در بدنه اصلی کد.

در ادامه کد، باید دو آبجکت (شی) Pin ایجاد کنیم؛ یکی از برای LED در GPIO 12 و دیگری برای سنسور حرکت PIR در GPIO 14.

led = Pin(12, Pin.OUT)
pir = Pin(14, Pin.IN)

سپس با فراخوانی متد ()irq، یک وقفه در pir تظینم کنید.

pir.irq(trigger=Pin.IRQ_RISING, handler=handle_interrupt)

در ()loop، وقتی متغیر motion مقدار True دارد، LED را برای ۲۰ ثانیه روشن می‌کنیم و یک پیغام چاپ می‌کنیم که حرکت تشخیص داده شده است و کدام پین باعث وقفه شده است.

if motion:
  print('Motion detected! Interrupt caused by:', interrupt_pin)
  led.value(1)
  sleep(20)

بعد از ۲۰ ثانیه، LED را خاموش کرده و پیغامی را چاپ کنید که نشان دهد حرکت متوقف شده است.

led.value(0)
print('Motion stopped!')

در آخر متغیر motion را False تنظیم کنید.

motion = False

متغیر motion تنها زمانی می‌تواند دوباره True َشود که حرکت تشخیص داده شود و تابع handle_interrupt فراخونی شود.

برای سادگی، در این مثال برای اینکه LED به مدت ۲۰ ثانیه روشن شود، از تاخیر استفاده کردیم. در حالت ایده‌آل، باید از تایمرها استفاده کنید.

نمایش عملی

کد را در برد ESP32/ESP8266 آپلود کنید. وقتی حرکت تشخیص داده می‌شود، LED باید ۲۰ ثانیه روشن و پیغام نیز در Shell چاپ شود.

تشخیص حرکت

پس از ۲۰ ثانیه LED خاموش می‌شود.

توجه مهم : سنسور حرکت AM312 PIR به صورت پیش‌فرض زمان تاخیر ۸ ثانیه دارد. یعنی اگر ۸ ثانیه از آخرین باری که فعال شده است نگذشته باشد، مجددا فعال نمی‌شود.

جمع‌بندی

امیدواریم این آموزش برای شما جالب بوده باشد. در این آموزش یاد گرفتیم چگونه:

یک پین را به عنوان وقفه تنظیم کنیم.
وقفه در کد را مدیریت کنیم.
تشخیص دهیم کدام GPIO باعث وقفه شده است.

در این مثال، برای فعال‌سازی وقفه ما از سنسور حرکت PIR استفاده کردیم. این مثال می‌تواند برای تشخیص فشار دادن دکمه فشاری نیز استفاده شود.

2 دیدگاه در “آموزش میکروپایتون: وقفه‌ها با ESP32 و ESP8266

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

قبلا حساب کاربری ایجاد کرده اید؟
گذرواژه خود را فراموش کرده اید؟
Loading...