পালস উইডথ মড্যুলেশন পরিচিতি

Last updated 2 months ago

যা যা লাগবে:

  • Arduino [Predictable! Isn’t it? :P]

  • Breadboard

  • Jumper

  • Led

  • Resistor [Recommended 100Ohm, but 220/330 Will work too]

PWM সম্পর্কে আলোচনা:

এতক্ষণে আপনারা ডিজিটাল ইনপুট আউটপুট দেখলেন, এবার দেখাব অ্যানালগ আউটপুট কিভাবে আর্ডুইনোর মাধ্যমে তৈরি করা যায়। ডিজিটাল আউটপুটের ক্ষেত্রে আমরা দেখেছি কোন পিনে আমরা digitalWrite() ফাংশনটি প্রয়োগ করলেই 5V যাচ্ছে। কিন্তু আমাদের অনেক সময় শুধু 5V দিলে হয় না, কম ভোল্টেজ হলে সুবিধা হয়। ডিজিটাল I/O Led ব্লিংকিং কিংবা মোটর ঘুরানোর জন্য যথেষ্ট, কিন্তু মনে করুন আপনার মোটরটির স্পিড কন্ট্রোল কিংবা Led এর ব্রাইটনেস কন্ট্রোল করার দরকার হল, তাহলে কী করবেন? যেহেতু 5V অ্যাপ্লাই করলে মোটরটি ফুল স্পিডে ও Led টি ফুল ব্রাইটনেসে জ্বলবে তাই তার জন্য একটা ব্যবস্থা নেওয়া জরুরি।

যখন আপনি এই সমস্যায় ভুগছেন, ঠিক তখনই PWM করা লাগবে। এটা দ্বারা ভোল্টেজ কমানো হয় না, একটি সাইকেলে ভোল্টেজ কতক্ষণ দেব কি দেব না সেটা নির্ধারণ করাই PWM এর কাজ! PWM এর আরক নাম DAC [Digital to Analog Conversion], এটি DAC থেকে PWM নামেই বেশি পরিচিত। যেহেতু PWM এর মাধ্যমে ভোল্টেজ আমরা টাইম ধরে দেই ও দেই না, তাই এটা প্রায় অ্যানালগ আউটপুট দেয়।

PWM সিগনাল জেনারেট করার জন্য আমরা analogWrite(int pin, int value) ফাংশনটি ব্যবহার করি, analogWrite এর প্রথ্ম আর্গুমেন্ট pin নির্দেশ করে কত নাম্বার পিনে সিগনাল দিতে হবে এবং value নির্দেশ করে কত ভ্যালুর PWM সিগনাল দিতে হবে। একটা কথা মাথায় রাখতে হবে, value এর মান 8-bit এর মধ্যে সীমাবদ্ধ রাখতে হবে বা 0 থেকে 2^8 – 1 বা 0 – 255 পর্যন্ত ভ্যালুর মান হতে পারে, এর চেয়ে বেশি হলে কাজ করবে না।

আর হ্যাঁ, আর্ডুইনোর সব পিন PWM Signal জেনারেট করতে পারে না, UNO এর ক্ষেত্রে যেসব পিনের আগে ‘~’ চিহ্নটি আছে কেবল ওই পিনগুলোই PWM Signal জেনারেট করতে পারবে, যেমন 3, 5, 6, 9, 10, 11 পিনগুলো UNO এর PWM পিন। কোন মোটর স্পিড কন্ট্রোল বা Led এর ব্রাইটনেস কন্ট্রোলিংয়ের জন্য আপনাকে অবশ্যই সেই ডিভাইস/কম্পোনেন্টগুলো এই পিনগুলোতে কানেক্ট করতে হবে।

সার্কিট ডায়াগ্রাম:

সার্কিটটা হুবহু তৃতীয় পরিচ্ছদের এর মত, তফাৎ হচ্ছে এখানে 3 নাম্বার পিনকে Led এর সাথে কানেক্ট করা হয়েছে।

alt text

প্রোগ্রাম:

const int led = 3;
void setup()
{
pinMode(led, OUTPUT);
}
void loop()
{
for (int i = 0; i < 256; i++){
analogWrite(led, i);
delay(10);
}
for (int i = 255; i >= 0; i--){
analogWrite(led, i);
delay(10);
}
}

প্রোগ্রাম Walkthrough:

* একটি ধ্রুব তৈরি কর led নামে এবং তার মধ্যে 3 সংখ্যাটি জমা কর
* led কে আউটপুট হিসেবে চিহ্নিত কর
* ফর লুপ বানাও, নতুন ইন্টিজার লোকাল* ভ্যারিয়েবল i কে Initialize করে 0 জমা কর; লুপটি ততক্ষণ রান করবে যতক্ষণ i, 256 এর চেয়ে ছোট থাকে; প্রতিবার লুপ চালানোর পর i এর মান 1 করে বাড়াবে
* led তে i এর ভ্যালু অনুযায়ী analogWrite এর মাধ্যমে analog সিগনাল জেনারেট কর
* ১০ মিলিসেকেন্ড অপেক্ষা কর
* i এর মান 1 বাড়াও, i কি 256 এর ছোট? যদি হ্যাঁ হয় তাহলে লুপে ঢুক; না হলে লুপে না ঢুকে পরের স্টেটমেন্ট রান করো
* i একটি লোকাল ভ্যারিয়েবল নাও যার মধ্যে 255 জমা কর; i কি ০ এর সমান বা বড়? হ্যাঁ হলে লুপে প্রবেশ কর, না হলে প্রবেশ কোরো না; প্রতি লুপ চালানোর পর i এর মান ১ করে কমাবে
* led তে i ভ্যালু অনুযায়ী analogWrite এর মাধ্যমে analog সিগনাল জেনারেট কর
* ১০ মিলি সেকেন্ড অপেক্ষা কর
* …. …. … void loop() এর মধ্যকার জিনিস বারংবার চলতেই থাকবে

প্রোটিয়াস সিম্যুলেশন:

alt text

নোট:

লোকাল ভ্যারিয়েবল ও গ্লোবাল ভ্যারিয়েবল:

লোকাল ভ্যারিয়েবলগুলোকে যেকোন ফাংশন বা কোড ব্লকের মধ্যে ডিক্লেয়ার করা হয় এবং তার অস্তিত্ব থাকে শুধু ওই ব্লকের মধ্যেই। আলোচ্য প্রোগ্রামটিতে i, i হল লোকাল ভ্যারিয়েবল এবং led নামক ভ্যারিয়েবলটি গ্লোবাল ভ্যারিয়েবল। আমরা জানি, প্রোগ্রামিংয়ে সাধারণত একই নামের জিনিসকে ২বার ডিক্লেয়ার করা যায় না। কিন্তু আমরা এই প্রোগ্রামে দেখতে পাচ্ছি i কে দুইবার ডিক্লেয়ার করা হয়েছে দুই লুপের ক্ষেত্রে। এটি সম্ভব হয়েছে শুধু একটা কারণেই, সেটা হল লুপ চালানোর পর কম্পিউটার তার মেমরিতে i নামের কিছুই জমা করে রাখেনি। লুপ শেষ হওয়ার সাথে সাথে সে i কে ভুলে যাচ্ছে। তাই i দুইবার ডিক্লেয়ার করা গেছে।

গ্লোবাল ভ্যারিয়েবল কোন সাধারণত ফাংশনে থাকে না একে প্রোগ্রামের যেকোন জায়গায় ডিক্লেয়ার করা যায়। গ্লোবাল ভ্যারিয়েবলগুলো একবার ডিক্লেয়ার করলেই হয়, দুই বা ততোধিকবার করতে গেলেই প্রোগ্রাম রান করবে না আমরা উপরের প্রোগ্রামটি i কে গ্লোবাল হিসেবে ডিক্লেয়ার করেও কাজটি সম্পন্ন করতে পারি। যেমন:

int i;
... ... ....
void loop()
{
for (i = 0; i < 256; i++){ /* code */ }
for (i = 255; i >= 0; i--) { /* code */ }
}

Duty Cycle:

এটি সম্পর্কে Wikipedia কী বলছে?

A duty cycle is the percentage of one period in which a signal is active. A period is the time it takes for a signal to complete an on-and-off cycle.

অর্থাৎ, Duty Cycle হল এমন একটি টার্ম, কোন একটি সিগনালের ক্ষেত্রে Duty Cycle এর মান জানলে আপনি তৎক্ষণাৎ বলে দিতে পারবেন একক পর্যায়কালে সিগনালটি কতক্ষণের জন্য On ছিল আর কতক্ষণের জন্য Off ছিল। আমরা যেহেতু DC এর আলোচনা করছি তাই On মানে ধরে নেব 5V আছে এবং Off মানে ধরে নেব 0V। নিচের এনিমেশন দেখলে ধারণা পাওয়ার কথা:

alt text

সূত্র: উইকিপিডিয়া

PWM এ আমরা আসলে কি করছি?

PWM করে আমরা আসলে Duty Cycle কন্ট্রোল করছি। যখন আমি analogWrite(pin, 255) আর্গুমেন্ট দিচ্ছি তার মানে এটি ওই পিনে 100% duty cycle এর সিগনাল দিবে তার মানে আমরা বলতে পারি, digitalWrite(led, HIGH) == analogWrite(led, 255)। কী? ব্যাপারটা Confusing লাগছে? কনফিউশনের দরকার নেই, এবার আপনিই ভাবুন, আমি যদি পর্যায়কালের ৫০% সময় ভোল্টেজ দিতে চাই ও বাকি ৫০% সময় ভোল্টেজ অফ রাখতে চাই তাহলে আমি analogWrite এ কত Value পাস করব? ঠিক ধরেছেন, 127

তার মানে, যদি ভোল্টেজের পর্যায়কাল 2 millisecond হয় তাহলে ১ম মিলিসেকেন্ডে ৫ ভোল্ট থাকবে কিন্তু ২য় মিলিসেকেন্ডে ০ ভোল্ট থাকবে। আবার ৩য় মিলিসেকেন্ডে ভোল্টেজ থাকবে, ৪র্থ মিলিসেকেন্ডে থাকবে না.. … …।

সচরাচর জিজ্ঞাস্য প্রশ্ন [F. A. Q]:

প্রশ্ন:

PWM যদি ভোল্টেজ না-ই কমায় তাহলে স্পিড বা ব্রাইটনেস কমে কীভাবে? এগুলো কী ভোল্টেজের উপর নির্ভরশীল নয়?

উত্তর:

PWM এ যত Low Duty Cycle হয় আমরা তত Dim Light পর্যবেক্ষণ করি। আসলে Dim Light এর জন্য দায়ী PWM নয়, আপনার চোখ! হ্যাঁ, Arduino এর Square Wave এর ফ্রিকোয়েন্সি প্রায় 490Hz এর মত। তার মানে, এটি প্রতি সেকেন্ডে 490 বার 5V থেকে 0V এ পরিবর্তিত হয়ে থাকে। আমরা জানি, T = 1 / f। তারমানে, আর্ডুইনোর পর্যায়কাল প্রায় 0.002 Second। এই কারণেই duty cycle কম দিলে dim দেখায় কারণ এটি এতটাই তাড়াতাড়ি ব্লিংকিং করে যে আপনার চোখ সেটা ধরতে পারে না। তারমানে আপনার চোখ আপনাকে বুঝায় যে led এর ব্রাইটনেস কমছে। আসলে led ফুল ব্রাইটনেসেই জ্বলে যা আপনি ধরতে পারেন না।