اطلاعیه

Collapse
No announcement yet.

مشکل با timer و interrupt (نوشتن کدهای adc در تایمر برای افزایش سرعت عملکرد میکرو)

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

    مشکل با timer و interrupt (نوشتن کدهای adc در تایمر برای افزایش سرعت عملکرد میکرو)

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

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

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

    خوستم ببینم میشه این کدهارو توی timer یا interrupt گذاشت که میکرو اینقدر درگیرش نباشه و عماکردش کم نشه.

    اینم نمونه کد :

    کد:
    [LEFT]
    #define ADC_VREF_TYPE ((0<<REFS1) | (1<<REFS0) | (0<<ADLAR))
    
    /////////////////////////////////////////////////////////////////////
    
    unsigned int adc_data;
    
    interrupt [ADC_INT] void adc_isr(void)
    {
     adc_data=ADCW;
    }
    
    unsigned int read_adc(unsigned char adc_input)
    {
     ADMUX=adc_input | ADC_VREF_TYPE;
     delay_us(10);
     #asm
        in   r30,mcucr
        cbr  r30,__sm_mask
        sbr  r30,__se_bit | __sm_adc_noise_red
        out  mcucr,r30
        sleep
        cbr  r30,__se_bit
        out  mcucr,r30
     #endasm
     return adc_data;
    }
    
    
    ///////////////////////////////////////////////////////////////////////////////////
    
    
    void CurrentTemp()
        {
         ADMUX = ADC_VREF_TYPE;
         ADCSRA = (1<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (1<<ADIE) | (0<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
         SFIOR = (0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
    
         temporary = 0;
         for(i = 0; i < 60; i ++)
         {
          ADC0 = read_adc(0);
          temporary = temporary + ADC0;
          delay_ms(20);
         }
         ADC0 = temporary / 60;
    
    
          for(adcin = 0; adcin < 300; adcin ++)
          {
           if(ADC0 <= t[adcin] && ADC0 >= t[adcin-1])
           {
            temp = adcin;
            break;
           }
          }
        }
    
    //////////////////////////////////////////////////////////////////////
    
    
    #asm("sei")
                             lcd_clear();
                             lcd_gotoxy(0,0);
                             lcd_putsf("CURRENT TEMPERATURE:");
                             lcd_gotoxy(0,1);
                             lcd_putsf("--------------------");
                             lcd_gotoxy(1,2);
                             lcd_putsf("TEMP = ");
                             
                             OffSet  = _OffSet;
                             while(1)
                            {
                             temp = OffSet + temp;
                             CurrentTemp();
                             
                             
                             sprintf(Buffer_LCD,"%3d\xdf""C",temp);
                             lcd_gotoxy(8,2);
                             lcd_puts(Buffer_LCD);
               }
    [/LEFT]

    این قسمت های مرتبط با برنامه هست
    *\ وقتی ارزش ها عوض بشن، عوضی ها باارزش می شن /*

    #2
    پاسخ : مشکل با timer و interrupt (نوشتن کدهای adc در تایمر برای افزایش سرعت عملکرد میکرو)

    نوشته اصلی توسط shoniz نمایش پست ها
    وقت همه دوستان بخیر

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

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

    خوستم ببینم میشه این کدهارو توی timer یا interrupt گذاشت که میکرو اینقدر درگیرش نباشه و عماکردش کم نشه.

    اینم نمونه کد :

    کد:
    [LEFT]
    #define ADC_VREF_TYPE ((0<<REFS1) | (1<<REFS0) | (0<<ADLAR))
    
    /////////////////////////////////////////////////////////////////////
    
    unsigned int adc_data;
    
    interrupt [ADC_INT] void adc_isr(void)
    {
     adc_data=ADCW;
    }
    
    unsigned int read_adc(unsigned char adc_input)
    {
     ADMUX=adc_input | ADC_VREF_TYPE;
     delay_us(10);
     #asm
        in   r30,mcucr
        cbr  r30,__sm_mask
        sbr  r30,__se_bit | __sm_adc_noise_red
        out  mcucr,r30
        sleep
        cbr  r30,__se_bit
        out  mcucr,r30
     #endasm
     return adc_data;
    }
    
    
    ///////////////////////////////////////////////////////////////////////////////////
    
    
    void CurrentTemp()
        {
         ADMUX = ADC_VREF_TYPE;
         ADCSRA = (1<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (1<<ADIE) | (0<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
         SFIOR = (0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
    
         temporary = 0;
         for(i = 0; i < 60; i ++)
         {
          ADC0 = read_adc(0);
          temporary = temporary + ADC0;
          delay_ms(20);
         }
         ADC0 = temporary / 60;
    
    
          for(adcin = 0; adcin < 300; adcin ++)
          {
           if(ADC0 <= t[adcin] && ADC0 >= t[adcin-1])
           {
            temp = adcin;
            break;
           }
          }
        }
    
    //////////////////////////////////////////////////////////////////////
    
    
    #asm("sei")
                             lcd_clear();
                             lcd_gotoxy(0,0);
                             lcd_putsf("CURRENT TEMPERATURE:");
                             lcd_gotoxy(0,1);
                             lcd_putsf("--------------------");
                             lcd_gotoxy(1,2);
                             lcd_putsf("TEMP = ");
                             
                             OffSet  = _OffSet;
                             while(1)
                            {
                             temp = OffSet + temp;
                             CurrentTemp();
                             
                             
                             sprintf(Buffer_LCD,"%3d\xdf""C",temp);
                             lcd_gotoxy(8,2);
                             lcd_puts(Buffer_LCD);
               }
    [/LEFT]

    این قسمت های مرتبط با برنامه هست
    سلام
    سرویس وقفه باید تا جای ممکن سبک باشه و این که بخوایید کارهای سنگین رو به سرویس وقفه منتقل کنید اصلا جالب نیست.
    توی پروژه هایی که میکروکنترلر کشش داشته باشه معمولا از RTOS برای انجام وظایف در موازات هم استفاده میشه. نمیدونم AVR کشش پروژه شما رو داشته باشه یا نه وگرنه میگفتم از FreeRTOS استفاده کنید که البته در اون صورت لازمه از کمپایلر GCC استفاده کنید.
    برای مورد شما به نظرم بهتره از وقفه ADC و تایمر استفاده بشه اما نه برای محاسبات! شما ADC رو استارت میکنید و توی سرویس وقفه ADC نمونه ها رو داخل یک بافر ذخیره میکنید. برای تریگ کردن ADC هم میتونید از وقفه تایمر استفاده کنید. نمونه ها که گرفته شدن، توی برنامه خیلی راحت در یک مرحله روشون محاسبات انجام میدید. میتونید از 2 بافر به صورت پینگ پنگی استفاده کنید که عملکرد بهتر بشه.

    دیدگاه


      #3
      پاسخ : مشکل با timer و interrupt (نوشتن کدهای adc در تایمر برای افزایش سرعت عملکرد میکرو)

      نوشته اصلی توسط shoniz نمایش پست ها
      وقت همه دوستان بخیر

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

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

      خوستم ببینم میشه این کدهارو توی timer یا interrupt گذاشت که میکرو اینقدر درگیرش نباشه و عماکردش کم نشه.

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

      دیدگاه


        #4
        پاسخ : مشکل با timer و interrupt (نوشتن کدهای adc در تایمر برای افزایش سرعت عملکرد میکرو)

        نوشته اصلی توسط hossein.m98 نمایش پست ها
        سلام
        سرویس وقفه باید تا جای ممکن سبک باشه و این که بخوایید کارهای سنگین رو به سرویس وقفه منتقل کنید اصلا جالب نیست.
        توی پروژه هایی که میکروکنترلر کشش داشته باشه معمولا از RTOS برای انجام وظایف در موازات هم استفاده میشه. نمیدونم AVR کشش پروژه شما رو داشته باشه یا نه وگرنه میگفتم از FreeRTOS استفاده کنید که البته در اون صورت لازمه از کمپایلر GCC استفاده کنید.
        برای مورد شما به نظرم بهتره از وقفه ADC و تایمر استفاده بشه اما نه برای محاسبات! شما ADC رو استارت میکنید و توی سرویس وقفه ADC نمونه ها رو داخل یک بافر ذخیره میکنید. برای تریگ کردن ADC هم میتونید از وقفه تایمر استفاده کنید. نمونه ها که گرفته شدن، توی برنامه خیلی راحت در یک مرحله روشون محاسبات انجام میدید. میتونید از 2 بافر به صورت پینگ پنگی استفاده کنید که عملکرد بهتر بشه.
        کلاً AVR کند هست و برنامه های دستگاههای ما هم سنگین و بسیار حساس.
        باید از AVR کوچ کنم به ARM که اونم یهو قیمتش رفت بالا و کمیاب هم شد.

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

        نوشته اصلی توسط evergreen نمایش پست ها
        با سلام و احترام
        از آنجا که در اغلب کاربردها تغییردما پدیده ایی سریع نمیباشد لازم نیست که در هر لوپ اجرای برنامه و با اختلاف زمانی کم مرتبا تابع اندازه گیری دما را صدا بزنید بلکه میتوانید با توجه به شرایط محیطی که میخواهید دمای آن را اندازه گیری کنید و با استفاده از اینتراپت تایمر، مثلا هر یک یا چند ثانیه یکبار دما را اندازه گیری نمایید. در مورد دکمه ها نیز با وجود اینکه در این کد چیزی از دکمه ها مشاهده نمیشود ولی برای آنها نیز میتوانید اینتراپت تعریف کنید تا برنامه سریعا به آنها جواب دهد.
        موفق باشید.
        متوجه هستم. اما دستگاه ها مرتبط با آزمایشگاه ها و تجهیزات پزشکی هست و سرعت خیلی مهمه.
        گفته شما توی دمای پایین کاملا درسته. اما دما بالای 200 درجه خیلی مهمه. چند میلی ثانیه خیلی مهمه. مهمه که زود تشخیص بده و به المنت فرمان بده. کالیبراسیون اختلاف دمای بالا 1 درجه رو رد میکنه. اگه سریع نخونه و فرمان نده اختلاف چند درجه ای ایجاد میکنه.

        با نیم ثانیه فکر کنم مشکلی نداشته باشه.

        دکمه ها عادی نوشته شدن.

        if(enterkey == 0)
        {
        delay_ms(20);
        if(enterkey == 0)
        {
        buzz();
        while(enterkey == 0);
        info_process();
        }
        }
        این یه نمونه از تعریف کلید ها.

        البته بصورت مثال نوشتم.
        جدیدترین ویرایش توسط shoniz; ۲۱:۵۰ ۱۴۰۰/۰۶/۲۴.
        *\ وقتی ارزش ها عوض بشن، عوضی ها باارزش می شن /*

        دیدگاه


          #5
          پاسخ : مشکل با timer و interrupt (نوشتن کدهای adc در تایمر برای افزایش سرعت عملکرد میکرو)

          سلام.
          به نظرم بهتره از GCC استفاده کنید و اگه حافظه میکرو کم نباشه ،کامپایلر رو برای سرعت اپتیمایز کنید.
          تا حد امکان از متغیر های هشت بیتی مثل unsigned char استفاده کنید.در صورتی که از مود هشت بیتی adc با فرض کاهش دقت استفاده کنید سرعت برنامه بیشتر هم میشه.
          در کل avr میکروکنترلر بسیار سریعی هست ،چون در هر پالس کلاک یک دستورالعمل اجرا میکنه.اینکه شما چقدر از امکانات بهینه استفاده کنید مهمه.تا حد امکان عملکرد ها سخت افزاری باشن بهتره مثلا به جای lcd هایی که پارالل متصل میشن از انواع IIC یا SPI استفاده کنید.

          دیدگاه


            #6
            پاسخ : مشکل با timer و interrupt (نوشتن کدهای adc در تایمر برای افزایش سرعت عملکرد میکرو)

            نوشته اصلی توسط shoniz نمایش پست ها
            کلاً AVR کند هست و برنامه های دستگاههای ما هم سنگین و بسیار حساس.
            باید از AVR کوچ کنم به ARM که اونم یهو قیمتش رفت بالا و کمیاب هم شد.

            متوجه هستم. اما دستگاه ها مرتبط با آزمایشگاه ها و تجهیزات پزشکی هست و سرعت خیلی مهمه.
            گفته شما توی دمای پایین کاملا درسته. اما دما بالای 200 درجه خیلی مهمه. چند میلی ثانیه خیلی مهمه. مهمه که زود تشخیص بده و به المنت فرمان بده. کالیبراسیون اختلاف دمای بالا 1 درجه رو رد میکنه. اگه سریع نخونه و فرمان نده اختلاف چند درجه ای ایجاد میکنه.

            با نیم ثانیه فکر کنم مشکلی نداشته باشه.
            با سلام مجدد
            با توجه به اینکه گفتید نیم ثانیه مشکلی نیست بنظرم شما در مرحله اول بیایید و بجای مرتب چک کردن دما، توسط اینتراپت تایمر هر 200ms یکبار دما را اندازه گیری کنید. برای کلیدها هم از اینتراپت استفاده کنید. اگر پروسس شما در همین حد تنظیم دما و چند کلید باشد بعید میدانم از لحاظ سرعت مشکلی با AVR پیدا کنید. البته وقتی شما دستگاه آزمایشگاهی و پزشکی طراحی میکنید اگر از لحاظ فنی به این باور رسیدید که AVR نمیتواند استانداردهای لازم برای کارتان را تامین کند دیگر نباید بدلیل قیمت، در استفاده از کنترلری که میتواند نیازهایتان را برآورده کند شک و یا تعلل کنید.
            موفق باشید.
            جدیدترین ویرایش توسط evergreen; ۲۲:۳۵ ۱۴۰۰/۰۶/۲۴.

            دیدگاه


              #7
              پاسخ : مشکل با timer و interrupt (نوشتن کدهای adc در تایمر برای افزایش سرعت عملکرد میکرو)

              نوشته اصلی توسط evergreen نمایش پست ها
              با سلام مجدد
              با توجه به اینکه گفتید نیم ثانیه مشکلی نیست بنظرم شما در مرحله اول بیایید و بجای مرتب چک کردن دما، توسط اینتراپت تایمر هر 200ms یکبار دما را اندازه گیری کنید. برای کلیدها هم از اینتراپت استفاده کنید. اگر پروسس شما در همین حد تنظیم دما و چند کلید باشد بعید میدانم از لحاظ سرعت مشکلی با AVR پیدا کنید. البته وقتی شما دستگاه آزمایشگاهی و پزشکی طراحی میکنید اگر از لحاظ فنی به این باور رسیدید که AVR نمیتواند استانداردهای لازم برای کارتان را تامین کند دیگر نباید بدلیل قیمت، در استفاده از کنترلری که میتواند نیازهایتان را برآورده کند شک و یا تعلل کنید.
              موفق باشید.
              برنامه توی پروسه تغریبا سنگین هست چون همزمان داره چک میکنه فن از کار نیفته و اگه افتاد آلارم و بعد دستگاه خاموش. دما بیشتر از 2 درجه نشه و اگه شد آلارم . رفرش ال سیدی و زمان استیج های مختلف و کمپرسور و ..... .

              دکمه ها رو چطوری بذارم تو اینتراپت.(نمونه کد)

              تایمر 2 بیکاره. اگه میشد adc رو اونجا تعریف کنم که بدون دخالت توی وقفه خود میکرو کارش و میکرد فعلا کارم حل بود.(نمونه کد)

              درمورد ARM هم باید یه سرچ کنم و میکرو مورد استفاده که مشکل کمیابی و ... نداشته باشه پیدا کنم و کارهام و از AVR ببرم روی STM .
              *\ وقتی ارزش ها عوض بشن، عوضی ها باارزش می شن /*

              دیدگاه


                #8
                پاسخ : مشکل با timer و interrupt (نوشتن کدهای adc در تایمر برای افزایش سرعت عملکرد میکرو)

                نوشته اصلی توسط shoniz نمایش پست ها
                برنامه توی پروسه تغریبا سنگین هست چون همزمان داره چک میکنه فن از کار نیفته و اگه افتاد آلارم و بعد دستگاه خاموش. دما بیشتر از 2 درجه نشه و اگه شد آلارم . رفرش ال سیدی و زمان استیج های مختلف و کمپرسور و ..... .

                دکمه ها رو چطوری بذارم تو اینتراپت.(نمونه کد)

                تایمر 2 بیکاره. اگه میشد adc رو اونجا تعریف کنم که بدون دخالت توی وقفه خود میکرو کارش و میکرد فعلا کارم حل بود.(نمونه کد)

                درمورد ARM هم باید یه سرچ کنم و میکرو مورد استفاده که مشکل کمیابی و ... نداشته باشه پیدا کنم و کارهام و از AVR ببرم روی STM .
                با سلام مجدد
                اگر فرصت کردید وقت بگذارید و یکبار این مطلب رو به دقت مطالعه کنید ( http://www.gammon.com.au/interrupts ) خیلی کامل و همراه مثال اینتراپتها رو توضیح داده. توی همین مطلب یه قسمتی هست که انواع اینتراپتها و اولویت بندی اونها را عنوان کرده. برای کلیدها میتوانید با توجه به اینکه از نظر سخت افزاری روی کدوم پورت قرار دارند یکی از Pin Change Interrupt های صفر تا دو را برایشان در نظر بگیرید.
                موفق باشید.

                دیدگاه


                  #9
                  پاسخ : مشکل با timer و interrupt (نوشتن کدهای adc در تایمر برای افزایش سرعت عملکرد میکرو)

                  این برنامه از بیس مشگل داره
                  شما دارین 61 نمونه میگیرین بعد آخر سر تقسیم 60 میکنید !!
                  نکته بعدی اینکه باید مقادیر adc رو تو آرایه بریزین بعد آخر سر تقسیم کنید .
                  و اینکه delay 10us کافیه حالا بخواین خیلی فرجه بدین 1 میلی ثانیه کافیه کل فرآیند adc گیری 6-7 تا کلاک بود فکر کنم ..
                  تو چند میلیون کلاک( کف کف 1 مگ باشه) گمه با حساب هر گرد و اینا همون 1 میلی ثانیه هم زیاده ..
                  نکته بعدی اینکه توی تابع هر بار اومدین کل adc رو کانفیگ میکنید ...
                  یه بار کانفیگ کنید کافیه توی تابع صرفا flag رو چک کنین ..
                  یه سوالم دارم جسارتا به نظر حرکت قوی ای بوده
                  اون break که دادین برا چی بوده تو حلقه ؟

                  دیدگاه


                    #10
                    پاسخ : مشکل با timer و interrupt (نوشتن کدهای adc در تایمر برای افزایش سرعت عملکرد میکرو)

                    نوشته اصلی توسط l2qf نمایش پست ها
                    این برنامه از بیس مشگل داره
                    شما دارین 61 نمونه میگیرین بعد آخر سر تقسیم 60 میکنید !!
                    نکته بعدی اینکه باید مقادیر adc رو تو آرایه بریزین بعد آخر سر تقسیم کنید .
                    و اینکه delay 10us کافیه حالا بخواین خیلی فرجه بدین 1 میلی ثانیه کافیه کل فرآیند adc گیری 6-7 تا کلاک بود فکر کنم ..
                    تو چند میلیون کلاک( کف کف 1 مگ باشه) گمه با حساب هر گرد و اینا همون 1 میلی ثانیه هم زیاده ..
                    نکته بعدی اینکه توی تابع هر بار اومدین کل adc رو کانفیگ میکنید ...
                    یه بار کانفیگ کنید کافیه توی تابع صرفا flag رو چک کنین ..
                    یه سوالم دارم جسارتا به نظر حرکت قوی ای بوده
                    اون break که دادین برا چی بوده تو حلقه ؟
                    نمونه های ADC هست. انتگرال گیری بهش میگن. نوسانات ADC رو میگیره.
                    کل ADC و کانفیگ و ... از هم جدا هستن من قسمت قسمت کپی کردم.(اما شما درست میگی کل کانفیگ و دارم رفرش میکنم.) اصلاح میکنم.

                    پیشنهاد شما چیه؟
                    *\ وقتی ارزش ها عوض بشن، عوضی ها باارزش می شن /*

                    دیدگاه


                      #11
                      پاسخ : مشکل با timer و interrupt (نوشتن کدهای adc در تایمر برای افزایش سرعت عملکرد میکرو)

                      نوشته اصلی توسط l2qf نمایش پست ها
                      این برنامه از بیس مشگل داره
                      شما دارین 61 نمونه میگیرین بعد آخر سر تقسیم 60 میکنید !!
                      نکته بعدی اینکه باید مقادیر adc رو تو آرایه بریزین بعد آخر سر تقسیم کنید .
                      و اینکه delay 10us کافیه حالا بخواین خیلی فرجه بدین 1 میلی ثانیه کافیه کل فرآیند adc گیری 6-7 تا کلاک بود فکر کنم ..
                      تو چند میلیون کلاک( کف کف 1 مگ باشه) گمه با حساب هر گرد و اینا همون 1 میلی ثانیه هم زیاده ..
                      نکته بعدی اینکه توی تابع هر بار اومدین کل adc رو کانفیگ میکنید ...
                      یه بار کانفیگ کنید کافیه توی تابع صرفا flag رو چک کنین ..
                      یه سوالم دارم جسارتا به نظر حرکت قوی ای بوده
                      اون break که دادین برا چی بوده تو حلقه ؟
                      مشکل حل شد.
                      ضمناً break باید باشه
                      *\ وقتی ارزش ها عوض بشن، عوضی ها باارزش می شن /*

                      دیدگاه

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