PWM জেনারেশন ও অ্যাপ্লিকেশন
এই পাঠে যা শিখবেন
- PWM কীভাবে একই টাইমার হার্ডওয়্যার (L18) থেকে তৈরি হয় — compare বনাম period রেজিস্টার
- ডিউটি সাইকেল গণনার সূত্র এবং তা থেকে গড় আউটপুট ভোল্টেজের সম্পর্ক
- একটি সত্যিকারের tick-by-tick HIGH/LOW ওয়েভফর্ম সিমুলেশন দিয়ে সূত্রের গণনা যাচাই
- PWM-এর তিনটি বাস্তব অ্যাপ্লিকেশন — LED ডিমিং, DC মোটর স্পিড, সার্ভো কন্ট্রোল
১ · PWM কী এবং কেন
মাইক্রোকন্ট্রোলারের ডিজিটাল আউটপুট পিন সরাসরি শুধু দুটো অবস্থায় থাকতে পারে — সম্পূর্ণ HIGH অথবা সম্পূর্ণ LOW, মাঝামাঝি কোনো ভোল্টেজ দিতে পারে না (একটি প্রকৃত অ্যানালগ আউটপুটের জন্য L21-এর DAC লাগে)। কিন্তু বাস্তবে প্রায়ই আমাদের "মাঝারি" পাওয়ার লাগে — যেমন একটি LED-কে অর্ধেক উজ্জ্বলতায় জ্বালানো। এর সমাধান হলো PWMPulse Width Modulationপিনকে খুব দ্রুত বারবার HIGH ও LOW-এর মধ্যে সুইচ করানো, যেখানে HIGH থাকার সময়ের অনুপাতই নিয়ন্ত্রণ করে গড় আউটপুট কতটুকু। — পিনকে এত দ্রুত বারবার সুইচ করানো যে লোড (LED, মোটর, মানুষের চোখ) শুধু গড় মানটাই অনুভব করে, প্রতিটি আলাদা টগল নয়।
L18-এর টাইমার হার্ডওয়্যারই এটি করে — একই ফ্রি-রানিং কাউন্টার ব্যবহার করা হয়, কিন্তু এবার দুটো রেজিস্টার লাগে: একটি period রেজিস্টার (পুরো একটি PWM চক্র কত tick-এ শেষ হবে) এবং একটি compare রেজিস্টার (চক্রের কত tick পর্যন্ত পিন HIGH থাকবে)। কাউন্টার যখন compare-এর নিচে থাকে, পিন HIGH; compare ছাড়িয়ে গেলে পিন LOW; period-এ পৌঁছালে কাউন্টার আবার ০ থেকে শুরু হয়।
২ · ডিউটি সাইকেলের সূত্র
$$ D_{\%} = \dfrac{N_{compare}}{N_{period}} \times 100 $$
এখানে $N_{compare}$ হলো কতগুলো tick পর্যন্ত পিন HIGH থাকবে, আর $N_{period}$ হলো পুরো একটি চক্রে মোট tick সংখ্যা। PWM-এর ফ্রিকোয়েন্সি নির্ভর করে L18-এর সূত্র অনুযায়ী — $f_{PWM} = f_{clock} / (N_{prescaler} \times N_{period})$ — একই ক্লক/প্রিস্কেলার/period গণনা এখানেও প্রযোজ্য, শুধু এবার "reload" ভ্যালুর নাম হয়ে যায় "period"।
৩ · সিমুলেশন — সত্যিকারের tick-by-tick ওয়েভফর্ম
নিচের কোড সেলে একটি PwmTimer ক্লাস প্রতিটি tick-এর জন্য পিনের অবস্থা (HIGH=1, LOW=0)
সত্যিই গণনা করে একটি তালিকায় রাখছে — তারপর সেই তালিকা থেকে কতগুলো tick HIGH ছিল তা গুনে, সেই সংখ্যা
থেকে ডিউটি সাইকেল বের করে সূত্রের ফলাফলের সাথে মিলিয়ে দেখা হচ্ছে।
class PwmTimer:
def __init__(self, period_ticks, compare_ticks):
self.period_ticks = period_ticks
self.compare_ticks = compare_ticks
def formula_duty_pct(self):
return 100 * self.compare_ticks / self.period_ticks
def simulate_waveform(self):
# প্রতিটি tick-এ পিনের অবস্থা সত্যিই গণনা করা হচ্ছে
waveform = []
for tick in range(self.period_ticks):
level = 1 if tick < self.compare_ticks else 0
waveform.append(level)
return waveform
test_configs = [
("২৫% ডিউটি", PwmTimer(period_ticks=100, compare_ticks=25)),
("৬০% ডিউটি", PwmTimer(period_ticks=100, compare_ticks=60)),
("১০% ডিউটি", PwmTimer(period_ticks=200, compare_ticks=20)),
]
for name, pwm in test_configs:
waveform = pwm.simulate_waveform()
high_ticks = sum(waveform)
total_ticks = len(waveform)
measured_duty_pct = 100 * high_ticks / total_ticks
print(f"--- {name} (period={pwm.period_ticks}, compare={pwm.compare_ticks}) ---")
print(f" সূত্র থেকে ডিউটি সাইকেল = {pwm.formula_duty_pct():.2f}%")
print(f" সিমুলেশনে HIGH ticks = {high_ticks} / {total_ticks}")
print(f" সিমুলেশন থেকে ডিউটি = {measured_duty_pct:.2f}%")
print(f" দুটো মেলে? = {abs(pwm.formula_duty_pct() - measured_duty_pct) < 1e-9}")
period_ticks=200 ব্যবহার করা হয়েছে অথচ ডিউটি সাইকেল
একই থাকছে (১০%) — কারণ ডিউটি সাইকেল শুধু compare আর period-এর অনুপাতের উপর নির্ভর করে,
নিরঙ্কুশ tick সংখ্যার উপর নয়। একই ডিউটি সাইকেল বিভিন্ন period ভ্যালু দিয়ে অর্জন করা সম্ভব — তবে period
বদলালে PWM-এর ফ্রিকোয়েন্সি বদলে যায় (একই ক্লক ধরে বড় period মানে ধীর PWM ফ্রিকোয়েন্সি)।
৪ · PWM-এর বাস্তব অ্যাপ্লিকেশন
একটি LED-কে PWM দিয়ে চালালে মানুষের চোখ প্রতিটি দ্রুত টগল আলাদাভাবে দেখতে পায় না (persistence of vision) — বরং গড় উজ্জ্বলতা অনুভব করে, যা ডিউটি সাইকেলের সমানুপাতিক। ৫০% ডিউটি সাইকেল মানে LED-টি অর্ধেক সময় সম্পূর্ণ HIGH আর অর্ধেক সময় সম্পূর্ণ LOW থাকে, কিন্তু চোখে দেখায় "অর্ধেক উজ্জ্বল"।
একইভাবে একটি DC মোটরে PWM প্রয়োগ করলে মোটরের কয়েলে যে গড় ভোল্টেজ পৌঁছায় তা ডিউটি সাইকেলের সমানুপাতিক, এবং মোটরের গতি (মোটামুটিভাবে) সেই গড় ভোল্টেজের সমানুপাতিক — তাই ডিউটি সাইকেল বদলে মোটরের গতি নিয়ন্ত্রণ করা যায়। এই সম্পর্কের বিস্তারিত সিমুলেশন M9/L38 (DC ও সার্ভো মোটর কন্ট্রোল)-এ আসছে।
সার্ভো মোটর একটু ভিন্নভাবে PWM ব্যবহার করে — এখানে ডিউটি সাইকেলের শতাংশ নয়, বরং প্রতি ~২০ms period-এ HIGH পালসের প্রকৃত প্রস্থ (সাধারণত ~১-২ms রেঞ্জে) সরাসরি সার্ভোর কোণ নির্ধারণ করে — এই নির্দিষ্ট কনভেনশনের গণনা M9/L38-এ বিস্তারিতভাবে আসবে।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১
যদি compare_ticks সরাসরি period_ticks-এর সমান করে দেওয়া হয়, ডিউটি
সাইকেল কত হবে এবং পিন কেমন আচরণ করবে?
সূত্র অনুযায়ী $D = (N_{period}/N_{period}) \times 100 = 100\%$ — পিন পুরো পিরিয়ড জুড়েই HIGH
থাকবে (কোড সেলে tick < compare_ticks শর্তটি প্রতিটি tick-এর জন্যই সত্য হবে, কারণ
tick সর্বোচ্চ period_ticks - 1 পর্যন্ত যায়)। অর্থাৎ ১০০% ডিউটি সাইকেল
মানে কার্যত পিন সবসময় HIGH — PWM নয়, একটি সাধারণ স্থির আউটপুট।
প্র ০২ PWM দিয়ে LED ডিমিং কাজ করে কারণ মানুষের চোখ দ্রুত টগল আলাদা করে দেখতে পায় না — কিন্তু PWM ফ্রিকোয়েন্সি যদি খুব কম (যেমন ৫ Hz) হয়, তাহলে কী হবে?
৫ Hz মানে প্রতি সেকেন্ডে মাত্র ৫ বার সুইচ হচ্ছে — প্রতিটি চক্র প্রায় ২০০ms দীর্ঘ, যা মানুষের চোখের persistence-of-vision থ্রেশহোল্ডের (সাধারণত ~৫০-৬০ Hz-এর উপরে "স্থির" মনে হয়) চেয়ে অনেক ধীর। ফলে LED-টি "মিটমিট করছে" (flickering) বলে দেখাবে, মসৃণ ডিমিং নয় — তাই বাস্তব PWM LED ড্রাইভারে সাধারণত কয়েকশ Hz থেকে কয়েক kHz ফ্রিকোয়েন্সি ব্যবহার করা হয়।
প্র ০৩
কোড সেলের তৃতীয় কনফিগারেশন (period_ticks=200, compare_ticks=20) আর যদি
period_ticks=100, compare_ticks=10 ব্যবহার করা হতো, ডিউটি সাইকেলে কোনো পার্থক্য হতো
কি?
না, ডিউটি সাইকেলে কোনো পার্থক্য হতো না — দুটোই $10/100 = 10\%$ এবং $20/200 = 10\%$, একই অনুপাত।
তবে PWM-এর ফ্রিকোয়েন্সি ভিন্ন হবে, কারণ ছোট period_ticks মানে একই ক্লকে
দ্রুত পিরিয়ড সম্পন্ন হয় (L18-এর সূত্র অনুযায়ী $f_{PWM} = f_{clock}/(N_{prescaler} \times
N_{period})$) — ডিউটি সাইকেল আর ফ্রিকোয়েন্সি দুটো আলাদা, স্বাধীনভাবে নিয়ন্ত্রণযোগ্য প্যারামিটার।
অনুশীলন
-
চিন্তা করুন:
PwmTimer(period_ticks=50, compare_ticks=15)-এর ডিউটি সাইকেল কত হবে বলে আপনার ধারণা? কোড সেলে বসিয়ে যাচাই করুন।সূত্র অনুযায়ী $D = (15/50) \times 100 = 30\%$। সিমুলেশনে
simulate_waveform()চালালে মোট ৫০টি tick-এর মধ্যে প্রথম ১৫টি HIGH (মান ১) আর বাকি ৩৫টি LOW (মান ০) হবে, অর্থাৎsum(waveform) == 15, যা $15/50 \times 100 = 30\%$-এই মেলে। -
পরীক্ষা করুন: কোড সেলের
test_configsতালিকায় একটি নতুন এন্ট্রি যোগ করুন —("৭৫% ডিউটি", PwmTimer(period_ticks=100, compare_ticks=75))— এবং Run চেপে দেখুন আউটপুটে HIGH ticks ও মিলে যাওয়ার ফলাফল কী দেখায়।আউটপুটে "সূত্র থেকে ডিউটি সাইকেল = ৭৫.00%", "সিমুলেশনে HIGH ticks = ৭৫ / ১০০", "সিমুলেশন থেকে ডিউটি = ৭৫.00%" এবং "দুটো মেলে? = True" দেখাবে — নিশ্চিত করবে বড় ডিউটি সাইকেলেও (কম্পেয়ার period-এর কাছাকাছি হলেও) সূত্র ও tick-by-tick গণনা একই ফলাফল দেয়।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৭টি পাঠ মাইক্রোপ্রসেসর আর্কিটেকচার, এমবেডেড C, GPIO, টাইমার/PWM/ADC, সিরিয়াল প্রোটোকল, RTOS, সেন্সর/অ্যাকচুয়েটর, IoT আর্কিটেকচার, ওয়্যারলেস প্রোটোকল, MQTT/CoAP ও IoT সিকিউরিটি — বাকি পাঠগুলো শীঘ্রই যুক্ত হবে।
- Computer Architecture & Digital Logic কোর্স সহোদর কোর্স টাইমার হার্ডওয়্যারের সাধারণ রেজিস্টার ভিত্তি সেই কোর্সেই তৈরি হয়েছে — এই কোর্স PWM-এর মতো পেরিফেরাল-স্পেসিফিক ব্যবহারে গভীরে যায়।
- সব 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 ও আরও অনেক কোর্স — সব এক জায়গায়।