ایجاد یک پهپاد دنبال کننده بر اساس آردوینو
نکته: این مقاله توسط تست نشده است.
در این بخش از مقالات برنامه نویسی آردوینو برای پهپاد، به قطعات زیر نیاز داریم:
- موتورها
- باتری
- ملخ ها
- کنترل کننده رادیویی(Radio-controller یا رادیو کنترل)
- بورد آردوینو نانو(Nano)
- ماژول بلوتوث HC-05
- جی پی اس(GPS)
- ژیروسکوپ MPU6050 یا GY-86
- مقداری سیم
نکته: قطعه MPU6050 یک ماژول ژیروسکوپ و شتاب سنج است:


اتصالات ساده، و به صورت زیر هستند:
1. ما نیاز داریم موتورها را به ESC ها متصل کنیم و ESC ها را هم به باتری متصل کنیم. می توانیم از یک بورد توزیع برق چهارتایی، مانند تصویر زیر استفاده کنیم:

2. اکنون، رادیو را به Arduino Nano با استفاده از تنظیمات پین های زیر متصل کنید:
(پین آردوینو، سمت چپ و پین رادیو، سمت راست)

3. اکنون ژیروسکوپ را به آردوینو نانو با استفاده از تنظیمات زیر، متصل کنید:
(سمت چپ، پین آردوینو و سمت راست، پین ژیروسکوپ)

4. چهار سیم برای سیگنال ESC باقی مانده است. اجازه دهید آنها را به آردوینو نانو، با استفاده از تنظیمات زیر متصل کنیم:

اتصالات ما تقریباً کامل شده است. اکنون نیاز داریم تا برق را به آردوینو نانو و ESCها متصل کنیم. قبل از انجام این کار، باید بدانید که مشترک کردن زمین به معنای اتصال هر دو سیم به زمین است. قبل از اینکه جلوتر برویم، نیاز داریم تا کدها را در مغز پهپاد خود، یعنی در آردوینو نانو آپلود کنیم. این کدها کمی طولانی هستند. پس از اینکه کتابخانه های ضروری را نصب کردیم، به توضیح این کدها خواهیم پرداخت.
نکته: کدهای این بخش به صورت آزمایشی هستند و فعلاً فقط به صورت تئوری از آنها استفاده می شود و به صورت عملی نمی توانیم در پهپادها استفاده کنیم.
قبل از اینکه شروع به برنامه نویسی کنیم، نیاز داریم تا یک کتابخانه(library) را در پوشه ی کتابخانه آردوینو نصب کنیم. نام این کتابخانه PinChangeInt است. این کتابخانه را همان طور که در فصل 3 در مقاله ی اتصال ماژول ESP8266 به آردوینو مشاهده کرده اید نصب کنید. اکنون نیاز داریم تا کدهایی را برای پهپاد خود بنویسیم. برای دانلود کدهای کامل، اینجا کلیک کنید. یا به این لینک مراجعه کنید. فایل PinChangeInt نیز در همین فایل قرار دارد. اجازه دهید کمی این کدها را توضیح دهیم. در این کدها، تعداد زیادی تابع به همراه برخی محاسبات وجود دارند.
ما برای ژیروسکوپ خود، نیاز داریم تا موارد زیر را تعریف کنیم:
- محورها
- داده های سنسور
- تنظیم پین ها
- داده های همگام سازی دما(temperature synchronization)
- داده های I2C
- و غیره
در تابع زیر، ما دو ساختار(struct) را برای داده های شتاب سنج و ژیروسکوپ مشخص کرده ایم:
typedef union accel_t_gyro_union
{
struct
{
uint8_t x_accel_h;
uint8_t x_accel_l;
uint8_t y_accel_h;
uint8_t y_accel_l;
uint8_t z_accel_h;
uint8_t z_accel_l;
uint8_t t_h;
uint8_t t_l;
uint8_t x_gyro_h;
uint8_t x_gyro_l;
uint8_t y_gyro_h;
uint8_t y_gyro_l;
uint8_t z_gyro_h;
uint8_t z_gyro_l;
} reg;
struct
{
int x_accel;
int y_accel;
int z_accel;
int temperature;
int x_gyro;
int y_gyro;
int z_gyro;
} value;
};
در تابع void setup() در کدهای زیر، پین هایی که به موتورها وصل می شوند را تعریف می کنیم:
myservoT.attach(7); //7-TOP
myservoR.attach(8); //8-Right
myservoB.attach(9); //9 - BACK
myservoL.attach(10); //10 LEFT
در کدها، توابع test_gyr_acc() و test_radio_reciev() را فراخوانی کرده ایم تا به ترتیب، ژیروسکوپ و داده های دریافتی را از راه دور تست کنیم. در تابع test_gyr_acc() بررسی کرده ایم که آیا سنسور ژیروسکوپ ما تشخیص داده می شود یا نه و اگر یک خطا در دریافت داده های ژیروسکوپ وجود دارد آنگاه پین شماره 13 را به high تنظیم کنیم تا یک سیگنال را دریافت کنیم.
void test_gyr_acc()
{
error = MPU6050_read (MPU6050_WHO_AM_I, &c, 1);
if (error != 0)
{
while (true)
{
digitalWrite(13, HIGH);
delay(300);
digitalWrite(13, LOW);
delay(300);
}
}
}
پس از اینکه تست ژیروسکوپ تمام شد و متصل شد، نیاز داریم آن را کالیبره سازی کنیم. برای انجام این کار، نیاز داریم تا از ریاضیات کمک بگیریم. ما نیاز داریم تا هردو متغیرهای rad_tilt_TB و rad_tilt_LR را در 2.4 ضرب کنیم و آنها را به ترتیب با x_a و y_a جمع کنیم. سپس ما نیاز داریم محاسبات بیشتری انجام دهیم تا مقادیر صحیح x_adder و y_adder را به دست آوریم:
void stabilize()
{
P_x = (x_a + rad_tilt_LR) * 2.4;
P_y = (y_a + rad_tilt_TB) * 2.4;
I_x = I_x + (x_a + rad_tilt_LR) * dt_ * 3.7;
I_y = I_y + (y_a + rad_tilt_TB) * dt_ * 3.7;
D_x = x_vel * 0.7;
D_y = y_vel * 0.7;
P_z = (z_ang + wanted_z_ang) * 2.0;
I_z = I_z + (z_ang + wanted_z_ang) * dt_ * 0.8;
D_z = z_vel * 0.3;
if (P_z > 160)
{
P_z = 160;
}
if (P_z < -160)
{
P_z = -160;
}
if (I_x > 30)
{
I_x = 30;
}
if (I_x < -30)
{
I_x = -30;
}
if (I_y > 30)
{
I_y = 30;
}
if (I_y < -30)
{
I_y = -30;
}
if (I_z > 30)
{
I_z = 30;
}
if (I_z < -30)
{
I_z = -30;
}
x_adder = P_x + I_x + D_x;
y_adder = P_y + I_y + D_y;
}
سپس بررسی کرده ایم که ESCهای ما به درستی به تابع escRead() متصل شده باشند. همچنین توابع elevatorRead() و aileronRead() را برای پیکربندی بالَک بالا برنده(elevator) و آیلرون(aileron) در پهپاد، فراخوانی کرده ایم. ما تابع test_radio_reciev() را برای تست کردن رادیویی که متصل کرده ایم، فراخوانی کرده ایم که بررسی کند که آیا کار می کند یا نه. سپس تابع check_radio_signal() را فراخوانی کرده ایم تا بررسی کند که آیا سیگنال مورد نظر کار می کند یا نه. ما تمام توابع بیان شده را از تابع void loop() در کدهای آردوینوی خود فراخوانی می کنیم. در تابع void loop() ما همچنین نیاز داریم تا توزیع برق سیستم را پیکربندی کنیم.
مانند کدهای زیر، ما یک شرط را اضافه کرده ایم:
if(main_power > 750)
{
stabilize();
} else
{
zero_on_zero_throttle();
}
ما همچنین در کدهای بالا، یک کران یا مرز را تعریف می کنیم. اگر main_power بزرگتر از 750 (که یک مقدار ثابت برای برنامه ی ما است) باشد، آنگاه ما سیستم را تثبیت می کنیم یا تابع zero_on_zero_throttle() را فراخوانی می کنیم؛ که تمام مقادیر برای تمام جهت ها را مقدار دهی اولیه(initializes) می کند. پس از آپلود کردن کدها، می توانیم پهپاد خود را با ارسال سیگنال هایی از ریموت کنترل، کنترل کنیم.
اکنون ما پهپاد را به یک پهپاد دنبال کننده(Follow Me) تبدیل می کنیم؛ برای این کار نیاز داریم تا یک ماژول بلوتوث یا GPS را به آن متصل کنیم. ما می توانیم گوشی هوشمند خود را با استفاده از یک ماژول بلوتوث(ترجیحاً HC-05) یا یک ماژول بلوتوث دیگر به پهپاد متصل کنیم. و البته برای اینکه پهپاد ما را دنبال کند، به GPS نیاز داریم. بنابراین اجازه دهید آنها را به پهپاد خود متصل کنیم. برای متصل کردن ماژول بلوتوث، تنظیمات و پیکربندی های زیر را اعمال کنید:

برای شفاف سازی کار، به تصویر زیر توجه کنید:

برای تنظیم GPS، آن را مانند تنظیمات زیر تنظیم و متصل کنید:


برای شفاف سازی کار، به تصویر زیر توجه کنید:

نکته: چونکه تمام سنسورها، از برق 5 ولت تغذیه می کنند، توصیه می کنیم که از یک منبع تعذیه ی 5 ولت برای ارتباطات بهتر، به خصوص برای GPS استفاده کنید.
اگر از ماژول بلوتوث استفاده کنیم، نیاز داریم تا ماژول پهپاد را بعنوان ماژول برده(slave) تنظیم کنیم و ماژول دیگری را بعنوان ماژول ارباب(master) مشخص کنیم. برای انجام این کار، می توانید یک تابع pin mode را برای ماژول ارباب(master) تنظیم کنید و آنگاه نرخ انتقال(baud rate) را به حداقل 38400 تنظیم کنید. این مقدار، مینیمم نرخ انتقال، برای ماژول بلوتوث است. سپس نیاز داریم تا بررسی کنیم که آیا یکی از این ماژول ها می تواند با ماژول دیگری ارتباط برقرار کند یا نه. برای این کار، می توانیم تابع void loop() خود را به صورت زیر بنویسیم:
if(Serial.available() > 0)
{
state = Serial.read();
}
if (state == '0')
{
digitalWrite(Pin, LOW);
state = 0;
}
else if (state == '1')
{
digitalWrite(Pin, HIGH);
state = 0;
}
و برای ماژول دیگری، برعکس عمل کنید و آن را به یک آردوینوی دیگر متصل کنید. به یاد داشته باشید که ما تنها نیاز داریم تا سیگنال ها را ارسال یا دریافت کنیم، بنابراین دیگر خدمات ماژول بلوتوث، را نادیده بگیرید. اگر از GPS استفاده کنیم، نیاز داریم تا قطب نما را آماده سازی کنیم و آن را قادر سازیم تا با یک ماژول GPS دیگر نیز ارتباط برقرار کند. ما نیاز داریم برای قرائت مقدار long از I2C به صورت زیر عمل کنیم:
float readLongFromI2C()
{
unsigned long tmp = 0;
for (int i = 0; i < 4; i++)
{
unsigned long tmp2 = Wire.read();
tmp |= tmp2 << (i*8);
}
return tmp;
}
float readFloatFromI2C()
{
float f = 0;
byte* p = (byte*)&f;
for (int i = 0; i < 4; i++)
p[i] = Wire.read();
return f;
}
سپس، ما باید فاصله ی geo را مانند کدهای زیر دریافت کنیم. در کدهای زیر DEGTORAD یک متغیر است که درجه را به رادیان تبدیل می کند:
float geoDistance(struct geoloc &a, struct geoloc &b)
{
const float R = 6371000; // Earth radius
float p1 = a.lat * DEGTORAD;
float p2 = b.lat * DEGTORAD;
float dp = (b.lat-a.lat) * DEGTORAD;
float dl = (b.lon-a.lon) * DEGTORAD;
float x = sin(dp/2) * sin(dp/2) + cos(p1) * cos(p2)
* sin(dl/2) * sin(dl/2);
float y = 2 * atan2(sqrt(x), sqrt(1-x));
return R * y;
}
ما همچنین نیاز داریم تا برای برینگ جغرافیایی(Geo bearing) یک تابع بنویسیم، به طوری که lat و lon به ترتیب همان عرض جغرافیایی(latitude) و طول جغرافیایی(longitude) هستند، که از داده های خام به دست آمده از سنسور GPS استفاده می کنند:
float geoBearing(struct geoloc &a, struct geoloc &b)
{
float y = sin(b.lon-a.lon) * cos(b.lat);
float x = cos(a.lat)*sin(b.lat) - sin(a.lat)*cos(b.lat)*cos(b.lon-a.lon);
return atan2(y, x) * RADTODEG;
}
ما همچنین می توانیم از یک اپلیکیشن موبایل برای ارتباط با GPS استفاده کنیم که باعث شود پهپاد به دنبال ما حرکت کند. بقیه کارها ساده هستند. GPS را به پهپاد متصل کنید و داده های TX و RX را از آردوینو دریافت کنید و آن را از طریق رادیو(radio) مخابره کنید و آن را از راه دور دریافت کنید. و سپس از GPS در گوشی خود با اپلیکیشن های DroidPlanner یا Tower استفاده کنید. ما همچنین نیاز داریم تا در کدهای اصلی، برای آماده سازی قطب نما، چند خط کد را اضافه کنیم.
ما می توانیم کدهای کالیبره سازی قبل را مشاهده کنیم. کالیبره سازی قطب نما، از یک مکان تا مکان دیگر متفاوت است. بنابراین ما به شما توصیه می کنیم که از روش آزمون و خطا استفاده کنید. در بخش های بعدی، توضیح می دهیم که چگونه می توانیم از ESP8266 برای ایجاد یک ردیاب GPS برای پهپاد خود استفاده کنیم.
- بازدید: 951
1. سعی کنید نظرات شما مرتبط با مقاله ی مورد نظر باشد، در غیر این صورت پاسخ داده نخواهد شد.
2. سوالات خود را به صورت کوتاه بیان کنید و از پرسیدن چند سوال به طور همزمان خودداری کنید.
3. سوال خود را به طور واضح بیان کنید و از کلمات مبهم استفاده نکنید.