محاسبه سرعت موتور DC با انکودر در آردوینو

موتور DC و انکودر
0

محاسبه سرعت موتور jga25-371 با انکودر در آردوینو

در دانشنامه‌های قبلی با انکودر و نحوه‌ی کار آن آشنا شدید. همچنین چگونگی راه‌اندازی موتور DC را در آردوینو آموختید. در این نوشتار نحوه‌ی محاسبه‌ی سرعت موتور با استفاده از یک انکودر دوار نوری آموزش داده می‌شود.

ابزار استفاده شده

همچنین به جای استفاده از موتور ذکر شده می‌توانید از یک موتور DC دلخواه در کنار یک انکودر دلخواه استفاده کنید.

نحوه‌ی اتصال سیم‌ها

در تصویر زیر پین‌های انکودر موتور jga25-371 مشخص شده‌اند. دو پین بالایی (سیم‌های سفید و زرد) مربوط به سیگنال‌های خروجی انکودر هستند که در بعضی از محصولات با نام CHA و CHB (کانال A و کانال B) نام‌گذاری شده‌اند. پین‌های VCC و GND مربوط به تغذیه‌ی انکودر هستند که در این موتور باید 3.3 ولت باشد. پین‌های M- و M+ نیز دو سر موتور DC هستند که خروجی درایور موتور به آن‌ها وصل می‌شود.

نحوه‌ی اتصال سیم‌های موتور و انکودر
نحوه‌ی اتصال سیم‌های موتور و انکودر

نحوه‌ی اتصال سیم‌ها برای راه‌اندازی موتور و انکودر در شماتیک زیر نشان داده شده است.

شماتیک پروژه
شماتیک پروژه

کد نویسی

کد نویسی برای حالتی که سرعت و جهت چرخش موتور محاسبه شود انجام شده است. با توجه به اینکه جهت حرکت موتور توسط ماژول l298 و به دلخواه کاربر تنظیم می‌شود، در اکثر کاربری‌ها نیاز به تشخیص جهت حرکت توسط انکودر نیست و می‌توان تنها به محاسبه سرعت موتور پرداخت.

در ادامه توضیحاتی در مورد تابع pulseIn در آردوینو ارائه می‌شود و سپس کد ذکر شده قرار داده می‌شود.

تابع pulseIn

برای اندازه‌گیری فواصل زمانی بین امواج مربعی سیگنال‌های خروجی از انکودر در آردوینو راه‌های بسیار متنوعی وجود دارد. در این پروژه از دستور pulseIn استفاده شده است. این تابع مدت زمان High یا Low بودن یک سیگنال را به واحد میکروثانیه و در بازه‌ی 10 میکروثانیه تا 3 دقیقه به عنوان خروجی می‌دهد. طبق توضیحات رفرنس آردوینو این تابع سه ورودی لازم دارد: تعیین پین مربوط به سیگنال، انتخاب اندازه‌گیری زمان برای حالت High یا Low بودن سیگنال و مقداری به عنوان timeout که یک ورودی دلخواه است و بصورت پیش‌فرض برای یک ثانیه در نظر گرفته شده است. در صورتی‌که مدت زمان انتظار تابع برای شروع یکی از حالت‌های High یا Low بیشتر از مقدار timeout تنظیم شده باشد، خروجی این تابع صفر خواهد بود.

محاسبه سرعت و جهت چرخش

در این روش پین دیجیتال 2 که به کانال A از انکودر متصل است به عنوان پین اینتراپت در نظر گرفته شده است. مود اینتراپت روی حالت RISING قرار داده شده است. بنابراین هر زمان که خروجی کانال A از پایین به بالا حرکت کند روتین (تابع) اینتراپت فراخوانده می‌شود.

در روتین اینتراپت بررسی می‌شود که کانال B در این لحظه در حالت Low قرار دارد یا High و بسته به این موضوع جهت حرکت موتور تشخیص داده می‌شود (مثبت 1 برای چرخش ساعتگرد و منفی 1 برای پادساعتگرد). جهت درک بهتر این موضوع حتما مقاله آشنایی با انکودر دوار را مطالعه کنید.

CPR موتور استفاده شده طبق اطلاعات درج شده روی موتور 360 است. یعنی سیگنال‌های کانال A و B در هر دور چرخش کامل موتور، 360 بار تناوب می‌کنند. تابع pulseIn تنها زمان Low یا High بودن سیگنال را به عنوان خروجی می‌دهد، یعنی نصف زمان تناوب سیگنال مربعی. بنابراین حالصضرب خروجی این تابع در مقدار CPR و در عدد 2 زمان چرخش یک دور کامل موتور با سرعت لحظه‌ای که تابع pulseIn فراخوانی شده را در واحد میکروثانیه می‌دهد. تابع pulseIn در تابع Loop فرخوانی شده است. همچنین در Loop سرعت موتور با توجه به خروجی تابع pulseIn و در نظر گرفتن نسبت چرخ‌دنده و جهت چرخش به واحد دور بر دقیقه محاسبه و پرینت می‌شود.

در این کد دو تابع setPWM برای تعیین pwm اعمالی به موتور و setDirection برای تعیین جهت چرخش موتور نیز تعریف و استفاده شده‌اند.

برای بررسی عملکرد کد، سیگنال pwm به صورت سینوسی به موتور اعمال شده است و نمودار سرعت موتور و pwm اعمالی نمایش داده شده است.

سرعت موتور در کنار ولتاژ اعمالی
سرعت موتور در کنار ولتاژ PWM اعمالی - رنگ قرمز: سیگنال PWM رنگ آبی: سرعت موتور
//      _____               _                          _        
//     |  __ \             | |                        (_)       
//     | |__) |   ___    __| |  _ __    ___    _ __    _    ___ 
//     |  _  /   / _ \  / _` | | '__|  / _ \  | '_ \  | |  / __|
//     | | \ \  |  __/ | (_| | | |    | (_) | | | | | | | | (__ 
//     |_|  \_\  \___|  \__,_| |_|     \___/  |_| |_| |_|  \___|
                                                                                                              
// www.wiki.redronic.com
#define _60secInMicrisec 60000000.0f
#define GearRatio 34.0f
#define EncoderCPR 360
#define pi 3.1415f
int ENA=10;  // to EnA of L298
int IN1=9;   // to IN1 of L298
int IN2=8;   // to IN2 of L298
const byte ChA = 2; // to ENA (OutA / ChA) of Encoder 
const byte ChB = 3; // to ENB (OutA / ChA) of Encoder

volatile unsigned long _1RevDuration; // Duration of 1 Revolution
float rpm=0; // Motor Speed 
volatile int feedbackDirection; // Direction Detected by Encoder
enum desiredDirection{ // Desired Direction
  CW = 0, // Clockwise
  CCW = 1 // Counter Clockwise
};

float pwm; // PWM to L298 
long counter =0; // Counter for Sinusoidal PWM Generation 

void setPWM(float outputPWM); // Apply PWM to motor (input between 0-100)
void setDirection(desiredDirection dir); // Select Direction of Rotation

void setup() {
  Serial.begin(9600);
  pinMode(ENA, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  setDirection(CW); // set Initial Diretion to Clockwise
  setPWM(90); // initialize Motor
  attachInterrupt(digitalPinToInterrupt(ChA), checkDirection, RISING); // Define Pin ChA as Intrrupt Pin
}

void loop() {
  pwm = 80.0f*sin(2.0f*pi*counter/100.0f);
  counter += 1;
  if (pwm > 0)
    setDirection(CW);
  else
    setDirection(CCW);
  setPWM(fabs(pwm));
  //delay(100);
  _1RevDuration =  pulseIn(ChA, LOW,10000)*EncoderCPR*2; // Calculating the Duration of a Revolution in micro seconds
  if (_1RevDuration == 0) // Avoiding from Singularity Problem
    rpm = 0;
  else
    rpm = feedbackDirection*_60secInMicrisec/((float)_1RevDuration*GearRatio); // Calculating Motor RPM
  Serial.print(rpm);  
  Serial.print("   ");
  Serial.println(pwm); 
}

void setDirection(desiredDirection dir){
  switch(dir){
    case CW:
      digitalWrite(IN1,LOW);
      digitalWrite(IN2,HIGH);
      break;
    case CCW:
      digitalWrite(IN2,LOW);
      digitalWrite(IN1,HIGH);
      break;
  }
}
void setPWM(float outputPWM){
  analogWrite(ENA,outputPWM*255/100);
}
void checkDirection(){
  feedbackDirection = -2*bitRead(PIND,ChB)+1;
} 
Choose your Reaction!
دیدگاه خود را بنویسید

آدرس ایمیل شما منتشر نخواهد شد.

رفتن به نوار ابزار