• برچسب ها: آردوینو | ساخت ربات | پروژه رباتیک
  • 0.0/5 rating (0 votes)
  • سه شنبه, 13 بهمن 1394

در پایان این آموزش قادر خواهید تا با استفاده از آردوینو یک ربات تعقیب خط بسازید. با ما همراه باشید.

این ربات از یک الگوریتم کنترل PID استفاده می کند که به طور همزمان می تواند خطوط مشکی روی زمینه سفید را دنبال کند. در این ربات آرایه ای از هشت سنسور انعکاسی مادون قرمز (IR reflectance sensors) مورد استفاده قرار گرفته است که مکان ربات را روی خط تعیین می کنند و همچنین از یک میکروکنترلر آردوینو نانو استفاده شده است که عملکرد مناسب برای نگه داشتن ربات روی خط را محاسبه می کند.

گام اول: ابزار و قطعات مورد نیاز

آردوینو نانو × 1  
بردبورد 400 نقطه (400 point) × 1  
بردبورد 170 نقطه (170 point ) × 1  
تنظیم کننده ولتاژ 5 ولت × 1  
کنترلر موتور دوگانه × 1  
سیم جامپر برد بورد × 1  
محفظه باتری لیتیومی دو تایی × 1  
موتور گیربکس دوقلو × 1  
آرایه سنسور انعکاسی مادون قرمز × 1  
باتری لیتیومی 3.7 ولت 18650 × 2  
چرخ × 2  
چرخ کاستور × 2  
سیم لخت کن × 1  
ورق آکریلیک 1.8" × 1  
برش لیزری یا ابزار مشابه برش CNC × 1  

در صورت عدم دسترسی به ابزارهای برش CNC، ابزارهای برش دستی نیز مناسب هستند.

academy 941113 Line Following Arduino Robot 02academy 941113 Line Following Arduino Robot 03academy 941113 Line Following Arduino Robot 04academy 941113 Line Following Arduino Robot 05

 

گام دوم : آردوینو

academy 941113 Line Following Arduino Robot 06

بورد های آردوینو میکروکنترلرهای ساده ای هستند که اهمیت زیادی برای دانش آموزان و دانشجویان مهندسی دارند. نوشتن کد در آردوینو IDE کار ساده ای است که در صورت نیاز به کمک می توانید از انواع آموزش ها، انجمن ها و افرادی که بتوانند به شما کمک کنند، بهره مند شوید. در این پروژه از یک آردوینو نانو استفاده شده است ، اما شما می توانید در صورت تمایل از هر بورد دیگری که دارای 8 ورودی آنالوگ، 4 خروجی PWM و یک پین دیجیتال اضافی است، استفاده کنید. آردوینو نانو بسیار مناسب است چون می توانید بدون استفاده از سیم های جامپر، به صورت مستقیم آن را داخل بردبورد قرار دهید. آردوینو مانند مغز ربات عمل می کند و بر اساس اطلاعاتی که از سنسورها دریافت می کند تصمیم گیری می کند.

گام سوم: اسکلت ربات

اسکلت، بدنه ی فیزیکی ربات است. از یک برش دهنده ی لیزری برای برش دادن قطعات اسکلت ربات استفاده کنید، البته به صورت دستی نیز می توان این برش ها را انجام داد. برای برش دهنده های لیزری یا دیگر ابزارهای CNC از فایل ai و dxf و drwاستفاده کنید و برای برش دستی از فایل pdf dimensioned استفاده کنید. برچسب سوراخ ها در فایل pdf به دستورالعمل های ساخت بدنه که در زیر آمده است، اشاره دارد.
بعد از برش قطعات بالایی و پایینی بدنه، توپ های کاستر را با استفاده از سوراخ های A5 ، A6 ، A7 و A8 نصب کنید.
سپس با استفاده از سوراخ های B1 ، B2 ، B3 و B4 گیربکس را نصب کنید. شما تنها به دو سوراخ نیاز دارید، اما جعبه دنده، دو مجموعه متفاوت از دنده ها است که شما می توانید برای تغییر سرعت، تغییرش دهید.
اگر آنها را تغییر دهید در واقع مکان چرخ ها را تغییر داده اید و باید موقعیت جعبه دنده را نیز تغییر دهید. راهنمای مونتاژ گیربکس و تغییر نسب دنده ها داخل گیربکس وجود دارند.
در مرحله ی بعد با استفاده از سوراخ هایD1 ، D2 ، D3 و D4 قسمت بالایی و پایینی اسکلت را به هم وصل کنید. به منظور اطمینان در سرعت های بیشتر برای اتصال دو نیمه شاسی از استندآف های (standoff) بلند 1.25" استفاده کنید.
برای نگه داشتن باتری از سوراخهای C1 و C2 استفاده کنید. در اینجا از دو باتری قابل شارژ لیتیومی 3.7 ولت 18650 ضد حریق استفاده شده است که به صورت سری قرار گرفته اند ، بنابراین ولتاژ خروجی کل معادل 7.4 ولت خواهد بود. شما می توانید از منبع تغذیه دیگری نیز استفاده کنید، مثلا یک باتری 9 ولتی، اما ظرفیت آنها حدود 950 mAh است در حالی که باتری های لیتیومی حدود 3000 mAh هستند.
بردبوردها با استفاده از چسب دو طرفه و نوار چسب در قسمت بالایی اسکلت ربات نصب می شوند. میتوانید برای نگه داشتن بردبورد از چسبهای قوی استفاده کنید، اما این کار استفاده از بردبورد را در پروژه های دیگر غیرممکن می سازد.
برای نصب سنسورها از سوراخ های A1 ، A2 ، A3 و A4 استفاده می شود که در مرحله ی بعد بحث می شود.

گام چهارم: آرایه سنسورها

academy 941113 Line Following Arduino Robot 07academy 941113 Line Following Arduino Robot 08

آرایه سنسورها به عنوان چشم های ربات عمل می کنند. هشت سنسور بر روی قسمت جلویی ربات وجود دارد که می تواند سیاه را از سفید تشخیص دهند. بر اساس اینکه کدامیک از سنسورها سیاه را می بیننند و کدامیک سفید را می بینند ، آردوینو می تواند مسیر ربات را بر روی خط پیدا کند. اگر ربات کاملا بر روی خط سیاه باقی بماند، در چرخش های 90 درجه نمی تواند راست را از چپ تشخیص دهد، به همین دلیل به گونه ای برنامه ریزی شده است که روی لبه خط باقی بماند.
آرایه سنسور با استفاده از پیچ های #2-56 روی دو ورق آکریلیک سوار شده است. برای این قسمت فایل هایی ضمیمه شده است.
پین های سنسور از 1 تا 8 شماره گذاری شده اند و باید به پین های آنالوگ متناظر روی آردوینو که از A0 تا A7 نام گذاری شده اند، متصل شوند. پین VCC به 5V و پین GND به زمین وصل می شود. دیاگرام کلی مدار در قسمت بعد شرح داده شده است.

گام پنجم: دیاگرام مدار

academy 941113 Line Following Arduino Robot 09

اتصال سنسورها در مقایسه با سیم پیچی دیاگرام که در بالا به آن اشاره شد، فرآیند ساده ای است. تمام سیم های قرمز نشان دهنده ی قدرت یا ولتاژ مثبت هستند، سیم های قرمز تیره ولتاژ پایین و قرمز روشن ولتاژ بالا را نشان می دهند.
سوییچ 1 سیستم را روشن کرده و ولتاژ مورد نیاز را از بسته باتری که به پین خارجی سوییچ متصل است به پین مرکزی سوییچ رسانده و از آنجا به VCC In (پین 4) رگولاتور ولتاژ می برد.
VCC-out (پین 1) بر روی رگولاتور، ولتاژ کمی را به بورد می فرستد تا ولتاژ بقیه مدار را تامین کند، در حالیکه بسته باتری تامین کننده ولتاژ برای زمین است. سوییچ 2 تعیین می کند که آیا ماشین در حالت خودکار است یا حالت دستی. ولتاژ این سوییچ از رگولاتور و زمین تامین می شود. پین مرکزی بر روی سوییچ 2 به پین D4 بر روی آردوینو نانو متصل می شود تا با مد ارتباط برقرار کند.
کنترل کننده موتور با پین های 1 و 16 بورد تغذیه می شود. قدرت به پین 2 ارسال می شود و سیم های قدرت از موتور 1 و 2 متناظرا به پین 3 و 5 متصل می شوند. زمین هر موتور متناظرا به پین های 4 و 6 متصل می شوند. کنترل کننده موتور سیگنال خود را از پین های D9، D6 ، D5 و D3 آردوینو که متناظرا به پین های 11، 12، 13 و 14متصل شده اند، دریافت می کند.
آردوینو بر اساس سیگنال هایی که از آرایه بورد (array board) دریافت کرده، دستوراتی را به کنترل کننده می دهد. هر LED مادون قرمز از طریق پین های آنالوگ یک سیگنال بازگشتی به آردوینو می فرستند. پین های 1، 2، 3، 4، 5، 6، 7 و 8 آرایه LED متناظرا به پین های A0، A1 ، A2 ، A3 ، A4 ، A5 ، A6 و A7 آنالوگ متصل می شوند.

گام ششم: کد

کد زیر در واقع با توجه به سنسورهای IR و خواندن مقادیر از آن ها به موتورها فرمان می دهد که با چه سرعتی حرکت کنند تا ربات به سمت دلخواه بچرخد. این ربات دارای 8 سنسور است. اگر فرض کنیم ربات همواره در یک طرف خط قرار دارد در این صورت در هر زمان ربات می تواند در یکی از 9 موقعیت از 0 تا 8 باشد که با توجه به اینکه کدامیک از سنسورها روشن هستند این موقعیت مشخص می شود. ما می خواهیم در هر زمان مرکز ربات روی لبه خط سیاه قرار گیرد بنابراین setpoint را روی عدد 4 تنظیم می کنیم که در واقع فاصله بین سنسور چهارم و پنجم می باشد. کنترلر PID به این صورت عمل می کند که یک مقدار مطلوب را در نظر گرفته و با توجه به مقدار فعلی و تفاوت آن با مقدار مطلوب، که آن را خطا می نامیم عملکرد مناسب را نشان می دهد.
در این حالت خطا برابر است با تفاضل setpoint از موقعیت مکانی ربات. حال باید ثابت های KP و Kd را که به آن ها ثایت های تناسبی و مشتقی گفته می شود بیابیم.
برای محاسبه ترم تناسبی کنترلر PID ، باید تفاضل PWM بیت دو موتور را بر واحد خطا تقسیم کرده و در در خود خطا ضرب نماییم. ترم مشتقی این کنترلر نیز با ضرب کردن ضریب مشتقی Kd در تغییرات خطا محاسبه می گردد.
و سپس این دو ترم با هم جمع شده و فرمان کنترل را صادر می نمایند.
کد نوشته شده در زیر این مراحل را انجام می دهد. این کد را کپی کرده و در نرم افزار آردوینوی خود پیست نمایید.


#define NUM_SENSORS 8
#define avgSpeed 255
int leftWheelf=3;
int leftWheelr = 5;
int rightWheelf=6;
int rightWheelr = 9;
int setpoint=4, val;
unsigned long lastTime=0, timeChange=0;
int Sampletime=20, outMax=255, outMin=-255;
float error,sumerr,lastError,output,ITerm,DTerm;
float Kp=avgSpeed/4, Ki=0, Kd=.25*Kp;
int pos;
unsigned int sensor[]={A0,A1,A2,A3,A4,A5,A6,A7};
unsigned int sensorValue[NUM_SENSORS];
int threshold = 200;
byte incomingByte;  
int bias=5;
  
void setup() {
  Serial.begin(115200);
  pinMode(4,INPUT);
  
}
void loop() {
//  Serial.println(digitalRead(4));
  if (digitalRead(4)== true) {
  unsigned int Wsum=0;
  int sum=0;
  for (int i=0;i<NUM_SENSORS;i++) {
    sensorValue[i]=analogRead(sensor[i]);
    if (sensorValue[i] < threshold) sensorValue[i]=1;
    else sensorValue[i]=0;
    //Serial.print(i); Serial.print(": "); Serial.println(sensorValue[i]);
    //delay(250);
  }
  for (int i=0;i<NUM_SENSORS;i++) {
    sum=sensorValue[i]+sum;
    pos=sum;
  } 
  
//  Serial.println(pos);
  //delay(100);
  timeChange = millis()-lastTime;
  if (timeChange >= Sampletime){
    pid(pos);
  }
 }
 
 else {
   if (Serial.available() > 0) {
      incomingByte = Serial.read();
  }
    if (incomingByte == 'w') {
      forward();
    }
    else if (incomingByte == 's') {
      reverse();
    }
    else if (incomingByte == 'd') {
      rightTurn();
    }
    else if (incomingByte == 'a') {
      leftTurn();
    }
    else {
      brake();
    }
 }
}
void pid (int val) {
  error=setpoint-val;
  ITerm+=(Ki*error);
  DTerm=Kd*(error-lastError)/(Sampletime/1000.0);
  lastError=error;
  if(ITerm > outMax) ITerm=outMax;
  else if (ITerm < outMin) ITerm=outMin;
  output=Kp*error+ITerm+DTerm;
  if (output>outMax) output=outMax;
  else if (output<outMin) output=outMin;
  lastTime=millis();
  Serial.println(val);
  if (output>0) {
    analogWrite(leftWheelf,avgSpeed);
    analogWrite(rightWheelf,avgSpeed);
    analogWrite(leftWheelr,abs(output));
    analogWrite(rightWheelr,0);
  }
  else if (output<0) {
    analogWrite(leftWheelf,avgSpeed);
    analogWrite(rightWheelf,avgSpeed);
    analogWrite(leftWheelr,0);
    analogWrite(rightWheelr,abs(output));
  }
  else {
    analogWrite(leftWheelf,avgSpeed);
    analogWrite(rightWheelf,avgSpeed);
    analogWrite(leftWheelr,0);
    analogWrite(rightWheelr,0);
  }
}
  
void forward() {
  analogWrite(leftWheelf, avgSpeed - bias);
  analogWrite(leftWheelr, 0);
  analogWrite(rightWheelr, 0);
  analogWrite(rightWheelf, avgSpeed);
}
void leftTurn() {
  analogWrite(leftWheelf,0);
  analogWrite(leftWheelr, 0);
  analogWrite(rightWheelr,0);
  analogWrite(rightWheelf, avgSpeed);
}
void rightTurn() {
  analogWrite(leftWheelf,avgSpeed);
  analogWrite(leftWheelr, 0);
  analogWrite(rightWheelr,0);
  analogWrite(rightWheelf, 0);
}
void reverse() {
  analogWrite(leftWheelf, 0);
  analogWrite(leftWheelr, avgSpeed-bias);
  analogWrite(rightWheelr, avgSpeed);
  analogWrite(rightWheelf, 0);
}
void brake() {
  analogWrite(leftWheelf, 0);
  analogWrite(leftWheelr, 0);
  analogWrite(rightWheelr, 0);
  analogWrite(rightWheelf, 0);
}

 


گام هفتم: کنترل از راه دور

academy 941113 Line Following Arduino Robot 10

اگر دوست دارید ربات را به صورت دستی و از راه دور کنترل کنید، به یک آداپتور بلوتوث نیاز دارید.
اگر GND را به زمین، Vin را به +5 ولت، Tx را به پین 0 روی آردوینو و Rx را به پین 1 روی آردوینو وصل کنید، می توانید کامپیوتر خود را با آردینو تان جفت کنید. این کار درست مانند یک ارتباط سریال است که می توانید از آن برای آپلود اسکریپ یا ارسال اطلاعات استفاده کنید. کد اسکریپ زیر به شما اجازه میدهد تا ربات را با استفاده از کلیدهای WASD کنترل کنید.


// Click on the image to give it focus,
// and then press any key.
import processing.serial.*;
int value = 0;
String word = "       ";
String mode = "      ";
boolean auto = false;
Serial myPort;
void setup() {
  size(300, 90);  // size always goes first!
  String portName = Serial.list() [0];
  myPort = new Serial(this, portName, 115200);
}
void draw() {
  background(0);
  
  myPort.write(key);
  if (auto) {
    mode = "  AUTO ";
    word = "       "; 
  }
  else {
    mode = "MANUAL";
  }
  
  fill(255);
  textSize(40);
  textAlign(CENTER);
  text(mode, width/2, 40); 
  textAlign(CENTER);
  text(word, width/2, 80); 
}
void keyPressed() {
  if (key == ' ') {
      auto = !auto;
    } 
  
  if (!auto) {
    if (key == 'w') {
      word = "FORWARD";
    }
    else if (key == 'd') {
      word = " RIGHT ";
    }
    else if (key == 'a') {
      word = "  LEFT ";
    }
    else if (key == 's') {
      word = "REVERSE";
    }
    else {key = 'p';}
  }
}
void keyReleased() {
  key = 'p';
}

 

 منبع : سایت instructables

افزودن نظر