اطلاعیه

Collapse
No announcement yet.

[آموزش] ساخت فلایت کنترل توسط جایروسکوپ

Collapse
این موضوع برجسته شده است.
X
X
 
  • فیلتر
  • زمان
  • Show
Clear All
new posts

    [آموزش] ساخت فلایت کنترل توسط جایروسکوپ

    سلام
    تو این تایپ قراره یک فلایت کنترل بسازیم با استفاده از یک اردینو پرو مینی و یک سنسور imu6050
    نکته : اساس کار این فلایت کنترل سرعت زاویه است و قابلیت auto leveling نداره
    برای ساخت واجرای پروژه باید چند تا کار انجام داد
    سیگنال ورودی از رادیو کنترل رو بخونیم
    سرعت زاویه ای از هر محور رو بخونیم
    بتونیم سیگنال رو به اسپید کنترل اعمال کنیم و سرعت موتور ها رو تغییر بدیم
    نکته: این فلایت کنترل رو برای یک کوادروتور از X میسازیم (البته بعدا میتونید برای هر نوع مولتی روتور ارتقاش بدید
    برای شروع میرم سراغ خوندن سیگنال pwm از رادیو


    دلیل: ادغام دو پست برای جلوگیری از اسپم

    در ضمن این نکته رو بگم : دوستان پیش نیاز این اموزش اینه که اولا بدونید کواد چیه ؟
    اجزای تشکیل دهنده و کار هر کدوم از اجرا؟
    نحوه حرکت کواد و ...
    خلاصه اطلاعات کافی درباره کواد داشته باشید که سوال های متفرقه پیش نیاد
    ایشالا اگه دوستان استقبال کنن ادامه میدیم
    آدلان پایا متخصص در حوضه ربات های پرنده
    https://adlanpaya.ir/

    #2
    پاسخ : ساخت مدیریتگر پرواز توسط جایروسکوپ

    بِسْمِ اللَّـهِ الرَّحْمَـٰنِ الرَّحِیمِ
    با سلام و درود
    با تشکر فراوان از آغازگر این موضوع.

    ربات پرنده:

    کاربران عزیزی که با مبحث ربات های پرنده و مدیریتگرهای پرواز آشنایی ندارند می توانند با مطالعه ی این مجموعه از مقالات در این زمینه ها اطلاعاتی را کسب نمایند:

    1- ربات های پرنده | رباتیکال

    2- کوادکوپتر Archives - الکترونیک

    3- کوادروتور بایگانی - آموزش ساده رباتیک



    آردوینو:

    1- آموزش مقدماتی آردوینو: http://www.eca.ir/forums/thread59899.html

    2- آموزش برنامه نویسی آردوینو


    برخی مبانی فیزیکی که باید بدانید:

    1- شتاب زاویه ای

    2- سرعت زاویه ای

    3- ژیروسکوپ

    4- شتاب سنج

    (جهت داشتن اطلاعات بهتر، بیشتر تحقیق کنید)


    مدیریتگر پرواز و نقش شتابِ خطی سنج و سرعتِ زاویه ای سنج در آن:

    کار اصلی مدیرتگر پرواز (flight controller) این است که مانع برهم خوردن تعادل ربات شود.
    شما فرض کنید که ربات خود را به پرواز در آورده اید و ناگهان باد می وزد و اگر ربات شما دارای مدیرتگر پرواز نباشد در چنین شرایطی سقوط خواهد کرد. البته دقت داشته باشید که بدون مدیرتگر پرواز حتی کوچکترین اختلافی در سرعت چرخش موتورها و یا تفاوت وزن در بدنه ربات باعث سقوط ربات می شود و یا اصلاً امکان پرواز فراهم نمی گردد و همان ابتدای کار ملخ ها به زمین برخورد می کنند.

    یکی دیگر از کارهای مدیرتگر پرواز ترکیب و پردازش اطلاعات 4 اهرم حرکتی است که از فرستنده ارسال می شود یعنی:
    1- اهرم گاز که برای بالا و پایین آمدن ربات استفاده می شود.(throttle)
    2- اهرم ساعتگرد و پادساعتگرد(به طور خلاصه سا پاد سا نامیده می شود) که برای چرخاندن سر ربات در جهت عقربه های ساعت و یا خلاف آن استفاده می شود که به نام (سُکّان) هم شناخته می شود.(در ربات پرنده yaw و در هواپیما rudder)
    3- اهرم جلو و عقب رفتن ربات(به طور خلاصه ج.ع نامیده می شود).(در ربات پرنده pitch و در هواپیما elevator)
    4- اهرم راست و چپ رفتن ربات(به طور خلاصه ر.چ نامیده می شود).(در ربات پرنده roll و در هواپیما aileron)

    شما فرض کنید که در فرستنده اهرم ج.ع را به طور کامل بالا گرفته ایم تا ربات به سمت جلو حرکت کند ولی بادی شدید از سمت مخالف ربات می وزد و اجازه کج شدن ربات به سمت جلو را نمی دهد، در اینجا مدیرتگر پرواز وارد عمل شده و با بیشتر کردن سرعت موتور یا موتورهای عقب ربات و با کاهش سرعت موتور یا موتورهای جلوی ربات باعث می شود.
    خب چیزی که باعث می شود مدیرتگر پرواز بفهمد که ربات به هر دلیلی نتوانسته به سمت جلو حرکت کند همان چیزی است که ما می خواهیم با MPU6050 آن را مورد بررسی قرار دهیم یعنی شتابِ خطی سنج(accelerometer) و سرعتِ زاویه ای سنج(gyroscope).

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

    در حسگر MPU6050 در کل 6 محور استفاده شده است که 3 تا برای سنجش سرعتِ زاویه ای و 3 تا برای سنجش شتابِ خطی است و هر کدام از این محورها دارای مقدار مثبت و مقدار منفی اند.
    مثلاً اگر MPU6050 در حالت ساکن باشد ولی ناگهان به سمت بالا صعود کند مقدار محور خطی Z مثبت می شود و اگر از حالت مثلا از حالت ساکن ناگهان به سمت پایین سقوط کند محور خطی Z منفی می شود.





    (تصویر 1: محورهای قابل تشخیص توسط حسگر MPU6050)

    توضیحاتی پیرامون وسایل:

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

    1- تخته مدار آزمایشی: برای بستن مدارها به صورت آزمایشی کاربرد دارد. (bread board)

    2- حسگر MPU6050

    3- آردوینو pro mini: این آردوینو دارای یک عدد میکروکنترلر ATmega328 است و ما به عنوان هسته پردازشی مدیرتگر پرواز از آن استفاده می کنیم. این آردوینو برخلاف برخی آردوینو ها مثل Uno دارای مبدل USB به Serial نمی باشد و ما باید از ی مبدل جداگانه استفاده کنیم.

    4- مبدل USB به Serial نوع CH340G: بنده از این مبدل برای ریختن برنامه ها از نرم افزار آردوینو بر روی آردوینو pro mini استفاده می کنم. شما می توانید از مبدل های به Serial دیگری نیز استفاده نمایید ولی دقت داشته باشید که مبدل باید پایه باز نشانی یا همان Reset که گاهی به نام RST و یا DTR نوشته می شود را داشته باشد زیرا برای ریختن برنامه در آردوینو این پایه لازم است.

    5- یک عدد گیرنده فرامین(radio control) که خروجی PWM داشته باشد و یا مدار جایگزین آن.ما خروجی این وسیله را می خواهیم به ورودی آردوینو دهیم تا پس از این کار، مقادیری که از گیرنده و حسگر MPU6050 رسیده است در آردوینو ترکیب شود.


    (تصویر 2: برخی وسایل مورد استفاده بنده)


    خروجی گیرنده های فرامین(radio control) چه چیزی است؟
    (منظور از فرامین همان فرامین حرکتی است که از فرستنده به سمت گیرنده ارسال می شود و radio control هم نامیده می شود.)

    انواع گیرنده ها وجود دارد که به روش هایی مثل SBUS و یا PPM و یا PWM و... خروجی می دهند و ما در این طرح با PWM کار داریم که بر مبنای تغییر پهنای Pulse یا همان موج مربعی استوار است.

    جهت آشنایی با روش PPM می توانید این مطلب را مطالعه کنید: http://www.eca.ir/forums/thread70819.html

    حالا ممکن است شما فرستنده و گیرنده نداشته باشید که بخواهید از PWM خروجی گیرنده استفاده کنید. باید دقت داشته باشید Pulse خروجی گیرنده دقیقاً مشخصات همان Pulse دارد که برای حرکت دادن موتور فرمان یار(servo) استفاده می شود پس اگر شما یک مداری بسازید که توانایی حرکت دادن موتور فرمان یار را داشته باشد، می توان از همان مدار به عنوان جایگزین گیرنده استفاده کرد.

    این هم مشخصات آن Pulse که به آن نیاز داریم و برای راه اندازی موتور فرمان یار(servo) و موتور بدون جاروبک(brush less) استفاده می شود و خروجی گیرنده هم همین هست:
    باید میزان تناوب(Frequency) 50 هرتز باشد.
    برای اینکه موتور در حداقل مقدار باشد باید زمان 1 بودن Pulse داده شده به موتور 1 میلی ثانیه باشد و زمان 0 بودن باید 19 میلی ثانیه باشد.
    برای اینکه موتور در حداکثر مقدار باشد باید زمان 1 بودن Pulse داده شده به موتور 2 میلی ثانیه باشد و زمان 0 بودن باید 18 میلی ثانیه باشد.


    با توجه به اینکه گفته شد خروجی گیرنده و مداراتی که برای حرکت دادن موتور فرمان یار استفاده می شود یکسان است شما با استفاده از این موارد می توانید اقدام به ساخت وسیله ای کنید که خروجی اش مشابه گیرنده است:

    آموزش کامل و پروژه سرو موتور با آردوینو

    Control the position of a RC (hobby) servo motor with your Arduino and a potentiometer

    البته گیرنده مورد نیاز حداقل 4 کاناله باید باشد و اگر اقدام به ساخت مدار جایگزین گیرنده کردید دقت داشته باشید که دارای 4 خروجی PWM باشد.



    در مطالبی که نوشتم اگر اشتباهی وجود داشت اطلاع دهید.
    جدیدترین ویرایش توسط فکر; ۱۲:۵۸ ۱۳۹۵/۱۲/۲۴.

    دیدگاه


      #3
      پاسخ : ساخت فلایت کنترل توسط جایروسکوپ (آموزش)

      بسیار عالی دوست عززمون زحمت کشیدن و به طور مفسل پیش نیاز ها رو مطر کردن حالا وقت شروع کردنه
      اولین مرحله خوندن سیگنال pwm توسط اردینو هست
      قبل هر چیزی به یاید داشته باشید که تو برنامه نویسی یه فلایت کنترل سرعت پردازش خیلی مهمه پس از دستوراتی استفاده کنید که سرعت اجرای بالا و دقت کافی داشته باشند تا در حلقه اجرایی برنامه وقفه ای ایجاد نشه
      راه های زیادی برای خوندن pwm هست برای مثال
      سه راه خوندن pwm تو این مطلب مطرح شده:


      خوب کدوم راه رو انتخاب کنیم؟
      آدلان پایا متخصص در حوضه ربات های پرنده
      https://adlanpaya.ir/

      دیدگاه


        #4
        پاسخ : ساخت فلایت کنترل توسط جایروسکوپ (آموزش)

        مناسب ترین راه برای خوندن pwm تبدیل اون به سطح دیسی و اندازه گیری اون با adc هست
        برای تبدیل از یه فیلتر پایین گذر و یه آپ امپ میشه بهره برد

        دیدگاه


          #5
          پاسخ : ساخت فلایت کنترل توسط جایروسکوپ (آموزش)

          نوشته اصلی توسط اشکان غفارزاده نمایش پست ها
          مناسب ترین راه برای خوندن pwm تبدیل اون به سطح دیسی و اندازه گیری اون با adc هست
          برای تبدیل از یه فیلتر پایین گذر و یه آپ امپ میشه بهره برد
          دوست عزیز این مطلبی رو که میگید من امتحان نکردم و باید تست بشه
          خوب برای خوندن سیگنال از کد زیر استفاده میکنیم
          کد:
          //Declaring Variables
          byte last_channel_1, last_channel_2, last_channel_3, last_channel_4;
          int receiver_input_channel_1, receiver_input_channel_2, receiver_input_channel_3, receiver_input_channel_4;
          unsigned long timer_1, timer_2, timer_3, timer_4;
          
          //Setup routine
          void setup(){
            //Arduino (Atmega) pins default to inputs, so they don't need to be explicitly declared as inputs
            PCICR |= (1 << PCIE0);    // set PCIE0 to enable PCMSK0 scan
            PCMSK0 |= (1 << PCINT0);  // set PCINT0 (digital input 8) to trigger an interrupt on state change
            PCMSK0 |= (1 << PCINT1);  // set PCINT1 (digital input 9)to trigger an interrupt on state change
            PCMSK0 |= (1 << PCINT2);  // set PCINT2 (digital input 10)to trigger an interrupt on state change
            PCMSK0 |= (1 << PCINT3);  // set PCINT3 (digital input 11)to trigger an interrupt on state change
            Serial.begin(115200); 
          }
          
          //Main program loop
          void loop(){
            //delay(250);
            print_signals();
          }
          
          //This routine is called every time input 8, 9, 10 or 11 changed state
          ISR(PCINT0_vect){
            //Channel 1=========================================
            if(last_channel_1 == 0 && PINB & B00000001 ){         //Input 8 changed from 0 to 1
              last_channel_1 = 1;                                 //Remember current input state
              timer_1 = micros();                                 //Set timer_1 to micros()
            }
            else if(last_channel_1 == 1 && !(PINB & B00000001)){  //Input 8 changed from 1 to 0
              last_channel_1 = 0;                                 //Remember current input state
              receiver_input_channel_1 = micros() - timer_1;      //Channel 1 is micros() - timer_1
            }
            //Channel 2=========================================
            if(last_channel_2 == 0 && PINB & B00000010 ){         //Input 9 changed from 0 to 1
              last_channel_2 = 1;                                 //Remember current input state
              timer_2 = micros();                                 //Set timer_2 to micros()
            }
            else if(last_channel_2 == 1 && !(PINB & B00000010)){  //Input 9 changed from 1 to 0
              last_channel_2 = 0;                                 //Remember current input state
              receiver_input_channel_2 = micros() - timer_2;      //Channel 2 is micros() - timer_2
            }
            //Channel 3=========================================
            if(last_channel_3 == 0 && PINB & B00000100 ){         //Input 10 changed from 0 to 1
              last_channel_3 = 1;                                 //Remember current input state
              timer_3 = micros();                                 //Set timer_3 to micros()
            }
            else if(last_channel_3 == 1 && !(PINB & B00000100)){  //Input 10 changed from 1 to 0
              last_channel_3 = 0;                                 //Remember current input state
              receiver_input_channel_3 = micros() - timer_3;      //Channel 3 is micros() - timer_3
            }
            //Channel 4=========================================
            if(last_channel_4 == 0 && PINB & B00001000 ){         //Input 11 changed from 0 to 1
              last_channel_4 = 1;                                 //Remember current input state
              timer_4 = micros();                                 //Set timer_4 to micros()
            }
            else if(last_channel_4 == 1 && !(PINB & B00001000)){  //Input 11 changed from 1 to 0
              last_channel_4 = 0;                                 //Remember current input state
              receiver_input_channel_4 = micros() - timer_4;      //Channel 4 is micros() - timer_4
            }
          }
          //Subroutine for displaying the receiver signals
          void print_signals(){
            Serial.print("Roll:");
            if(receiver_input_channel_1 - 1480 < 0)Serial.print("<<<");
            else if(receiver_input_channel_1 - 1520 > 0)Serial.print(">>>");
            else Serial.print("-+-");
            Serial.print(receiver_input_channel_1);
            
            Serial.print("  Nick:");
            if(receiver_input_channel_2 - 1480 < 0)Serial.print("^^^");
            else if(receiver_input_channel_2 - 1520 > 0)Serial.print("vvv");
            else Serial.print("-+-");
            Serial.print(receiver_input_channel_2);
            
            Serial.print("  Gas:");
            if(receiver_input_channel_3 - 1480 < 0)Serial.print("vvv");
            else if(receiver_input_channel_3 - 1520 > 0)Serial.print("^^^");
            else Serial.print("-+-");
            Serial.print(receiver_input_channel_3);
            
            Serial.print("  Yaw:");
            if(receiver_input_channel_4 - 1480 < 0)Serial.print("<<<");
            else if(receiver_input_channel_4 - 1520 > 0)Serial.print(">>>");
            else Serial.print("-+-");
            Serial.println(receiver_input_channel_4);
          }
          اینم لینک دانلود کد:
          پرشین گیگ، ارائه دهنده انواع خدمات هاستینگ و میزبانی فایل و خرید سرور مجازی برای اولین بار در ایران به صورت ابری، با کیفیت عالی و قیمت مناسب
          جدیدترین ویرایش توسط avr68; ۱۶:۱۰ ۱۳۹۵/۰۳/۱۷.
          آدلان پایا متخصص در حوضه ربات های پرنده
          https://adlanpaya.ir/

          دیدگاه


            #6
            پاسخ : ساخت فلایت کنترل توسط جایروسکوپ (آموزش)

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

            دیدگاه


              #7
              پاسخ : ساخت فلایت کنترل توسط جایروسکوپ (آموزش)



              خوب اینم شماتیک مدار هستش تو یه اردینو یه ال ای دی و یه imu6050( به جای ماژول l3g4200d) داره
              جدیدترین ویرایش توسط avr68; ۱۶:۱۱ ۱۳۹۵/۰۳/۱۷.
              آدلان پایا متخصص در حوضه ربات های پرنده
              https://adlanpaya.ir/

              دیدگاه


                #8
                پاسخ : ساخت فلایت کنترل توسط جایروسکوپ (آموزش)

                نوشته اصلی توسط اشکان غفارزاده نمایش پست ها
                مناسب ترین راه برای خوندن pwm تبدیل اون به سطح دیسی و اندازه گیری اون با adc هست
                برای تبدیل از یه فیلتر پایین گذر و یه آپ امپ میشه بهره برد
                نکته بسیار خوبی مطرح کردید جناب غفار زاده... میشه بیشتر توضیح بدید در این مورد

                دیدگاه


                  #9
                  پاسخ : ساخت فلایت کنترل توسط جایروسکوپ (آموزش)

                  نوشته اصلی توسط murcheh نمایش پست ها
                  نکته بسیار خوبی مطرح کردید جناب غفار زاده... میشه بیشتر توضیح بدید در این مورد
                  میدونیم که با تغییر دیوتی سایکل موجpwm ، سطح دیسی سیگنال تغییر میکنه
                  با گذاشتن یک فیلتر پایین گذر میشه سطح دیسی رو از سیگنال جدا کرد
                  مقدار دیسی موج که میشه معادل دیوتی سایکل رو با adc به سادگی اندازه گیری میکنیم

                  دیدگاه


                    #10
                    پاسخ : ساخت فلایت کنترل توسط جایروسکوپ (آموزش)

                    خوببببببببب
                    تا این جای کار که هیشکی استقبال نکرده ولی ادامه میدم
                    تا اینجا سخت افزار فلایت کنترل و شماتیک اون طراحی شده و در اختیار شماس شما میتونید به هر نحوی که مایلید اون رو منتاژ کنید
                    از طرفی ما تونستیم سیگنال های 4 کانال رادیو کنترل یعنی
                    roll - pitch - thr - yaw
                    رو بخونیم.یعنی دستور های ارسالی از راهبر کوادکوپر رو روی فلایت کنترل داریم
                    حالا نوبت به اطلاعات خود ربات میرسه ما برای این که ربات رو متعادل نگه داریم از یک جاروسکوپ سه محور استفاده میکنیم که سرعت راویه ای سه محور رو به ما میده
                    خوب ما تو این پروژه از یک imu6050 استفاده کردیم
                    برای راه اندازی اون از کد زیر استفاده میکنیم
                    البته کد زیر هم اطلاعات جایروسکوپ 3 محور هم شتاب سنج 3 محور هم هم زاویه 2 محور pitch و roll رو نمایش میده


                    کد:
                    #include <Wire.h>
                    
                    //Declaring some global variables
                    int gyro_x, gyro_y, gyro_z;
                    long acc_x, acc_y, acc_z, acc_total_vector;
                    int temperature;
                    long gyro_x_cal, gyro_y_cal, gyro_z_cal;
                    float angle_pitch, angle_roll;
                    int angle_pitch_buffer, angle_roll_buffer;
                    boolean set_gyro_angles;
                    float angle_roll_acc, angle_pitch_acc;
                    double angle_pitch_output, angle_roll_output;
                    
                    
                    
                    
                    
                    void setup() {
                      Wire.begin();                                                        //Start I2C as master
                      Wire.setClock(400000L);
                      pinMode(13, OUTPUT);                                                 //Set output 13 (LED) as output
                      setup_mpu_6050_registers();                                          //Setup the registers of the MPU-6050 (500dfs / +/-8g) and start the gyro
                      digitalWrite(13, HIGH);                                              //Set digital output 13 high to indicate startup                       
                      for (int cal_int = 0; cal_int < 2000 ; cal_int ++){                  //Run this code 2000 times
                        read_mpu_6050_data();                                              //Read the raw acc and gyro data from the MPU-6050
                        gyro_x_cal += gyro_x;                                              //Add the gyro x-axis offset to the gyro_x_cal variable
                        gyro_y_cal += gyro_y;                                              //Add the gyro y-axis offset to the gyro_y_cal variable
                        gyro_z_cal += gyro_z;                                              //Add the gyro z-axis offset to the gyro_z_cal variable
                        delay(3);                                                          //Delay 3us to simulate the 250Hz program loop
                      }
                      gyro_x_cal /= 2000;                                                  //Divide the gyro_x_cal variable by 2000 to get the avarage offset
                      gyro_y_cal /= 2000;                                                  //Divide the gyro_y_cal variable by 2000 to get the avarage offset
                      gyro_z_cal /= 2000;                                                  //Divide the gyro_z_cal variable by 2000 to get the avarage offset
                      digitalWrite(13, LOW);                                               //All done, turn the LED off
                      Serial.begin(115200);
                    
                    }
                    
                    void loop(){
                      
                      read_mpu_6050_data();                                                //Read the raw acc and gyro data from the MPU-6050
                      gyro_x -= gyro_x_cal;                                                //Subtract the offset calibration value from the raw gyro_x value
                      gyro_y -= gyro_y_cal;                                                //Subtract the offset calibration value from the raw gyro_y value
                      gyro_z -= gyro_z_cal;                                                //Subtract the offset calibration value from the raw gyro_z value
                      //Gyro angle calculations
                      //0.0000611 = 1 / (250Hz / 65.5)
                      angle_pitch += gyro_x * 0.0000611;                                   //Calculate the traveled pitch angle and add this to the angle_pitch variable
                      angle_roll += gyro_y * 0.0000611;                                    //Calculate the traveled roll angle and add this to the angle_roll variable
                      //0.000001066 = 0.0000611 * (3.142(PI) / 180degr) The Arduino sin function is in radians
                      angle_pitch += angle_roll * sin(gyro_z * 0.000001066);               //If the IMU has yawed transfer the roll angle to the pitch angel
                      angle_roll -= angle_pitch * sin(gyro_z * 0.000001066);               //If the IMU has yawed transfer the pitch angle to the roll angel
                      //Accelerometer angle calculations
                      acc_total_vector = sqrt((acc_x*acc_x)+(acc_y*acc_y)+(acc_z*acc_z));  //Calculate the total accelerometer vector
                      //57.296 = 1 / (3.142 / 180) The Arduino asin function is in radians
                      angle_pitch_acc = asin((float)acc_y/acc_total_vector)* 57.296;       //Calculate the pitch angle
                      angle_roll_acc = asin((float)acc_x/acc_total_vector)* -57.296;       //Calculate the roll angle
                      //Place the MPU-6050 spirit level and note the values in the following two lines for calibration
                      angle_pitch_acc -= 0.0;                                              //Accelerometer calibration value for pitch
                      angle_roll_acc -= 0.0;                                               //Accelerometer calibration value for roll
                      if(set_gyro_angles){                                                 //If the IMU is already started
                        angle_pitch = angle_pitch * 0.9996 + angle_pitch_acc * 0.0004;     //Correct the drift of the gyro pitch angle with the accelerometer pitch angle
                        angle_roll = angle_roll * 0.9996 + angle_roll_acc * 0.0004;        //Correct the drift of the gyro roll angle with the accelerometer roll angle
                      }else{                                                                //At first start
                        angle_pitch = angle_pitch_acc;                                     //Set the gyro pitch angle equal to the accelerometer pitch angle 
                        angle_roll = angle_roll_acc;                                       //Set the gyro roll angle equal to the accelerometer roll angle 
                        set_gyro_angles = true;                                            //Set the IMU started flag
                      }
                      //To dampen the pitch and roll angles a complementary filter is used
                      angle_pitch_output = angle_pitch_output * 0.9 + angle_pitch * 0.1;   //Take 90% of the output pitch value and add 10% of the raw pitch value
                      angle_roll_output = angle_roll_output * 0.9 + angle_roll * 0.1;      //Take 90% of the output roll value and add 10% of the raw roll value
                      
                      Serial.print(gyro_x);
                      Serial.print("\t");
                      Serial.print(gyro_y);
                      Serial.print("\t");
                      Serial.print(gyro_z);
                      Serial.print("\t");
                    
                      Serial.print(acc_x);
                      Serial.print("\t");
                      Serial.print(acc_y);
                      Serial.print("\t");
                      Serial.print(acc_z);
                      Serial.print("\t");
                    
                      Serial.print(angle_pitch_output);
                      Serial.print("\t");
                      Serial.println(angle_roll_output);
                    }
                    
                    
                    void read_mpu_6050_data(){                                             //Subroutine for reading the raw gyro and accelerometer data
                      Wire.beginTransmission(0x68);                                        //Start communicating with the MPU-6050
                      Wire.write(0x3B);                                                    //Send the requested starting register
                      Wire.endTransmission();                                              //End the transmission
                      Wire.requestFrom(0x68,14);                                           //Request 14 bytes from the MPU-6050
                      while(Wire.available() < 14);                                        //Wait until all the bytes are received
                      acc_x = Wire.read()<<8|Wire.read();                                  //Add the low and high byte to the acc_x variable
                      acc_y = Wire.read()<<8|Wire.read();                                  //Add the low and high byte to the acc_y variable
                      acc_z = Wire.read()<<8|Wire.read();                                  //Add the low and high byte to the acc_z variable
                      temperature = Wire.read()<<8|Wire.read();                            //Add the low and high byte to the temperature variable
                      gyro_x = Wire.read()<<8|Wire.read();                                 //Add the low and high byte to the gyro_x variable
                      gyro_y = Wire.read()<<8|Wire.read();                                 //Add the low and high byte to the gyro_y variable
                      gyro_z = Wire.read()<<8|Wire.read();                                 //Add the low and high byte to the gyro_z variable
                    
                    }
                    
                    
                    void setup_mpu_6050_registers(){
                      //Activate the MPU-6050
                      Wire.beginTransmission(0x68);                                        //Start communicating with the MPU-6050
                      Wire.write(0x6B);                                                    //Send the requested starting register
                      Wire.write(0x00);                                                    //Set the requested starting register
                      Wire.endTransmission();                                              //End the transmission
                      //Configure the accelerometer (+/-8g)
                      Wire.beginTransmission(0x68);                                        //Start communicating with the MPU-6050
                      Wire.write(0x1C);                                                    //Send the requested starting register
                      Wire.write(0x10);                                                    //Set the requested starting register
                      Wire.endTransmission();                                              //End the transmission
                      //Configure the gyro (500dps full scale)
                      Wire.beginTransmission(0x68);                                        //Start communicating with the MPU-6050
                      Wire.write(0x1B);                                                    //Send the requested starting register
                      Wire.write(0x08);                                                    //Set the requested starting register
                      Wire.endTransmission();                                              //End the transmission
                    }

                    توجه:برای راه اندازی این سنسور از کتاب خانه ی خاصی استفاده نشده و راه اندازی ان با توجه به دیتاشیت ماژول بوده
                    لینک دانلود برنامه:
                    پرشین گیگ، ارائه دهنده انواع خدمات هاستینگ و میزبانی فایل و خرید سرور مجازی برای اولین بار در ایران به صورت ابری، با کیفیت عالی و قیمت مناسب
                    آدلان پایا متخصص در حوضه ربات های پرنده
                    https://adlanpaya.ir/

                    دیدگاه


                      #11
                      پاسخ : ساخت فلایت کنترل توسط جایروسکوپ (آموزش)

                      با سلام و درود
                      بسیار بسیار از زحمات ارزشمند avr68 ممنونم.
                      نحوه اتصال پایه های آردوینو به مبدل برای ریختن برنامه در آردوینو:

                      نحوه اتصال پایه های مبدل USB به Serial نوع CH340G برای ریختن برنامه در آردوینو:
                      CH340G ---------- Arduino Pro mini
                      DTR ---------------------------- DTR
                      RXD ---------------------------- TXD
                      TXD
                      ---------------------------- RXD
                      VC ----------------------------- VCC
                      GND ---------------------------- GND

                      کار پایه DTR این است که در پایان مراحل ریختن برنامه، میکروکنترلر را بازنشانی(reset) می کند.


                      (تصویر 3: نحوه اتصال پایه های CH340G به آردوینو Pro mini)


                      خواندن چرخه ی کاری نبض با آردوینو:

                      بنده برای خواندن میزان چرخه کاری(duty cycle) نبض(Pulse) ورودی به آردوینو از این برنامه استفاده کردم:

                      /*
                      بسم الله الرحمن الرحیم

                      برنامه خواندن چرخه کاری نبض با آردوینو
                      */

                      double khandan;

                      void setup() {
                      pinMode(2, INPUT);
                      Serial.begin(9600);
                      }

                      void loop() {
                      khandan = pulseIn(2, HIGH);
                      Serial.println(khandan);
                      }




                      توضیح این برنامه:
                      1-

                      double khandan;

                      تعریف یک متغیر از نوع double و با نام khandan

                      توضیح بیشتر در مورد double :
                      Open-source electronic prototyping platform enabling users to create interactive electronic objects.


                      2-

                      pinMode(2, INPUT);

                      تعریف پایه شماره 2 آردوینو به عنوان ورودی

                      3-

                      Serial.begin(9600);

                      تعریف نرخ تبادل بیت با رایانه در هر ثانیه
                      توضیح بیشتر:
                      The Arduino programming language Reference, organized into Functions, Variable and Constant, and Structure keywords.

                      و


                      4-

                      khandan = pulseIn(2, HIGH);

                      فعال کردن پایه شماره 2 برای خواندن مقادیر

                      5-

                      Serial.println(khandan);

                      نمایش مقادیر متغیری که khandan نام داشت


                      دیدن مقادیر با استفاده از نمایشگر Serial در نرم افزار آردوینو:

                      برای دیدن مقادیر خوانده شده از بخش Serial Monitor نرم افزار آردوینو استفاده می شود.
                      برای اجرای نمایشگر Serial دکمه ذره بین که در سمت بالا راست نرم افزار آردوینو قرار دارد را انتخاب می کنیم.
                      اگر دیدیم که متون و اشکال نامفهومی ظاهر شد باید میزان نرخ در ثانیه(baud rate) را مثل همان چیزی که در برنامه نویسی نوشته بودیم، انتخاب کنیم.

                      (تصویر 4: نحوه اجرای نمایشگر Serial در نرم افزار آردوینو)


                      (تصویر 5: نحوه تنظیم نرخ در ثانیه(baud rate) در نمایشگر Serial در نرم افزار آردوینو)


                      ایجاد نبض با آردوینو:

                      بنده برای ایجاد نبض(Pulse) از این برنامه استفاده کردم:
                      /*
                      Controlling a servo position using a potentiometer (variable resistor)
                      by Michal Rinott

                      modified on 8 Nov 2013
                      by Scott Fitzgerald
                      http://www.arduino.cc/en/Tutorial/Knob
                      */

                      #include <Servo.h>

                      Servo myservo;

                      int potpin = 0;
                      int val;

                      void setup() {
                      myservo.attach(9);
                      }

                      void loop() {
                      val = analogRead(potpin);
                      val = map(val, 0, 1023, 47, 142);
                      myservo.write(val);
                      }



                      توضیح این برنامه:

                      1-
                      #include <Servo.h>


                      کتابخانه Servo که جزء کتابخانه های پیش فرض است فراخوانی می شود.

                      2-
                      Servo myservo;


                      ایجاد یک شیء از نوع Servo و با نام myservo

                      3-
                      int potpin = 0;


                      تعریف یک متغیر از نوع int و با نام potpin و تعیین پایه A0 آردوینو به عنوان پایه مورد استفاده این متغیر

                      4-
                      int val;


                      تعریف یک متغیر از نوع int و با نام val

                      5-
                        myservo.attach(9);


                      تعریف پایه شماره 9 آردوینو به عنوان خروجی متغیر myservo

                      6-
                        val = analogRead(potpin);


                      خواندن مقدار رسیده به متغیر potpin و ریختن آن در متغیر val

                      7-
                        val = map(val, 0, 1023, 47, 142);


                      نسبت گرفتن از مقادیر موجود در متغیر val با استفاده از دستور ()map


                      توجه: در برنامه اصلی این دستور به این شکل بود:
                        val = map(val, 0, 1023, 0, 180);


                      بنده اعداد 0 و 180 را به 47 و 142 تغییر دادم.
                      زیرا اعداد 0 و 180 باعث می شود که چرخه کاری(duty cycle) نبض(Pulse) از مقدار 1 میلی ثانیه(معادل 1000 میکروثانیه) کم تر و از 2 میلی ثانیه(معادل 2000 میکروثانیه) بیشتر شود در صورتی که ما نیاز به نبضی با چرخه کاری بین 1 تا 2 میلی ثانیه داریم.

                      همچنین دقت داشته باشید که مقاومت های متغیر دارای مقداری خطا هستند و مناسب ترین اعداد برای مقاومت متغیری که بنده دارم اعداد اعداد 47 و 142 است.
                      و ممکن است شما نیاز باشد برای مقاومت متغیر خود این مقادیر را تغییر دهید. برای اینکه ببینید آیا این مقادیر برای مقاومت متغیر شما مناسب است و یا نه می توانید از نمایشگر Serial نرم افزار آردوینو استفاده کنید. به این صورت که ابتدا مقدار مقاومت متغیر را به حداقل برسانید و ببینید آیا اعداد موحود در نمایشگر Serial از 1000 کمتر می شود و یا نه. اگر کمتر از 1000 بود شما باید عدد 47 را زیاد کنید. اگر بیشتر از 1000 بود و فاصله قابل توجه ای داشت شما باید عدد 47 را کم کنید تا مقدار به 1000 نزدیک شود. دقیقاً لازم نیست مقدار 1000 باشد، همین که به این عدد نزدیک شود کافی است.

                      برای عدد 142 نیز همین کار را انجام دهید و آن قدر عدد را تغییر دهید که مقدار به 2000 نزدیک شود ولی از 2000 بیشتر نشود.

                      توجه: مقاومت متغیر استفاده شده 10 کیلو اهمی است.

                      8-
                        myservo.write(val);


                      ریختن مقادیر نسبت گرفته شده از متغیر val در متغیر myservo که به پایه شماره 9 آردوینو وصل است.


                      این برنامه جزء مثال های کتابخانه ی servo در نرم افزار آردوینو است. توضیحات بیشتر: https://www.arduino.cc/en/Tutorial/Knob

                      بنده دستور زیر را که در آخر برنامه قرار داشت را حذف کردم.

                      delay(15);



                      یکی از دستورات ریاضی که در آردوینو وجود دارد، دستور ()map است که کارش گرفتن نسبت از اعداد است.
                      به مثال زیر توجه کنید:

                      /* Map an analog value to 8 bits (0 to 255) */
                      void setup() {}

                      void loop()
                      {
                      int val = analogRead(0);
                      val = map(val, 0, 1023, 0, 255);
                      analogWrite(9, val);
                      }




                      در این برنامه ابتدا یک مقدار آنالوگ(اگر میکروکنترلر با 5 ولت تغذیه شود مقدار آنالوگ برابر با ولتاژی بین 0 تا 5 ولت است) از پایه A0 آردوینو خوانده می شود.
                      سپس متغیر val که درون آن مقدار آنالوگ خوانده شده موجود است در ابتدای دستور map قرار می گیرد و اعداد 0 تا 1023 که مقدار دیجیتال همان مقدار آنالوگ اند نیز به عنوان بازه عددی متغیر val معرفی می شود.(یعنی اینکه اگر به پایه A0 آردوینو 0 ولت رسید عدد دیجیتال 0 است و اگر 5 ولت رسید عدد دیجیتال 1023 است).

                      سپس تعیین می شود که بازه خروجی اعدادی بین 0 تا 255 باشد یعنی اینکه اگر مقدار متغیر val عدد 0 بود در خروجی نیز 0 داریم و اگر مقدار متغیر val عدد 1023 در خروجی 255 داریم.
                      بقیه اعداد نیز به همین صورت نسبت گرفته می شود مثلاً اگر مقدار متغیر val عدد 512 بود در خروجی عددی حدود 127 خواهیم داشت.

                      دستور ;analogWrite(9, val) باعث ایجاد یک ولتاژ آنالوگ در پایه شماره 9 می شود.

                      توضیح بیشتر: https://www.arduino.cc/en/Reference/Map
                      جدیدترین ویرایش توسط فکر; ۰۲:۲۲ ۱۳۹۵/۱۲/۰۳.

                      دیدگاه


                        #12
                        پاسخ : ساخت فلایت کنترل توسط جایروسکوپ (آموزش)

                        با سلام و خسته نباشید و ممنون از همکاریتون
                        نکته رو لازمه که بکم شما برای خوندن سیگنال دارید از دستوری که استفاده میکنید که سرعت اون پاینه و در حلقه برنامه ایجاد وقفه میکنه و موجب کند شدن میشه
                        کد:
                        khandan = pulseIn(2, HIGH);
                        حال فرض کنیده قرار باشه 4 کانال رو با همین دستور بخونید سرعت فوالعاده کاهش پیدا میکنه
                        آدلان پایا متخصص در حوضه ربات های پرنده
                        https://adlanpaya.ir/

                        دیدگاه


                          #13
                          پاسخ : ساخت فلایت کنترل توسط جایروسکوپ (آموزش)

                          با عرض سلام و خسته نباشید. من با توجه به شماتیک ، سخت افزار رو طراحی کردم و نوبت به برنامه نویسی رسیده. اگه می شه لینک دانلود برنامه ی فلایت کنترل رو سرجمع و کامل بذارین. با تشکر
                          جدیدترین ویرایش توسط فکر; ۱۷:۴۴ ۱۳۹۵/۰۳/۱۹. دلیل: کاهش تعداد شکلک ها

                          دیدگاه


                            #14
                            پاسخ : ساخت فلایت کنترل توسط جایروسکوپ (آموزش)

                            نوشته اصلی توسط ho3ein rc نمایش پست ها
                            با عرض سلام و خسته نباشید. من با توجه به شماتیک ، سخت افزار رو طراحی کردم و نوبت به برنامه نویسی رسیده. اگه می شه لینک دانلود برنامه ی فلایت کنترل رو سرجمع و کامل بذارین. با تشکر
                            با سلام و درود
                            قرار دادن یکباره برنامه ها بدون تحلیل و بررسی شدن قدم به قدم باعث کاهش بار علمی موضوع می گردد.
                            اگر قصد تحلیل قدم به قدم ندارید می توانید از طرح های متن باز مثل Multiwii استفاده نمایید که هم نقشه و هم برنامه هایش به طور کامل در فضای مجازی موجود است.

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

                            پایگاه مجازی Multiwii :
                            MultiWii project related stuffs


                            انجمن Multiwii:


                            مطالب آموزشی Multiwii:

                            دیدگاه


                              #15
                              پاسخ : ساخت فلایت کنترل توسط جایروسکوپ (آموزش)

                              نوشته اصلی توسط avr68 نمایش پست ها


                              خوب اینم شماتیک مدار هستش تو یه اردینو یه ال ای دی و یه imu6050( به جای ماژول l3g4200d) داره
                              با سلام و درود
                              سوال:
                              1- دلیل استفاده از مقاومت R2 و R3 چیست؟ با تغییر مقدار این مقاومت ها چه اتفاقی می افتد؟
                              2- در حالت عادی برای کار با آردوینو نیازی به اعمال ولتاژ به پایه VIN نیست. چرا در این نقشه به این پایه ولتاژ اعمال شده است؟
                              3- چرا از بین مقاومت R2 و R3 یک سیم به پایه A0 وصل شده است؟
                              4- حروف RF و RR و LR و LF که جلوی هر کدام از ESC ها نوشته شده اند، مخفف چه کلماتی اند؟


                              باید دقت داشته باشیم که ESC مخفف سه کلمه Electronic speed controller است و این ها در واقع راه انداز های موتورهای بدون جاروبک(brush less) هستند.




                              نوشته اصلی توسط avr68 نمایش پست ها
                              با سلام و خسته نباشید و ممنون از همکاریتون
                              نکته رو لازمه که بکم شما برای خوندن سیگنال دارید از دستوری که استفاده میکنید که سرعت اون پاینه و در حلقه برنامه ایجاد وقفه میکنه و موجب کند شدن میشه
                              کد:
                              khandan = pulseIn(2, HIGH);
                              حال فرض کنیده قرار باشه 4 کانال رو با همین دستور بخونید سرعت فوالعاده کاهش پیدا میکنه

                              بسیار بسیار از شما ممنونم.
                              برنامه اولی که قرار داده بودید با استفاده از interrupt مقادیر ورودی نبض(Pulse) را می خواند و بهینه تر بود.
                              برنامه اول: http://www.eca.ir/forums/thread71896.html#post620574

                              در برنامه دومی که قرار دادید متوجه نشدم کدام بخش مربوط به خواندن مقادیر نبض ورودی به آردوینو از طرف گیرنده است. لطفاٌ آن بخش را مشخص کنید.
                              برنامه دوم:http://www.eca.ir/forums/thread71896.html#post620799

                              دیدگاه

                              لطفا صبر کنید...
                              X