اطلاعیه

Collapse
No announcement yet.

فیلتر دیجیتال با AVR

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

    فیلتر دیجیتال با AVR

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


    تو این فایلها هم برنامه ی نوشته شده برای FIR هست،هم برای IIR،تو برنامه من برای هر کدوم دو سری ضرایب نوشتم ، شما میتونید ضریب دلخواه رو با پاک کردن /*......*/ وارد برنامه کنین و البته مرتبه ی فیلتر رو هم با تغییر متغیر m تصحیح کنید، این کار رو برای این کردم تا متوجه تغییر پاسخ فیلتر متناسب با مرتبه بشین،مثلا برای فیلتر FIR یک سری ضریاب مرتبه ی 5 هست ویک سری ضرایب مرتبه 10 ، یا برای فیلر IIR یک سری ضرایب Butterworth هست ، و یک سری ضرایب Bessel .
    یک مطلب جالبی که در امر پردازش سیگنال دیجیتال وجود داره،میشه در این پروژه به چشم دید و اون پدیده ی در هم روی(Aliasing)هست...از اونجا که این یک فیلتر دیجیتال پایین گذر با فرکانس فطع 100 هرتز هست،انتظار میره که در فرکانس مثلا 1.2k هرتز هیچ سیگنالی عبور نکنه،اما به دلیل اینکه این فرکانس از نصف فرکانس نمونه برداری بزگتره(فرکانس نایکوییست) ، فیلتر اون رو عبور میده.

    http://upload.yazdkit.com/download.php?file=109Digital%20Filter.rar

    #2
    پاسخ : فیلتر دیجیتال با AVR

    با سلام خدمت جناب soleares و دوستان
    امکانش هست جناب soleares یا یکی از دوستان که سورس برنامه دانلود کرده یه بار دیگه پلود کنه؟
    خیلی نیازش دارم.
    تشکر

    دیدگاه


      #3
      پاسخ : فیلتر دیجیتال با AVR

      نوشته اصلی توسط mir elk
      با سلام خدمت جناب soleares و دوستان
      امکانش هست جناب soleares یا یکی از دوستان که سورس برنامه دانلود کرده یه بار دیگه پلود کنه؟
      خیلی نیازش دارم.
      تشکر
      با سلام،

      بفرمائید عزیز :mrgreen:

      http://s3.picofile.com/file/7385389137/AVR_Digital_Filter.rar.html
      مادامی که از شخصی یاد میشود، او و افکارش زنده اند ....

      Sh_Nourbakhsh@Yahoo.com

      http://s2.picofile.com/file/7170362468/_Wall_e_.jp

      دیدگاه


        #4
        پاسخ : فیلتر دیجیتال با AVR

        نوشته اصلی توسط aivhl
        با سلام،

        بفرمائید عزیز :mrgreen:

        http://s3.picofile.com/file/7385389137/AVR_Digital_Filter.rar.html
        سلام؛جناب استاد نوربخش دست گلت درد نکنه

        دیدگاه


          #5
          پاسخ : فیلتر دیجیتال با AVR

          سلام به دوستان عزیز..
          کاری که من میخوام بکنم مرحله اولش فیلتر کردن هست، در نهایت مقدار خروجی ها رو downsample کنه..
          به این ترتیب که اگه خروجی ما این گونه باشه:
          y=[0 2 3 8 8 6 6 8 9] out
          بعد از downsample 8 تایی این گونه میشه:
          y=[0 9] out
          یعنی تک تک خروجی ها رو باید چک کنه و اگر نمونه اول رو برداره ،8 تا بشمره ونمونه 9 ام رو برداره..ودر نهایت این نمونه ها رو که در اینجا 0 و 9 هستند به توان 2 برسونه و در یکمتغیر ذخیره کنه..
          به عبارتی همان محاسبه توان(انرژی) سیگنال خروجی فیلتر شده ولی به دلیل حجم محاسبات بالا میخوام از هر 8 نمونه ،1 نمونه رو انتخاب و به توان برسونم.
          تغییراتی که خودم در برنامه دادم رو با قرمز نشون دادم.مشکل بعدی این هست که میخوام سیگنال ورودی رو فقط به مدت 2 ثانیه بخونه(در حقیقت سیگنال ورودی سیگنال صوت کوتاه در حد 2 ثانیه هست،نباید انرژی نویز در نظر گرفته بشه)
          ممنون میشم هرکسی از جمله جناب soleares میتونند کمک کنند.

          برنامه :
          [pre][/pre]


          #include <mega16.h>
          #include <delay.h>
          #include <math.h>
          #define m 9

          float sample;
          int z;
          float su1;
          float f;


          float u[m+1]; //FIR delay buffer

          /*float h[m+1]={0.1513653,0.1870979,0.2,0.1870979,0.1513653}; //FIR coefficients-5*/
          float h[m+1]={0.2502002716,-5.811788924e-006,-0.0002395180782,-7.617651136e-006,5.27895063e-005,
          5.27895063e-005,-7.617651136e-006,-0.0002395180782,-5.811788924e-006,0.2502002716}; //FIR coefficients-10

          float fir(unsigned char n,float *h,float *u,float x);


          #define ADC_VREF_TYPE 0x20

          // Read the 8 most significant bits
          // of the AD conversion result
          unsigned char read_adc(unsigned char adc_input)
          {
          ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
          // Delay needed for the stabilization of the ADC input voltage
          delay_us(10);
          // Start the AD conversion
          ADCSRA|=0x40;
          // Wait for the AD conversion to complete
          while ((ADCSRA & 0x10)==0);
          ADCSRA|=0x10;
          return ADCH;
          }


          // Timer 0 overflow interrupt service routine
          interrupt [TIM0_OVF] void timer0_ovf_isr(void)
          {

          z++;
          while(z%8 == 1)
          {



          sample=read_adc(0);

          sample=0.3529*sample;

          su1+=pow(fir(m,h,u,sample),2);


          }
          }

          // Declare your global variables here

          void main(void)
          {
          char k;


          PORTC=0x00;
          DDRC=0xFF;

          // Timer/Counter 0 initialization
          // Clock source: System Clock
          // Clock value: 1000.000 kHz
          // Mode: Normal top=FFh
          // OC0 output: Disconnected
          TCCR0=0x02;
          TCNT0=0x00;
          OCR0=0x00;
          // Timer(s)/Counter(s) Interrupt(s) initialization
          TIMSK=0x01;
          // ADC initialization
          // ADC Clock frequency: 1000.000 kHz
          // ADC Voltage Reference: AREF pin
          // ADC Auto Trigger Source: Free Running
          // Only the 8 most significant bits of
          // the AD conversion result are used
          ADMUX=ADC_VREF_TYPE & 0xff;
          ADCSRA=0xA3;
          SFIOR&=0x1F;

          for(k=0;k<m;k++)
          u[k]=0.0; //reset delay buffer


          #asm("sei&quot

          while (1)
          {


          };



          }


          float fir(unsigned char n,float *h,float *u,float x){

          char i;
          float y;

          u[0]=x; //read new input sample

          for(y=0,i=0;i<=n;i++)
          y+=h[i]*u[i]; //calculate output

          for(i=n;i>=1;i--) //update delay buffer
          u[i]=u[i-1]; //done in reverse order

          return y;
          }

          دیدگاه


            #6
            پاسخ : فیلتر دیجیتال با AVR

            الگوریتم شما دارای اشکال است ، میتونم به این اشاره کنم که نوشتن whlile در روتین وفقه ی این برنامه مشکل ایجاد میکنه و تابع pow برای به توان رسوندن xبه توان y ساخته شده که هر دو float هستند و این یعنی بار پردازشی بسیار سنگین به cpu که قاعدتا با توجه به کاربرد مورد نظرتون real time نخواهد بود. من الگوریتم زیر رو پیشنهاد میکنم:
            /************************************************** ***
            Chip type : ATmega16
            Program type : Application
            AVR Core Clock frequency: 8.000000 MHz
            Memory model : Small
            External RAM size : 0
            Data Stack size : 256

            Author: Pourya.Soleares
            ************************************************** ***/

            #include <mega16.h>
            #include <delay.h>
            #define m 11
            #define FACTOR 8

            float sample;
            volatile long power=0;

            float u[m+1]; //FIR delay buffer


            float h[m+1]={ 0.06814654917, 0.08101402223, 0.09188619256, 0.1001388431, 0.1052922085,
            0.1070443541, 0.1052922085, 0.1001388431, 0.09188619256, 0.08101402223,
            0.06814654917}; //FIR coefficients-10

            float fir(unsigned char n,float *h,float *u,float x);


            #define ADC_VREF_TYPE 0x20

            // Read the 8 most significant bits
            // of the AD conversion result
            unsigned char read_adc(unsigned char adc_input)
            {
            ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
            // Delay needed for the stabilization of the ADC input voltage
            delay_us(10);
            // Start the AD conversion
            ADCSRA|=0x40;
            // Wait for the AD conversion to complete
            while ((ADCSRA & 0x10)==0);
            ADCSRA|=0x10;
            return ADCH;
            }


            // Timer 0 overflow interrupt service routine
            interrupt [TIM0_OVF] void timer0_ovf_isr(void)
            {
            static unsigned char counter=0;
            float out;
            TCNT0=0x82;

            sample=read_adc(0);

            sample=0.3529*sample;

            out=fir(m,h,u,sample);
            PORTC=(char)out; //filter output

            if(++counter>=FACTOR)
            {
            counter=0; // FACTOR is the factor of downsampling
            power+=out*out;
            PORTD=(char)power; //Calculated power of the Downsampled signal
            }

            }

            // Declare your global variables here

            void main(void)
            {
            char k;

            PORTC=0x00;
            DDRC=0xFF;

            DDRD=0xFF;


            // Timer/Counter 0 initialization
            // Clock source: System Clock
            // Clock value: 1000.000 kHz
            // Mode: Normal top=FFh
            // OC0 output: Disconnected
            TCCR0=0x03;
            TCNT0=0x82;
            OCR0=0x00;
            // Timer(s)/Counter(s) Interrupt(s) initialization
            TIMSK=0x01;
            // ADC initialization
            // ADC Clock frequency: 1000.000 kHz
            // ADC Voltage Reference: AREF pin
            // ADC Auto Trigger Source: Free Running
            // Only the 8 most significant bits of
            // the AD conversion result are used
            ADMUX=ADC_VREF_TYPE & 0xff;
            ADCSRA=0xA3;
            SFIOR&=0x1F;

            for(k=0;k<m;k++)
            u[k]=0.0; //reset delay buffer


            #asm("sei&quot

            while (1)
            {


            };
            }
            float fir(unsigned char n,float *h,float *u,float x){

            char i;
            float y;

            u[0]=x; //read new input sample

            for(y=0,i=0;i<=n;i++)
            y+=h[i]*u[i]; //calculate output

            for(i=n;i>=1;i--) //update delay buffer
            u[i]=u[i-1]; //done in reverse order

            return y;
            }

            دیدگاه


              #7
              پاسخ : فیلتر دیجیتال با AVR

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

              دیدگاه


                #8
                پاسخ : فیلتر دیجیتال با AVR

                اگر بعد از دو ثانیه سیگنال قطع شود،خروجی پردازش صفر نخواهد بود و این میتونه هم به خاطر نویز باشه و هم به خاطر quantization error.
                اگر هم می خوای کلا بعد از چند ثانیه بعد از راه اندازی کلا کار پردازش سیگنال متوقف بشه،خب راه حل سادست:استفاده از یک تایمر دیگه که بعد از زمان مورد نظر بیاد و در اون وقفه ی تایمر صفر رو غیر فعال کنه.
                جهت کامل کردن بحث قبل باید بگم که اشتباهی در مقدار دهی به TCNT0 شده است،در کد خود به جای TCNT0=0x82 قرار دهید TCNT0=0x83 تا فرکانس نمونه برداری دقیقا 1kHz شود. از طرفی در شبیه سازی با پروتئوس وقتی که عمل محاسبه ی توان بدون downsampling انجام شد(یعنی محاسبه توان به ازای هر ورودی جدید،به عبارتی در برنامه عبارات if , static char counter پاک شد) ، نشانه ای از کم آوردن CPU دیده نشد و پردازش به صورت Real-Time انجام شد. پس اگر نگران این بودید،دیگه نباشید!

                دیدگاه


                  #9
                  پاسخ : فیلتر دیجیتال با AVR

                  2 تا TCNT0 وجود داره،شما منظورتون TCNT0 هست که در وقفه تایمر رخ میدهد؟
                  حق با شماست ولی اگر بخواهم صوت رو پردازش کنم باید فرکانس نمونه برداری بالای 6 کیلو هرتز باشه..مثلا 8 کیلو هرتز.
                  از کجا باید بفهمیم نرخ نمونه برداری چقدر هست؟
                  مثلا برای همین 8 کیلو هرتز،چه تغییراتی باید بدهم؟
                  باید در تنظیمات ADC در قسمت(codewizardAVR) گزینه ADC Clock رو تغییر بدهم؟
                  در مورد اینکه مدت 2 ثانیه سیگنال ورودی رو بگیره میشه از طریق وقفه ADC عمل نمود؟..یکم کار با کانترها مشکل هست که دیگر ورودی نگیره؟اون موقع پردازش دیگه صورت نمیگیرد؟

                  با تشکر

                  دیدگاه


                    #10
                    پاسخ : فیلتر دیجیتال با AVR

                    آیا با این تنظیمات تایمر 1 ،تایمر 0 متوقف میشه؟
                    clock timer 1 = 1000 000 khz//
                    // Timer1 overflow interrupt service routine
                    interrupt [TIM1_OVF] void timer1_ovf_isr(void)
                    {
                    TIMSK=0x00;

                    }

                    // Timer/Counter 1 initialization
                    TCCR1A=0x00;
                    TCCR1B=0x02;
                    TCNT1H=0x00;
                    TCNT1L=0x00;
                    ICR1H=0x00;
                    ICR1L=0x00;
                    OCR1AH=0x00;
                    OCR1AL=0x00;
                    OCR1BH=0x00;
                    OCR1BL=0x00;
                    ------------------------------------------------------------------
                    متغیر power که تعریف کردین،آیا میشه در انتهای برنامه اونو call کنم؟چون هدف ارسال متغیر power روی پورت ها نیست..صرفا میخوام بدونم عددش چند هست و با چندتا عدد دیگه در انتهای برنامه مقایسه کنم.

                    بازم ممنون

                    دیدگاه


                      #11
                      پاسخ : فیلتر دیجیتال با AVR


                      خروجی من اینطوری شده!! :eek: یه سیگنال تقریبا پریودیک
                      http://www.iimmgg.com/image/c3a708e118f0f67cc279269895afee70
                      (چون تمامی سایت های اپلود فیلتر شدن مجبور شدم اینجا اپلود کنم)

                      مگه out مثلا نمیشه:[2 3 4 5 0 7 5...] =out
                      [4 9 16 25 0 49 25...]=out*out ؟
                      که اگر داخل متغیر power بریزیم 4+9+16+...
                      بنابراین خروجی از پورت D ، باید در هر لحظه رشد کنه..یعنی یک سیگنال پله ای رو به افزایش باشه..چون همینطور ما داریم ورودی میدیم و خروجی میگیریم و اونها رو جمع میکنیم..

                      دیدگاه


                        #12
                        پاسخ : فیلتر دیجیتال با AVR

                        در مورد اینکه power باید صعودی باشه حق با شماست،اشکال در کامپایلر هستش،به جای:
                        power+=out*out
                        بنویسید:
                        (power=power+(out*out
                        ...........................................
                        در مورد روش کار با تایمر 1 هم کارتون درست هست و این روش جواب میده،فقط اگه میخواین تقریبا 2 ثانیه سیگنال رو بخونید بنویسید:
                        TCCR1A=0x00;
                        TCCR1B=0x04;

                        // Timer(s)/Counter(s) Interrupt(s) initialization
                        TIMSK=0x05;
                        (البته همه ی اینها با فرض کلاک 8MHz هستش)
                        ..........................................
                        متغییر power چون به صورت یک متغییر عمومی تعریف شده،پس همه جا قابل دسترس هستش.

                        دیدگاه


                          #13
                          پاسخ : فیلتر دیجیتال با AVR

                          دوستان من یه سوال دارم..خیلی نیاز دارم یه نفر جوابمو بده..
                          الان فانکشنی که برای فیلتر FIR تعریف شده،میتونم ازش 8 بار در همون وقفه ی 0 ازش استفاده کنم؟
                          یعنی اینجوری باشه:
                          فرض کنید که 8 تا h به صورت
                          h1....h8 که هرکدوم مثلا تعداد آرایه هاشون 50 تا هست تعریف کردم.
                          هر تعداد که تعداد آرایه های h کم میشه و همچنین تعداد فیلترهایی که فراخونی میشه کم میشه..شکل خروجی بهتر میشه..
                          در حال حاضر اگه هر 8 تا فیلتر فراخونی بشه..خروجی کمتر به حالت قبل نزدیک میشه..یعنی سطح های کوانتیزه شکل خروجی کمتر میشه(مثلا اگه در حالت اول یعنی یه فیلتر 30 تا 256 تا سطح باشه..در این حالت اخر 8 تا سطح میشه!!)
                          نمیدونم مشکل کجا هست
                          کلاک سیستم حتی تا 40 مگا بردم ولی تاثیری نداره..نرخ نمونه برداری سیگنال ورودی هم تاثیری نداره..


                          float sample;

                          float u[m+1];


                          float fir(unsigned char n,float *h1,float *u,float x);
                          float fir(unsigned char n,float *h2,float *u,float x);
                          //float fir(unsigned char n,float *h3,float *u,float x);
                          //float fir(unsigned char n,float *h4,float *u,float x);
                          //float fir(unsigned char n,float *h5,float *u,float x);
                          //float fir(unsigned char n,float *h6,float *u,float x);
                          //float fir(unsigned char n,float *h7,float *u,float x);
                          //float fir(unsigned char n,float *h8,float *u,float x);


                          #define ADC_VREF_TYPE 0x20

                          // Read the 8 most significant bits
                          // of the AD conversion result
                          unsigned char read_adc(unsigned char adc_input)
                          {
                          ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
                          // Delay needed for the stabilization of the ADC input voltage
                          delay_us(10);
                          // Start the AD conversion
                          ADCSRA|=0x40;
                          // Wait for the AD conversion to complete
                          while ((ADCSRA & 0x10)==0);
                          ADCSRA|=0x10;
                          return ADCH;
                          }


                          // Timer 0 overflow interrupt service routine
                          interrupt [TIM0_OVF] void timer0_ovf_isr(void)
                          {

                          float out1, out2, out3, out4, out5, out6, out7, out8;
                          TCNT0=0x83;

                          sample=read_adc(0);

                          sample=0.3529*sample;

                          out1=fir(p,h1,u,sample);
                          out2=fir(t,h2,u,sample);
                          //out3=fir(t,h3,u,sample);
                          //out4=fir(t,h4,u,sample);
                          //out5=fir(t,h5,u,sample); //filter outputs
                          //out6=fir(t,h6,u,sample);
                          //out7=fir(t,h7,u,sample);
                          //out8=fir(m,h8,u,sample);


                          PORTC=(int)out1;




                          // Timer1 overflow interrupt service routine
                          interrupt [TIM1_OVF] void timer1_ovf_isr(void)
                          {
                          TIMSK=0x00;

                          }



                          // Declare your global variables here

                          void main(void)
                          {
                          char k;

                          PORTC=0x00;
                          DDRC=0xFF;

                          DDRD=0xFF;


                          // Timer/Counter 0 initialization
                          // Clock source: System Clock
                          // Clock value: 125 kHz
                          // Mode: Normal top=FFh
                          // OC0 output: Disconnected
                          TCCR0=0x03;
                          TCNT0=0x82;
                          OCR0=0x00;

                          // Timer/Counter 1 initialization
                          // Clock source: System Clock
                          // Clock value: Timer1 Stopped
                          // Mode: Normal top=0xFFFF
                          // OC1A output: Discon.
                          // OC1B output: Discon.
                          // Noise Canceler: Off
                          // Input Capture on Falling Edge
                          // Timer1 Overflow Interrupt: On
                          // Input Capture Interrupt: Off
                          // Compare A Match Interrupt: Off
                          // Compare B Match Interrupt: Off
                          TCCR1A=0x00;
                          TCCR1B=0x03;
                          TCNT1H=0x00;
                          TCNT1L=0x00;
                          ICR1H=0x00;
                          ICR1L=0x00;
                          OCR1AH=0x00;
                          OCR1AL=0x00;
                          OCR1BH=0x00;
                          OCR1BL=0x00;







                          // Timer(s)/Counter(s) Interrupt(s) initialization
                          TIMSK=0x05;
                          // ADC initialization
                          // ADC Clock frequency: 1000.000 kHz
                          // ADC Voltage Reference: AREF pin
                          // ADC Auto Trigger Source: Free Running
                          // Only the 8 most significant bits of
                          // the AD conversion result are used
                          ADMUX=ADC_VREF_TYPE & 0xff;
                          ADCSRA=0xA3;
                          SFIOR&=0x1F;

                          for(k=0;k<m;k++)
                          u[k]=0.0; //reset delay buffer


                          #asm("sei&quot

                          while (1)
                          {


                          };
                          }
                          float fir(unsigned char n,float *h,float *u,float x){

                          char i;
                          float y;

                          u[0]=x; //read new input sample

                          for(y=0,i=0;i<=n;i++)
                          y+=h[i]*u[i]; //calculate output

                          for(i=n;i>=1;i--) //update delay buffer
                          u[i]=u[i-1]; //done in reverse order

                          return y;
                          }

                          دیدگاه


                            #14
                            پاسخ : فیلتر در اردوینور

                            [QUOTE=soleares;189976]سلام به همگی...
                            در این پروژه که لینکش رو در زیر قرار دادم یک فیلتر دیجیتال با AVR پیاده کردم..فقط یادتون باشه که مقادیر ولتاژ غیر واقعییند و برای پیاده سازی به صورت عملی یکم تغییرات ساده ای اعمال کنید.


                            تو این فایلها هم برنامه ی نوشته شده برای FIR هست،هم برای IIR،تو برنامه من برای هر کدوم دو سری ضرایب نوشتم ، شما میتونید ضریب دلخواه رو با پاک کردن /*......*/ وارد برنامه کنین و البته مرتبه ی فیلتر رو هم با تغییر متغیر m تصحیح کنید، این کار رو برای این کردم تا متوجه تغییر پاسخ فیلتر متناسب با مرتبه بشین،مثلا برای فیلتر FIR یک سری ضریاب مرتبه ی 5 هست ویک سری ضرایب مرتبه 10 ، یا برای فیلر IIR یک سری ضرایب Butterworth هست ، و یک سری ضرایب Bessel .
                            یک مطلب جالبی که در امر پردازش سیگنال دیجیتال وجود داره،میشه در این پروژه به چشم دید و اون پدیده ی در هم روی(Aliasing)هست...از اونجا که این یک فیلتر دیجیتال پایین گذر با فرکانس فطع 100 هرتز هست،انتظار میره که در فرکانس مثلا 1.2k هرتز هیچ سیگنالی عبور نکنه،اما به دلیل اینکه این فرکانس از نصف فرکانس نمونه برداری بزگتره(فرکانس نایکوییست) ، فیلتر اون رو عبور میده.

                            http://upload.yazdkit.com/download.p...gital%20Filter[.rar/QUOTE]

                            دیدگاه

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