این آموزش به شما نشان میدهد چگونه با استفاده از میکروپایتون، ESP32 را به حالت خواب عمیق ببرید و آن را با منابع مختلف بیدار کنید. ما زمان بیدار شدن تایمر و بیدار شدن خارجی را بررسی میکنیم.
همچنین ESP32 می تواند با استفاده از پین های لمسی با تعیین آستانه(threshold) از خواب عمیق بیدار شود.
خواب عمیق در ESP8266 کمی متفاوت از ESP32 است.
پیشنیازها
برای دنبال کردن این آموزش نیاز دارید که فریمور MicroPython روی برد ESP32 شما نصب باشد. همچنین برای نوشتن و آپلود کد در بردتان به یک IDE نیاز دارید. ما پیشنهاد میکنیم از Thonny IDE یا uPyCraft IDE استفاده کنید.
معرفی خواب عمیق
داشتن ESP32 در حالت فعال با باتری، ایدهآل نیست؛ چون انرژی باتریها به سرعت تخلیه میشوند.
اگر شما ESP32 را در حالت خواب عمیق بگذارید، توان مصرفی کاهش مییابد و عمر باتریهایتان طولانیتر خواهد بود. نگه داشتن ESP32 در خواب عمیق به این معناست که فعالیتهایی که در حین کار مصرف انرژی بیشتری دارند، قطع میشوند اما فعالیت کافی را برای بیدار کردن پردازنده وقتی اتفاق جالبی میافتد، باقی میگذارند.
وقتی که ESP32 در حالت خواب عمیق کار میکند، مصرف توان آن در رنج μA است. با یک برد سفارشی و با دقت طراحی شده میتوانید کمترین مصرف ۵ میکروآمپر را دریافت کنید.
هرچند اگر از برد ESP32 توسعه کامل و با تمام ویژگیها، با برنامهنویسی داخلی، LED روی برد و…(مانند برد ESP32 DOIT) استفاده کنید، نمیتوانید به همچین وضعیت کم توانی برسید اما همچنان میتوانید انرژی را ذخیره کنید.
منابع بیداری
بعد از این که ESP23 را به مود خواب عمیق بردیم، چند روش برای بیدار کردن آن وجود دارد:
- شما میتوانید از تایمر(timer) استفاده کنید: بیدار کردن ESP32 بعد از دوره زمانی از پیش تعریف شده
- میتوانید از بیداری خارجی(external wake up) استفاده کنید: یعنی وقتی تغییر وضعیت پین رخ میدهد، ESP32 بیدار میشود.
- میتوانید از پینهای لمسی استفاده کنید: ما آن را در این جا بررسی نمکنیم.
- میتوانی از پردازنده مشترک ULP برای بیدار کردن استفاده کنید: این ویژگی را هنوز امتحان نکردهایم
تایمر(timer) بیداری
ESP32 میتواند به خواب عمیق برود و بعد از مدت زمانی که از پیش تعیین شده است، بیدار شود. مخصوصا این ویژگی وقتی کارآمد است که پروژه هایی که اجرا می کنید، نیاز به زمان بندی یا دستورات روتین دارند؛ این در حالی است که مصرف انرژِی را پایین نگه میدارید.
برای این که ESP32 را برای زمان مشخص شدهای به حالت خواب عمیق ببریم، نیاز است که از تابع ()deepsleep در ماژول machine استفاده کنیم. این تابع زمان خواب را بر حسب میلیثانیه به عنوان آرگومان میپذیرد:
machine.deepsleep(sleep_time_ms)
به مثال سادهای نگاه بیاندازیم که ببینیم چگونه کار میکند. در کد زیر، ESP32 به مدت ۱۰ ثانیه به خواب عمیق رفته است؛ سپس بیدار میشود، یک LED چشمک میزند و دوباره به خواب عمیق میرود.
import machine
from machine import Pin
from time import sleep
led = Pin (2, Pin.OUT)
#blink LED
led.value(1)
sleep(1)
led.value(0)
sleep(1)
# wait 5 seconds so that you can catch the ESP awake to establish a serial communication later
# you should remove this sleep line in your final script
sleep(5)
print('Im awake, but Im going to sleep')
#sleep for 10 seconds (10000 milliseconds)
machine.deepsleep(10000)
کد چگونه کار میکند
ابتدا کتابخانههای مورد نیاز را وارد میکنیم:
import machine
from machine import Pin
from time import sleep
یک آبجکت Pin با نام led ایجاد کنید که به GPIO 2 یعنی به LED روی برد اشاره دارد:
led = Pin (2, Pin.OUT)
با دستورات زیر LED چشمک میزند:
led.value(1)
sleep(1)
led.value(0)
sleep(1)
در این جا ما با هدف نمایش عملی، کدی نوشتیم که LED چشمک بزند اما ایده این است که کد اصلی خود را در این بخش از اسکریپت اضافه کنید.
قبل از به خواب رفتن، یک تاخیر(delay) 5 ثانیهای اضافه میکنیم و سپس یک پیغام مبنی بر این که ESP32 به خواب خواهد رفت، نماش داده میشود:
sleep(5)
print('Im awake, but Im going to sleep')
وقتی در حال بهبود کد هستیم، مهم است که قبل از به خواب رفتن، ۵ ثانیه تاخیر را اضافه کنیم. وقتی شما میخواهید کد جدید را در کدتان آپلود کنید، نیاز است که بیدار باشد. بنابراین اگر تاخیر را اضافه نکرده باشید، دشوار خواهد بود که بیدار بماند تا بعداً کد جدید آپلود را کنید. پس از نوشتن کد نهایی، میتوانید تاخیر را پاک کنید.
نهایتا ESP32 را ۱۰ ثانیه(۱۰۰۰۰ میلیثانیه) به خواب عمیق میبریم:
machine.deepsleep(10000)
بعد از ۱۰ ثانیه ESP32 بیدار میشود و کد را از ابتدا اجرا میکند؛ مشابه زمانی که دکمه EN/RST را فشار میدهید.
نمایش عملی
کد آماده شده را در فایل main.py برد ESP32 خود کپی کنید. کد جدید را آپلود کنید و بعد از آن دکمه EN/RST را بزنید.
LED روی برد ESP32 باید چشمک بزند و پیغام را چاپ کند؛ سپس به خواب میرود. این روند مجددا تکرار میشود.
بیدار شدن خارجی(External Wake Up)
ESP32 زمانی که تغییری در وضعیت یک پین ایجاد شود هم میتواند بیدار شود. دو نوع امکان بیدار کردن خارجی برای ESP32 وجود دارد: ext0 و ext1
حالت ext0 به شما اجازه میدهد از یک GPIO را به عنوان منبع بیداری استفاده کنید. حالت ext1 به شما امکان میدهد همزمان بیشتر از یک GPIO را به عنوان منابع بیداری تنظیم کنید.
تنها RTC GPIOها میتوانند به عنوان منابع بیداری استفاده شوند. GPIOهای RTC با مستطیل نارنجی در دیاگرام زیر مشخص شدهاند:
بیداری خارجی با ext0
برای این که نشان دهیم چگونه از بیداری خارجی با ext0 استفاده کنید، از یک دکمهفشاری به عنوان منبع بیداری استفاده میکنیم. وقتی که دکمه فشار داده شود، ESP32 بیدار میشود.
برای این مثال شما به قطعات زیر نیاز دارید:
ESP32 (بهترین بردهای توسعه ESP32)
دکمهفشاری
مقاومت ۱۰ کیلواهم
بردبرد
سیم جامپر
دیاگرام شماتیک
با توجه به دیاگرام شماتیک زیر مدار را ببندید. در این مثال، ما از GPIO 14 برای بیداری ESP32 استفاده میکنیم؛ اما شما میتوانید از هر RTC GPIO دیگری هم استفاده کنید.
نوشتن کد
کد زیر نشان میدهد ext0 چگونه کار میکند. از یک GPIO به عنوان منبع بیداری استفاده شده است:
import machine
import esp32
from machine import Pin
from time import sleep
wake1 = Pin(14, mode = Pin.IN)
#level parameter can be: esp32.WAKEUP_ANY_HIGH or esp32.WAKEUP_ALL_LOW
esp32.wake_on_ext0(pin = wake1, level = esp32.WAKEUP_ANY_HIGH)
#your main code goes here to perform a task
print('Im awake. Going to sleep in 10 seconds')
sleep(10)
print('Going to sleep now')
machine.deepsleep()
کد چگونه کار میکند
ابتدا نیاز دارید که ماژولهای مورد نیاز خود را وارد کنید. برای این کار، ماژول esp32 را وارد کنید که شامل متدهایی است که یک پین را به عنوان منبع بیداری انتخاب میکند.
بعد از وارد کردن ماژولها، یک پین را برای بیداری تعریف کنید. این جا ما از GPIO 14 استفاده میکنیم و آن را wake1 مینامیم. این GPIO باید به عنوان ورودی تنظیم شود.(Pin.IN)
wake1 = Pin(14, mode = Pin.IN)
سپس با استفاده از متد ()wake_on_ext0 ، میتوانید ext0 را به عنوان منبع بیداری تنظیم کنید.
esp32.wake_on_ext0(pin = wake1, level = esp32.WAKEUP_ANY_HIGH)
- pin: یک آبجکتی(شی) از نوع Pin (یعنی GPIO که به عنوان منبع بیداری عمل میکند.)
- level: وضعیت GPIO که ESP32 را بیدار میکند را تعریف میکند. level میتواند یکی از پارامترهای زیر باشد:
WAKEUP_ANY_HIGH
WAKEUP_ALL_LOW
در این جا ما از WAKEUP_ANY_HIGH استفاده میکنیم که وقتی GPIO به حالت HIGH میرود، ESP32 را بیدار میکند.
کد اصلی شما که میخواهد کاری را انجام دهد، باید بعد از منبع بیداری و درست قبل از به خواب رفتن قرار بگیرد.
ما قبل از به خواب رفتن، ۱۰ ثانیه تاخیر ایجاد میکنیم. برای این که ESP32 را به خواب عمیق ببرید، باید از متد ()deepsleep به شکل زیر استفاده کنید:
machine.deepsleep()
نمایش عملی
کد را در فایل main.py آپلود کنید. دکمه EN/RESET را فشار دهید تا کد اجرا شود. ESP32 باید به خواب رود.
حال دکمه را فشار دهید تا آن را از خواب عمیق بیدار کنید.
بیداری خارجی با ext1
بیداری خارجی با ext1 خیلی مشابه ext0 کار میکند اما این امکان را به شما میدهد که بیشتر از یک GPIO را به عنوان منبع بیداری انتخاب کنید. برای نمایش عملی این که چگونه کار میکند، ما از دو دکمهفشاری که به GPIOهای متفاوتی وصل شدهاند استفاده میکنیم.
برای این مثال ما به قطعات زیر احتیاج داریم:
ESP32 (بهترین بردهای توسعه ESP32)
۲ عدد دکمهفشاری
۲ عدد مقاومت ۱۰ کیلواهم
بردبرد
سیم جامپر
دیاگرام شماتیک
با توجه به دیاگرام شماتیک زیر، مدار را ببندید.
در این جا ما از GPIO 14 و GPIO 12 استفاده میکنیم. شما میتوانید از هر GPIO دیگری هم استفاده بکنید اما باید RTC باشند؛ در غیر این صورت این روش کار نخواهد کرد.
نوشتن کد
کد زیر نشان میدهد که ext1 چگونه کار میکند. از دو GPIO به عنوان منابع بیداری استفاده میشود اما شما اگر بخواهید میتوانید از GPIOهای بیشتری استفاده کنید.
import machine
import esp32
from machine import Pin
from time import sleep
wake1 = Pin(14, mode = Pin.IN)
wake2 = Pin(12, mode = Pin.IN)
#level parameter can be: esp32.WAKEUP_ANY_HIGH or esp32.WAKEUP_ALL_LOW
esp32.wake_on_ext1(pins = (wake1, wake2), level = esp32.WAKEUP_ANY_HIGH)
#your main code goes here to perform a task
print('Im awake. Going to sleep in 10 seconds')
sleep(10)
print('Going to sleep now')
machine.deepsleep()
کد چگونه کار میکند
این کد مشابه مثال ext0 است اما از این جا از متد ()wake_on_ext1 استفاده شده است
esp32.wake_on_ext1(pins = (wake1, wake2), level = esp32.WAKEUP_ANY_HIGH)
متد ()wake_on_ext1 دو آرگومان pins و level را دارد.
- pins: یک تاپل یا لیستی با آبجکت نوع Pin (یعنی GPIO که به عنوان منبع بیداری عمل میکند.)
- level: وضعیت GPIO که ESP32 را بیدار خواهد کرد را تعریف میکند. level یکی از دو پارامتر زیر میتواند باشد:
WAKEUP_ANY_HIGH
WAKEUP_ALL_LOW
بعد از تعریف منابع بیداری، میتوانید ESP32 را به خواب عمیق ببرید.
machine.deepsleep()
جمعبندی
امیدواریم که این آموزش مفید بوده باشد. ما در این آموزش تایمر بیداری و بیداری خارجی را پوشش دادیم. البته این امکان نیز وجود دارد که ESP32 را با پینهای لمسی بیدار کرد.