نویزگیری کلید در آردوینو (دیبانسینگ سوییچ)
فرقی نمیکند تازه کار را با آردوینو را شروع کرده باشید و یا اینکه بخواهید سراغ پروژه های حرفهای بروید، در هر صورت لازم است نحوه دی بانسینگ و نویزگیری کلید در آردوینو را بلد باشید. نویزی که زمان فشار دادن کلیدهای مکانیکی ایجاد میشود در بیشتر مواقع میتواند مشکل ساز باشد.
در واقع این نویز باعث میشود تشخیص باز یا بسته بودن کلید برای آردوینو دشوار باشد و یا اینکه آردوینو فکر کند کلید را چند بار فشار دادهاید، در حالی که فشردن کلید توسط شما تنها یک بار انجام شدهاست. برای اینکه این بانس را در پروژه های خود از بین ببرید میتوان در مدار و سخت افزار خود تغییرات جزئی ایجاد کنید، یا اینکه از طریق کدنویسی بانس و نویز کلید را برطرف کنید. در ادامه این مطلب آموزشی هر دو راهکار بررسی شده است. لطفا در ادامه این مطلب آموزشی با ما همراه باشید.
بانس یا پرش کلید چیست؟
میکروکنترلر به صورت دائم وضعیت کلیدها (یعنی باز یا بسته بودن آن) را بررسی میکند و هر گونه تغییر سیگنال را تشخیص میدهد. زمانی که دست خود را روی کلید میگذارید، اتصالات فلزی داخل کلید نمیتوانند به صورت فوری و در آن واحد سیگنال الکتریکی را وصل کنند.
در حقیقت با فشار دادن دکمه، کنتاکت های کلید چندین بار وصل و قطع میشوند و در نهایت جریان الکتریکی را به شکل ثابت از خود عبور میدهند. علاوه بر آن ممکن است روی اتصالات داخل کلید آلودگی یا برجستگی ایجاد شده باشد و تماس بین صفحات فلزی به شکل ایده آل صورت نگیرد. به همین خاطر قبل از اینکه اتصال به صورت کامل برقرار شود، طی چند میلی ثانیه در کلید شاهد بانس و نویز خواهیم بود.
سرعت اجرای دستورات در آردوینو بسیار زیاد است و به همین نویزهای ایجاد شده در کلید (زمان فشار دادن آن) نادیده گرفته نخواهد شد. با توجه به توضیحات بالا، زمانی که یک کلید به صورت ایده آل و بدون نویز کار میکند، خروجی اسیلوسکوپ به صورت خواهد بود:
با فشار دادن کلید سیگنال از 0 به 1 تبدیل میشود و در همین حالت باقی میماند. اما در حالت عادی این اتفاق نمی افتد و بانس کلید سیگنال زیر را تولید میکند:
سیگنال چند بار بین 0 و 1 تغییر میکند و در نهایت روی 1 (یا همان 5 ولت) ثابت میشود. این اتفاق در چند میلی ثانیه رخ میدهد و با این وجود آردوینو همه این سیگنال ها را تشخیص داده و دستورات را طبق برنامه اجرا میکند که این اتفاق ناخواسته میتواند دردسر ساز شود.
نویزگیری کلید با سخت افزار
مدار اشمیت تریگر ساده ترین راه سخت افزاری حل مشکل دی بانسینگ کلید است. این مدار اغلب برای تبدیل سیگنال های آنالوگ به دیجیتال مورد استفاده قرار میگیرد و در اینجا میخواهیم به کمک آن نویز کلید را از بین ببریم.
این مدار در ورودی یک سیگنال آنالوگ را دریافت میکند و در خروجی یک سیگنال دیجیتال تولید میکند. در تصویر زیر عملکرد این مدار قابل مشاهده است:
زمانی که سیگنال ورودی اشمیت تریگر از آستانه ولتاژ بالا بیشتر شود، سیگنال دیجیتال در خروجی 1 میشود. زمانی که سیگنال ورودی از حد مشخص پایین تر باشد، سیگنال دیجیتال در خروجی 0 میشود.
برای راه اندازی اشمیت تریگر از آی سی SN74HC14N که توسط Texas Instruments ارائه شده است، استفاده کرده ایم:
آی سی SN74HC14N دارای 6 اشمیت تریگر مجزا است، پین های 1A، 2A، 3A، 4A، 5A و 6A ورودی های اشمیت تریگر بوده و پین های 1Y، 2Y، 3Y، 4Y، 5Y و 6Y خروجی های آن هستند. پایه های Vcc و GND نیز مربوط به تغذیه آی سی هستند.
راه اندازی اشمیت تریگر با آردوینو
حالا میخواهیم با استفاده از اشمیت تریگر، به نویزگیری کلید در آردوینو بپردازیم. در ادامه یک پروژه را راه اندازی کرده ایم که با هر بار فشار دادن دکمه، یک واحد به شمارنده اضافه شود.
برای راه اندازی این پروژه قطعات زیر مورد نیاز است:
- آردوینو UNO
- سیم های جامپر
- بردبورد
- آی سی SN74HC14N
- میکروسوییچ فشاری
- مقاومت 10 کیلو اهم
- خازن 1 میکروفاراد
قطعات را به صورت زیر به آردوینو متصل کنید:
برنامه نویسی پروژه اشمیت تریگر
در برنامه زیر سیگنال خروجی اشمیت تریگر توسط آردوینو خوانده شده و با هر بار فشار دادن دکمه یک واحد به شمارنده اضافه میشود. عدد شمارنده از طریق سریال مانیتور آردوینو قابل مشاهده خواهد بود.
پس از اینکه قطعات را مطابق با تصویر قبل به یکدیگر متصل کردید، برنامه زیر را روی برد آردوینو خود آپلود کنید:
int inputPin = 7;
int counter = 0;
int buttonState = 0;
int lastButtonState = 0;
void setup() {
pinMode(inputPin, INPUT);
Serial.begin(9600);
}
void loop() {
buttonState = digitalRead(inputPin);
if (buttonState != lastButtonState) {
if (buttonState == LOW) {
counter++;
Serial.println(counter);
}
}
lastButtonState = buttonState;
}
حالا باید سریال مانیتور آردوینو را باز کنید و پروژه را تست کنید. باید با هربار فشار دادن کلید یک واحد به شمارنده اضافه شود. پیشنهاد میشود کلید را به صورت مستقیم (و بدون مدار اشمیت تریگر) به پین 7 آردوینو متصل کنید و دوباره شمارنده را تست کنید. حالا میتوانید نویزگیری کلید در آردوینو و عملکرد شمارنده را مجددا بررسی کنید.
نویزگیری کلید با کدنویسی
در بخش قبل مطمئن ترین روش راه اندازی کلید و نویزگیری آن را با استفاده از سخت افزار بررسی کردیم اما ممکن در بخواهید پروژه را در بهینه ترین حالت ممکن نگه دارید یا اینکه به آیسی و قطعات اضافی دسترسی نداشته باشید. در این بخش میخواهیم روش نرم افزاری برطرف کردن نویز کلید را آموزش دهیم.
اما چطور این کار را انجام بدیم؟ برای برطرف کردن بانس کلید باید زمانی که اولین تغییر سیگنال کلید رخ داد، تایمر را راه اندازی کنیم و تعداد پرش ها را در یک مدت زمان مشخص نادیده بگیریم. در واقع آردوینو مدت کوتاهی را صبر میکند و دوباره وضعیت کلید را بررسی میکند تا 0 و 1 بودن آن را تشخیص دهد.
مثال: سیگنال دکمه در طول 50 میلی ثانیه ممکن است 3 بانس را تجربه کند. باید در برنامه نویسی پروژه این 50 ثانیه را نادیده بگیریم و سپس وضعیت کلید را بررسی کنیم.
در ادامه برنامه نویسی پروژه شمارنده را دوباره انجام داده ایم و این بار دی بانسینگ را از طریق کدنویسی پروژه ایجاد کرده ایم:
int inputPin = 7;
int counter = 0;
int buttonState = 0;
int lastButtonState = 0;
int currentButtonState = 0;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
void setup() {
pinMode(inputPin, INPUT);
Serial.begin(9600);
}
void loop() {
currentButtonState = digitalRead(inputPin);
if (currentButtonState != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (currentButtonState != buttonState) {
buttonState = currentButtonState;
if (buttonState == LOW) {
counter++;
Serial.println(counter);
}
}
}
lastButtonState = currentButtonState;
}
توضیح کدهای برنامه
در بخش اول برنامه متغیرهایی را تعریف کردیم که در پروژه اول نیز مورد استفاده قرار گرفتهاست. در این پروژه به چند متغیر دیگر نیاز داریم که شامل موارد زیر است:
- currentButtonState: وضعیت کلید را ذخیره میکند.
- lastDebounceTime: وقتی اولین سیگنال کلید تشخیص داده شد، این متغیر زمان آن لحظه را ذخیره میکند.
- debounceDelay: در این متغیر مدت زمان لازم برای نادیده گرفتن بانس کلید بر حسب میلی ثانیه ذخیره میشود.
بخش setup() در این برنامه درست مثل پروژه قبل است.
بخش loop()
سیگنال خوانده شده توسط inputPin را در متغیر currentButtonState ذخیره میکنیم.
در ادامه با یک دستور شرطی متغیر currentButtonState را با متغیر lastButtonState مقایسه میکنیم و اگر برابر نبودند، دستورات مرتبط به این حلقه شرطی را اجرا میکنیم. به عبارتی، در صورتی که وضعیت کلید در حال حاضر نسبت به قبل تغییر کرده باشد (دکمه فشار داده شده باشد)، دستور شرطی if اجرا میشود.
این این حلقه شرطی دستور lastDebounceTime = millis() را داریم. تابع millis() مدت زمانی که آردوینو روشن بوده است را نمایش میدهد. بنابراین در این لاین زمانی که اولین سیگنال از سمت کلید تشخیص داده شد، زمان آن لحظه را در متغیر lastDebounceTime ذخیره میکنیم.
در حلقه شرطی دوم زمان فعلی millis() را منهای lastDebounceTime میکنیم و اگر عدد به دست آمده از مقدار debounceDelay بزرگتر بود، دستورات حلقه شرطی اجرا میشود. مقدار زمان خروجی تابع millis() به طور منظم در حال افزایش است. با این وجود در متغیر lastDebounceTime لحظه فشردن کلید را ثبت کردهایم.
بنابراین:
millis() – lastDebounceTime : مدت زمانی از فشار دادن کلید گذشته است.
در صورتی که این زمان از مقدار متغیر debounceDelay بیشتر شود، دستورات حلقه if اجرا خواهد شد. درصورتی که این زمان از مقدار متغیر debounceDelay کمتر باشد، آردوینو مقدار شمارنده را افزایش نمیدهد، دستورات حلقه if را نادیده میگیرد و مدت زمان بیشتری را صبر میکند را بانس کلید به صورت کامل از بین برود. تا اینجا با بخش قابل توجهی از کدهای نویزگیری کلید در آردوینو و دی بانسینگ آشنا شده اید.
چطور زمان فشرده شدن کلید را ثبت میکنیم؟
مثلا فرض کنید دکمه را فشار داده ایم و 50 میلی ثانیه طول میکشد تا بانس کلید از بین برود. مقدار ذخیره شده در متغیر lastButtonState (یعنی وضعیت قبلی کلید) یک بوده و مقدار currentButtonState (یعنی وضعیت فعلی کلید) صفر است. از آنجایی که این دو متغیر با هم برابر نیستند اولین دستور حلقه شرطی اجرا میشود، یعنی مقدار millis() در متغیر lastDebounceTime ذخیره میشود.
مثال:
10000 میلی ثانیه از روشن شدن آردوینو میگذرد. تابع millis() در لحظه فعلی مقدار 10000 را دارد و آن را در متغیر lastDebounceTime ذخیره میکند. در حلقه شرطی دوم یعنی زمانی که millis() و lastDebounceTime هر دو مقدار 10000 را دارند، millis() – lastDebounceTime برابر 0 خواهد بود.
از آنجایی که مقدار debounceDelay صفر است و از عدد 50 (که در بخش متغیرها آن را مقداردهی کردیم) کوچک تر است، دستورات حلقه شرطی اجرا نمیشود و مقدار شمارنده افزایش نمی یابد.
آشنایی با وضعیت فعلی و قبلی کلید
در ادامه برنامه در حلقه loop() مقدار متغیر lastButtonState با متغیر currentButtonState برابر میشود. به این خاطر که آردوینو دستورات را با سرعت بسیار بالا و چیزی حدود چند میلیون بار در ثانیه اجرا میکند و تا زمانی که بانس کلید از بین برود، وضعیت قبلی کلید نیز 0 شده است.
در ادامه از آنجایی که inputPin هنوز صفر است، مقدار currentButtonState نیز صفر است و علاوه بر آن وضعیت فعلی کلید (currentButtonState) برابر با وضعیت قبلی (lastButtonState) است، اولین حلقه شرطی if اجرا نخواهد شد.
در صورتی که 1 میلی ثانیه از فشار دادن کلید گذشته باشد: millis() – lastDebounceTime برابر 1 خواهد بود. در نتیجه دستور شرطی دوم نیز نادیده گرفته میشود. این چرخه بارها و بارها ادامه می یابد تا زمانی که 50 میلی ثانیه طی شود و بانس کلید به صورت کامل از بین برود.
فرض کنید به 50 میلی ثانیه نرسیده ایم و دست را از روی کلید برمیداریم: در اینجا پین ورودی آردوینو 1 شده است، پس مقدار currentButtonState نیز برابر با 1 میشود. به همین خاطر مقدار فعلی کلید با مقدار قبلی آن برابر نیست و لازم است تایمر رو دوباره ریست کنیم: lastDebounceTime = millis()
در نهایت: کلید را برای 50 میلی ثانیه فشار داده ایم و مقدار آن صفر است و برنامه حلقه شرطی مربوط به شمارنده را اجرا میکند.
نویزگیری کلید در آردوینو (بخش پایانی)
در این مطلب آموزشی با روش سخت افزاری و روش نرم افزاری نویزگیری کلید آشنا شدیم. درک کامل دستورات بخش loop() شاید در ابتدا گیج کننده به نظر برسد اما اگر چندبار این مطالب را مرور کنید همه چیز واضح خواهد شد. در انتها امیدواریم مقاله آموزشی نویزگیری کلید در آردوینو برای شما مفید باشد و از این که تا انتهای این مطلب آموزشی با ما همراه بودید از شما متشکریم.