درایور موتور L298N– رابط آردوینو، نحوهی عملکرد، کدها و شماتیکها
راه اندازی موتور dc با آردوینو را در این آموزش بررسی خواهیم کرد ، قصد داریم تا کنترل موتورهای DCبا استفاده از آردوینو را اجرا کنیم. در ادامه، به خوبی نگاهی به تکنیکهای پایهای برای کنترل موتورهای DC خواهیم انداخت و دو مثال را مورد بررسی قرار میدهیم که به ما آموزش میدهد که چگونه موتورهای DC را با استفاده از درایور L298N و برد آردوینو کنترل کنیم.
بررسی اجمالی
میتوانیم سرعت موتورهای DC را بهسادگی با کنترل ولتاژ ورودی موتور و رایجترین روش انجام این کار که استفاده از سیگنال PWM است، انجام دهیم.
کنترل PWM موتور DC
PWM یا مدولاسیون پهنای باند روشی است که به ما اجازه میدهد تا مقدار میانگین ولتاژ را طوری تنظیم کنیم که تجهیزات الکترونیکی با نسبت سریعتری خاموش و روشن شود. مقدار میانگین ولتاژ به سیکل کاری D، یا زمان روشن بودن سیگنال در مقابل زمان خاموش بودن سیگنال در یک دوره زمانی، بستگی دارد؛ بنابراین، بسته بهاندازهی موتور میتوانیم بهسادگی خروجی یک آردوینوی PWM را به بیس ترانزیستور یا گیت یک ماسفت متصل کنیم و سرعت موتور را با کنترل خروجی PWM، کنترل کنیم. سیگنال توان پایین آردوینوی PWM، گیت ماسفت را که موتور توان بالا از طریق آن درایو میشود، خاموش و روشن میکند.
کنترل H-Bridge موتور DC
از سوی دیگر، برای کنترل جهت چرخش موتور، تنها به معکوس کردن جهت جریان عبوری از موتور نیاز داریم و متداولترین شیوه برای انجام آن، استفاده از یک H-Bridge است. یک مدار H-Bridge شامل چهار عنصر کلیدزنی، ترانزیستورها یا ماسفتها است و موتور در مرکز این قطعات، یک H-Bridge را تشکیل میدهد. با فعالسازی دو کلید مشخص بهصورت همزمان، میتوانیم جهت جریان را تغییر دهیم، پس جهت چرخش موتور نیز تغییر خواهد کرد. بهاینترتیب، اگر دو روش PWM و H-Bridge را با هم ترکیب کنیم، میتوانیم کنترل کاملی بر موتور DC داشته باشیم. تعداد زیادی از درایورهای موتور DC وجود دارند که این ویژگیها را دارند و L298N یکی از آنها است.
درایور L298N
L298N یک درایور موتور با دو H-Bridge است که قادر است تا سرعت و جهت دو موتور DC را به صورت هم زمان کنترل کند. این ماژول میتواند موتورهای DC که ولتاژی بین 5 و 35 ولت دارند را با جریان قلهی بیش از 2 آمپر راهاندازی کند. ما در بخش های مختلف آموزش رباتیک از درایورها خصوصا درایور L298 استفاده خواهیم کرد بنابراین آشنایی با به کارگیری آن بسیار ضروری است.
حالا میتوان نگاه دقیقتری به پینهای ماژول L298N انداخت و نحوهی کار آن را تشریح کرد. این ماژول دو پیچ بلوک ترمینال برای موتور A و B دارد و پیچهای بلوک ترمینال دیگری برای پین زمین، VCC برای موتور و یک پین 5 ولتی که میتواند خروجی یا ورودی باشد، نیز دارد که وابسته به ولتاژ مورد استفاده برای VCC موتور است.
این ماژول یک تنظیمکنندهی 5 ولتی نیز دارد که با استفاده از یک جامپر فعال یا غیرفعال میشود. اگر ولتاژ تغذیهی موتور بیش از 12 ولت باشد، میتوانیم رگولاتور 5 ولتی را فعال کنیم و پین 5 ولتی میتواند بهعنوان خروجی مورد استفاده قرار گیرد، مثلاً برای تغذیه برد آردوینو. اما اگر ولتاژ موتور بیش از 12 ولت باشد باید جامپر را قطع کنیم زیرا ولتاژهای بالاتر از این سطح، به تنظیم کنندهی 5 ولتی قرار گرفته روی برد، آسیب میزند. در این شرایط، پین 5 ولتی بهعنوان ورودی مورد استفاده قرار خواهد گرفت زیرا ما نیاز به اتصال آن به یک منبع تغذیهی 5 ولتی خواهیم داشت تا IC بهدرستی کار کند.
میتوان به این نکته اشاره کرد که IC افت ولتاژی حدود 2 ولت ایجاد میکند؛ بنابراین برای مثال، اگر از یک منبع تغذیهی 12 ولتی استفاده کنیم، ولتاژ ترمینالهای موتور حدود 10 ولت خواهد بود که به این معنی است که ما قادر نخواهیم بود که از بالاترین سرعت موتور 12 ولتی بهرهوری داشته باشیم.
مورد بعدی، ورودیهای کنترل منطقی است. از پینهای Enable A و Enable B برای فعال کردن و کنترل سرعت موتور استفاده میشود. اگر یک جامپر روی این پایه وجود داشته باشد، موتور فعال شده و با حداکثر سرعت کار میکند و اگر جامپر را برداریم، میتوانیم ورودی PWM را به این پایه متصل کنیم و از این طریق سرعت موتور را کنترل کنیم. اگر این پایه را به Ground متصل کنیم موتور از کار میافتد.
گام بعدی، بررسی کاربرد پایههای ورودی 1 و ورودی 2 برای کنترل جهت چرخش موتور A و ورودیهای 3 و 4 برای موتور B است. با استفاده از این پایهها، ما در واقع کلیدهای پل H را در داخل IC L298N کنترل میکنیم. اگر ورودی 1 LOW و ورودی 2 HIGH باشد، موتور به جلو حرکت میکند و بالعکس، اگر ورودی 1 HIGH و ورودی 2 LOW باشد، موتور به عقب حرکت میکند. در صورت یکسان بودن هر دو ورودی، چه در حالت LOW و چه در حالت HIGH، موتور متوقف میشود. همین امر برای ورودیهای 3 و 4 و موتور B اعمال میشود.
راه اندازی موتور dc با آردوینو
حال زمان آن فرارسیده است تا در کاربرد عملی نیز موارد گفته شده بررسی شوند. در اولین مثال ما سرعت موتور را با استفاده از یک پتانسیومتر و تغییر جهت چرخش با استفاده از یک دکمهی فشاری بررسی خواهیم کرد. در زیر شماتیک مداری این مثال آورده شده است؛ بنابراین، به یک درایور موتور L298N، یک موتور DC، یک پتانسیومتر، یک دکمهی فشاری و یک برد آردوینو نیاز داریم.
کد آردوینو
کد مورد نیاز آردوینو در زیر آورده شده است.
/* Arduino DC Motor Control - PWM | H-Bridge | L298N - Example 01 by Dejan Nedelkovski, www.HowToMechatronics.com */ #define enA 9 #define in1 6 #define in2 7 #define button 4 int rotDirection = 0; int pressed = false; void setup() { pinMode(enA, OUTPUT); pinMode(in1, OUTPUT); pinMode(in2, OUTPUT); pinMode(button, INPUT); // Set initial rotation direction digitalWrite(in1, LOW); digitalWrite(in2, HIGH); } void loop() { int potValue = analogRead(A0); // Read potentiometer value int pwmOutput = map(potValue, 0, 1023, 0 , 255); // Map the potentiometer value from 0 to 255 analogWrite(enA, pwmOutput); // Send PWM signal to L298N Enable pin // Read button - Debounce if (digitalRead(button) == true) { pressed = !pressed; } while (digitalRead(button) == true); delay(20); // If button is pressed - change rotation direction if (pressed == true & rotDirection == 0) { digitalWrite(in1, HIGH); digitalWrite(in2, LOW); rotDirection = 1; delay(20); } // If button is pressed - change rotation direction if (pressed == false & rotDirection == 1) { digitalWrite(in1, LOW); digitalWrite(in2, HIGH); rotDirection = 0; delay(20); } }
توضیحات: بنابراین در ابتدا به تعریف پایهها (پینها) و چند متغیر مورد نیاز برای برنامه نیاز داریم. در بخش تنظیمات، باید حالتهای پین و جهت چرخش اولیهی موتور تنظیم شوند. در بخش حلقه (لوپ) با خواندن مقدار پتانسیومتر شروع میکنیم و پس از آن مقداری را که از آن میگیریم را از 0 تا 1023 را به مقداری از 0 تا 255 برای بهدستآوردن سیکل کاری سیگنال PWM نگاشت میکنیم. سپس با استفاده از تابع analogWrite () سیگنال PWM را به پین Enable برد L298N ارسال میکنیم که در واقع موتور را راهاندازی میکند. سپس، این موضوع را بررسی میکنیم که آیا دکمه را فشردهایم یا خیر و اگر درست بود، تغییر جهت چرخش موتور با تنظیم معکوس حالات ورودی 1 و 2 انجام میشود. دکمهی فشاری بهعنوان یک ضامن در این سیستم کار میکند و هر بار که فشرده شود، جهت چرخش موتور را تغییر خواهد داد.
کنترل ربات اتومبیل آردوینو با استفاده از درایور موتور L298N
پس از یادگیری این موضوع، اکنون میتوانیم اتومبیل ربات آردوینو را بسازیم. نمودار شماتیک مدار مطابق شکل زیر است. تمام آنچه که نیاز داریم شامل دو موتور DC، درایور موتور L298N، یک برد آردوینو و یک جوی استیک برای کنترل این مدار است. با توجه به منبع تغذیه، سه باتری 3.7 ولتی لیتیوم یون انتخاب میشود که ولتاژی در حدود 11 ولت تأمین میکند. شاسی نیز از تخته چوب سه لایهی 3 میلیمتری ساخته شده است که موتور با استفاده از براکتهای فلزی به آن متصل شده است. چرخها هم به موتور متصل شدهاند و چرخهای جلو وظیفهی گردش را برعهده دارند.
کد آردوینو مطابق زیر است:
int xAxis = analogRead(A0); // Read Joysticks X-axis int yAxis = analogRead(A1); // Read Joysticks Y-axis
بعد از تعریف پینها، در بخش حلقه، با خواندن مقدار X و Y جوی استیک کار آغاز میشود. در واقع جوی استیک از دو پتانسیومتر تشکیل شده است که متصل به ورودیهای آنالوگ آردوینو هستند و مقادیری از 0 تا 1023 دارند. هنگامیکه جوی استیک در موقعیت مرکزی قرار دارد، مقدار هر دو پتانسیومتر در حدود 512 است.
با اضافهکردن مقدار تلورانس میتوان مقادیر 470 تا 550 بهعنوان مرکز در نظر داشت؛ بنابراین اگر محور Y جوی استیک را به عقب ببریم و مقدار آن زیر 470 باشد، جهت چرخش دو موتور با استفاده از چهار پین ورودی، طوری خواهد بود که مجموعه را به عقب میکشاند. سپس، مقادیر کاهشیافته را از 470 به 0 به مقادیر افزایش PWM از 0 تا 255 تبدیل خواهیم کرد که در واقع سرعت موتور است.
// Y-axis used for forward and backward control if (yAxis < 470) { // Set Motor A backward digitalWrite(in1, HIGH); digitalWrite(in2, LOW); // Set Motor B backward digitalWrite(in3, HIGH); digitalWrite(in4, LOW); // Convert the declining Y-axis readings for going backward from 470 to 0 into 0 to 255 value for the PWM signal for increasing the motor speed motorSpeedA = map(yAxis, 470, 0, 0, 255); motorSpeedB = map(yAxis, 470, 0, 0, 255); }
به طرز مشابهی، اگر محور Y جوی استیک را به جلو حرکت دهیم و مقدار آن از 550 تجاوز کند، موتور برای حرکت به جلو تنظیم خواهد شد و مقادیر خوانده شده از 550 تا 1023 به مقادیر PWM از 0 تا 255 تبدیل خواهند شد. اگر جوی استیک در مرکز خود باشد، سرعت موتور برابر با صفر خواهد بود. در ادامه، نگاهی به استفاده از محور X برای کنترل حرکت اتومبیل به سمت چپ و راست خواهیم داشت.
// X-axis used for left and right control if (xAxis < 470) { // Convert the declining X-axis readings from 470 to 0 into increasing 0 to 255 value int xMapped = map(xAxis, 470, 0, 0, 255); // Move to left - decrease left motor speed, increase right motor speed motorSpeedA = motorSpeedA - xMapped; motorSpeedB = motorSpeedB + xMapped; // Confine the range from 0 to 255 if (motorSpeedA < 0) { motorSpeedA = 0; } if (motorSpeedB > 255) { motorSpeedB = 255; } }
بنابراین مجدداً، نیاز به تبدیل مقادیر خوانده شده از محور X به مقادیر سرعت از 0 تا 255 شوند. برای حرکت به سمت چپ، از این مقدار برای کاهش سرعت موتور به سمت چپ و افزایش سرعت موتور به راست استفاده میکنیم. در اینجا، به دلیل توابع حسابی مورد استفاده، دو عبارت “if” اضافی برای محدود کردن محدودهی دور موتور از 0 تا 255 بهکار رفته است.
بسته به ولتاژ اعمال شده و موتور، در سرعتهای پایین موتور قادر به شروع حرکت نیست و صدای وزوز تولید میکند. در نمونهی حاضر، موتور قادر به حرکت در سیگنالهای PWM زیر 70 نیست؛ بنابراین، با استفاده از دو عبارت “if” در محدودهی سرعت 70 تا 255 این موتور میتواند حرکت کند. در پایان تنها سرعت نهایی موتور یا سیگنال PWM را به پینهای enable درایور L298N اعمال میکنیم.
// Prevent buzzing at low speeds (Adjust according to your motors. My motors couldn't start moving if PWM value was below value of 70) if (motorSpeedA < 70) { motorSpeedA = 0; } if (motorSpeedB < 70) { motorSpeedB = 0; } analogWrite(enA, motorSpeedA); // Send PWM signal to motor A analogWrite(enB, motorSpeedB); // Send PWM signal to motor B
در زیر، کد کامل آردوینو برای مثال ربات اتومبیلی آورده شده است:
/* Arduino DC Motor Control - PWM | H-Bridge | L298N Example 02 - Arduino Robot Car Control by Dejan Nedelkovski, www.HowToMechatronics.com */ #define enA 9 #define in1 4 #define in2 5 #define enB 10 #define in3 6 #define in4 7 int motorSpeedA = 0; int motorSpeedB = 0; void setup() { pinMode(enA, OUTPUT); pinMode(enB, OUTPUT); pinMode(in1, OUTPUT); pinMode(in2, OUTPUT); pinMode(in3, OUTPUT); pinMode(in4, OUTPUT); } void loop() { int xAxis = analogRead(A0); // Read Joysticks X-axis int yAxis = analogRead(A1); // Read Joysticks Y-axis // Y-axis used for forward and backward control if (yAxis < 470) { // Set Motor A backward digitalWrite(in1, HIGH); digitalWrite(in2, LOW); // Set Motor B backward digitalWrite(in3, HIGH); digitalWrite(in4, LOW); // Convert the declining Y-axis readings for going backward from 470 to 0 into 0 to 255 value for the PWM signal for increasing the motor speed motorSpeedA = map(yAxis, 470, 0, 0, 255); motorSpeedB = map(yAxis, 470, 0, 0, 255); } else if (yAxis > 550) { // Set Motor A forward digitalWrite(in1, LOW); digitalWrite(in2, HIGH); // Set Motor B forward digitalWrite(in3, LOW); digitalWrite(in4, HIGH); // Convert the increasing Y-axis readings for going forward from 550 to 1023 into 0 to 255 value for the PWM signal for increasing the motor speed motorSpeedA = map(yAxis, 550, 1023, 0, 255); motorSpeedB = map(yAxis, 550, 1023, 0, 255); } // If joystick stays in middle the motors are not moving else { motorSpeedA = 0; motorSpeedB = 0; } // X-axis used for left and right control if (xAxis < 470) { // Convert the declining X-axis readings from 470 to 0 into increasing 0 to 255 value int xMapped = map(xAxis, 470, 0, 0, 255); // Move to left - decrease left motor speed, increase right motor speed motorSpeedA = motorSpeedA - xMapped; motorSpeedB = motorSpeedB + xMapped; // Confine the range from 0 to 255 if (motorSpeedA < 0) { motorSpeedA = 0; } if (motorSpeedB > 255) { motorSpeedB = 255; } } if (xAxis > 550) { // Convert the increasing X-axis readings from 550 to 1023 into 0 to 255 value int xMapped = map(xAxis, 550, 1023, 0, 255); // Move right - decrease right motor speed, increase left motor speed motorSpeedA = motorSpeedA + xMapped; motorSpeedB = motorSpeedB - xMapped; // Confine the range from 0 to 255 if (motorSpeedA > 255) { motorSpeedA = 255; } if (motorSpeedB < 0) { motorSpeedB = 0; } } // Prevent buzzing at low speeds (Adjust according to your motors. My motors couldn't start moving if PWM value was below value of 70) if (motorSpeedA < 70) { motorSpeedA = 0; } if (motorSpeedB < 70) { motorSpeedB = 0; } analogWrite(enA, motorSpeedA); // Send PWM signal to motor A analogWrite(enB, motorSpeedB); // Send PWM signal to motor B }