تصویر شاخص نوشته: راهنمای کاملِ پایه‌های ESP32 — کدام پایه را کجا استفاده کنم؟

راهنمای کاملِ پایه‌های ESP32 — کدام پایه را کجا استفاده کنم؟

۱۱ مرداد ۱۴۰۵ مبانی الکترونیک

سنسور را وصل کرده‌ای، کد را از یک نمونهٔ کارکرده کپی کرده‌ای، و عددی که برمی‌گردد تکان نمی‌خورد: یا صفر است، یا همیشه 4095، یا هر بار یک چیز تصادفی. یا نسخهٔ بدترش: بعد از وصل کردن آخرین سیم، برد اصلاً بالا نمی‌آید — نه >>> ای در Shell، نه هیچ نشانه‌ای از زنده بودن.

اولین واکنش همه یکی است: برگردیم کد را نگاه کنیم. ولی روی ESP32 این دو نشانه تقریباً همیشه یک ریشهٔ مشترک دارند، و ریشه‌شان در کد نیست: قطعه روی پایه‌ای نشسته که از پسِ آن کار برنمی‌آید.

پایه‌های ESP32 با هم برابر نیستند: چهارتایشان اصلاً نمی‌توانند چیزی را روشن کنند، شش‌تایشان از قبل رزرو شده‌اند، و چند تای دیگر در لحظهٔ روشن شدن تصمیم می‌گیرند برد چطور بالا بیاید. هیچ‌کدام از این‌ها روی خودِ برد نوشته نشده.

پایه یعنی چه و چرا همه‌شان یکسان نیستند

تصور کن چیپ ESP32 یک ساختمان است و هر پایه یکی از درهایش. از بیرون همه شبیه هم‌اند: یک سوراخ روی هدر با یک عدد کنارش. ولی پشت هر در وضع فرق می‌کند.

پشت یک درِ کامل سه چیز هست: کسی که می‌تواند در را هل بدهد (خروجی)، کسی که پشت در گوش می‌ایستد (ورودی)، و فنری که وقتی هیچ‌کس کاری نمی‌کند در را در وضعیت مشخصی نگه می‌دارد — همان که به آن pull-up یا pull-down داخلی می‌گویند. پشت بعضی درها این فنر نیست. پشت بعضی، اصلاً کسی برای هل دادن نیست و فقط شنونده‌ای ایستاده. و پشت شش تا از درها، خودِ ساختمان شبانه‌روز در رفت‌وآمد است.

از تشبیه که بیرون بیاییم: پشت هر پایهٔ GPIO چند مدار کوچک هست — درایور خروجی، بافر ورودی، مقاومت‌های pull-up و pull-down داخلی، و واحدهای تخصصی مثل ADC و PWM. اینکه کدام‌یک پشت یک پایهٔ مشخص هست، موقع ساخته‌شدنِ سیلیکون تعیین شده و با نرم‌افزار نمی‌شود چیزی را که آنجا نیست اضافه کرد.

و یک حساب‌وکتاب که خیلی‌ها را غافلگیر می‌کند. چیپ ESP32 روی کاغذ ۳۴ پایهٔ GPIO دارد، با شماره‌هایی بین 0 تا 39 (شماره‌های 20 و 24 و 28 تا 31 وجود ندارند). ولی این ۳۴ تا دستِ تو نیست: شش‌تا — 6 تا 11 — به حافظهٔ flash وصل‌اند، و دوتا — 37 و 38 — روی ماژول‌های ESP32-WROOM-32 به بیرون سیم‌کشی نشده‌اند. پس در بهترین حالت ۲۶ پایه به ماژول می‌رسد، و اینکه چندتایشان به هدرِ برد می‌رسد به مدل برد بستگی دارد.

جدول: هر پایه در کدام گروه است

این را جایی بگذار که موقع سیم‌کشی ببینی. یک پایه می‌تواند هم‌زمان در چند سطر باشد.

گروه پایه‌ها یعنی چه
امن برای هر کاری 4 13 16 17 18 19 21 22 23 25 26 27 32 33 ورودی، خروجی، PWM و pull-up داخلی — هر چهارتا. سیم‌کشی را از این‌ها شروع کن. روی ماژول‌های ESP32-WROVER (که PSRAM دارند) 16 و 17 آزاد نیستند.
فقط ورودی 34 35 36 39 فقط می‌خوانند و هیچ‌وقت چیزی را روشن نمی‌کنند. pull-up و pull-down داخلی هم ندارند. روی بیشتر بردها 36 و 39 به‌جای شماره با برچسبِ VP و VN چاپ شده‌اند.
ADC1 32 33 34 35 36 39 خواندن سیگنال آنالوگ. با WiFi روشن هم بی‌مشکل کار می‌کنند.
ADC2 0 2 4 12 13 14 15 25 26 27 خواندن آنالوگ، ولی فقط تا وقتی WiFi خاموش است.
strapping 0 2 5 12 15 در لحظهٔ ری‌ست خوانده می‌شوند و حالتِ بالا آمدن برد را تعیین می‌کنند.
سیگنال هنگام boot 1 3 5 14 15 در کسری از ثانیهٔ اولِ روشن شدن، خودشان چیزی بیرون می‌دهند.
اشغال — پورت USB 1 3 UART0؛ مسیری که Thonny و Serial Monitor با آن حرف می‌زنند.
هرگز 6 7 8 9 10 11 مستقیم به SPI flash وصل‌اند.

5 و 14 عمداً در سطر «امن برای هر کاری» نیستند، ولی ممنوع هم نیستند: هر دو به‌عنوان خروجی معمولی سالم کار می‌کنند — 5 برای TRIG سنسور فاصله، 14 برای ورودی درایور موتور — فقط هنگام روشن شدنِ برد پالس کوتاهی می‌دهند. برای LED بی‌اهمیت است؛ برای Servo نه.

چهار پایه‌ای که فقط گوش می‌دهند

پایه‌های 34 و 35 و 36 و 39 درایور خروجی ندارند. اگر روی یکی LED ببندی و value(1) بدهی، نه خطایی می‌گیری و نه هیچ اتفاقی می‌افتد. برای سنسورها عالی‌اند و برای همین ساخته شده‌اند.

تلهٔ دومشان گران‌تر تمام می‌شود: مقاومت pull-up و pull-down داخلی ندارند. وقتی روی یک پایهٔ عادی می‌نویسی Pin(32, Pin.IN, Pin.PULL_UP)، مقاومتی داخلِ چیپ پایه را بالا نگه می‌دارد تا وقتی دکمه فشرده نشده عددِ ثابتِ 1 بخوانی. روی 34 تا 39 چنین مقاومتی نیست؛ بسته به نسخهٔ firmware یا خطا می‌گیری، یا — که بدتر است — هیچ خطایی نمی‌گیری و پایه شناور می‌ماند.

راه‌حل یک مقاومت ۱۰ کیلواهمی بیرونی است، دقیقاً همان کاری که چیپ خودش نمی‌کند: مقاومت از پایه به 3V3، و دکمه از همان پایه به GND. دکمه که رها است پایه از راه مقاومت بالا می‌ماند و 1 می‌خوانی؛ فشار که می‌دهی مسیر مستقیمِ GND برنده می‌شود و 0.

# dokme roye paye-ye faghat-vorudi 34 ba pull-up birooni 10k
# sim-keshi: moghavemat 10k az paye 34 be 3V3 - dokme az paye 34 be GND
from machine import Pin
import time

button = Pin(34, Pin.IN)   # bedun-e PULL_UP: in paye pull-up dakheli nadarad

while True:
    if button.value() == 0:
        print("feshorde shod")
        time.sleep_ms(200)   # debounce-e sade
    time.sleep_ms(20)

اگر برایت فرقی نمی‌کند دکمه کجا باشد، ساده‌ترین کار این است که روی 32 یا 33 ببندی و از pull-up داخلی استفاده کنی. علتِ اینکه چرا فشردن یعنی 0، در مقالهٔ دکمهٔ فشاری کامل باز شده.

ADC1 و ADC2 — تفاوتی که فقط با WiFi خودش را نشان می‌دهد

ESP32 دو واحد مبدل آنالوگ به دیجیتال جدا دارد، نه یکی، و کدام پایه به کدام واحد وصل است در سیلیکون ثابت است: ADC1 روی 32 33 34 35 36 39، و ADC2 روی 0 2 4 12 13 14 15 25 26 27.

در یک پروژهٔ آفلاین هر دو یکسان کار می‌کنند. ماجرا از لحظه‌ای شروع می‌شود که WiFi را روشن می‌کنی: درایور WiFi خودش از ADC2 استفاده می‌کند و تا وقتی فعال است آن را برای خودش برمی‌دارد. از آن لحظه، خواندن هر پایهٔ ADC2 یا خطا می‌دهد یا عددی بی‌معنی برمی‌گرداند — کدام‌یک، به نسخهٔ firmware بستگی دارد.

بدترین بخشش این است که دیر خودش را نشان می‌دهد: سنسور را می‌بندی و عدد می‌گیری؛ یک هفته بعد wlan.connect را اضافه می‌کنی و ناگهان همان سنسور جواب نمی‌دهد، در حالی که به کدِ سنسور دست نزده‌ای. قاعدهٔ ساده: اگر پروژه‌ات WiFi دارد یا ممکن است روزی داشته باشد، هر سنسور آنالوگ را روی ADC1 ببند.

خواندن درست یک ریزه‌کاری هم دارد: بازهٔ پیش‌فرض ورودی ADC فقط تا حدود ۱ ولت است، یعنی سنسوری که تا ۳٫۳ ولت بالا می‌رود خیلی زود به سقفِ 4095 می‌چسبد و دیگر تکان نمی‌خورد. خط atten بازه را باز می‌کند.

برنامهٔ زیر هر دو نکته را با هم نشان می‌دهد. یک بار همین‌طور اجرایش کن، بعد فقط عدد 35 را به 25 عوض کن — پایه‌ای از ADC2 — و دوباره اجرا کن. (WiFi نمی‌خواهی؟ خط‌های network را حذف کن؛ بقیه همان خواندن سادهٔ آنالوگ است.)

# sensor-e analog + WiFi roshan: ADC1 salem mimanad, ADC2 na
from machine import ADC, Pin
import network
import time

WIFI_SSID = "name-e-shabake"
WIFI_PASS = "ramz-e-shabake"

sensor = ADC(Pin(35))            # 35 = ADC1 - ba WiFi ham kar mikonad
sensor.atten(ADC.ATTN_11DB)      # bedun-e in khat faghat ta hodud-e 1 volt dide mishavad

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(WIFI_SSID, WIFI_PASS)

while not wlan.isconnected():
    time.sleep_ms(500)

print("IP:", wlan.ifconfig()[0])

while True:
    print("sensor:", sensor.read())
    time.sleep_ms(500)

این عددِ 0 تا 4095 از کجا می‌آید و چطور به مقداری مفید تبدیل می‌شود؟ مقالهٔ پتانسیومتر و مقالهٔ LDR همین را نشان می‌دهند.

پایه‌های strapping — جایی که برد اصلاً بالا نمی‌آید

این خطرناک‌ترین گروه است، چون نشانه‌اش «کار نکردن» نیست؛ «هیچ‌چیز» است. در لحظهٔ ری‌ست، قبل از اجرای اولین خطِ برنامه‌ات، چیپ سطح ولتاژ چند پایه را می‌خواند و از رویشان تصمیم می‌گیرد چطور بالا بیاید. به این‌ها strapping pin می‌گویند و روی ESP32 پنج‌تا هستند:

  • 0 — اگر در لحظهٔ ری‌ست پایین باشد، برد به‌جای اجرای برنامه وارد حالت دانلود می‌شود. دکمهٔ BOOT روی برد دقیقاً همین کار را می‌کند، پس هر چیزی که موقع روشن شدن این پایه را به GND بکشد جای دکمهٔ BOOT را می‌گیرد. (روی بعضی بردها به هدر می‌رسد و روی بعضی نه.)
  • 2 — روی بسیاری از بردها به LED آبیِ روی برد وصل است و در حالت دانلود باید پایین یا آزاد باشد.
  • 5 — پیش‌فرضش بالا است و زمان‌بندی داخلی را تعیین می‌کند؛ به‌عنوان خروجی مشکلی ندارد.
  • 12 — بدترینشان. ولتاژ حافظهٔ flash را انتخاب می‌کند: پایین یعنی ۳٫۳ ولت، حالتِ درستِ ماژول‌های رایج. اگر در لحظهٔ ری‌ست بالا باشد، چیپ فرض می‌کند flash یک‌ونیم‌ولتی است و برد اصلاً بالا نمی‌آید — یک مقاومت pull-up ساده کافی است تا فکر کنی برد سوخته.
  • 15 — اگر موقع ری‌ست پایین کشیده شده باشد، پیام‌های اولیهٔ برد روی پورت سریال چاپ نمی‌شوند.

این پایه‌ها بعد از بالا آمدن برد کاملاً عادی‌اند؛ مشکل فقط در همان چند میلی‌ثانیهٔ اول است. ساده‌ترین سیاست: در پروژه‌های معمولی اصلاً سراغ 0 و 2 و 12 و 15 نرو — پایهٔ آزاد به‌قدر کافی هست.

6 تا 11 — پایه‌هایی که مالِ تو نیستند

این شش پایه به SPI flash روی خودِ ماژول وصل‌اند؛ همان حافظه‌ای که برنامهٔ MicroPython تو در آن ذخیره شده و لحظه‌به‌لحظه از آن خوانده می‌شود. اگر یکی را به‌عنوان GPIO دست بگیری، مسیرِ خواندنِ کدِ در حال اجرا را قطع کرده‌ای؛ نتیجه فوری است: ری‌ست، یا یک حلقهٔ ری‌ستِ بی‌پایان.

خبر خوب اینکه روی بردهای ۳۰ پین معمولاً روی هدر نیستند. روی بعضی بردهای ۳۸ پین بیرون آورده شده‌اند، با برچسب‌هایی مثل SD0 و CLK و CMD به‌جای شماره — اگر چنین برچسبی دیدی، همان‌هاست.

۳٫۳ ولت یعنی ۳٫۳ ولت

ESP32 یک قطعهٔ ۳٫۳ ولتی است و حداکثر ولتاژ مجاز روی یک پایه ۳٫۶ ولت. یعنی سنسوری که خروجی ۵ ولت می‌دهد، ۱٫۴ ولت بالاتر از سقف مجاز است. گاهی همان لحظه چیزی نمی‌سوزد و همین فریبنده است: پایه به‌مرور آسیب می‌بیند و چند هفته بعد فقط «یک پایهٔ خراب» داری، بدون اینکه بدانی چرا.

جهت مهم است: اینکه ESP32 با ۳٫۳ ولت به یک قطعهٔ ۵ ولتی فرمان بدهد معمولاً بی‌خطر است، چون بیشتر قطعات ۵ ولتی هر چیزِ بالای حدود ۲ ولت را «روشن» حساب می‌کنند. مشکل جهت برعکس است. نمونهٔ کلاسیکش HC-SR04 است: TRIG را می‌شود مستقیم وصل کرد، ولی ECHO جواب را با ۵ ولت پس می‌فرستد و حتماً باید مهار شود. یا ماژول HC-SR04P را بگیر که نسخهٔ ۳٫۳ ولتیِ همان سنسور است، یا مقسم ولتاژ ببند: ۱۰ کیلواهم از ECHO به پایهٔ ورودی، و ۲۰ کیلواهم (دو تا ۱۰ کیلواهمِ سری) از همان نقطه به GND. عددش دقیق درمی‌آید: 5 V × 20k / (10k + 20k) = 3.33 V.

سقف دومی هم هست که کمتر دیده می‌شود: جریان. هر پایهٔ GPIO حداکثر ۴۰ میلی‌آمپر مطلق تحمل می‌کند و کارِ امن زیر ۲۰ میلی‌آمپر است؛ یک LED قرمز با مقاومت ۲۲۰ اهم حدود ۶ میلی‌آمپر می‌کشد، کاملاً داخل بازه. ولی موتور و Servo صدها میلی‌آمپر می‌کشند و هرگز نباید از یک پایه تغذیه شوند؛ حتی پایهٔ 3V3 برد هم برایشان کافی نیست: ولتاژ کل برد افت می‌کند و ESP32 وسط کار ری‌ست می‌شود. قطعهٔ پرمصرف از VIN یا منبع جدا تغذیه می‌شود، با GND مشترک.

سه اشتباهی که بیشترین وقت را می‌گیرند

۱. دکمه روی یک پایهٔ فقط-ورودی

نشانه: عددی که می‌خوانی بدون اینکه به دکمه دست بزنی بین 0 و 1 می‌پرد، یا روی یکی گیر می‌کند؛ نزدیک‌کردن دست به سیم هم عدد را عوض می‌کند.

علت: دکمه روی 34 تا 39 بسته شده و در کد Pin.PULL_UP نوشته‌ای؛ آن مقاومت داخلی اینجا وجود ندارد و پایهٔ رهاشده شناور می‌ماند و نویز محیط را می‌خواند.

درمان: یک مقاومت ۱۰ کیلواهمی از پایه به 3V3 اضافه کن، یا دکمه را ببر روی 32 یا 33.

۲. سنسور آنالوگ روی ADC2 در یک پروژهٔ WiFi

نشانه: سنسور هفتهٔ پیش عالی کار می‌کرد؛ امروز WiFi اضافه شده و همان سنسور یا عدد ثابت می‌دهد یا خطا.

علت: سنسور روی یکی از پایه‌های ADC2 است و درایور WiFi این واحد را در اختیار گرفته.

درمان: سیم سنسور را ببر روی یک پایهٔ ADC1: 32 33 34 35 36 39. کد لازم نیست عوض شود، فقط شمارهٔ پایه.

۳. چیزی روی یک پایهٔ strapping در لحظهٔ روشن شدن

نشانه: برد بالا نمی‌آید، یا هر بار به حالت دانلود می‌رود، یا Thonny چیزی پیدا نمی‌کند. اگر Servo بسته‌ای، نشانه‌اش یک تکان ناگهانی در لحظهٔ روشن شدن است.

علت: یک مقاومت یا سنسوری که خروجی‌اش در حالت استراحت بالا است، سطح یکی از 0 2 12 15 را در لحظهٔ ری‌ست عوض می‌کند؛ برای 12 همین کافی است که برد اصلاً بالا نیاید. تکان Servo ریشهٔ دیگری دارد: 1 3 5 14 15 در همان کسری از ثانیهٔ اول خودشان پالسی بیرون می‌دهند و Servo آن را فرمان واقعی حساب می‌کند.

درمان: تشخیصش دو دقیقه‌ای است — همه‌چیز را از برد جدا کن و بردِ خالی را روشن کن. اگر بالا آمد، مشکل از سیم‌کشی است نه از برد؛ بعد قطعه‌ها را یکی‌یکی برگردان. برای پیشگیری، Servo را روی پایه‌ای مثل 13 ببند.

قبل از سیم‌کشی، این چهار سؤال را بپرس

۱. این پایه باید حرف بزند یا فقط گوش بدهد؟ اگر قرار است چیزی را روشن کند — LED، Buzzer، ورودی درایور موتور، فرمان Servo — 34 35 36 39 از فهرست حذف می‌شوند.

۲. سیگنالش آنالوگ است یا دیجیتال؟ آنالوگ + احتمالِ WiFi یعنی فقط ADC1: 32 33 34 35 36 39.

۳. این قطعه با چند ولت به سمت من حرف می‌زند؟ بیشتر از ۳٫۳ ولت یعنی یا نسخهٔ ۳٫۳ ولتیِ قطعه، یا مقسم ولتاژ. و بیشتر از ۲۰ میلی‌آمپر یعنی تغذیه‌اش از پایهٔ GPIO نیست.

۴. اگر همین حالا دکمهٔ EN را بزنم، این پایه چه می‌کند؟ اگر یکی از 0 2 12 15 است، بپرس آنچه بسته‌ای سطحِ آن را در لحظهٔ ری‌ست عوض می‌کند یا نه. و اگر Servo روی 5 یا 14 است، جایش را عوض کن.

بعد از این چه بخوانی

بهترین راه جا افتادن این قواعد، امتحان کردنِ پایهٔ اشتباه است — جایی که هیچ قطعه‌ای نمی‌سوزد. در آزمایشگاه سنسور را روی پایه‌های مختلف ببند، عدد خروجی را زنده ببین و همین کدها را بدون سخت‌افزار اجرا کن.

اگر هنوز برد نخریده‌ای، آردوینو یا ESP32؟ همین تصمیم را باز می‌کند. و اگر مدارت روی Breadboard بسته می‌شود، ساختار داخلی Breadboard دستهٔ کاملاً جدایی از اشکال‌ها را از سرِ راهت برمی‌دارد — اشکال‌هایی که به پایه ربطی ندارند و درست شبیه همین‌ها به نظر می‌رسند.