این مطلب بخش یازدهم از آموزش جامع آردوینو (مبتدی و پیشرفته) است. در این آموزش شناختی نسبت به موتورهای DC و نحوه راهاندازی آن پیدا خواهید کرد. موتورهای DC بدون اغراق از پرکاربردترین انواع عملگرها به خصوص مواقعی که نیاز به نیروهای خیلی زیادی نباشد هستند. بیشتر لوازم خانگی الکتریکی، رباتها، پرندههای بدون سرنشین و خیلی از تجهیزات صنعتی درون خودشان موتور DC دارند. در انتهای این آموزش خواهید توانست موتور DC را به کمک ترانزیستور، درایور و آردوینو راهاندازی کنید.
قطعات مورد نیاز:
معرفی موتور DC
در یک تقسیمبندی کلی موتورها به دو دسته تقسیم میشود: موتورهای DC و موتورهای AC. موتورهای AC با برق شهر (جریان متناوب) کار میکند در حالی که موتورهای DC با برق مستقیم (ولتاژ ثابت) کار میکنند. موتورهای DC خود شامل انواع مختلفی مانند: سروو موتور (Servo motor)، استپر موتور (Stepper motor)، موتور براش (Brushed motor) و موتور براشلس (Brushless motor) هستند. یک مزیت موتور DC این است که میتواند با باتری کار کند؛ به همین دلیل تنها گزینه در طراحی و ساخت وسیلههای متحرک مثل رباتها و پرندهها است. هرچند که تمام موارد ذکر شده با جریان DC کار میکنند اما معمولا منظور از موتور DC ، موتور براش است.
مبنای کار موتورهای DC استفاده از نیروی الکترومغناطیسی ناشی از یک آهنربای دائم یا موقت است. موتور براش از دو بخش اصلی تشکیل شده است: استاتور و روتور. استاتور یک آهنربای دائم بوده و حرکتی ندارد. روتور بر روی خود سیمپیچی دارد (تعداد سیمپیچها مختلف است) که در اثر اعمال ولتاژ، تبدیل به آهنربا میشود، نیروی به وجود آمده بین دو آهنربا (استاتور و روتور) باعث چرخش روتور و ایجاد نیرو میشود. از آنجا که روتور با سرعت در حال چرخش است (و نمیتوان به آن سیم وصل کرد!) ولتاژ از طریق براش (یک قطعه رسانا از جنس گرافیت) به دو سر سیمپیچ اعمال میشود. هرچه ولتاژ بیشتر شود، نیروی بیشتری تولید شده و سرعت چرخش موتور افزایش مییابد. پس با تغییر ولتاژ میتوان سرعت موتور را کنترل کرد. موتورهای براش نسبتا ارزانقیمت هستند و ساخت آنها مشکل نیست، اما وجود براش کارایی و طول عمر موتور را اندکی کاهش میدهد.
در موتورهای الکتریکی چند پارامتر مهم وجود دارد که اگر میخواهید یک موتور تهیه کنید باید به آنها توجه داشته باشید:
ولتاژ کاری: موتور میتواند در محدودهای از ولتاژها کار کند اما در ولتاژ کاری خود بیشترین کارایی را خواهد داشت. هیچوقت از ولتاژهای خارج از محدوده کاری موتور استفاده نکنید. این کار میتواند به موتورتان آسیب برساند.
بار: نیرو یا وزنی که به شفت موتور متصل شده است. افزایش بار فشار وارد شده به موتور را افزایش میدهد.
سرعت بدون بار: سرعتی که موتور در حالتی که شفت آن آزاد است خواهد داشت. این سرعت در یک ولتاژ خاص و بر اساس دور بر دقیقه تعریف میشود.
گشتاور توقف: اگر بار موتور را به تدریج افزایش دهید، در یک بار خاص موتور از حرکت خواهد ایستاد. به گشتاور موتور در این شرایط گشتاور توقف (Stall torque) میگویند. نگه داشتن موتور در حالت توقف میتواند به آن آسیب برساند. معمولا گشتاور مناسب برای موتور بسیار کمتر از گشتاور توقف است.
جریان توقف: جریانی که موتور در حالت توقف (Stall) مصرف میکند.
قطر شفت: این پارامتر برای نصب موتور اهمیت دارد.
توجه: هیچ وقت موتور الکتریکی را با استفاده از پایههای آردوینو راهاندازی نکنید، مگر برای موتورهای بسیار کوچک. موتور جریان زیادی کشیده و میتواند باعث آسیب به آردوینو شود. برای راهاندازی موتور از قطعات جانبی مانند درایور یا ترانزیستور استفاده میشود که میتوانند توان مورد نیاز موتور را تامین کنند. نحوه کار با آنها در ادامه توضیح داده شده است.
راه اندازی موتور با ترانزیستور و دیود
ترانزیستور یک قطعه بسیار پرکاربرد در الکترونیک است که استفادههای بیشماری از آن میشود. اساس کار پردازندهها مدارات ترانزیستوری است. درون یک CPU چند صد میلیون تا چند میلیارد ترانزیستور قرار دارد! یکی از سادهترین کاربردهای ترانزیستور به عنوان کلید است. ترانزیستور سه پایه دارد: Base، Emitter و Collector. دستور قطع و وصل جریان بین E و C از طریق پایه B ارسال میشود.
پایه 5V آردوینو میتواند حداکثر 500mA جریان را تامین کند، در حالی که پایههای I/O جریان بسیار کمتری میدهند. دلیل استفاده از ترانزیستور همین موضوع است؛ پایه دیجیتال میتواند فرمان قطع و وصل را داده و جریان از پایه 5V تامین شود. برای بعضی از موتورهای کوچک این مقدار کافیست، پس نیاز به منبع تغذیه خارجی نیست. اگر در این مورد مطمئن نیستید، ریسک نکنید و از منبع خارجی استفاده کنید.
نکته دیگری نیز در مورد این نوع راهاندازی موتور اهمیت دارد. موتور در هنگام شروع حرکت و توقف یک جریان معکوس در مدار القا میکند. این جریان میتواند به بردتان آسیب برساند. برای حل این مشکل یک دیود را به دو سر موتور وصل کنید به طوری که سمت علامتدار آن به سر مثبت مدار متصل باشد. در این صورت جریان معکوس تولید شده، وارد موتور شده و از بین میرود.
موتور را به همراه دیود و یک ترانزیستور از نوع NPN به صورت مدار زیر به آردوینو وصل کنید. پایه ٩ آردوینو را با یک مقاومت 1kΩ به پایه B ترانزیستور و پایه های C و E ترانزیستور را به ترتیب سمت منفی موتور و GND مدار وصل کنید. اگر میخواهید از منبع تغذیه خارجی استفاده کنید، بخشهای مثبت و منفی مدار را به جای آردوینو به مثبت و منفی منبع تغذیه وصل کنید.
توجه: ترتیب پایههای ترانزیستورهای مختلف متفاوت است. شماره هر پایه را میتوانید در دفترچه راهنمای ترانزیستور پیدا کنید.
با دادن ولتاژ به پایه ٩ آردوینو موتور شروع به حرکت خواهد کرد. برنامه زیر را بر روی آردوینو اجرا کنید و نتیجه را مشاهده کنید:
/*
automee
Arduino Tutorial Series
Author: Davood Dorostkar
Website: www.automee.ir
*/
#define motorPin 9
void setup()
{
pinMode(motorPin, OUTPUT);
}
void loop()
{
digitalWrite(motorPin, HIGH);
delay(1000);
digitalWrite(motorPin, LOW);
delay(1000);
}
همانطور که دیدید با این برنامه، موتور به مدت ١ ثانیه حرکت کرده و ١ ثانیه متوقف میشود. با همین مدار میتوانید سرعت موتور را هم کنترل کنید. کنترل سرعت موتور بر اساس تکنیک PWM صورت میگیرد. عدد بزرگتر PWM به این معنی است که مدت زمان بیشتری ولتاژ به ترانزیستور اعمال میشود و در نتیجه ولتاژ بیشتری در عمل به موتور میرسد و سرعت آن بیشتر میشود. برنامه زیر را روی آردوینو اجرا کنید؛ مشاهده میکنید که سرعت موتور از صفر شروع شده و به حداکثر رسیده و سپس دوباره تا صفر کم میشود.
/*
automee
Arduino Tutorial Series
Author: Davood Dorostkar
Website: www.automee.ir
*/
#define motorPin 9
void setup()
{
pinMode(motorPin, OUTPUT);
}
void loop()
{
for (int i = 0; i < 255; i++)
{
analogWrite(motorPin, i);
delay(30);
}
for (int i = 255; i > 0; i--)
{
analogWrite(motorPin, i);
delay(30);
}
delay(2000);
}
معرفی درایور موتور
شاید تا اینجا متوجه شده باشید که مدار قبل، موتور را تنها در یک جهت میچرخاند. برای اینکه بتوانید موتور را در دو جهت بچرخانید یک راه این است که جای سیمهای موتور را عوض کنید. اگر نمیخواهید این کار را به صورت دستی انجام دهید، نیاز به یک مدار پیچیدهتر به نام H-Bridge دارید. در این جا قصد نداریم به نحوه کار H-bridge بپردازیم. فقط همین را بدانید که این مدار میتواند جهت اعمال ولتاژ و در نتیجه چرخش موتور را بین دو حالت انتخاب کند. دلیل نامگذاری این مدار این است که چهار ترانزیستور به گونهای قرار گرفتهاند که یک شکل H مانند را ایجاد میکنند.
این مدار اساس کار قطعهای به نام درایور (Driver) است. درایور یک قطعه الکتریکی است که به روشی عملکرد موتور الکتریکی را کنترل میکند. درایورهای متنوعی برای راهاندازی موتورهای DC وجود دارد. درایورها ممکن است حرکت یا توقف موتور، موقعیت، سرعت، شتاب، جریان یا گشتاور موتور را کنترل کنند. کنترل سرعت موتور DC سادهترین نوع کنترل است. درایورهایی که سایر پارامترها را کنترل میکنند، پیچیده و گرانقیمت هستند.
راه اندازی موتور DC با درایور L298n
در اینجا ما از درایور L298n استفاده میکنیم که درون خود یک مدار H-Bridge دارد. L298n معروفترین درایور برای کنترل موتور DC است. این درایور به صورت IC تنها و نیز به صورت ماژول موجود است. استفاده از ماژول L298n راحتتر است چرا که پینهای ورودی و خروجی آن به هدرهای خارجی وصل و نامگذاری شده است. به علاوه مدارات محافظتی و هیتسینک آن استفاده از درایور را مطمئنتر کرده است. درایور L298n قابل استفاده برای راهاندازی 2 موتور DC یا یک استپر موتور است. این درایور میتواند تا 2A جریان برای هر موتور DC تامین کند.
برای شروع میتوانید یک موتور را با استفاده از سیگنال PWM کنترل کنید. در دو سمت درایور یک جفت هدر وجود دارد که هر کدام برای اتصال یک موتور DC است. سیمهای موتور را به یکی از این جفت هدرها وصل کنید.
در سمت دیگر درایور هدر تغذیه قرار دارد. پایه GND و 12V را به ترتیب به منفی و مثبت منبع تغذیه وصل کنید. از پایه سوم (5V) میتوانید در صورت نیاز خروجی ٥ ولت بگیرید.
بر روی برد درایور یک جامپر برای تنظیم ولتاژ ورودی وجود دارد؛ در صورتی که ولتاژ تغذیه بیشتر از 12V است این جامپر را جدا کنید تا به درایورتان آسیبی نرسد.
در همین سمت درایور، ٦ پایه دیگر وجود دارد که به آردوینو وصل میشود. پایههای IN1، IN2 و EN1 مربوط به موتور ١ و پایههای IN3، IN4 و EN2 مربوط به موتور ٢ هستند. EN1 برای ارسال دستور فعال شدن موتور است و IN1 و IN2 جهت چرخش را تعیین میکنند. اگر IN1 فعال و IN2 صفر باشد موتور در یک جهت میچرخد و اگر IN1 صفر و IN2 فعال باشد در جهت مخالف خواهد چرخید. اگر هر دو پایه صفر یا هر دو ١ باشند، موتور متوقف میشود. برای موتور ٢ نیز وضعیت مشابه است.
دقت کنید که موتور DC معمولا جریان زیادی میکشد. مثلا یک موتور کوچک میتواند به راحتی 1A جریان مصرف کند. علاوه بر این، خود درایور هم تا حدی ولتاژ را تلف میکند. پس اگر میخواهید با یک موتور نسبتا قوی کار کنید باید از باتری قویتر یا منبع تغذیههایی که به برق شهر وصل میشوند استفاده کنید.
بد نیست همان کاری که با ترانزیستور کردید را با درایور هم تکرار کنید با این تفاوت که این بار موتور در دو جهت میچرخد. برنامه زیر را در آردوینو اجرا کنید و نتیجه را ببینید.
/*
automee
Arduino Tutorial Series
Author: Davood Dorostkar
Website: www.automee.ir
*/
#define enablePin 10
#define input1Pin 9
#define input2Pin 8
void forwardTurn(uint8_t speed)
{
digitalWrite(input1Pin, HIGH);
digitalWrite(input2Pin, LOW);
analogWrite(enablePin, speed);
}
void backwardTurn(uint8_t speed)
{
digitalWrite(input1Pin, LOW);
digitalWrite(input2Pin, HIGH);
analogWrite(enablePin, speed);
}
void setup()
{
pinMode(enablePin, OUTPUT);
pinMode(input1Pin, OUTPUT);
pinMode(input2Pin, OUTPUT);
}
void loop()
{
for (int i = 0; i < 255; i++)
{
forwardTurn(i);
delay(30);
}
for (int i = 255; i > 0; i--)
{
forwardTurn(i);
delay(30);
}
for (int i = 0; i < 255; i++)
{
backwardTurn(i);
delay(30);
}
for (int i = 255; i > 0; i--)
{
backwardTurn(i);
delay(30);
}
delay(2000);
}
کنترل دو موتور DC با جویاستیک
همانطور که قبلا گفتیم درایور L298n توانایی راهاندازی دو موتور را به صورت همزمان دارد. این کار تفاوت چندانی با حالت تکموتور ندارد. کافیست سیمهای موتور را به درایور وصل کرده و پینهای IN3، IN4 و EN2 را هم به پینهای دیجیتال آردوینو متصل کنید. دقت کنید که پینهای EN1 و EN2 باید به پایههای PWM وصل شده باشند. برای اینکه پروژه را جذابتر کنید میتوانید یک جویاستیک که قبلا در آموزش قسمت ششم توضیح داده شد را هم به آن اضافه کنید.
با این دو موتور میتوانید یک ربات کنترلی بسازید! جویاستیک میتواند در دو جهت حرکت کند. طوری کدتان را بنویسید که با حرکت جویاستیک به جلو و عقب، یکی از موتور ها چرخیده و با حرکت آن به چپ و راست، موتور دیگر بچرخد. با آپلود برنامه زیر در آردوینو میتوانید دو موتور را به حرکت در آورید:
/*
SanatBazar
Arduino Tutorial Series
Author: Davood Dorostkar
Website: www.sanatbazar.com
*/
#define enableMotor1 5
#define input1Motor1 6
#define input2Motor1 7
#define input1Motor2 8
#define input2Motor2 9
#define enableMotor2 10
#define joystickX A0
#define joystickY A1
void setup()
{
pinMode(enableMotor1, OUTPUT);
pinMode(enableMotor2, OUTPUT);
pinMode(input1Motor1, OUTPUT);
pinMode(input1Motor2, OUTPUT);
pinMode(input2Motor1, OUTPUT);
pinMode(input2Motor2, OUTPUT);
pinMode(joystickX, INPUT);
pinMode(joystickY, INPUT);
}
void motor1ForwardDrive(int speed)
{
analogWrite(enableMotor1, speed);
digitalWrite(input1Motor1, HIGH);
digitalWrite(input2Motor1, LOW);
}
void motor2ForwardDrive(int speed)
{
analogWrite(enableMotor2, speed);
digitalWrite(input1Motor2, HIGH);
digitalWrite(input2Motor2, LOW);
}
void motor1BackwardDrive(int speed)
{
analogWrite(enableMotor1, speed);
digitalWrite(input1Motor1, LOW);
digitalWrite(input2Motor1, HIGH);
}
void motor2BackwardDrive(int speed)
{
analogWrite(enableMotor2, speed);
digitalWrite(input1Motor2, LOW);
digitalWrite(input2Motor2, HIGH);
}
void motionPlan(int speedMotor1, int speedMotor2)
{
if (speedMotor1 > 550)
{
speedMotor1 = map(speedMotor1, 550, 1024, 0, 255);
motor1ForwardDrive(speedMotor1);
}
else if (speedMotor1 < 460)
{
speedMotor1 = map(speedMotor1, 460, 0, 0, 255);
motor1BackwardDrive(speedMotor1);
}
if (speedMotor2 > 550)
{
speedMotor2 = map(speedMotor2, 550, 1024, 0, 255);
motor2ForwardDrive(speedMotor2);
}
else if (speedMotor2 < 460)
{
speedMotor2 = map(speedMotor2, 460, 0, 0, 255);
motor2BackwardDrive(speedMotor2);
}
}
void loop()
{
int speedMotor1 = analogRead(joystickX);
int speedMotor2 = analogRead(joystickY);
motionPlan(speedMotor1, speedMotor2);
}
راهاندازی موتور DC به همراه پتانسیومتر و انکودر
یک کار جالب دیگر این است که موتور را با پتانسیومتر و انکودر که قبلا کار با آن را یاد گرفتهاید ترکیب کنید. قصد داریم با یک پتانسیومتر سرعت موتور را تنظیم کنیم؛ به علاوه با چرخش پتانسیومتر به راست، موتور ساعتگرد بچرخد و برعکس. همچنین میزان چرخش موتور را با استفاده از انکودر در سریال مانیتور نمایش دهیم. کاری که باید انجام دهید این است که انکودر را به موتور وصل کنید. برای این کار باید انکودر و موتور قابلیت اتصال به یکدیگر را داشته باشند. بر روی بعضی موتورهای DC انکودر سوار شده است که کار را سادهتر میکند. در اینجا ما از یک موتور گیربکسدار استفاده کردهایم. گیربکس وسیلهای است که به موتور وصل شده، سرعت آن را کاهش داده و قدرت (گشتاور) را افزایش میدهد.
سیم A و B انکودر را به پینهای ٢ و ٣ آردوینو وصل کنید. سایر اتصالات مانند قبل است.
قبل از اینکه کد ما را ببینید، با توجه به مطالبی که تاکنون آموختهاید سعی کنید خودتان این برنامه را بنویسید. میتوانید کدتان را با برنامه زیر مقایسه کنید:
/*
automee
Arduino Tutorial Series
Author: Davood Dorostkar
Website: www.automee.ir
*/
#define potentiometerPin A0
#define enablePin 10
#define input1Pin 8
#define input2Pin 9
#define encoderPinA 2
#define encoderPinB 3
volatile int encoderPosition = 0;
float encoderAngle = 0.0;
void forwardTurn(int speed)
{
digitalWrite(input1Pin, HIGH);
digitalWrite(input2Pin, LOW);
analogWrite(enablePin, speed);
}
void backwardTurn(int speed)
{
digitalWrite(input1Pin, LOW);
digitalWrite(input2Pin, HIGH);
analogWrite(enablePin, speed);
}
void motorDrive(int speed)
{
if (speed < 550 && speed > 470)
speed = 0;
else if (speed <= 470)
{
speed = map(speed, 0, 512, 255, 0);
forwardTurn(speed);
}
else
{
speed = map((speed - 512), 0, 512, 0, 255);
backwardTurn(speed);
}
}
void doEncoderA()
{
if (digitalRead(encoderPinA) == HIGH)
{
if (digitalRead(encoderPinB) == LOW)
encoderPosition++; // CW
else
encoderPosition--; // CCW
}
else
{
if (digitalRead(encoderPinB) == HIGH)
encoderPosition++; // CW
else
encoderPosition--; // CCW
}
}
void doEncoderB()
{
if (digitalRead(encoderPinB) == HIGH)
{
if (digitalRead(encoderPinA) == HIGH)
encoderPosition++; // CW
else
encoderPosition--; // CCW
}
else
{
if (digitalRead(encoderPinA) == LOW)
encoderPosition++; // CW
else
encoderPosition--; // CCW
}
}
void setup()
{
Serial.begin(9600);
pinMode(enablePin, OUTPUT);
pinMode(input1Pin, OUTPUT);
pinMode(input2Pin, OUTPUT);
pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);
attachInterrupt(digitalPinToInterrupt(2), doEncoderA, CHANGE);
attachInterrupt(digitalPinToInterrupt(3), doEncoderB, CHANGE);
}
void loop()
{
int speed = analogRead(potentiometerPin);
motorDrive(speed);
// There is 4 pulses per step
// Encoder has 334 steps per revolution
// Gearbox ratio is 1:25
encoderAngle = (encoderPosition / 4) * (360 / 334) / 25;
Serial.print("Angle= ");
Serial.print(encoderPosition);
Serial.println(" deg");
}
در برنامه بالا دو تابعforwardTurnوbackwardTurnتعریف شده است تا موتور را در زمان مناسب ساعتگرد و پادساعتگرد بچرخاند:
void forwardTurn(int speed)
{
digitalWrite(input1Pin, HIGH);
digitalWrite(input2Pin, LOW);
analogWrite(enablePin, speed);
}
void backwardTurn(int speed)
{
digitalWrite(input1Pin, LOW);
digitalWrite(input2Pin, HIGH);
analogWrite(enablePin, speed);
}
همچنین تابعmotorDriveدادههای پتانسیومتر را بررسی کرده و تعیین میکند که موتور با چه سرعتی و به چه سمتی بچرخد. برای جلوگیری از ایجاد صدای مزاحم وقتی موتور نزدیک نقطه صفر است، در محدوده ٤٧٠ تا ٥٥٠ پتانسیومتر، موتور ثابت نگه داشته میشود:
void motorDrive(int speed)
{
if (speed < 550 && speed > 470)
speed = 0;
else if (speed <= 470)
{
speed = map(speed, 0, 512, 255, 0);
forwardTurn(speed);
}
else
{
speed = map((speed - 512), 0, 512, 0, 255);
backwardTurn(speed);
}
}
در حلقه اصلی برنامه، میزان چرخش پتانسیومتر دریافت شده و به عنوان سرعت به موتور داده میشود. سپس میزان زاویه انکودر بر حسب درجه محاسبه شده و در سریال مانیتور نمایش داده میشود. برای محاسبه زاویه انکودر باید تعداد پالسهای آن را به ٤ تقسیم کنید چون همان طور که قبلا دیدیم، هر ٤ پالس انکودر نسبی، یک گام محسوب میشود. سپس عدد به دست آمده را به زاویه تبدیل کنید. انکودری که ما استفاده کردیم دارای ٣٣٤ گام در هر دور چرخش است، بنابراین عدد حاصل را در ٣٦٠/٣٣٤ ضرب کردهایم. مقداری که تا اینجا به دست آمده است، زاویه چرخش موتور است. برای اینکه زاویه خروجی گیربکس را به دست آورید باید این عدد را بر نسبت تبدیل گیربکس (برای این موتور ١:٢٥) هم تقسیم کنید. از آنجا که این موتور گیربکسدار است، سرعت چرخش خروجی آن کمتر از فرمانی است که به موتور میدهید. در واقع سرعت خروجی به نسبت تبدیل گیربکس کم میشود. مثلا اگر به موتور دستور سرعت ١٠٠ دور بر ثانیه بدهید، سرعت خروجی ٤=٢٥÷١٠٠ خواهد بود.
void loop()
{
int speed = analogRead(potentiometerPin);
motorDrive(speed);
// There is 4 pulses per step
// Encoder has 334 steps per revolution
// Gearbox ratio is 1:25
encoderAngle = (encoderPosition / 4) * (360 / 334) / 25;
Serial.print("Angle= ");
Serial.print(encoderPosition);
Serial.println(" deg");
}
نتیجهگیری
در این قسمت با موتور DC آشنا شدید و نحوه راهاندازی آن را یاد گرفتید. ممکن است درایور دیگری داشته باشید؛ راهاندازی موتور چندان تفاوت نمیکند. کافیست دفترچه راهنمای درایور را مطالعه کنید تا ورودی و خروجیهای آن را پیدا کنید. اگر به رباتیک علاقهمند هستید، مطالبی که در این آموزش یاد گرفتید، میتواند نقطه شروع خوبی باشد.
در آموزش بعدی، نحوه راهاندازی و کار با استپر موتور را خواهید آموخت. نظرات شما باعث بهبود محتوای آموزشی ما میشود. اگر این آموزش را دوست داشتید، همینطور اگر سوالی در مورد آن دارید، از شنیدن نظراتتان خوشحال خواهیم شد.