به نام خالق عزم و اختیار : در قسمت قبلی ( آموزش ساخت کوادکوپتر با رزبری پای قسمت 1 )، یه موتور براشلس رو با درایورش راه انداختیم و کد زاویه سنجی با MPU6050 رو گذاشتیم؛ در این مطلب، ابتدا یه اصلاحیه داریم برای راه اندازی موتور، و در ادامه، به دو مبحث پردازش موازی در رزبری پای و دریافت کلید از صفحه کلید در رزبری پای می پردازیم ( آموزش ساخت کوادکوپتر با رزبری پای قسمت 2 )
آموزش ساخت کوادکوپتر با رزبری پای قسمت 2
اصلاحیه از این قراره که ما اومدیم چهار تا موتور کوادکوپتر رو به چهار تا پایه pwm رزبری پای وصل کردیم، و موتور ها رو روشن کردیم ولی متاسفانه موتورها حین کار ریپ می زدن!!! از یه کتابخونه دیگه استفاده کردیم، حتی زبون برنامه نویسی رو عوض کردیم ( پایتون ) و حتی pwm نرم افزاری ساختیم ولی باز هم موتورها ریپ میزد این ریپ زدن، باعث ناپایداری کواد می شد؛ محیط کاری ما به این شکل بود :
نتیجه اش ( فاجعه ) رو در ویدئو زیر مشاهده می کنید : http://www.aparat.com/v/ijwNU
به همین دلیل، مجبور شدیم برای کنترل موتورها از یه ATmega32 استفاده کنیم؛ این میکرو کنترلر دارای 4 واحد pwm می باشد که ما از هر چهار تاش استفاده می کنیم.
موضوع دیگه ای که متوجه شدیم، این بود که درایور موتور براشلس به دو صورت راه اندازی میشود :
- فرکانس ثابت : فرکانس ثابته؛ برای تغییر سرعت، دیوتی سایکل رو تغییر می دیم ( از این به بعد، از این استفاده می کنیم )
- دیوتی سایکل ثابت : دیوتی سایکل ثابته؛ برای تغییر سرعت، باید فرکانس رو تغییر بدیم ( این مورد در قسمت اول بررسی شد )
یک نکته اساسی دیگه، برای اینکه از خالی شدن باتری حین پرواز (یعنی سقوط کواد) جلو گیری بشه،از ADC میکرو هم استفاده می کنیم تا وقتی باتری از یه حدی کمتر شد، اخطار بده یا اتوماتیک خودش بشینه رو زمین ( رزبری پای، adc داخلی نداره !!! )
ساخت سیگنال برای تست درایور و موتور براشلس رو با میکروکنترلر درکد ویزارد ببینید : http://www.aparat.com/v/mPTK6
این هم کد تست موتور براشلس با میکروکنترلر atmega32 که در ویدئو بالا شبیه سازی شد.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
#include <mega32a.h> #include <delay.h> unsigned int i=0; void main(void) { DDRA=(0<<DDA7) | (0<<DDA6) | (0<<DDA5) | (0<<DDA4) | (0<<DDA3) | (0<<DDA2) | (0<<DDA1) | (0<<DDA0); PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0); DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0); PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0); DDRC=(0<<DDC7) | (0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (0<<DDC2) | (0<<DDC1) | (0<<DDC0); PORTC=(0<<PORTC7) | (0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (1<<PORTC3) | (1<<PORTC2) | (1<<PORTC1) | (1<<PORTC0); DDRD=(0<<DDD7) | (0<<DDD6) | (1<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0); PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0); // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 11059/200 kHz // Mode: Fast PWM top=ICR1 // OC1A output: Non-Inverted PWM // OC1B output: Disconnected // Noise Canceler: Off // Input Capture on Falling Edge // Timer Period: 2 ms // Output Pulse(s): // OC1A Period: 2 ms Width: 0 us // Timer1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=(1<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (1<<WGM11) | (0<<WGM10); TCCR1B=(0<<ICNC1) | (0<<ICES1) | (1<<WGM13) | (1<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10); TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x56; ICR1L=0x65; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; while(1) { if( PINC.0 == 0 ) { delay_ms(50); while(PINC.0==0){} i+=10; } if( PINC.1 == 0 ) { delay_ms(50); while(PINC.1==0){} i-=10; } if( PINC.2 == 0 ) { delay_ms(50); while(PINC.2==0){} i+=100; } if( PINC.3 == 0 ) { delay_ms(50); while(PINC.3==0){} i-=100; } if( i > 22117 ) { i=22117; OCR1A=i; } } |
بریم سر اصل مطلب؛ ابتدا تشخیص کلید های صفحه کلید؛ برای این کار چند روش پیدا کردم که بهینه ترینش استفاده از کتابخونه gtk است، برای نصب این کتابخونه، دستورات زیر رو در ترمینال وارد کنید :
1 2 3 4 5 |
sudo apt-get update sudo apt-get install libgtk-3-dev LIBS=’pkg-config –libs gtk+-3.0’ CFLAGS=’pkg-config –cflags gtk+-3.0’ sudo apt-get install c++ |
سپس برنامه زیر رو بنویسید و کامپایل کنید :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
//g++ key.cpp -o key `pkg-config --libs --cflags gtk+-3.0` #include <gtk/gtk.h> #include <gdk/gdkkeysyms.h> #include <iostream> using namespace std; static gboolean key_event(GtkWidget *widget,GdkEventKey *event) { cout << gdk_keyval_name (event->keyval)<<endl; return FALSE; } int main( int argc,char *argv[] ) { GtkWidget *window; gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_signal_connect(G_OBJECT(window), "key-press-event", G_CALLBACK(key_event), NULL); gtk_widget_show (window); gtk_main (); return 0; } |
نتیجه رو در ویدئو زیر مشاهده فرمایید : http://www.aparat.com/v/eRVB1
پردازش موازی در رزبری پای
بخش بعدی، پردازش موازی؛ پردازش موازی چیست؟ و به چه دردی میخوره؟
پردازش موازی، یعنی اینکه چند تابع مختلف رو به صورت همزمان اجرا کنیم؛ وقتی بخوایم چند تا کار مختلف رو به صورت همزمان توسط یک CPU ( یک یا چند هسته ای ) انجام بدیم، از پردازش موازی استفاده می کنیم؛ مثلا تابعی شامل یک حلقه بی نهایت، برای دریافت کلید از صفحه کلید و یک تابع دیگر برای دریافت تصویر از دوربین،ویک تابع دیگر برای زاویه سنجی و دیگری،برای کنترل موتورها…که وقتی تابع صفحه کلید،منتظر فشرده شدن کلید است،بقیه توابع،بدون مشکل به کار خودشون ادامه می دن و کواد،سقوط نمیکنه!!!
برای نصب کتابخونه pthread ( همون کتابخونه برای پردازش موازی ) در ترمینال تایپ کنید :
1 2 |
sudo apt-get update sudo apt-get install libpthread-stubs0-dev |
یه مثال کوچیک از پردازش موازی به زبان ++C با رزبری پای :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
//g++ thread.cpp -o thread -lpthread -lwiringPi #include <stdio.h> #include <stdlib.h> #include <iostream> #include <pthread.h> #include"wiringPi.h" using namespace std; void *thread0(void *l0) { while(1) { cout<<"0"<<endl; delay(0.5); } } void *thread1(void *l1) { while(1) { cout<<"1"<<endl; delay(0.5); } } void *thread2(void *l2) { while(1) { cout<<"2"<<endl; delay(0.5); } } void *thread3(void *l3) { while(1) { cout<<"3"<<endl; delay(0.5); } } void *thread4(void *l4) { while(1) { cout<<"4"<<endl; delay(0.5); } } int main() { delay(10000); pthread_t a0,a1,a2,a3,a4; pthread_create(&a0,NULL,thread0,NULL); pthread_create(&a1,NULL,thread1,NULL); pthread_create(&a2,NULL,thread2,NULL); pthread_create(&a3,NULL,thread3,NULL); pthread_create(&a4,NULL,thread4,NULL); while(1) { cout<<"main"<<endl; delay(0.5); } pthread_join(a0,NULL); pthread_join(a1,NULL); pthread_join(a2,NULL); pthread_join(a3,NULL); pthread_join(a4,NULL); return 0; } |
نتیجه کد بالا رو در ویدئو زیر ببینید : http://www.aparat.com/v/6ef9n
برای کوادکوپتر، ما برنامه زاویه سنجی رو تو یکی از این پردازش ها، و مشاهده دوربین رو تو یکی دیگه و دریافت کلید کنترلی رو هم تو یکی دیگه انجام می دیم.
به امید خدا، در قسمت بعدی، ارتباط ( سریال ) بین میکرو و رزبری رو راه می ندازیم و برنامه موتور ها رو کامل می کنیم؛ احتمالا به همراه مدار پی سی بی شامل میکرو و متعلقاتش…
جا داره تشکر ویژه ای از آقای ملا اسماعیلی به جا بیارم به خاطر کمک و وقتی که گذاشتن و بنده رو یاری کردن.
جهت هرچه مستحکم تر شدن مقام ولایت فقیه و تعجیل در ظهور بابای خوبمون مهدی عج صلوات
مهمان
سلام.چه جوری میشه توی اون بخش gtk بگیم که مثلا اگه فلان کلید روی کیبرد خورد تو فلان کارو بکن؟

یعنی مثلا اگه کلید O خورد پایه 17 یک شه.
نویسنده این مطلب
سلام
در تابع key_event
بایید if بنویسید
تو شرط if هم باید از تابع
gdk_keyval_name
استفاده کنید.
مهمان
در ضمن وقتی کد LIBS=’pkg-config –libs gtk+-3.0’ رو میزنم این -bash: –libs: command not found
ارورو میده.چرا؟
نویسنده این مطلب
سلام.
قبل از دستور
Sudo apt-get update
دستور زیر رو وارد کنید
Sudo apt-get upgrade
********
اگر نشد،یه عکس بعد از وارد کردن دستورات،از ترمینال آپلود کنید.
مهمان
سلام اون کدی رو که مال کتابخونه gtk است رو میشه تشریحش کنین.متوجه نمیشم توش چه اتفاقاتی افتاده
نویسنده این مطلب
سلام
خط ۱ تا ۶:فراخوانی کتابخونه ها وباز کردن فضای نام و تعریف متغیر .
خط ۷ تا ۱۱،تعریف تابع برای تشخیص و چاپ کلید فشرده شده.
خط ۱۲:شروع تابع اصلی با دو آرگومان(آرگومان های مربوط به فشردن کلید)
خط ۱۴:ساختن یک اشاره گر که به شی پنجره اشاره می کند.
خط ۱۵:تنظیمات اولیه توابع تشخیص کلید.
خط ۱۶:ساخت پنجره برای دریافت کلید
خط ۱۷:اتصال سیگنال کلید به پنجره.
خط ۱۸:نمایش پنجره.
خط ۱۹:فراخوانی تابع کار با کلیدها(درونش حلقه بینهایت استفاده شده)
یه پنجره می سازه و آرگومانهای تابع main رو بهش می دیم.
با فشردن کلید،تابع key_event