
# Pull-up و Pull-down چیست و چرا؟
اگر با Arduino، ESP32 یا هر میکروکنترلر دیگری کار کرده باشید، احتمالاً با عبارت های Pull-up و Pull-down روبه رو شده اید.
شاید در نگاه اول موضوع ساده ای به نظر برسد: یک مقاومت را به پایه GPIO وصل می کنیم و تمام!
اما همین مقاومت ساده یکی از مهم ترین اجزای بسیاری از مدارهای دیجیتال است. اگر Pull-up یا Pull-down را درست درک نکنیم، ممکن است ورودی میکروکنترلر بدون اینکه دلیلش را بدانیم، بین HIGH و LOW تغییر کند و مدار ما رفتارهای عجیب و غیرقابل پیش بینی داشته باشد.
در این مقاله از پایه شروع می کنیم و قدم به قدم می بینیم:
- Pull-up و Pull-down دقیقاً چه هستند؟
- چرا یک ورودی دیجیتال به آنها نیاز دارد؟
- وقتی یک پایه آزاد باشد چه اتفاقی می افتد؟
- تفاوت Pull-up و Pull-down چیست؟
- در چه شرایطی از Pull-up استفاده کنیم؟
- چه زمانی Pull-down انتخاب بهتری است؟
- مقاومت مناسب چه مقداری دارد؟
- مقاومت Pull داخلی میکروکنترلر چه کاربردی دارد؟
- چند مثال واقعی با Arduino و ESP32 چگونه پیاده می شوند؟
ابتدا یک مسئله ساده: ورودی GPIO
فرض کنید یک کلید را به پایه GPIO یک ESP32 متصل کرده ایم.
می خواهیم برنامه این کار را انجام دهد:
- وقتی کلید فشرده نشده است، GPIO مقدار
LOWداشته باشد. - وقتی کلید فشرده می شود، GPIO مقدار
HIGHداشته باشد.
در نگاه اول شاید فکر کنیم کافی است کلید را بین GPIO و 3.3V قرار دهیم.
اما یک سؤال مهم وجود دارد:
وقتی کلید باز است، GPIO چه مقداری دارد؟
پاسخ این است:
اگر هیچ مسیر مشخصی برای تعیین وضعیت GPIO وجود نداشته باشد، پایه در حالت Floating یا شناور قرار می گیرد.
ورودی Floating چیست؟
ورودی دیجیتال میکروکنترلر معمولاً امپدانس بالایی دارد.
یعنی وقتی آن را به جایی متصل نکرده ایم، جریان بسیار کمی وارد پایه می شود.
در نتیجه، اگر GPIO آزاد باشد، نمی توانیم انتظار داشته باشیم که همیشه LOW یا همیشه HIGH باشد.
این پایه ممکن است تحت تأثیر عوامل مختلف قرار بگیرد:
- نویز الکتریکی
- میدان های الکترومغناطیسی
- سیم های اطراف
- طول سیم
- مدارهای مجاور
- حتی لمس کردن سیم با دست
در نتیجه ممکن است برنامه یک بار HIGH و بار دیگر LOW بخواند.
به این وضعیت Floating Input می گوییم.
به زبان ساده:
ورودی Floating مثل کلیدی است که هیچ کس آن را به طور مشخص روی روشن یا خاموش قرار نداده است.
برای حل این مشکل باید یک وضعیت پیش فرض برای ورودی تعیین کنیم.
اینجاست که Pull-up و Pull-down وارد مدار می شوند.
Pull-up چیست؟
در Pull-up یک مقاومت بین پایه GPIO و ولتاژ مثبت مدار، مثلاً 3.3V، قرار می گیرد.
به صورت ساده:
3.3V
|
[R]
|
+------ GPIO
|
Switch
|
GNDوقتی کلید باز است، مقاومت GPIO را به سمت 3.3V می کشد.
بنابراین:
Switch = باز
GPIO = HIGHاما وقتی کلید فشرده می شود، GPIO مستقیماً به زمین متصل می شود:
Switch = بسته
GPIO = LOWبنابراین در Pull-up:
| وضعیت کلید | وضعیت GPIO |
|---|---|
| باز | HIGH |
| فشرده | LOW |
به همین دلیل Pull-up را می توان این طور به خاطر سپرد:
Pull-up یعنی وقتی ورودی رها شده است، پیش فرض آن HIGH باشد.
چرا مقاومت لازم است؟
ممکن است سؤال مهمی پیش بیاید:
چرا GPIO را مستقیماً به 3.3V وصل نکنیم؟
چون اگر GPIO را مستقیماً به 3.3V وصل کنیم و سپس کلید را به GND متصل کنیم، عملاً یک اتصال کوتاه بین 3.3V و GND ایجاد می شود.
مثلاً:
3.3V
|
|
GPIO
|
Switch
|
GNDوقتی کلید بسته شود، جریان زیادی از منبع تغذیه عبور می کند.
اما با قرار دادن مقاومت:
3.3V
|
[R]
|
GPIO
|
Switch
|
GNDمقاومت جریان را محدود می کند.
این یکی از مهم ترین وظایف مقاومت Pull است.
Pull-down چیست؟
Pull-down دقیقاً برعکس Pull-up عمل می کند.
در Pull-down، یک مقاومت بین GPIO و GND قرار می دهیم:
3.3V
|
Switch
|
+------ GPIO
|
[R]
|
GNDوقتی کلید باز است، مقاومت GPIO را به سمت GND می کشد:
Switch = باز
GPIO = LOWوقتی کلید فشرده می شود، GPIO مستقیماً به 3.3V متصل می شود:
Switch = بسته
GPIO = HIGHبنابراین:
| وضعیت کلید | وضعیت GPIO |
|---|---|
| باز | LOW |
| فشرده | HIGH |
پس:
Pull-down یعنی وقتی ورودی رها شده است، پیش فرض آن LOW باشد.
تفاوت Pull-up و Pull-down در یک نگاه
| ویژگی | Pull-up | Pull-down |
|---|---|---|
| اتصال مقاومت | GPIO به VCC | GPIO به GND |
| وضعیت پیش فرض | HIGH | LOW |
| کلید به | GND | VCC |
| با فشردن کلید | LOW | HIGH |
| کاربرد رایج | کلیدها، I2C و ورودی های دیجیتال | کلیدها و ورودی های دیجیتال |
پس کدام را انتخاب کنیم؟
پاسخ به این سؤال به نوع مدار و منطقی که برای ورودی در نظر گرفته ایم بستگی دارد.
اگر می خواهیم:
رها = HIGH
فعال = LOWاز Pull-up استفاده می کنیم.
اگر می خواهیم:
رها = LOW
فعال = HIGHاز Pull-down استفاده می کنیم.
این انتخاب لزوماً به معنی بهتر بودن یکی نسبت به دیگری نیست.
هر دو یک وظیفه اصلی دارند:
جلوگیری از شناور ماندن ورودی و تعیین یک وضعیت پیش فرض مشخص.
یک مثال واقعی با کلید
فرض کنید یک کلید داریم که با فشرده شدن باید LED را روشن کند.
روش اول: Pull-up
مدار:
3.3V
|
[10kΩ]
|
GPIO
|
[Switch]
|
GNDبرنامه:
pinMode(4, INPUT_PULLUP);در این حالت:
کلید باز → HIGH
کلید بسته → LOWبنابراین اگر بخواهیم هنگام فشردن کلید کاری انجام دهیم، باید دنبال LOW باشیم:
if (digitalRead(4) == LOW) {
// کلید فشرده شده است
}این موضوع برای تازه کارها کمی عجیب است.
ممکن است فکر کنند:
«چرا وقتی کلید را فشار می دهم، مقدار LOW دریافت می کنم؟»
دلیل آن ساده است:
چون در این مدار کلید با فشار دادن، GPIO را به GND متصل می کند.
روش دوم: Pull-down
مدار:
3.3V
|
[Switch]
|
GPIO
|
[10kΩ]
|
GNDدر این حالت:
کلید باز → LOW
کلید بسته → HIGHبنابراین:
if (digitalRead(4) == HIGH) {
// کلید فشرده شده است
}هر دو مدار کاملاً معتبر هستند.
مقاومت Pull چه مقدار باشد؟
یکی از سؤال های رایج این است که:
مقاومت Pull-up یا Pull-down چند اهم باشد؟
مقادیر رایج عبارتند از:
4.7kΩ
10kΩ
22kΩ
47kΩ
100kΩمقدار مناسب به مدار بستگی دارد.
برای بسیاری از ورودی های معمولی، 10kΩ یک انتخاب متداول و مناسب است.
اما همیشه نباید بدون بررسی از 10kΩ استفاده کرد.
اگر مقاومت خیلی کوچک باشد
مثلاً:
1kΩجریان بیشتری از مقاومت عبور می کند.
در مدار Pull-up وقتی کلید به GND وصل شود:
3.3V
|
[1kΩ]
|
GNDجریان تقریباً برابر است با:
I = V / R
I = 3.3 / 1000
I ≈ 3.3mAاین مقدار برای بسیاری از مدارها قابل قبول است، اما نسبت به یک مقاومت 10kΩ جریان بیشتری مصرف می کند.
اگر مقاومت خیلی بزرگ باشد
مثلاً:
1MΩجریان بسیار کمی مصرف می شود، اما ورودی نسبت به نویز حساس تر می شود و اثر ظرفیت های انگلی و محیطی نیز بیشتر اهمیت پیدا می کند.
بنابراین مقاومت Pull باید یک تعادل بین مصرف جریان، سرعت و پایداری ورودی ایجاد کند.
برای بسیاری از کاربردهای معمول دیجیتال:
10kΩ نقطه شروع بسیار خوبی است.
Pull داخلی میکروکنترلر چیست؟
یکی از امکانات بسیار کاربردی در Arduino و ESP32 این است که در بسیاری از GPIOها، مقاومت Pull داخلی وجود دارد.
یعنی لازم نیست همیشه یک مقاومت خارجی روی برد قرار دهیم.
مثلاً:
pinMode(4, INPUT_PULLUP);یعنی:
پایه GPIO شماره 4 را به عنوان ورودی تنظیم کن و Pull-up داخلی را فعال کن.
در این حالت می توانیم یک کلید را به شکل ساده تری وصل کنیم:
GPIO
|
[Switch]
|
GNDو Pull-up را داخل میکروکنترلر فعال کنیم.
به همین دلیل در بسیاری از پروژه های Arduino و ESP32 می بینیم:
pinMode(BUTTON_PIN, INPUT_PULLUP);و دیگر مقاومت 10kΩ خارجی در شماتیک وجود ندارد.
آیا Pull داخلی همیشه کافی است؟
خیر.
مقاومت داخلی معمولاً مقدار دقیقی مثل یک مقاومت خارجی 10kΩ ندارد و مقدار آن می تواند در محدوده ای قرار داشته باشد که توسط سازنده مشخص شده است.
بنابراین در مدارهای حساس یا شرایط خاص، استفاده از مقاومت خارجی ممکن است انتخاب مناسب تری باشد.
مثلاً در مواردی مانند:
- خطوط طولانی
- محیط های نویزی
- سرعت های بالاتر
- مدارهای حساس
- نیاز به مقدار مقاومت دقیق
- طراحی محصول نهایی
بهتر است مشخصات میکروکنترلر و شرایط مدار بررسی شود.
یک کاربرد بسیار مهم: I2C
Pull-up فقط برای کلیدها نیست.
یکی از کاربردهای بسیار مهم آن در ارتباط I2C است.
در I2C خطوط:
SDA
SCLمعمولاً به Pull-up نیاز دارند.
به صورت ساده:
VCC
|
[R]
|
SDA
|
Devicesو مشابه همین برای SCL.
در I2C، دستگاه ها معمولاً خط را به سمت LOW می کشند و برای برگشت به HIGH از Pull-up استفاده می شود.
به همین دلیل اگر در مدار I2C مقاومت Pull-up مناسب وجود نداشته باشد، ممکن است ارتباط به درستی کار نکند.
چرا در I2C بیشتر Pull-up می بینیم؟
این موضوع به ساختار خروجی های مورد استفاده در I2C مربوط است.
دستگاه ها معمولاً می توانند خط را به LOW بکشند، اما برای ایجاد HIGH از مقاومت Pull-up استفاده می شود.
بنابراین خط در حالت عادی:
HIGHاست و هر دستگاهی که بخواهد صفر منطقی ایجاد کند، خط را به:
LOWمی کشد.
به همین دلیل Pull-up در I2C یک موضوع بنیادی است، نه صرفاً یک راه حل برای کلیدها.
Pull-up و Pull-down فقط برای کلید نیستند
این مقاومت ها را می توان برای بسیاری از ورودی های دیجیتال استفاده کرد.
مثلاً:
- کلیدها
- Push Button
- سنسورها
- ورودی های دیجیتال
- سیگنال های Enable
- پایه های Reset
- خطوط ارتباطی خاص
- I2C
- تشخیص وضعیت مدار
در همه این موارد یک سؤال مهم وجود دارد:
وقتی دستگاه خارجی هیچ سیگنالی تولید نمی کند، این ورودی باید چه وضعیتی داشته باشد؟
اگر پاسخ HIGH است، Pull-up می تواند انتخاب مناسبی باشد.
اگر پاسخ LOW است، Pull-down می تواند انتخاب مناسبی باشد.
یک اشتباه رایج
فرض کنید یک Push Button داریم و آن را به GPIO وصل کرده ایم.
بعضی افراد تصور می کنند:
pinMode(BUTTON_PIN, INPUT);کافی است.
اما این دستور فقط می گوید:
این پایه ورودی است.
این دستور به تنهایی مشخص نمی کند که وقتی کلید باز است، ورودی باید HIGH باشد یا LOW.
اگر هیچ مقاومت Pull وجود نداشته باشد، پایه ممکن است Floating شود.
پس تفاوت مهم این دو را به خاطر بسپارید:
pinMode(pin, INPUT);یعنی:
پایه ورودی است.
اما:
pinMode(pin, INPUT_PULLUP);یعنی:
پایه ورودی است و Pull-up داخلی آن نیز فعال است.
آیا می توان هم Pull-up و هم Pull-down داشت؟
از نظر مدار ممکن است هر دو مقاومت را قرار دهیم، اما معمولاً برای یک ورودی ساده نیازی به این کار نیست.
اگر هر دو مقاومت را همزمان قرار دهیم:
VCC
|
[R1]
|
GPIO
|
[R2]
|
GNDیک تقسیم مقاومتی ایجاد می شود.
در این حالت مقدار GPIO به نسبت مقاومت ها تعیین می شود.
بنابراین این مدار دیگر یک Pull-up یا Pull-down ساده نیست و باید بر اساس نیاز واقعی طراحی شود.
یک نکته مهم درباره منطق Active-Low
در مدارهای Pull-up زیاد با مفهوم Active-Low روبه رو می شویم.
مثلاً:
Button = LOW → فعال
Button = HIGH → غیرفعالممکن است در ابتدا عجیب باشد که چرا «فعال» با صفر منطقی مشخص شده است.
اما این موضوع کاملاً طبیعی است.
در یک مدار Pull-up، وضعیت عادی ورودی HIGH است و وقتی کلید یا مدار خارجی آن را به زمین می کشد، LOW می شود.
به همین دلیل بسیاری از مدارهای واقعی از منطق Active-Low استفاده می کنند.
ممکن است در نام سیگنال ها نیز آن را به شکل هایی مانند زیر ببینید:
RESET_N
ENABLE_N
CS_N
BUTTON_Nحرف یا خط زیرین N معمولاً نشان می دهد که سیگنال Active-Low است.
چگونه بین Pull-up و Pull-down تصمیم بگیریم؟
برای انتخاب، این سه سؤال را از خودمان بپرسیم:
سؤال اول: وضعیت عادی ورودی چیست؟
اگر در حالت عادی می خواهیم:
HIGHباشد، Pull-up را در نظر بگیرید.
اگر می خواهیم:
LOWباشد، Pull-down را در نظر بگیرید.
سؤال دوم: دستگاه خارجی چگونه سیگنال را فعال می کند؟
اگر فعال شدن با اتصال به GND انجام می شود، Pull-up معمولاً انتخاب طبیعی است.
اگر فعال شدن با اتصال به VCC انجام می شود، Pull-down معمولاً انتخاب طبیعی است.
سؤال سوم: آیا مقاومت داخلی کافی است؟
برای یک کلید ساده که نزدیک میکروکنترلر قرار دارد، Pull داخلی معمولاً بسیار کاربردی است.
اما در یک محصول واقعی باید شرایط نویز، طول سیم، سرعت سیگنال و مشخصات میکروکنترلر را نیز در نظر گرفت.
یک روش ساده برای به خاطر سپردن
می توانید این قانون را همیشه در ذهن داشته باشید:
Pull-up
GPIO ─── مقاومت ─── VCC
وضعیت پیش فرض = HIGHو:
Pull-down
GPIO ─── مقاومت ─── GND
وضعیت پیش فرض = LOWیا حتی ساده تر:
Pull-up به بالا می کشد.
Pull-down به پایین می کشد.
Pull-up یا Pull-down؛ مسئله اصلی چیست؟
نکته اصلی این نیست که کدام مقاومت «بهتر» است.
مسئله این است که ورودی دیجیتال نباید بدون تعیین وضعیت رها شود.
میکروکنترلر باید بتواند در هر لحظه تشخیص دهد:
HIGHیا:
LOWPull-up و Pull-down به ورودی یک وضعیت پیش فرض مشخص می دهند.
در واقع مقاومت Pull به ما اجازه می دهد بگوییم:
«اگر هیچ کس کاری با این ورودی ندارد، من می خواهم مقدار آن مشخص باشد.»
جمع بندی
Pull-up و Pull-down از ساده ترین و در عین حال مهم ترین مفاهیم طراحی مدارهای دیجیتال هستند.
اگر یک ورودی را بدون تعیین وضعیت رها کنیم، ممکن است Floating شود و مقدار آن قابل پیش بینی نباشد.
با Pull-up:
ورودی آزاد → HIGH
فعال شدن → LOWو با Pull-down:
ورودی آزاد → LOW
فعال شدن → HIGHبنابراین انتخاب بین آنها به منطق مورد نیاز مدار بستگی دارد.
در پروژه های Arduino و ESP32 نیز در بسیاری از موارد می توان به جای مقاومت خارجی از Pull داخلی استفاده کرد:
pinMode(BUTTON_PIN, INPUT_PULLUP);اما در طراحی مدارهای واقعی، همیشه باید شرایط مدار، نویز، طول سیم، سرعت سیگنال و مشخصات میکروکنترلر را نیز در نظر گرفت.
اگر همین یک مفهوم را به خوبی یاد بگیریم، بسیاری از مشکلاتی که هنگام کار با GPIO، کلیدها، سنسورها و ارتباطات دیجیتال پیش می آیند، بسیار ساده تر قابل درک و عیب یابی خواهند بود.
