الگوریتم زنبور عسل

الهام گرفتن از طبیعت یکی از مهمترین راهکارها برای حل مسایل در بهینه سازی و طراحی هوش مصنوعی می باشد .

یکی از مهمترین الگوریتم های تکاملی ، الگوریتم زنبور عسل است .

زنبورهای عسل روش جالبی برای جستجو و یافتن غذا در گستره وسیع دارند .

در ابتدا زنبورهای عسل برای جستجوی غذا بصورت تصادفی و محلی به جستجو می پردازند .

زنبور ها در هنگام جستجوی غذا معمولا به سه دسته تقسیم می شوند ؛ زنبورهای کارگر ، زنبورهای تماشاگر و زنبورهای دیده بان( پیشاهنگ ) .

جستجوی غذا در ابتدا توسط زنبورهای دیده بان (scout bee ) با جستجو در مناطقی که امید بیشتری برای یافتن غذا دارد آغاز می گردد .

پس از جستجو و دیدن تمامی منطقی که امیدی برای یافتن غذا در آنها وجود دارد ، زنبور دیده بان بر بالای منطقه ای که امید بیشتری برای

یافتن غذا در آن می رود ، به رقصیدن مشغول می شود.

این رقص اطلاعات مناسبی در خصوص منطقه یافت شده به دیگر زنبورها می دهد .

این روش باعث می شود دیگر زنبورها ( onlooker bee , employed bee ) وارد محل یافت شده شوند و بهره برداری کنند .

سپس زنبورهای دیده بان پس از پایان رقصیدن ، به جستجو در نقاط همسایگی محل یافت شده می پردازند تا نواحی امید بخش جدیدی پیدا کنند .

در تصویر بالا ، نحوه عملکرد زنبورها در جستجوی غذا نمایش داده شده است .

نحوه عملکرد الگوریتم

یک کلونی زنبور عسل می تواند تا شعاع چهارده کیلومتر در جهت های مختلف را به جستجوی غذا بپردازد ، تا شهد و گرده گل را از مناطق مختلف

بهره برداری کند .

بخش کوچکی از کلونی ، که زنبورهای پیشاهنگ ( scout bee ) نام دارند به صورت مداوم به جستجوی محل های جدید برای بهرده برداری می پردازند .

این دسته از زنبورها به صورت تصادفی به جستجوی مناطق با سودآوری بالا ( بازدهی خوب ) می پردازند .

پس از بازگشت زنبورهای پیشاهنگ ، آنها در منطقی از کندو که پیست رقص نامیده می شود می روند و مشغول رقصیدن می شوند .

از طریق این نوع رقصیدن ، زنبورهای پیشاهنگ ، مکان کشف خود را به اطلاع زنبورهای تماشاگر (onlooker bee ) بیکار می رساند .

پس از اتمام رقصیدن به منطقه ای که منبع غذایی مناسب کشف کرده بودند بازمیگردند .

تا زمانیکه آن منبع غذایی کشف شده ، غنی از مواد غذایی باشد ، توسط زنبور پیشاهنگ تبلیغ خواهد شد .

زنبورهای کارگر ( employed bee )به بهره برداری از منبع غذایی کشف شده می پردازند .

با استفاده از این روش ، کلونی زنبور عسل به بهترین روش منابع غذایی خوب و مناسب و با بازدهی بالا را انتخاب کرده و از آنها بهره برداری می کند .

کاربردها

الگوریتم زنبور عسل در بسیاری از مسائل کاربردی استفاده می گردد . در ریاضیات ، اقتصاد ، علوم مهندسی ، فیزیک ، هوافضا ، کیهان شناسی و..

یکی از مهمترین کاربردهای این الگوریتم ها در علوم کامپیوتر و همچنین در مسائل بهینه سازی می باشد .

استفاده مهم دیگر این الگوریتم در طراحی هوش مصنوعی و سیستم های هوشمند است .

همچنین ترکیب این الگوریتم با سایر الگوریتم های هوش مصنوعی از جمله الگوریتم ژنتیک ، شبکه عصبی ، منطق فازی ، الگویتم مورچگان و ..

می تواند هوش مصنوعی قوی تری ایجاد نماید .

سیستم های کنترل ، دسته بندی اطلاعات ، بهینه سازی تجهیزات مکانیکی و رباتیک نیز از دیگر موارد استفاده از این الگوریتم می باشد .

نمونه برنامه

نمونه کد پایتون با استفاده از الگوریتم زنبور عسل در انتهای این مقاله بارگزاری می شود .

"""
To find the minimum  of sphere function on interval (-10 to 10) with
۲ dimensions in domain using default parameters:
"""

from beecolpy import abc

def sphere(x):
	total = 0
	for i in range(len(x)):
		total += x[i]**2
	return total
	
abc_obj = abc(sphere, [(-10,10), (-10,10)]) #Load data
abc_obj.fit() #Execute the algorithm

#If you want to get the obtained solution after execute the fit() method:
solution = abc_obj.get_solution()

#If you want to get the number of iterations executed, number of times that
#scout event occur and number of times that NaN protection actuated:
iterations = abc_obj.get_status()[0]
scout = abc_obj.get_status()[1]
nan_events = abc_obj.get_status()[2]

#If you want to get a list with position of all points (food sources) used in each iteration:
food_sources = abc_obj.get_agents()

توسعه آینده

در حال حاضر مدل های مختلفی از الگوریتم های زنبور عسل طراحی و توسعه یافته است .

الگوریتم های qABC ، BABC ، GABC ، CABC ، MABC ، DFnABC از جمله این الگوریتم ها هستند .

خصوصا الگوریتم DFnABC از عملکرد و قابلیت اجرایی بسیار مناسبی برخوردار است که در مقاله جدا به این الگوریتم پرداخته ایم .

چالش ها

چالش ها و مسائل پیش روی توسعه این الگوریتم شامل اجرایی سازی ، توسعه و ترکیب با الگوریتم های دیگر هوش مصنوعی از جمله منطق فازی

و عصبی می باشد .

جمع بندی

با توجه به مسائل مطرح شده ، الگوریتم کلونی رنبور عسل می تواند کاربردهای وسیعی در حوزه ی بهینه سازی ، یافتن کوتاهترین مسیر ، جستجو

و ردیابی ، توسعه هوش مصنوعی ، بالا بردن دقت و حساسیت سیستم ها ، ساده سازی سیستم های پیچیده و … داشته باشد .

بازوی رباتیک کنترل شده با حرکت دست با استفاده از آردوینو نانو

بازوهای رباتیک یکی از خلاقیت های جذاب مهندسی است و تماشای نحوه عملکرد برای انجام کارهای پیچیده درست مانند بازوی انسان همیشه قابل توجه بوده است . این بازوهای رباتیک معمولاً در صنایع در خط مونتاژ که کارهای مکانیکی شدید مانند جوشکاری، حفاری، نقاشی و غیره را انجام می دهند، یافت می شوند.

بازوهای رباتیک پیشرفته اخیر با دقت بالا نیز برای انجام عملیات های جراحی پیچیده در حال توسعه هستند.

ما از بازوی رباتیک ایجاد شده توسط پرینتر سه بعدی استفاده خواهیم کرد تا با استفاده از آردوینو نانو، ژیروسکوپ MPU6050 و حسگر فلکس، یک بازوی رباتیک کنترل شده با حرکت دست ایجاد کنیم.

سنسور فلکس برای کنترل سروو دستگیره بازوی رباتیک و MPU6050 برای حرکت رباتیک در محور X و Y استفاده می شود. اگر چاپگر ندارید، می توانید بازوی خود را با مقوای ساده همانطور که برای پروژه بازوی رباتیک آردوینو ساختیم بسازید.

قبل از پرداختن به جزئیات، ابتدا با سنسور MPU6050 و سنسور فلکس آشنا می شویم.

سنسور ژیروسکوپی و شتاب سنج MPU6050

MPU6050 مبتنی بر فناوری سیستم های میکرو مکانیکی (MEMS) است. این سنسور دارای شتاب سنج ۳ محوره، ژیروسکوپ ۳ محوره و سنسور دمای داخلی است. می توان از آن برای اندازه گیری پارامترهایی مانند شتاب، سرعت، جهت، جابجایی و غیره استفاده کرد.

ویژگی های سنسور MPU6050:

ارتباط: پروتکل I2C با آدرس I2C قابل تنظیم

منبع تغذیه ورودی: ۳-۵ ولت

ADC 16 بیتی داخلی دقت بالایی را ارائه می دهد

DMP داخلی قدرت محاسباتی بالایی را ارائه می دهد

می توان از آن برای ارتباط با سایر دستگاه های I2C مانند مغناطیس سنج استفاده کرد

سنسور دمای داخلی

جزئیات پین اوت MPU6050:

سنسور فلکس

حسگرهای فلکس چیزی جز یک مقاومت متغیر نیستند. مقاومت سنسور فلکس زمانی که سنسور خم می شود تغییر می کند. آنها معمولا در دو اندازه ۲٫۲ اینچ و ۴٫۵ اینچ موجود هستند.

چرا در پروژه خود از سنسورهای انعطاف پذیر استفاده می کنیم؟

در این بازوی رباتیک کنترل شده با اشاره، از یک حسگر انعطاف پذیر برای کنترل گیره بازوی رباتیک استفاده شده است. هنگامی که سنسور فلکس روی دستکش خم می شود، موتور سروو متصل به گیره می چرخد ​​و گیره باز می شود.

سنسورهای فلکس می توانند در بسیاری از پروژه ها مفید باشد و کاربرد فراوانی در ساخت انواع ربات ها دارد .

آماده سازی بازوی رباتیک پرینت سه بعدی:

بازوی رباتیک پرینت سه بعدی مورد استفاده در این آموزش با پیروی از طرح ارائه شده توسط EEZYbotARM ساخته شده است که در Thingiverse موجود است. روش کامل ساخت بازوی روباتیک پرینت سه بعدی و جزئیات مونتاژ با ویدئو در پیوند Thingiverse وجود دارد که در بالا به اشتراک گذاشته شده است.

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

آردوینو نانو

سنسور فلکس

مقاومت ۱۰k

MPU6050

دستکش

سیم های اتصال

برد بورد

مدار پروژه :

اتصال مدار بین MPU6050 و آردوینو نانو:

اتصال مدار بین سروو موتور و آردوینو نانو:

یک سنسور فلکس شامل دو پین است. این شامل پایانه های قطبی نیست. بنابراین پین یک P1 به پین ​​آنالوگ A0 آردوینو نانو با مقاومت pull-up 10k متصل می شود و پایه دو P2 به آردوینو متصل می شود.

نصب MPU6050 و سنسور فلکس روی دستکش :

ما MPU6050 و سنسور فلکس را روی یک دستکش نصب کرده ایم. در اینجا از یک اتصال سیمی برای اتصال دستکش و بازوی رباتیک استفاده می شود، اما می توان آن را با استفاده از اتصال RF یا اتصال بلوتوث بی سیم کرد.

پس از هر اتصال، تنظیمات نهایی بازوی رباتیک کنترل شده با حرکت مانند تصویر زیر به نظر می رسد:

برنامه نویسی آردوینو نانو برای بازوی رباتیک

در اینجا چند خط مهم کد توضیح داده شده است.

۱٫ ابتدا فایل های کتابخانه ای لازم را وارد کنید. کتابخانه Wire.h برای ارتباط I2C بین Arduino Nano & MPU6050 و servo.h برای کنترل سروو موتور استفاده می شود.

#include<Wire.h>                
#include<Servo.h>  

۲٫ در مرحله بعد، اشیاء برای کلاس servo اعلام می شود. همانطور که از چهار موتور سروو استفاده می کنیم، چهار شی مانند servo_1، servo_2، servo_3، servo_4 ایجاد می شود.

Servo servo_1;      
Servo servo_2;
Servo servo_3;
Servo servo_4; 

۳٫ سپس آدرس I2C MPU6050 و متغیرهای مورد استفاده اعلام می شود.

const int MPU_addr=0x68;        //MPU6050 I2C Address
int16_t axis_X,axis_Y,axis_Z;
int minVal=265;
int maxVal=402;
double x;
double y;
double z;​

۴٫ در مرحله بعدی در تنظیم void، نرخ باود ۹۶۰۰ برای ارتباط سریال تنظیم شده است.

Serial.begin(9600);

و ارتباط I2C بین Arduino Nano و MPU6050 برقرار است:

 Wire.begin();                      //Initilize I2C Communication
  Wire.beginTransmission(MPU_addr);  //Start communication with MPU6050
  Wire.write(0x6B);                  //Writes to Register 6B
  Wire.write(0);                     //Writes 0 into 6B Register to Reset
  Wire.endTransmission(true);        //Ends I2C transmission

همچنین چهار پایه PWM برای اتصالات سروو موتور تعریف شده است.

 servo_1.attach(2);   // Forward/Reverse_Motor
  servo_2.attach(3);   // Up/Down_Motor
  servo_3.attach(4);   // Gripper_Motor
  servo_4.attach(5);   // Left/Right_Motor

۵٫ سپس در تابع حلقه خالی، دوباره اتصال I2C را بین MPU6050 و آردوینو نانو برقرار کنید و سپس شروع به خواندن داده های X، Y، Z-Axis از رجیستر MPU6050 کنید و آنها را در متغیرهای مربوطه ذخیره کنید.

Wire.beginTransmission(MPU_addr);    
  Wire.write(0x3B);                  //Start with regsiter 0x3B 
  Wire.endTransmission(false);     
  Wire.requestFrom(MPU_addr,14,true);  //Read 14 Registers 
                         axis_X=Wire.read()<<8|Wire.read();                
                         axis_Y=Wire.read()<<8|Wire.read();
                         axis_Z=Wire.read()<<8|Wire.read();

پس از آن، مقدار حداقل و حداکثر داده های محور را از سنسور MPU6050 در محدوده ۹۰- تا ۹۰ ترسیم کنید.

                        int xAng = map(axis_X,minVal,maxVal,-90,90);    
                        int yAng = map(axis_Y,minVal,maxVal,-90,90);
                        int zAng = map(axis_Z,minVal,maxVal,-90,90);

سپس از فرمول زیر برای محاسبه مقادیر x، y، z از ۰ تا ۳۶۰ استفاده کنید.

x= RAD_TO_DEG * (atan2(-yAng, -zAng)+PI);       
  y= RAD_TO_DEG * (atan2(-xAng, -zAng)+PI);
                          z= RAD_TO_DEG * (atan2(-yAng, -xAng)+PI);

سپس داده های خروجی آنالوگ سنسور فلکس را در پین A0 آردوینو نانو بخوانید و با توجه به مقدار دیجیتال سنسور فلکس، زاویه سروو گیره را تنظیم کنید. بنابراین اگر داده های سنسور فلکس بیشتر از ۷۵۰ باشد، زاویه سروو موتور گیره ۰ درجه و اگر کمتر از ۷۵۰ باشد ۱۸۰ درجه است.

 int gripper;
  int flex_sensorip = analogRead(A0);             
  if(flex_sensorip > 750)      
        {
          gripper = 0;
        }
        else
        {
          gripper = 180;
        }
   servo_3.write(gripper);  

سپس حرکت MPU6050 در محور X از ۰ تا ۶۰ بر حسب ۰ تا ۹۰ درجه برای حرکت رو به جلو/عکوس سروو موتور بازوی رباتیک ترسیم می شود.

if(x >=0 && x <= 60) 
  {
     int mov1 = map(x,0,60,0,90);
     Serial.print("Movement in F/R = ");
     Serial.print(mov1);
     Serial.println((char)176);
     servo_1.write(mov1);
  } 

و حرکت MPU6050 در محور X از ۲۵۰ به ۳۶۰ بر حسب ۰ تا ۹۰ درجه برای بازوی روباتیک حرکتی UP/DOWN سروو موتور ترسیم شده است.

else if(x >=300 && x <= 360) 
  {
     int mov2 = map(x,360,250,0,90);
     Serial.print("Movement in Up/Down = ");
     Serial.print(mov2);
     Serial.println((char)176);
     servo_2.write(mov2);
  } 

حرکت MPU6050 در محور Y از ۰ تا ۶۰ بر حسب ۹۰ تا ۱۸۰ درجه برای حرکت سمت چپ بازوی رباتیک سروو موتور ترسیم شده است.

 if(y >=0 && y <= 60) 
  {
     int mov3 = map(y,0,60,90,180);
     Serial.print("Movement in Left = ");
     Serial.print(mov3);
     Serial.println((char)176);
     servo_4.write(mov3);
  } 

حرکت MPU6050 در محور Y از ۳۰۰ به ۳۶۰ بر حسب ۰ تا ۹۰ درجه برای حرکت سمت راست بازوی رباتیک سروو موتور ترسیم شده است.

else if(y >=300 && y <= 360) 
  {
     int mov3 = map(y,360,300,90,0);
     Serial.print("Movement in Right = ");
     Serial.print(mov3);
     Serial.println((char)176);
     servo_4.write(mov3);
  }

کارکرد بازوی رباتیک کنترل شده با اشاره با استفاده از آردوینو

در نهایت، کد را در آردوینو نانو آپلود کنید و دستکش نصب شده با سنسور MPU6050 و Flex را بپوشید.

۱٫ اکنون دست را به سمت پایین حرکت دهید تا بازوی رباتیک به سمت جلو حرکت کند و به سمت بالا حرکت کنید تا بازوی رباتیک به سمت بالا حرکت کند.

۲٫ سپس دست را به چپ یا راست خم کنید تا بازوی رباتیک به چپ یا راست بچرخد.

۳٫ کابل فلکس متصل شده با انگشت دستکش را خم کنید تا گیره باز شود و سپس آن را رها کنید تا ببندید.

کد :

//Code for Gesture Controlled Robotic ARM (Arduino Nano & MPU6050)

//Circuit Digest

#include<Wire.h>                //I2C Wire Library 

#include<Servo.h>               //Servo Motor Library

Servo servo_1;      

Servo servo_2;

Servo servo_3;

Servo servo_4;

const int MPU_addr=0x68;        //MPU6050 I2C Address

int16_t axis_X,axis_Y,axis_Z;

int minVal=265;

int maxVal=402;

double x;

double y;

double z;

 

void setup()

{

  Serial.begin(9600);

  

  Wire.begin();                      //Initilize I2C Communication

  Wire.beginTransmission(MPU_addr);  //Start communication with MPU6050

  Wire.write(0x6B);                  //Writes to Register 6B

  Wire.write(0);                     //Writes 0 into 6B Register to Reset

  Wire.endTransmission(true);        //Ends I2C transmission

  

  servo_1.attach(2);   // Forward/Reverse_Motor

  servo_2.attach(3);   // Up/Down_Motor

  servo_3.attach(4);   // Gripper_Motor

  servo_4.attach(5);   // Left/Right_Motor

  

}

void loop()

{

  Wire.beginTransmission(MPU_addr);    

  Wire.write(0x3B);                  //Start with regsiter 0x3B 

  Wire.endTransmission(false);     

  Wire.requestFrom(MPU_addr,14,true);  //Read 14 Registers 

  

  axis_X=Wire.read()<<8|Wire.read();                //Reads the MPU6050 X,Y,Z AXIS Value

  axis_Y=Wire.read()<<8|Wire.read();

  axis_Z=Wire.read()<<8|Wire.read();

  

  int xAng = map(axis_X,minVal,maxVal,-90,90);     // Maps axis values in terms of -90 to +90  

  int yAng = map(axis_Y,minVal,maxVal,-90,90);

  int zAng = map(axis_Z,minVal,maxVal,-90,90);

       

  x= RAD_TO_DEG * (atan2(-yAng, -zAng)+PI);       //Formula to convert into degree

  y= RAD_TO_DEG * (atan2(-xAng, -zAng)+PI);

  z= RAD_TO_DEG * (atan2(-yAng, -xAng)+PI);

  int gripper;

  int flex_sensorip = analogRead(A0);            //Reads flex sensor output

     

  if(flex_sensorip > 750)

        {

          gripper = 0;

        }

        else

        {

          gripper = 180;

        }

  

   servo_3.write(gripper);                    //Writes gripper value to 3rd servo motor

  

  if(x >=0 && x <= 60) 

  {

     int mov1 = map(x,0,60,0,90);

     Serial.print("Movement in F/R = ");

     Serial.print(mov1);

     Serial.println((char)176);

     servo_1.write(mov1);

  } 

 

  else if(x >=300 && x <= 360) 

  {

     int mov2 = map(x,360,250,0,180);

     Serial.print("Movement in Up/Down = ");

     Serial.print(mov2);

     Serial.println((char)176);

     servo_2.write(mov2);

  } 

 if(y >=0 && y <= 60) 

  {

     int mov3 = map(y,0,60,90,180);

     Serial.print("Movement in Left = ");

     Serial.print(mov3);

     Serial.println((char)176);

     servo_4.write(mov3);

  } 

 

  else if(y >=300 && y <= 360) 

  {

     int mov3 = map(y,360,300,90,0);

     Serial.print("Movement in Right = ");

     Serial.print(mov3);

     Serial.println((char)176);

     servo_4.write(mov3);

  } 

}

ربات کنترل شده با اشاره دست با استفاده از آردوینو

بیایید یک ربات با قابلیت کنترل با حرکات دست بسازیم که دوستان و خانواده شما را شگفت زده می کند – این مثل یک جادو هست! این راهنمای گام به گام به شما کمک می کند تا با استفاده از اجزای ساده ای مانند آردوینو، شتاب سنج MPU6050، جفت فرستنده و گیرنده nRF24L01 و ماژول درایور موتور L293D، یک ربات کنترل شده با اشاره دست بسازید. ما ربات را به دو قسمت تقسیم می کنیم: فرستنده و گیرنده.

بخش فرستنده شامل یک آردوینو Uno، شتاب سنج MPU6050 و ژیروسکوپ به همراه فرستنده گیرنده nRF24L01 است. از طرف دیگر، بخش گیرنده شامل یک آردوینو Uno، nRF24L01، دو موتور DC و یک درایور موتور L293D است. فرستنده به عنوان کنترل از راه دور عمل می کند و به ربات اجازه می دهد تا به اشارات پاسخ دهد و بر اساس آن حرکت کند. به طرز چشمگیری، حرکات ربات با حرکاتی که با دستان خود انجام می دهید کنترل می شود. این پروژه ترکیبی از فناوری حسگر، ارتباطات بی سیم و کنترل موتور برای ایجاد یک تجربه جذاب و تعاملی است. مراحل این آموزش را دنبال کنید تا این ربات جادویی که با اشاره کنترل می شود را زنده کنید و تأثیری ماندگار بر روی اطرافیان خود بگذارید.

ربات کنترل با اشاره چگونه کار می کند؟

این پروژه شامل دو مدار است: مدار فرستنده و مدار گیرنده. حسگر شتاب سنج MPU6050 حرکات دست را به سیگنال های الکتریکی تبدیل می کند.

آردوینو نانو این سیگنال ها را پردازش کرده و از طریق فرستنده RF ارسال می کند

در انتهای گیرنده، گیرنده RF این سیگنال ها را دریافت کرده و آنها را برای رمزگشایی به Arduino Uno ارسال می کند. پس از دریافت سیگنال ها، آردوینو Uno موتورها را از طریق درایور موتور فعال می کند و ربات را هدایت می کند تا “به جلو”، “به عقب”، “چپ” یا “راست” حرکت کند.

اگر مقدار شتاب در امتداد محور x کمتر از ۳۴۰ باشد، ربات باید به جلو حرکت کند.

اگر مقدار شتاب در امتداد محور x بیش از ۳۶۰ باشد، ربات باید به سمت عقب حرکت کند.

اگر مقدار شتاب در امتداد محور y کمتر از ۱۴۰ باشد، ربات باید به سمت چپ بچرخد.

اگر مقدار شتاب در امتداد محور y بیش از ۱۶۰ باشد، ربات باید به راست بچرخد.

اگر هیچ یک از شرایط بالا برآورده نشد، ربات باید متوقف شود.

اجزای مورد نیاز برای ساخت ربات

  1. آردینو UNO
  2. آردینو nano
  3. NRF24L01
  4. MPU6050
  5. ۲WD Acrylic Chassis kit
  6. L298N Motor Driver Module
  7. ۷٫۴V Li-ion battery/ 9V battery
  8. سیم و اتصالات

شتاب سنج و ژیروسکوپ MPU6050

ماژول حسگر MPU6050 مانند یک کامپیوتر کوچک است که می تواند حرکت را به ۶ روش مختلف حس کند: ۳ برای شتاب و ۳ برای چرخش (ژیروسکوپ). همچنین دارای سنسور دمای داخلی است. این ماژول می‌تواند با دستگاه‌های دیگر مانند میکروکنترلرها و حسگرها (مانند مغناطیس‌سنج یا سنسور فشار)، با استفاده از یک گذرگاه I2C و یک گذرگاه I2C کمکی مرتبط شود .

کار اصلی MPU6050 اندازه گیری سرعت حرکت یک چیز، جهت گیری آن و سایر موارد مرتبط با حرکت است.

با یک پردازشگر دیجیتال حرکتی همراه است، یک مینی کامپیوتر درون آن که می تواند محاسبات پیچیده را انجام دهد. این باعث می شود MPU6050 برای تجزیه و تحلیل و کنترل حرکت در برنامه های مختلف مفید باشد.

ماژول گیرنده NRF24L01

nRF24L01 یک فرستنده رادیویی فشرده است که برای باند جهانی ۲٫۴ – ۲٫۵ گیگاهرتز ISM طراحی شده است. بسته بندی شده در یک تراشه واحد، شامل یک سازنده ی فرکانس کاملاً یکپارچه، یک تقویت کننده قدرت، یک نوسان ساز کریستالی، یک دمدولاتور، مدولاتور و یک موتور پروتکل پیشرفته ShockBurst است.

شما به راحتی می توانید قدرت خروجی، کانال های فرکانس و پروتکل های آن را با استفاده از یک رابط SPI تنظیم کنید.

این ماژول فرستنده گیرنده در محدوده ولتاژ ۱٫۹ ولت تا ۳٫۶ ولت کار می کند. این دستگاه دارای حالت‌های Power Down و Standby داخلی است که استفاده از آن را کم مصرف و ساده می‌کند.

طراحی مدار ربات

مدارات این ربات به دو بخش کلی تقسیم بندی می شود :

  1. مدارات فرستنده
  2. مدارات گیرنده

مدار فرستنده

بخش فرستنده این پروژه شامل شتاب‌سنج و ژیروسکوپ MPU6050، فرستنده گیرنده nRF24L01 و آردوینو Uno است. آردوینو به دریافت اطلاعات از MPU6050 ادامه می دهد و سپس این داده ها را به فرستنده nRF ارسال می کند. سپس فرستنده RF این داده ها را به محیط اطراف پخش می کند.

مدار گیرنده ربات

بخشی از ربات کنترل‌شده با اشاره که سیگنال‌ها را دریافت می‌کند شامل Arduino Uno، فرستنده گیرنده nRF24L01، ۲ موتور DC و یک ماژول درایور موتور است. گیرنده NRF24L01 داده های ارسال شده از راه دور را ضبط می کند و آن را به آردوینو منتقل می کند. پس از آن، آردوینو بر اساس سیگنال های دریافتی، به حرکت موتورهای DC فرمان می دهد. نمودار مدار این بخش گیرنده در زیر ارائه شده است.

برنامه نویسی ربات

در این قسمت کد های برنامه نویسی ربات به همراه توضیحات آن ارائه می شود .

برنامه نویسی قسمت فرستنده ربات

کد فرستنده از شتاب سنج و ژیروسکوپ MPU6050 به همراه فرستنده گیرنده nRF24L01 برای برقراری ارتباط بی سیم با گیرنده استفاده می کند.

سنسور MPU6050 داده‌های حرکتی را می‌گیرد و سپس با استفاده از ماژول nRF24L01 نقشه‌برداری و به گیرنده منتقل می‌شود.

داده های ارسالی نشان دهنده حرکات دست در امتداد محورهای X و Y است که امکان کنترل حرکت ربات را فراهم می کند.

اطمینان حاصل کنید که کتابخانه های لازم را نصب کرده اید

SPI.h library — RF24.h library — Wire.h library — I2Cdev.h library — MPU6050.h library

#include <SPI.h>        //SPI library for communicate with the nRF24L01+
#include "RF24.h"       //The main library of the nRF24L01+
#include "Wire.h"       //For communicate
#include "I2Cdev.h"     //For communicate with MPU6050
#include "MPU6050.h"    //The main library of the MPU6050

در اینجا، کتابخانه های لازم فراخوان شده است. SPI برای ارتباط با ماژول nRF24L01، RF24 کتابخانه اصلی برای nRF24L01، Wire برای ارتباطات عمومی و I2Cdev و MPU6050 برای رابط با شتاب سنج و ژیروسکوپ MPU6050 استفاده می شود.

//Define the object to access and cotrol the Gyro and Accelerometer (We don't use the Gyro data)
MPU6050 mpu;
int16_t ax, ay, az;
int16_t gx, gy, gz;

در این قسمت از برنامه ، نمونه‌ای از کلاس MPU6050 ایجاد می‌شود و متغیرهایی برای ذخیره خوانش‌های شتاب‌سنج و ژیروسکوپ (ax، ay، az، gx، gy، gz) اعلام می‌شوند.

//Define packet for the direction (X axis and Y axis)
int data[2];
 
//Define object from RF24 library - 8 and 9 are a digital pin numbers to which signals CE and CSN are connected.
RF24 radio(8,9);

یک داده آرایه با اندازه ۲ برای ذخیره داده های محور X و Y معرفی می شود . یک تابع RF24 به نام رادیو با پین های دیجیتال ۸ و ۹ به عنوان پایه های CE و CSN ایجاد می شود.

//Create a pipe addresses for the communicate                                    
const uint64_t pipe = 0xE8E8F0F0E1LL;

یک آدرس منحصر به فرد برای ارتباط بین فرستنده و گیرنده تعریف شده است.

void setup(void)
{
  Serial.begin(9600);
  Wire.begin();
  mpu.initialize();              //Initialize the MPU object
  radio.begin();                 //Start the nRF24 communicate    
  radio.openWritingPipe(pipe);   //Sets the address of the receiver to which the program will send data.
}

تابع setup ارتباط سریال، کتابخانه سیم بندی ، MPU6050 و ارتباط nRF24 را مقداردهی اولیه می کند. و آدرس ارتباطی فرستنده را تنظیم می کند.

void loop(void){
 
  //With this function, the acceleration and gyro values of the axes are taken.
  //If you want to control the car axis differently, you can change the axis name in the map command.
  mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
 
  //In two-way control, the X axis (data [0]) of the MPU6050 allows the robot to move forward and backward.
  //Y axis (data [1]) allows the robot to right and left turn.
  data[0] = map(ax, -17000, 17000, 300, 400 ); //Send X axis data
  data[1] = map(ay, -17000, 17000, 100, 200);  //Send Y axis data
  radio.write(data, sizeof(data));
  Serial.print("X axix data = ");
  Serial.println(data[0]);
  Serial.print("Y axix data = ");
  Serial.println(data[1]);
}

در حلقه اصلی، تابع getMotion6 مقادیر شتاب سنج و ژیروسکوپ را می خواند. داده های محور X و Y به یک محدوده خاص نگاشت شده و در آرایه داده ذخیره می شوند.

سپس این داده ها با استفاده از تابع radio.write ارسال می شوند. داده‌های محور X و محور Y برای اشکال‌زدایی در مانیتور سریال چاپ می‌شوند.

برنامه سمت گیرنده

در سمت گیرنده، Arduino Uno با ماژول nRF24L01 داده های ارسالی را از فرستنده دریافت می کند. بسته به سیگنال های دریافتی که نشان دهنده حرکات دست هستند، آردوینو جهت دو موتور DC را با استفاده از یک ماژول درایور موتور (L293D) کنترل می کند. کد شامل منطق حرکت ربات به جلو، عقب، چپ، راست یا توقف بر اساس حرکات دست تفسیر شده است.

#include <SPI.h>      //SPI library for communicate with the nRF24L01+
#include "RF24.h"     //The main library of the nRF24L01+

این خطوط شامل کتابخانه های لازم برای ارتباط با ماژول nRF24L01 می باشد.

//Define enable pins of the Motors
const int enbA = 3;
const int enbB = 6;
 
//Define control pins of the Motors
//If the motors rotate in the opposite direction, you can change the positions of the following pin numbers
const int IN1 = 2;    //Right Motor (-)
const int IN2 = 4;    //Right Motor (+)
const int IN3 = 5;    //Left Motor (+)
const int IN4 = 7;    //Right Motor (-)
 
//Define variable for the motors speeds
//I have defined a variable for each of the two motors
//This way you can synchronize the rotation speed difference between the two motors
int RightSpd = 200;
int LeftSpd = 250;

این خطوط، پایه‌های کنترل موتور (فعال و پایه‌های ورودی) را مشخص می‌کنند و سرعت‌های اولیه را برای موتورهای راست و چپ تعیین می‌کنند.

//Define packet for the direction (X axis and Y axis)
int data[2];
 
//Define object from RF24 library - 8 and 9 are a digital pin numbers to which signals CE and CSN are connected
RF24 radio(8,9);

داده های آرایه ای با اندازه ۲ برای ذخیره داده های محور X و Y دریافت شده از فرستنده اعلام می شود. یک تابع RF24 به نام رادیو با پین های دیجیتال ۸ و ۹ به عنوان پایه های CE و CSN ایجاد می شود.

//Create a pipe addresses for the communicate
const uint64_t pipe = 0xE8E8F0F0E1LL;

یک آدرس منحصر به فرد برای ارتباط بین فرستنده و گیرنده تعریف شده است.

void setup()
{
  //Define the motor pins as OUTPUT
  pinMode(enbA, OUTPUT);
  pinMode(enbB, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
 
  Serial.begin(9600);
  radio.begin();                    //Start the nRF24 communicate            
  radio.openReadingPipe(1, pipe);   //Sets the address of the transmitter to which the program will receive data.
  radio.startListening();            
  }

تابع راه‌اندازی پین‌های کنترل موتور را به‌عنوان OUTPUT راه‌اندازی می‌کند، ارتباط سریال را انجام می دهد ، ماژول nRF24 را راه‌اندازی می‌کند، آدرس ارتباطی گیرنده را تنظیم می‌کند و آن را برای پذیرش داده‌های ورودی آماده می‌کند.

void loop(){
  if (radio.available()){
    radio.read(data, sizeof(data));
 
    if(data[0] < 340){
      //forward            
      analogWrite(enbA, RightSpd);
      analogWrite(enbB, LeftSpd);
      digitalWrite(IN1, HIGH);
      digitalWrite(IN2, LOW);
      digitalWrite(IN3, HIGH);
      digitalWrite(IN4, LOW);
      Serial.println("forward");
    }
   
    if(data[0] > 360){
      //backward              
      analogWrite(enbA, RightSpd);
      analogWrite(enbB, LeftSpd);
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, HIGH);
      digitalWrite(IN3, LOW);
      digitalWrite(IN4, HIGH);
      Serial.println("backward");
    }
     
    if(data[1] > 160){
       //right
      analogWrite(enbA, RightSpd);
      analogWrite(enbB, LeftSpd);
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, HIGH);
      digitalWrite(IN3, HIGH);
      digitalWrite(IN4, LOW);
      Serial.println("right");
    }
 
    if(data[1] < 140){
     //left
      analogWrite(enbA, RightSpd);
      analogWrite(enbB, LeftSpd);
      digitalWrite(IN1, HIGH);
      digitalWrite(IN2, LOW);
      digitalWrite(IN3, LOW);
      digitalWrite(IN4, HIGH);
      Serial.println("left");
    }
 
    if(data[0] > 340 && data[0] < 360 && data[1] > 140 && data[1] < 160){
      //stop car
      analogWrite(enbA, 0);
      analogWrite(enbB, 0);
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, LOW);
      digitalWrite(IN3, LOW);
      digitalWrite(IN4, LOW);
      Serial.println("stop");
    }
  }
}

در حلقه اصلی، برنامه بررسی می کند که آیا داده های موجود از فرستنده وجود دارد یا خیر. اگر داده در دسترس باشد، مقادیر محور X و Y را از فرستنده می خواند. بسته به مقادیر دریافتی، منطق کنترل موتور خاص برای حرکت روبات به جلو، عقب، راست، چپ یا توقف اجرا می‌شود. وضعیت حرکت برای اشکال زدایی در مانیتور سریال چاپ می شود.

توجه: در کد گیرنده، منطق کنترل موتور به طور کامل اجرا نشده است و ممکن است لازم باشد آن را بر اساس تنظیمات و تنظیمات درایور موتور خاص خود تغییر دهید. همچنین، کالیبراسیون MPU6050 ممکن است برای اطمینان از خوانش دقیق ضروری باشد. اطمینان حاصل کنید که اتصالات سیم کشی با تخصیص پین در کد مطابقت دارند.

تست ربات

هنگامی که اجزای سخت افزاری را مونتاژ کردید، فرستنده و گیرنده آردوینو را به لپ تاپ خود متصل کرده و کد ارائه شده را آپلود کنید. پس از آن، شتاب‌سنج MPU6050 را برای تأثیرگذاری بر حرکات ماشین ربات تنظیم کنید.

کد

//Arduino Code for gesture controlled robot

#include <SPI.h>        //SPI library for communicate with the nRF24L01+

#include "RF24.h"       //The main library of the nRF24L01+

#include "Wire.h"       //For communicate

#include "I2Cdev.h"     //For communicate with MPU6050

#include "MPU6050.h"    //The main library of the MPU6050


//Define the object to access and cotrol the Gyro and Accelerometer (We don't use the Gyro data)

MPU6050 mpu;

int16_t ax, ay, az;

int16_t gx, gy, gz;

//Define packet for the direction (X axis and Y axis)

int data[2];

//Define object from RF24 library - 8 and 9 are a digital pin numbers to which signals CE and CSN are connected.

RF24 radio(8,9);

//Create a pipe addresses for the communicate                                    

const uint64_t pipe = 0xE8E8F0F0E1LL;

void setup(void){

  Serial.begin(9600);

  Wire.begin();

  mpu.initialize();              //Initialize the MPU object

  radio.begin();                 //Start the nRF24 communicate     

  radio.openWritingPipe(pipe);   //Sets the address of the receiver to which the program will send data.

}

void loop(void){

  

  //With this function, the acceleration and gyro values of the axes are taken. 

  //If you want to control the car axis differently, you can change the axis name in the map command.

  mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

  //In two-way control, the X axis (data [0]) of the MPU6050 allows the robot to move forward and backward. 

  //Y axis (data [1]) allows the robot to right and left turn.

  data[0] = map(ax, -17000, 17000, 300, 400 ); //Send X axis data

  data[1] = map(ay, -17000, 17000, 100, 200);  //Send Y axis data

  radio.write(data, sizeof(data));

  Serial.print("X axix data = ");

  Serial.println(data[0]);

  Serial.print("Y axix data = ");

  Serial.println(data[1]);

}