اطلاعیه

Collapse
No announcement yet.

ایجاد زمان های دقیق و مستقل و اندازه گیری پالس با AVR

Collapse
X
 
  • فیلتر
  • زمان
  • Show
Clear All
new posts

    #16
    پاسخ : ایجاد زمان های دقیق و مستقل با یک تایمر در AVR

    داش دیگه قضیه ناموسی شد!! دست گذاشتی رو رگ غیرتم !! :mrgreen:
    ایندفعه به یه نتایجی رسیدم! فقط اومدم بگم جواب رو نگو تا من برنامه رو با توضیحاتش بنویسم. یکم وقت میخوام (نامردم اگه حلش نکنم! :angry
    https://www.linkedin.com/in/mohammadhosseini69

    http://zakhar.blog.ir

    دیدگاه


      #17
      پاسخ : ایجاد زمان های دقیق و مستقل با یک تایم&#1585

      سلام! با دست پر اومدم!
      یه ظهر تا عصر وقتم گرفته شد تا این جواب نسبتا کامل رو بگیرم. کارهایی که کردم رو توضیح میدم. با این که خیلی خسته ام، ولی سعی میکنم کم نذارم...

      mega64 ، چهار تا تایمر داره. تایمر 1 و 2 به ترتیب با خروجی OC0 و OC2، تایمر 1و3 شامل خروجی های OC1A ، OC1B ، OC1C ، OC3A ، OC3B ، OC3C . بدلیل مشترک بودن پین های OC2 و OC1C ، تایمر 2 رو کنار میذاریم. می خوایم 7 تا فرکانس رو این پایه ها با 3 تایمر 0 و 1 و 3 ایجاد کنیم.
      تایمر صفر که یه خروجی بیشتر نداره و خیلی راحت در مد CTC میتونیم فرکانس مورد نظر رو تولید کنیم. با توجه به فرمول OCR=(Fclk/2.N.Fout)-1 مقدار OCR بدست میاد. تایمر میشمره تا به مقدار OCR برسه. در این لحظه پورت toggle و مقدار تایمر هم صفر میشه.
      میمونه تایمرهای 1 و 3 هر کدوم با سه خروجی OCR. اگه بخوایم اینا رو هم در مد CTC راه اندازی کنیم، فقط میتونیم از یک OCR هرکدوم (A) استفاده کنیم. مشکل مسئله همینجاست!

      راه حل :
      تایمر رو در مد Normal راه اندازی می کنیم. در این مد تایمر تا max (0xFFFF در تایمرهای 1 و 3 که 8بیتی هستن) میشمره. در مد Normal میتونیم هر سه compare match رو برای A و B و C استفاده کنیم. پس با همون فرمول قبلی OCRnA و OCRnB و OCRnC (منظور از n تایمر 1و 3 است) رو بدست میاریم. تعداد شمارش ها رو با توجه به فرکانس داریم. تایمر میشمره و به هر کدوم از OCR ها که رسید پین مورد نظر Toggle میشه. اما اینجا دیگه مثل CTC مقدار تایمر صفر نمیشه. بله ادامه میده...
      فرض کنید تایمر1 از صفر شروع کرده به شمارش و مثلا مقدار OCR1B از 2 تای دیگه کمتره. به OCR1B میرسه و پین toggle میشه و شمارش ادامه پیدا میکنه تا به max برسه، صفر بشه و دوباره مقدارش با OCR1B برابر بشه و toggle کنه. می دونیم که ما همچین چیزی رو نمی خوایم. تو مد CTC این اتفاق نمی افته. فکر میکنید الان چه فرکانسی دارین؟ اگه دقت کنین می بینین که باید تو فرمول فرکانس در مد CTC مقدار OCR رو 0xFFFF بذارین... (ببخشید اگه کشش میدم. می خوام خیالم راحت باشه که همه بفهمن...) ضمنا در این حالت duty cycle هم 50 درصد نیست.
      خوب تا اینجا میدونیم وقتی از صفر میشمره و تا OCR1B برسه، زمان و تعداد شمارش درسته. ما دوباره به همین زمان و تعداد شمارش برای toggle بعدی احتیاج داریم. وقفه Compare B match رو فعال میکنیم. در این وقفه عددی رو که برای OCR بدست آوردیم به خودش اضافه می کنیم. تا در ادامه دوباره همون تعداد شمارش انجام بشه و به Compare match برسه. فرض کنید به 50 شمارش احتیاج داریم. به OCR1B مقدار 50 میدیم. در اولین compare match ، مقدار OCR1B میشه 100، دفعه بعد میشه 150 و همینطور ادامه ادامه داره و toggle هم در هر compare match انجام میشه.
      من اینطور برنامه رو نوشتم و رو پروتیوس امتحان کردم :
      هرچند نباید به پروتیوس اعتماد کرد. اما... یه گراف دیجیتال برای نمایش شکل موج ها گذاشتم
      با کلاک 1 مگاهرتز شروع کردم. درکمال تعجب دیدم فقط 1 یا 2 تا از شکل موج ها نمایش داده شدن! طراح عزیز هم سوالی طرح کرده ها!! 7 تا موج با اختلاف تناوب 0.25 میکرو ثانیه!! مشخض بود که میکرو زورش نمیرسه و تو وقفه ها قاطی میکنه. تا بخواد یکی رو اجرا کنه بقیه می پرن! کلاک رو گذاشتم رو 8 مگاهرتز. 1-2 تا شکل موج دیگه هم اومد اما هنوز کامل نبودن! اینجا بود دیدم باید با winavr یه حرکت درست حسابی بزنم. به وقفه ها، ویژگی ISR_NOBLOCK رو اضافه کردم تا سد هم نشن. چندتا موج دیگه هم ظاهر شد اما هنوز...
      دیگه زدم به سیم آخر! کریستال 16 مگاهرتز گذاشتم تا تمام زور mega16 رو بکار بگیرم که این وقفه ها با هم درگیر نشن. بالاخره همه شکل موج ها اومدن. همونطور که تو شکل می بینید دوره تناوب OC3A ، زمان 50 میکرو ثانیه است. فایل پروتیوس رو گذاشتم میتونید دانلود کنین و بقیه حالت ها رو هم ببینید.
      فقط نمیدونم چرا وقتی فرکانس رو بردم بالا OC0 خراب شد! حتی مثل بقیه بردمش تو مد Normal اما درست نشد!
      (رو تصاویر کلیک کنید تا بزرگش رو ببینین)


      بله مسئله جدید اینه که آیا در عمل و در یه محیط صنعتی جواب میده؟! فرکانس 16 مگاهرتز !!! ما 12 میذاریم میکرو بکس و باد میکنه! چه برسه به 16 ! اونم همچین برنامه ای! واویلا!!
      خلاصه ممنون از جناب طراح! 1 روز مغزم رو بکارگرفتی!! خیلی چیزا یاد گرفتم ولی از کار و زندگی (بخور و بخواب) افتادم!
      دیگه وقتشه که اگه راه حل بهتری دارین بگین... اگرم راهش همین بود که فکر میکنم باید یه بار دیگه استاد طراح توضیح بدن! بنظر نمیاد خوب مطلب رو رسونده باشم!

      لینک دانلود فایل پروتیوس
      کد برنامه هم تو این پست جا نشد، پست بعد ...
      https://www.linkedin.com/in/mohammadhosseini69

      http://zakhar.blog.ir

      دیدگاه


        #18
        پاسخ : ایجاد زمان های دقیق و مستقل با یک تایم&#1585

        کد برنامه :

        #include <avr/io.h>
        #include <avr/interrupt.h>

        int T1A, T1B, T1C, T3A, T3B, T3C;

        ISR(TIMER1_COMPA_vect, ISR_NOBLOCK){OCR1A += T1A;}
        ISR(TIMER1_COMPB_vect, ISR_NOBLOCK){OCR1B += T1B;}
        ISR(TIMER1_COMPC_vect, ISR_NOBLOCK){OCR1C += T1C;}
        ISR(TIMER3_COMPA_vect, ISR_NOBLOCK){OCR3A += T3A;}
        ISR(TIMER3_COMPB_vect, ISR_NOBLOCK){OCR3B += T3B;}
        ISR(TIMER3_COMPC_vect, ISR_NOBLOCK){OCR3C += T3C;}

        #define Period_OC0 0.000049
        #define Period_OC1A 0.00004925
        #define Period_OC1B 0.00004950
        #define Period_OC1C 0.00004975
        #define Period_OC3A 0.000050
        #define Period_OC3B 0.00005025
        #define Period_OC3C 0.00005050

        int main()
        {
        DDRB = 0xf0;
        DDRE = 0b00111000;

        // Timer0 - CTC mode - Toggle OC0 on Compare Match - clk/(No prescaling)
        TCCR0 = 0b00011001;
        OCR0 = (F_CPU*Period_OC0/2)-1;
        TCNT0 = 0;

        // Timer1 - Normal mode - Toggle OCnA/OCnB/OCnC on Compare Match - clk/(No prescaling)
        // Output Compare A/B/C Match Interrupt Enabled
        TCCR1A = 0b01010100;
        TCCR1B = 0b00000001;
        //TIMSK |= 1<<OCIE1A;
        //TIMSK |= 1<<OCIE1B;
        //ETIMSK |= 1<<OCIE1C;
        T1A = (F_CPU*Period_OC1A/2)-1;
        T1B = (F_CPU*Period_OC1B/2)-1;
        T1C = (F_CPU*Period_OC1C/2)-1;
        OCR1A = T1A;
        OCR1B = T1B;
        OCR1C = T1C;
        TCNT1 = 0;

        // Timer3 - Normal mode - Toggle OCnA/OCnB/OCnC on Compare Match - clk/(No prescaling)
        // Output Compare A/B/C Match Interrupt Enabled
        TCCR3A = 0b01010100;
        TCCR3B = 0b00000001;
        //ETIMSK |= 1<<OCIE3A;
        //ETIMSK |= 1<<OCIE3B;
        //ETIMSK |= 1<<OCIE3C;
        T3A = (F_CPU*Period_OC3A/2)-1;
        T3B = (F_CPU*Period_OC3B/2)-1;
        T3C = (F_CPU*Period_OC3C/2)-1;
        OCR3A = T3A;
        OCR3B = T3B;
        OCR3C = T3C;
        TCNT3 = 0;

        TIMSK = 0x18;
        ETIMSK = 0x1B;
        sei();
        while(1){}
        return 0;
        }


        جا داره یادآوری کنم حتی یه پالس اضافه هم نداریم! کدی که تو وقفه ها اجرا میشه هیچ تاثیری رو شمارش تایمرها نداره و پالس های خروجی کاملا سخت افزاری تولید میشن

        راستی شماره حساب رو باید به کی بدم؟؟!
        https://www.linkedin.com/in/mohammadhosseini69

        http://zakhar.blog.ir

        دیدگاه


          #19
          پاسخ : ایجاد زمان های دقیق و مستقل با یک تایمر در AVR

          سلام.
          تبریک میگم، برنامه خوبی نوشتید . فقط یک Warning دارد:
          برنامه در کلاک پایین کارایی خود رو از دست میدهد که خودتان نیز به آن اشاره نمودید.
          از آنجا که روش سوال و جواب، که آقای طراح در این تاپیک به کار بردند لذت کار با میکرو و حل مساله را دو چندان میکند در ادامه روش ایشان این سوال را مطرح میکنم:
          برای حل این مشکل چه کار می توان کرد؟ (راه حل در مقایسه با مساله اصلی که حل شد بسیار ساده میباشد)

          It's your attitude, not your aptitude,that makes your altitude

          << اللهم عجل لولیک الفرج >>

          دیدگاه


            #20
            پاسخ : ایجاد زمان های دقیق و مستقل با یک تایمر در AVR

            آفرین برشما
            اصل جواب صورت مسئله در جمع کردن مقادیر OCR با یک مقدار ثابت در مد Normal تایمر است که شما موفق به پی بردن به این روش شدید.
            قبل از بحث راجع به جنبه های فنی قضیه و علیرغم اینکه اعلام شد که مسئله جایزه منتفی است، به دلیل پشتکار و روحیه جنگندگی شما که امروز در حکم کیمیا محسوب می شود، تصمیم گرفتم با هماهنگی با مدیریت سایت جایزه ای را به شما اختصاص دهم. اعلام چگونگی و سقف جایزه شما را به عهده مدیریت سایت می گذارم تا توسط ایشان اعلام شود.

            اما به لحاظ فنی چند مورد در راه حل شما قابل ذکر است:

            1-مقدار اولیه تایمرها بصورت Default صفر است و نیازی به صفر کردن آنها نیست.
            2- در برنامه باید TIMSK=0x1A باشد تا وقفه مقایسه TIMER0 فعال شود.
            3-راه اندازی تایمرها اصولا باید بعد از مقداردهی اولیه به کل تایمرها انجام شود. این امر شامل دستورات TCCR1B = 0b00000001 و TCCR3B = 0b00000001 می شود.
            4-یک تایمر 8 بیتی نمی تواند در کلاک 16 مگاهرتز زمان 24.5 میکروثانیه را که برای ساخت موجی با پریود 49 میکروثانیه لازم است، تولید کند. زیرا اگر در فرمول محاسبه کنید، مقدار OCR0 برابر 391 بدست می آید. در حالی که TIMER0و OCR0 دارای طول 8 بیت هستند وگنجایش این عدد را ندارند.
            5-اما مهمترین نکته بعد از اصل صورت مسئله این است که هر روتین وقفه در کامپایلر مورد استفاده بسته به نوع کامپایلر به میزانی متفاوت از سایر کامپایلرها زمان می برد و این یک مثال از کاربردهای Tme critical است که حرف اول و آخر را در آن برنامه نویسی اسمبلی می زند. چنانکه کمترین فاصله زمانی دو وقفه در این کاربرد برای 24.5 میکروثانیه به ازای کلاک 8 مگاهرتز برابر 196 سیکل است. شخصا حساب کردم که با یک برنامه نویسی اسمبلی بهینه می توان بدون ایجاد هیچ مشکلی از کلاک 8 مگاهرتز و حتی کمتر هم برای تولید این 7 شکل موج جواب گرفت و این در حالی است که سایر کامپایلرها ممکن است برای چنین کلاکی به اصطلاح به آخر خط برسند. بنابراین باید بدانیم که همیشه استفاده از BASCOM و Codevision و حتی در مواردی GCC یا IAR پاسخگو نیست و نمی توان به اوج قله AVR رسید مگر آنکه در جایی که لازم باشد قادر به نوشتن روتین های حساس برنامه با اسمبلی باشیم.
            در پایان باز هم به جناب محمد حسینی به دلیل زود خسته نشدن و توانمندی در برخورد و مواجهه با یک چالش علمی، تبریک می گویم و برای ایشان آرزوی موفقیت دارم.
            اوژن: به معنای افکننده و شکست دهنده است
            دانایی، توانایی است-Knowledge is POWER
            برای حرفه ای شدن در الکترونیک باید با آن زندگی کرد
            وضعمان بهتر می شود، اگر همه نسبت به جامعه و اطراف خود مسوول باشیم و نگوئیم به ما چه
            قوی شدن و خوب ماندن - خوبی کردن به دیگران یک لذت ماندگار است
            اگر قرار باشد نفت و منابع خام را بدهیم و چرخ بگیریم، بهتر است چرخ را از نو اختراع کنیم
            ساعت کار بدن اکثر انسان ها کمتر از 800000 ساعت است و بعد از آن از کار می افتد

            دیدگاه


              #21
              پاسخ : ایجاد زمان های دقیق و مستقل با یک تایمر در AVR

              این که گفتم شماره حساب و .... شوخی کردم! :mrgreen: به جناب طراح هم pm دادم که نیازی به جایزه نیست... ممنون از این همه لطفت طراح جون! (میترسم جایزه بگیرم طراح پا به فرار بذاره! )

              آقای طراح به نکات جالبی اشاره کردن. مخصوصا تایمر صفر...
              خیلی علاقه مند شدم بیشتر رو اسمبلی کار کنم! مسئله جالبی بود که حقایق زیادی رو روشن کرد. طراح با مطرح کردن این سوال زیرکانه دعوایی که سر کامپایلرها میشه رو به سمت دیگه ای کشوند... بهرحال بازم به این نتیجه میرسیم که gcc و winavr بهتره دیگه!

              سوال بعدی رو کی مطرح میکنید؟؟!
              https://www.linkedin.com/in/mohammadhosseini69

              http://zakhar.blog.ir

              دیدگاه


                #22
                پاسخ : ایجاد زمان های دقیق و مستقل با یک تایمر در AVR

                نوشته اصلی توسط محمد حسینی
                این که گفتم شماره حساب و .... شوخی کردم! :mrgreen: به جناب طراح هم pm دادم که نیازی به جایزه نیست... ممنون از این همه لطفت طراح جون! (میترسم جایزه بگیرم طراح پا به فرار بذاره! )

                سوال بعدی رو کی مطرح میکنید؟؟!
                جایزه شما بزودی اعلام خواهد شد.
                صورت مسئله بعدی می تواند برنامه ای باشد که بتواند کوچکترین عرض پالس ممکن را با یک کلاک مشخص(مثلا 16 مگاهرتز) اندازه بگیرد. به عبارت دیگر با چه روشی می توان کمترین فاصله زمانی بین دو لبه مختلف را اندازه گرفت(از این کار می توان برای محاسبه فرکانس لحظه ای پالس استفاده کرد).
                اوژن: به معنای افکننده و شکست دهنده است
                دانایی، توانایی است-Knowledge is POWER
                برای حرفه ای شدن در الکترونیک باید با آن زندگی کرد
                وضعمان بهتر می شود، اگر همه نسبت به جامعه و اطراف خود مسوول باشیم و نگوئیم به ما چه
                قوی شدن و خوب ماندن - خوبی کردن به دیگران یک لذت ماندگار است
                اگر قرار باشد نفت و منابع خام را بدهیم و چرخ بگیریم، بهتر است چرخ را از نو اختراع کنیم
                ساعت کار بدن اکثر انسان ها کمتر از 800000 ساعت است و بعد از آن از کار می افتد

                دیدگاه


                  #23
                  پاسخ : ایجاد زمان های دقیق و مستقل با یک تایمر در AVR

                  نوشته اصلی توسط طراح
                  جایزه شما بزودی اعلام خواهد شد.
                  صورت مسئله بعدی می تواند برنامه ای باشد که بتواند کوچکترین عرض پالس ممکن را با یک کلاک مشخص(مثلا 16 مگاهرتز) اندازه بگیرد. به عبارت دیگر با چه روشی می توان کمترین فاصله زمانی بین دو لبه مختلف را اندازه گرفت(از این کار می توان برای محاسبه فرکانس لحظه ای پالس استفاده کرد).
                  موج مورد نظر رو به دو تا از وقفه های خارجی میکرو وصل میکنیم. یه وقفه رو لبه پایین رونده و یکی دیگه رو لبه بالارونده. هر لحظه که خواستیم فرکانس رو اندازه بگیریم. یکی از وقفه ها رو فعال میکنیم. تو این وقفه اول از همه مینویسیم که یکی از تایمرها شروع به شمارش کنه. بعد از فعال کردن شمارش تایمر، وقفه دیگه رو هم فعال میکنیم. تو این وقفه تایمر رو خاموش میکنیم، مقدارش رو میخونیم و با یه سری محاسبات ساده زمان بدست میاد. البته به اندازه چند پالس میکرو خطا داره دیگه! نمیدونم با نوشتن وقفه ها با اسمبلی میشه این خطا رو به کمتر کرد یا نه. مد nacked هم برای وقفه خوبه که البته من تا حالا باهاش کار نکردم. کدهای اول و آخر وقفه رو حذف میکنه اما چی بلایی سر برنامه میاد نمیدونم!!

                  اگه درست گفتم بگین که برنامه رو بنویسم و با برنامه قبلی تست کنم. خوب به هم ربط پیدا کردن...
                  https://www.linkedin.com/in/mohammadhosseini69

                  http://zakhar.blog.ir

                  دیدگاه


                    #24
                    پاسخ : ایجاد زمان های دقیق و مستقل و اندازه گیری پالس با AVR

                    البته این راه حل هم می تواند برای اندازه گیری پالس بکار رود. اما فاصله زیادی با روش ایده آل دارد و بسیار زمان بر است. برای هماهنگی راه حل، فرض کنید که IC مورد استفاده الف- mega32 ب- mega64 باشد و پالس مورد نظر هم بین 1 تا 99 سیکل کلاک باشد. اگر یک صفحه نمایش مانند LCD هم برای نمایش تعداد سیکل پالس وجود داشته باشد، بسیار بهتر خواهد بود.
                    این صورت مسئله در نقطه مقابل مسئله اول است که در ابتدا ایجاد پالس دقیق مورد نظر بود و در شکل جدید اندازه گیری دقیق پالس مورد نظر است. عنوان تاپیک هم متناسب با مسئله جدید تغییر پیدا کرد.
                    اوژن: به معنای افکننده و شکست دهنده است
                    دانایی، توانایی است-Knowledge is POWER
                    برای حرفه ای شدن در الکترونیک باید با آن زندگی کرد
                    وضعمان بهتر می شود، اگر همه نسبت به جامعه و اطراف خود مسوول باشیم و نگوئیم به ما چه
                    قوی شدن و خوب ماندن - خوبی کردن به دیگران یک لذت ماندگار است
                    اگر قرار باشد نفت و منابع خام را بدهیم و چرخ بگیریم، بهتر است چرخ را از نو اختراع کنیم
                    ساعت کار بدن اکثر انسان ها کمتر از 800000 ساعت است و بعد از آن از کار می افتد

                    دیدگاه


                      #25
                      پاسخ : ایجاد زمان های دقیق و مستقل و اندازه گیری پالس با AVR

                      نوشته اصلی توسط طراح
                      برای هماهنگی راه حل، فرض کنید که IC مورد استفاده الف- mega32 ب- mega64 باشد و پالس مورد نظر هم بین 1 تا 99 سیکل کلاک باشد. اگر یک صفحه نمایش مانند LCD هم برای نمایش تعداد سیکل پالس وجود داشته باشد، بسیار بهتر خواهد بود.
                      یعنی چی برای هماهنگی راه حل؟
                      متوجه نشدم منظورتون چی بود؟ یعنی باید تو فکر یه راه حل دیگه غیر از این روشی که من گفتم باشیم؟
                      https://www.linkedin.com/in/mohammadhosseini69

                      http://zakhar.blog.ir

                      دیدگاه


                        #26
                        پاسخ : ایجاد زمان های دقیق و مستقل و اندازه گیری پالس با AVR

                        سلام.
                        از اینکه علی رغم مساله جدید مطرح شده؛ در این پست به مساله قبلی می پردازم عذرخواهی می کنم.

                        به نظر بنده در صورتی که برنامه به شکل زیر تغییر کند، حساسیت زمانی برنامه؛ تا حد زیادی کاهش می یابد:
                        #include <avr/io.h>
                        #include <avr/interrupt.h>

                        int T1A, T1B, T1C, T3A, T3B, T3C;


                        ISR(TIMER3_COMPC_vect){
                        OCR1A += T1A;
                        OCR1B += T1B;
                        OCR1C += T1C;
                        OCR3A += T3A;
                        OCR3B += T3B;
                        OCR3C += T3C;
                        }

                        #define Period_OC0 0.000049
                        #define Period_OC1A 0.00004925
                        #define Period_OC1B 0.00004950
                        .
                        .
                        .

                        در این حالت وقتی پایه OC1A تغییر وضعیت داد؛ 1.25 میکرو ثانیه بعد وقفه OCR3C رخ می دهد. بنابراین تا تغییر وضعیت بعدی پایه OC1A زمان 47.5 میکرو ثانیه دیگر زمان باقی است و این یعنی 380 سیکل (کلاک 8M). که این مقدار، برای "یک پرش به وقفه به علاوه یک جمع هشت بیتی و پنج جمع شانزده بیتی" ؛ حتی با استفاده از کامپایلر های زبان سطح بالا (حتی بیسکام؟؟) به نظر کافی می آید.

                        اما آیا با این روش می توان با کلاک های پایین تر نیز مساله را حل کرد؟ :question:
                        با این الگوریتم و در صورت نوشته شدن برنامه با زبان اسمبلی، میکرو مشکلی با سرعت انجام دستورات نخواهد داشت. اما موردی که همه ما (من جمله خود بنده در پست قبل) از آن غافل بودیم، مساله کم شدن رزولیشن تایمرها با کم شدن کلاک میکرو است. به عنوان مثال با فرکانس 4MHz به دقتی بیشتر از 0.5 میکرو ثانیه دست نمیابیم، حال آن که صورت مساله دقت 0.25 میکرو ثانیه را طلب میکند.
                        پس فرکانس میکرو باید حداقل 8MHz باشد و در فرکانس های کمتر حل این مساله غیرممکن می باشد.

                        البته اصل مساله و قسمت مشکل کار، با پشتکار آقای حسینی حل شد و موارد ذکر شده فقط برای عملی تر کردن برنامه نوشته شده می باشد. بار دیگر به آقای حسینی به خاطر استعداد و تلاششان تبریک می گویم.
                        It's your attitude, not your aptitude,that makes your altitude

                        << اللهم عجل لولیک الفرج >>

                        دیدگاه


                          #27
                          پاسخ : ایجاد زمان های دقیق و مستقل و اندازه گیری پالس با AVR

                          این پست در مورد مساله دوم طرح شده در این تاپیک (اندازه گیری دقیق پالس) می باشد:

                          یک قاعده مهم و بسیار واضح در کار با هر نوع میکروکنترلر مطرح است: "در صورت نیاز به سرعت های بالا و نیز هنگام کار روی مرزهای زمانی میکرو، تمام تلاش برنامه نویس باید در جهت استفاده ی حداکثری از خواص سخت افزاری میکرو باشد"

                          بر طبق همین قاعده، الگوریتمی که تا اینجا برای حل این مساله ارئه شد، علی رغم درست بودن کارایی مناسب را ندارد.
                          راه حل بهینه تر، استفاده از مود تسخیر (Capture) می باشد.

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

                          1- میکرو در مود کپچر، با دریافت یک لبه پایین/بالا رونده روی پایه ICPn، مقدار تایمر مربوطه (TCNTn) را در رجیستر کپچر (ICRn) می نویسد و نیز پرچم وقفه مربوطه (ICFn) را نیز ست می نماید. نکته مهم در نوشته شدن مقدار TCNTn، این است که این عمل کاملا سخت افزاری و در سریع ترین زمان ممکن انجام می شود.

                          2- اگر خاصیت Noise Canceler برای سیگنال ورودی فعال باشد، یک فیلتر دیجیتال بعد از طبقه ورودی قرار می گیرد.
                          نحوه کار این فیلتر به این صورت است که با دریافت سیگنال ورودی، چهار نمونه از آن گرفته و در صورت برابری همه آن ها، کپچر انجام می شود.
                          بنابراین سیگنال ورودی، باید برای چهار سیکل (250ns با کلاک 16MHz) وجود داشته باشد. پس برای رسیدن به حداقل طول پالس قابل اندازه گیری، باید این واحد را غیر فعال کرده و مساله نویز را خارج از میکرو حل نمود.

                          به دلیل طولانی شدن این پست، جواب مساله مطرح شده در پست های بعدی ارسال می شود.
                          It's your attitude, not your aptitude,that makes your altitude

                          << اللهم عجل لولیک الفرج >>

                          دیدگاه


                            #28
                            پاسخ : ایجاد زمان های دقیق و مستقل و اندازه گیری پالس با AVR

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

                            با توجه به موارد 1و2 بیان شده در پست قبل، جواب سوال هوشمندانه ی طرح شده (اجرا هم در mega32 و هم در mega64) به این صورت می باشد:

                            الف- mega32: این میکرو تنها یک واحد کپچر دارد (پین ICP1). بنابراین الگوریتم پیشنهادی به این صورت می باشد:

                            1- واحد کپچر در حالت "لبه بالا رونده" تنظیم شود (بیت ICES1=1).
                            2- وقفه کپچر فعال شود.
                            3- تایمر یک راه اندازی شود.
                            4- وقفه سراسری فعال.
                            حال با اولین لبه بالا رونده، مقدار تایمر در ICR1 نوشته شده و برنامه به زیر روال وقفه پرش می کند:
                            5- در زیر روال وقفه:
                            if (ICES1=1){ // if rising edge:
                            First = ICR1;
                            ICES1=0; // set to falling edge.
                            {else{ // if falling edge:
                            ICES1=1;
                            TCNT1 = 0; // reset timer1.
                            Period = (First - ICR1)* CPU_CLK_PERIOD;
                            }
                            البته می توان برای دستیابی به سرعت بیشتر از ضرب CPU_CLK_PERIOD در متغیر Period در وقفه خودداری نموده
                            و این کار در تابع main روی متغیر Period انجام شود؛ در این حالت محاسبه حدودی از کمترین پریود قابل اندازه گیری به ترتیب زیر است (البته باید برنامه اسمبلی نوشته شود تا بتوان به مقدار دقیق دست یافت):
                            حداکثر 3 سیکل برای دستور پرش(اجرای if در اسمبلی) + 2 سیکل First = ICR1 و + 1سیکل ICES1=0 و + 1 سیکل ICES1=1 و + 2 سیکل ریست نمودن تایمر + 4 سیکل (Period = First - ICR1) که جمعا 13 سیکل می شود. یعنی 815.5ns یا 1.23MHz
                            دقت شود که در این حالت بر خلاف الگوریتم ارائه شده توسط آقای حسینی، زمانی را که میکرو هدر می دهد تا به اجرای روتین وقفه برسد و نیز از آن خارج شود، در خواندن مقدار رجیستر تایمر هیچ تاثیری ندارد؛ چون این کار سخت افزاری انجام می شود!
                            It's your attitude, not your aptitude,that makes your altitude

                            << اللهم عجل لولیک الفرج >>

                            دیدگاه


                              #29
                              پاسخ : ایجاد زمان های دقیق و مستقل و اندازه گیری پالس با AVR

                              ب- mega64:
                              از آنجایی که این میکرو، دو واحد تسخیر دارد می توان در آن از الگوریتم بهینه تر زیر بهره جست:

                              1- واحد کپچر1 در حالت "لبه بالا رونده" تنظیم شود (بیت ICES1=1). ر
                              2- واحد کپچر2 در حالت "لبه پایین رونده" تنظیم شود (بیت ICES1=0). ر
                              3- فقط وقفه کپچر 2 فعال شود.
                              4- تایمر های 1و2 راه اندازی شوند.
                              5- وقفه سراسری فعال.

                              حال با اولین لبه بالا رونده، مقدار تایمر 1 در ICR1 نوشته می شود.
                              و وقتی لبه پایین رونده رخ دهد، مقدار تایمر 2 در ICR2 نوشته شده و وقفه مربوط به کپچر 2 فعال می شود:
                              5- در زیر روال وقفه کپچر 2:

                              ;TCNT1 = 0 // ریست نمودن تایمر1.
                              ;TCNT2 = 0 // ریست نمودن تایمر2.
                              ;Period = (ICR3 - ICR1)* CPU_CLK_PERIOD

                              در اینجا نیز باید برای دستیابی به سرعت بیشتر باید از ضرب CPU_CLK_PERIOD در متغیر Period در وقفه خودداری نموده و این کار در تابع main انجام شود؛ در این حالت محاسبه ی حدودی از کمترین پریود قابل اندازه گیری به این ترتیب است (البته باید برنامه اسمبلی نوشته شود تا بتوان به مقدار دقیق دست یافت):

                              4 سیکل برای ریست نمودن تایمر 1و2 + 4 سیکل (Period = ICR3 - ICR1) که جمعا 8 سیکل می شود. یعنی 500ns یا 2MHz.
                              البته به نظر بنده، با نوشته شدن برنامه اسمبلی و بعضی ساده سازی های منطقی (Logic)، این الگوریتم توانایی رسیدن به 3 سیکل (و اندازه گیری 187.5ns یعنی سیگنالی با فرکانس 5.33MHz ) یا حتی 1 سیکل (و اندازه گیری پالسی با عرض یا 62.5ns با پریود تکرار 250ns یعنی فرکانس 4MHz) را دارد!!!

                              ملاحضه نمودید که با اضافه شدن تنها یک واحد کپچر، قدرت میکرو در راستای هدف مورد استفاده به راحتی تقریبا دو برابر شد (و پتانسیل بسیار بیشتری را نیز دارد)؛ که این، اهمیت توان سخت افزاری میکرو ها را به نمایش می گذارد.

                              با این تفاصیل، مرزهای توانایی Xmega کجاست!؟
                              It's your attitude, not your aptitude,that makes your altitude

                              << اللهم عجل لولیک الفرج >>

                              دیدگاه


                                #30
                                پاسخ : ایجاد زمان های دقیق و مستقل و اندازه گیری پالس با AVR

                                در ابتدا از جناب Fule بخاطر پاسخ های خوبشان تشکر می کنم و خوشحالم که افرادی در این انجمن فعالیت دارند که تا این مرتبه در مسایل بصورت دقیق و فنی مسلط هستند. شما اصل راه حل های مورد نظر را بیان کردید و مواردی هست که در ادامه توضیح داده می شود
                                دو مورد برای صورت مسئله قبلی قابل ذکر است. اول اینکه یک تایمر 8 بیتی در کلاک 16 مگاهرتز اگر بخواهد زمان 24.5 میکروثانیه را تولید کند، می توان تقسیم کننده آن را روی 8 قرار داد و مقدار OCR0 در اینحالت برابر 48 می شود. پس جمله ای که در پست های قبل گفته شد ( عدم امکان تولید این زمان با تایمر 8بیتی) برای شرایطی بود که جناب حسینی مسئله را حل کردند و تقسیم کننده را روی یک قرار دادند. اما با قرار دادن تقسیم کننده روی 8 می توان همین زمان را با TIMER0 تولید کرد.
                                مورد بعدی در راه حل جدید شماست که عملیات جمع را تنها در وقفه یکی از تایمرها انجام داده اید. مسئله ای که باید به آن توجه کنید این است که هر چند در اولین سیکل شکل موج ها، فاصله بین هر دو وقفه تنها 250 نانو ثانیه است. اما به مرور این فاصله ها تغییر می کنند و رابطه اولیه خود را از دست می دهند. بنابراین اگر اضافه شدن OCR ها تنها در یک وقفه انجام شود منجر به خراب شدن شکل موج ها می شود.
                                اما در صورت مسئله جدید اصل استفاده از واحد Capture کاملا صحیح است و این واحد اصولا به همین منظور در میکروکنترلر پیش بینی شده است. در mega32 که مجبور به استفاده از یکی از این واحدها هستیم، حداقل عرض پالس قابل اندازه گیری، به سرعت تغییر نوع حساسیت ورودی بستگی دارد و هرچه این عمل سریعتر انجام شود، عرض پالس کوچکتری را می توان اندازه گرفت. برای کاهش این زمان می توان از منطق IF صرف نظر کرد و به محض ایجاد وقفه، وضعیت ICES1 را NOT کرد. در هر صورت با لحاظ حداقل 4 سیکل برای پرش به وقفه و عملیات مذکور، حداقل عرض پالس اندازه گیری شده وابستگی کاملی به نوع دستورالعمل های اسمبلی دارد که در وقفه نوشته می شود و برای ادامه دار بودن این تاپیک، نوشتن این روتین را به عهده دوستان می گذارم.
                                اما در مورد mega64 به دلیل وجود دو واحد Capture، عملیات اندازه گیری می تواند بصورت کاملا موازی انجام شود و همانطور که تشخیص دادید با یک روش حساب شده حتی می توان تا یک سیکل را هم اندازه گرفت. در هر دو روشی که بیان کردید، صفر کردن مقدار تایمر بستگی به ماهیت پالس ورودی دارد و اگر بین دو پالس متوالی فاصله کافی وجود داشته باشد، خاموش کردن تایمر و مقدار دهی اولیه می تواند بعد از پروسه اندازه گیری و در شروع اندازه گیری بعدی انجام شود. وقفه هر دو تایمر هم می تواند تواما فعال باشد و نیازی به غیرفعال بودن وقفه تایمر دوم نیست.
                                در کاربردهایی که اندازه گیری دقیق عرض یک پالس مورد نظر باشد( مانند سنجش فرکانس لحظه ای یا حتی رادار و مانند آن)، استفاده از این دقت اندازه گیری می تواند بسیار مهم باشد. همینجا پیشنهادی را برای پیاده سازی یک پروژه مطرح می کنم که ممکن است تا حدی جالب باشد. از طریق دو میکروفن که در فاصله مشخصی قرار دارند و تولید یک صدای بلند شاید بتوان دستگاهی برای اندازه گیری و نمایش سرعت صوت ساخت که این امر مستلزم یکسان بودن زمان پاسخ میکروفن های مورد استفاده است.
                                بحث توانایی های XMEGA هم مجال دیگری را می طلبد و فقط می توان گفت که به علت بالاتر بودن کلاک آن و صرف نظر از سایر امکاناتی که منجر به بالا رفتن سرعت می شود، در بالا رفتن دقت اندازه گیری بهبود حاصل می شود.
                                اوژن: به معنای افکننده و شکست دهنده است
                                دانایی، توانایی است-Knowledge is POWER
                                برای حرفه ای شدن در الکترونیک باید با آن زندگی کرد
                                وضعمان بهتر می شود، اگر همه نسبت به جامعه و اطراف خود مسوول باشیم و نگوئیم به ما چه
                                قوی شدن و خوب ماندن - خوبی کردن به دیگران یک لذت ماندگار است
                                اگر قرار باشد نفت و منابع خام را بدهیم و چرخ بگیریم، بهتر است چرخ را از نو اختراع کنیم
                                ساعت کار بدن اکثر انسان ها کمتر از 800000 ساعت است و بعد از آن از کار می افتد

                                دیدگاه

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