ডিজিটাল ইনপুট ডিবাউন্সিং
এই পাঠে যা শিখবেন
- মেকানিক্যাল সুইচ বাউন্স কেন ঘটে, এবং এটি সফটওয়্যারে কী সমস্যা তৈরি করে
- কাউন্ট-বেসড ডিবাউন্স অ্যালগরিদম কীভাবে কাজ করে
- একটি সত্যিকারের সিমুলেশন — একটি নির্মিত বাউন্সি সিগন্যালে raw ট্রানজিশন গণনা বনাম ডিবাউন্স করার পরের ট্রানজিশন গণনা
- সফটওয়্যার ডিবাউন্সিং বনাম হার্ডওয়্যার (RC ফিল্টার) ডিবাউন্সিং-এর মধ্যে সংক্ষিপ্ত পার্থক্য
১ · সুইচ বাউন্স সমস্যা
L14-এ দেখানো হয়েছে কীভাবে একটি বাটন GPIO পিনকে পুল-আপ ডিফল্ট থেকে বিপরীত অবস্থায় টেনে নেয়। কিন্তু বাস্তব জগতে একটি মেকানিক্যাল বাটনের ভেতরের দুটি ধাতব কন্টাক্ট একে অপরকে স্পর্শ করার সময় নিখুঁতভাবে, তাৎক্ষণিকভাবে "ছুঁয়ে" যায় না — সূক্ষ্ম যান্ত্রিক স্প্রিং-ব্যাক ও কম্পনের কারণে কন্টাক্টগুলো কয়েক মিলিসেকেন্ড ধরে বারবার সংযুক্ত-বিচ্ছিন্ন হতে থাকে, তারপর স্থির হয়। একটি মাইক্রোকন্ট্রোলার এত দ্রুত স্যাম্পল নিতে পারে (মাইক্রোসেকেন্ড রেজোলিউশনে) যে এই পুরো "কাঁপুনি" — যাকে বাউন্সContact bounceএকটি মেকানিক্যাল সুইচের ধাতব কন্টাক্ট বন্ধ/খোলার সময় কয়েক মিলিসেকেন্ড ধরে বারবার সংযুক্ত-বিচ্ছিন্ন হওয়ার যান্ত্রিক ঘটনা। বলা হয় — একাধিক পৃথক HIGH/LOW ট্রানজিশন হিসেবে দেখতে পায়, যদিও ব্যবহারকারী বাস্তবে মাত্র একবারই বাটন চেপেছেন।
কোনো ফিল্টার ছাড়া সরাসরি ইন্টারাপ্ট বা পোলিং-বেসড কোড লিখলে — "প্রতিটি ট্রানজিশনে একটি কাউন্টার বাড়াও" — একটি একক বাস্তব বাটন প্রেস ভুলবশত ৫-১৫টি (বা তারও বেশি) প্রেস হিসেবে গণনা হতে পারে। এটি একটি সুপরিচিত, বাস্তব এমবেডেড বাগ ক্লাস।
২ · কাউন্ট-বেসড ডিবাউন্স অ্যালগরিদম
সবচেয়ে সহজ ও সাধারণ সফটওয়্যার ডিবাউন্স কৌশল হলো — একটি নতুন রিডিং তখনই "স্থিতিশীল" (accepted) হিসেবে মেনে
নেওয়া হবে যখন সেই একই রিডিং পরপর অন্তত N বার (উদাহরণ — ৪ বার) এসেছে। যদি মাঝপথে রিডিং আবার বদলে
যায়, তাহলে গণনা নতুন করে শুরু হয়। এভাবে দ্রুত এলোমেলো বাউন্স (যা কখনোই পরপর N বার একই মান দেয়
না) ফিল্টার হয়ে বাদ পড়ে যায়, কিন্তু বাস্তব স্থায়ী পরিবর্তন (যা বাউন্স স্থির হওয়ার পর দীর্ঘক্ষণ একই মান দিতে
থাকে) ধরা পড়ে।
# একটি বাস্তব বাটন-প্রেস-তারপর-রিলিজের বাউন্সি raw স্যাম্পল সিকোয়েন্স -- হাতে তৈরি,
# যেন প্রতিটি এন্ট্রি একটি দ্রুত টাইম-স্যাম্পলে পিনের অবস্থা বোঝায়
raw_signal = [
0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, # প্রেস: বাউন্স করে শেষে HIGH-এ স্থির
1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, # রিলিজ: বাউন্স করে শেষে LOW-এ স্থির
]
def count_raw_transitions(signal):
return sum(1 for i in range(1, len(signal)) if signal[i] != signal[i - 1])
def debounce(signal, n_required=4):
# পরপর n_required বার একই মান না আসা পর্যন্ত স্টেট বদলাবে না
stable_state = signal[0]
candidate = signal[0]
run_length = 0
output = []
debounced_transitions = 0
for sample in signal:
if sample == candidate:
run_length += 1
else:
candidate = sample
run_length = 1
if run_length >= n_required and candidate != stable_state:
stable_state = candidate
debounced_transitions += 1
output.append(stable_state)
return output, debounced_transitions
raw_transitions = count_raw_transitions(raw_signal)
debounced_output, debounced_transitions = debounce(raw_signal, n_required=4)
print(f"Raw সিগন্যাল ({len(raw_signal)} স্যাম্পল): {raw_signal}")
print(f"Raw ট্রানজিশন সংখ্যা: {raw_transitions}")
print()
print(f"ডিবাউন্স করা আউটপুট: {debounced_output}")
print(f"ডিবাউন্স করা ট্রানজিশন সংখ্যা: {debounced_transitions}")
সফটওয়্যার ডিবাউন্সিং (উপরের মতো, কোনো অতিরিক্ত হার্ডওয়্যার লাগে না, শুধু কোড) ছাড়াও একটি হার্ডওয়্যার RC ফিল্টার (একটি ছোট রেজিস্টর-ক্যাপাসিটর নেটওয়ার্ক বাটনের সাথে যুক্ত করে সিগন্যালটাকে বৈদ্যুতিকভাবেই "স্মুথ" করে দেওয়া) ব্যবহার করেও ডিবাউন্স করা যায় — এতে সফটওয়্যারে কিছু করতে হয় না, কিন্তু অতিরিক্ত ফিজিক্যাল কম্পোনেন্ট লাগে। বেশিরভাগ আধুনিক এমবেডেড ডিজাইনে খরচ বাঁচাতে সফটওয়্যার ডিবাউন্সিংই বেশি ব্যবহৃত হয়।
মেকানিক্যাল সুইচ বাউন্স একটি বাস্তব ফিজিক্যাল ঘটনা যা একটি একক বাটন প্রেসকে একাধিক ভুয়া ট্রানজিশন হিসেবে দেখায়। একটি কাউন্ট-বেসড ডিবাউন্স ফিল্টার (পরপর N-বার একই রিডিং নিশ্চিত হওয়া পর্যন্ত স্টেট বদলাবে না) এই ভুয়া ট্রানজিশনগুলো বাদ দিয়ে শুধু প্রকৃত স্টেট-পরিবর্তনগুলো ধরে রাখে — এটি প্রায় প্রতিটি বাস্তব এমবেডেড প্রজেক্টে বাটন/সুইচ ইনপুট হ্যান্ডল করার একটি অপরিহার্য অংশ।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১
উপরের কোড সেলে n_required-এর মান ১ করে দিলে debounce() ফাংশনটি
কার্যকরভাবে কী করবে?
n_required=1 মানে প্রতিটি নতুন মান-ই "পরপর ১ বার" শর্ত সাথে সাথেই পূরণ করে ফেলবে — অর্থাৎ
ফিল্টারিং কার্যত বন্ধ হয়ে যাবে এবং প্রতিটি raw ট্রানজিশনই সরাসরি গ্রহণ হয়ে যাবে। এই ক্ষেত্রে
debounced_transitions ঠিক raw_transitions-এর সমান (১৪) হয়ে যাবে — অর্থাৎ কোনো
বাউন্স ফিল্টার হবে না।
প্র ০২
n_required-এর মান অনেক বড় (যেমন ৫০) করে দিলে কী সমস্যা হতে পারে, বিশেষ করে দ্রুত পরপর
দুটি বাটন প্রেস করলে?
n_required খুব বড় হলে ডিবাউন্স ফিল্টার একটি প্রকৃত, দ্রুত স্টেট-পরিবর্তনকেও "যথেষ্ট
স্থিতিশীল নয়" ধরে বাতিল করে দিতে পারে — অর্থাৎ একটি বৈধ, দ্রুত ডাবল-ক্লিক বা দ্রুত বাটন প্রেস মিস হয়ে
যেতে পারে। তাই n_required-কে যথেষ্ট বড় রাখতে হয় (বাউন্স ফিল্টার করার জন্য) কিন্তু যথেষ্ট
ছোটও রাখতে হয় (বৈধ দ্রুত ইনপুট মিস না করার জন্য) — এটি একটি বাস্তব ইঞ্জিনিয়ারিং ট্রেড-অফ।
প্র ০৩ ডিবাউন্সিং কি শুধু বাটনের জন্যই দরকার, নাকি অন্য কোনো ধরনের ডিজিটাল ইনপুটেও দরকার হতে পারে?
যেকোনো মেকানিক্যাল কন্টাক্ট-ভিত্তিক সেন্সরে (রিলে, টগল সুইচ, মেকানিক্যাল লিমিট সুইচ, রোটারি এনকোডারের কিছু ধরন) একই বাউন্স সমস্যা হতে পারে — কারণ মূল কারণটা যান্ত্রিক (ধাতব কন্টাক্টের কম্পন), বাটন-নির্দিষ্ট নয়। তবে সম্পূর্ণ ইলেকট্রনিক সেন্সর (যেমন একটি অপটিক্যাল বা ক্যাপাসিটিভ টাচ সেন্সর) সাধারণত মেকানিক্যাল বাউন্স করে না, যদিও তাদের নিজস্ব ইলেকট্রিক্যাল নয়েজ ফিল্টারিং লাগতে পারে।
অনুশীলন
-
চিন্তা করুন: উপরের কোড সেলে
raw_signal-এর প্রথম উপাদানটি যদি1(0 এর বদলে) হতো,debounce()-এরstable_stateএর প্রাথমিক মান কী হতো?stable_state = signal[0]লাইন অনুযায়ী প্রাথমিকstable_stateসবসময় সিগন্যালের প্রথম উপাদানের সমান হয় — তাই সেক্ষেত্রে এটি1হতো,0নয়। -
পরীক্ষা করুন: উপরের কোড সেলে
debounce(raw_signal, n_required=8)কল করে Run চাপুন এবংdebounced_transitions-এর নতুন মান পর্যবেক্ষণ করুন — এটি কি এখনও ২, নাকি কমে যায়?debounced_transitionsকমে১-এ নেমে আসবে। কারণ রিলিজের পরের শেষ LOW রানটি raw_signal-এ মাত্র ৬টি স্যাম্পল লম্বা —n_required=8সেই রানের চেয়ে বড়, তাই ফিল্টার কখনোই "৮ বার পরপর একই মান" শর্ত পূরণ হতে দেখে না এবং রিলিজ ইভেন্টটাই ধরতে পারে না (পিন চিরকালের জন্য HIGH-এ আটকে থেকে যায় আউটপুটে)। এটাই দেখায় কেনn_requiredখুব বড় রাখলে বৈধ ট্রানজিশনও মিস হয়ে যেতে পারে — ঠিক যেমনটা প্র ০২-এ আলোচনা হয়েছে।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৭টি পাঠ মাইক্রোপ্রসেসর আর্কিটেকচার, এমবেডেড C, GPIO, টাইমার/PWM/ADC, সিরিয়াল প্রোটোকল, RTOS, সেন্সর/অ্যাকচুয়েটর, IoT আর্কিটেকচার, ওয়্যারলেস প্রোটোকল, MQTT/CoAP ও IoT সিকিউরিটি — বাকি পাঠগুলো শীঘ্রই যুক্ত হবে।
- GPIO ফান্ডামেন্টাল — ইনপুট, আউটপুট, পুল-আপ, পুল-ডাউন আগের পাঠ GPIO পিনের মোড ও পুল কনফিগারেশনের ভিত্তি — এই পাঠে সেই ইনপুট পিনকেই আরও নির্ভরযোগ্য করা হলো।
- সব Courses দেখুন ABCL TECH C, C++, Python, Java, JavaScript, DSA, DBMS, Discrete Mathematics, System Design, Cybersecurity, Cloud Computing & DevOps, Computer Networks, Operating Systems, Computer Architecture, Design and Analysis of Algorithms ও আরও অনেক কোর্স — সব এক জায়গায়।