Problem with filter desinger

General discussion on mikroC for dsPIC30/33 and PIC24.
Post Reply
Author
Message
tachin85
Posts: 2
Joined: 10 Jul 2009 20:01

Problem with filter desinger

#1 Post by tachin85 » 10 Dec 2009 19:20

Hi!

I'm doing a digital filter using the filter design tool mickro c for dsPIC, but I dont have the card mikroe development, I'm using the DSPIC30F4013 and the first problem I have is the ADC sampling rate, I sampled at 22kHz and just rebuild it up to 4kHz frequency, someone can tell me where I'm wrong. the ADC is programmed using the design tool mikroc filters.
and sorry for my english.

// This code was generated by filter designer tool by mikroElektronika
// Date/Time: 10/12/2009 10:28:37 a.m.
// Support info: http://www.mikroe.com

// Device setup:
// Device name: P30F4013
// Device clock: 012.000000 MHz
// Sampling Frequency: 22050 Hz
// Filter setup:
// Filter kind: IIR
// Filter type: Lowpass filter
// Filter order: 6
// Design method: Chebyshev type II

const unsigned int
BUFFER_SIZE = 8;
const unsigned int
FILTER_ORDER = 6;
const signed int
COEFF_B[FILTER_ORDER+1] = {
0x12AF, 0x226B, 0x3BC5, 0x4218, 0x3BC5, 0x226B, 0x12AF};
const signed int
COEFF_A[FILTER_ORDER+1] = {
0x2000, 0xAD3E, 0x6A84, 0xB1D2, 0x2287, 0xF78D, 0x00E7};
const unsigned int
SCALE_B = 4; //
const unsigned int
SCALE_A = -2; //
const unsigned int
LOAD_PIN = 4; // DAC load pin
const unsigned int
CS_PIN = 5; // DAC CS pin

unsigned int inext; // Input buffer index
unsigned int input[BUFFER_SIZE]; // Input buffer
unsigned int output[BUFFER_SIZE]; // Output buffer

// This is ADC interrupt handler.
// Analogue input is sampled and the value is stored into input buffer.
// Input buffer is then passed through filter.
// Finally, the resulting output sample is sent to DAC.
void ADC1Int() org 0x2A { // ADC interrupt handler
unsigned int CurrentValue;

input[inext] = ADCBUF0; // Fetch sample

CurrentValue = IIR_Radix( SCALE_B, //
SCALE_A, //
COEFF_B, // b coefficients of the filter
COEFF_A, // a coefficients of the filter
FILTER_ORDER+1,// Filter order + 1
input, // Input buffer
BUFFER_SIZE, // Input buffer length
output, // Input buffer
inext); // Current sample

output[inext] = CurrentValue;

inext = (inext+1) & (BUFFER_SIZE-1); // inext = (inext + 1) mod BUFFER_SIZE;

LATB=ADCBUF0;

IFS0.F11 = 0; // Clear AD1IF
} //~

// This is Timer1 interrupt handler.
// It is used to start ADC at
// periodic intervals.
void Timer1Int() org 0x1A { // Timer1 interrupt handler

ADCON1.F1 = 1; // Start sampling
ADCON1.F15 = 1; // Start conversion

IFS0.F3 = 0; // Clear TMR1IF
} //~


// Main program starts here.
// Firstly, hardware peripherals are initialized and then
// the program goes to an infinite loop, waiting for interrupts.
void main() {
inext = 0; // Initialize buffer index
Vector_Set(input, BUFFER_SIZE, 0); // Clear input buffer
Vector_Set(output, BUFFER_SIZE, 0); // Clear output buffer

// ADC setup
TRISB = 0x0003; // Use PORTB for input signal
ADCON1 = 0x00E2; // Auto-stop sampling, unsigned integer out
ADCON2 = 0x0000;
ADCON3 = 0x0204; // Sampling time= 3*Tad, minimum Tad selected
ADPCFG = 0x0000; // Configure PORTB as ADC input port
ADCHS = 0x0001; // Sample input on RB1
ADCSSL = 0; // No input scan

// Interrupts setup
IFS0 = 0;
IFS1 = 0;
IFS2 = 0;
INTCON1 = 0x8000; // Nested interrupts DISABLED
INTCON2 = 0;
IEC0 = 0x0808; // Timer1 and ADC interrupts ENABLED
IPC0.F12= 1; // Timer1 interrupt priority level = 1
IPC2.F13= 1; // ADC interrupt priority level = 2

// Timer2 setup
PR1 = 0x0015; // Sampling = 22050 Hz. Value of PR1 is dependent on clock.
T1CON = 0x8000; // Timer1 ON, internal clock FCY, prescaler 1:1

while (1); // Infinite loop,
// wait for interrupts
} //~

User avatar
zristic
mikroElektronika team
Posts: 6608
Joined: 03 Aug 2004 12:59
Contact:

Re: Problem with filter desinger

#2 Post by zristic » 11 Dec 2009 11:19

The value of 0x15 for the PR1 register is too low. Your timer interrupt is too frequent, you have to slow it down in order for the example to work.

This is how to calculate the value of PR1:

Code: Select all

PR1 = (unsigned long)(Get_Fosc_kHz()) * 1000 / (4 * SAMPLE_FREQ); 
"Get_Fosc_kHz" returns the frequency set in Project Settings in mikroIDE.

Also, if you are changing the sampling frequency you have to change the coefficients of the filter. The Filter Designer Tool helps you to do it.

I hope this helps.

edwardcullen
Posts: 93
Joined: 02 Sep 2010 20:27

Re: Problem with filter desinger

#3 Post by edwardcullen » 26 Nov 2010 15:24

hello sorry to barge like that but i have a problem:
want to sample at 125khz and am confused how to do it!!!
look below i have 2 programs and dunt know which i should use:
first one:::

Code: Select all

// Device setup:
//     Device name: P30F6014A
//     Device clock: 080.000000 MHz
//     Sampling Frequency: 40 kHz
// Filter setup:
//     Filter kind: IIR
//     Filter type: Lowpass filter
//     Filter order: 3
//     Design method: Butterworth
//     Filter borders:
//       Wpass:4000 Hz

const unsigned int  BUFFER_SIZE  = 8;
const unsigned int  FILTER_ORDER  = 3;
const signed int    COEFF_B[FILTER_ORDER+1] = {0x2511, 0x6F33, 0x6F33, 0x2511};
const signed int    COEFF_A[FILTER_ORDER+1] = {0x4000, 0x8F5B, 0x4BB5, 0xEE34};
const unsigned int  SCALE_B       = 4;
const unsigned int  SCALE_A       = -1;
  
const unsigned int  LOAD_PIN      = 2;   // DAC load pin
const unsigned int  CS_PIN        = 1;   // DAC CS pin

unsigned int inext;                      // Input buffer index
ydata unsigned int input[BUFFER_SIZE];   // Input buffer
ydata unsigned int output[BUFFER_SIZE];  // Output buffer

// This is ADC interrupt handler.
// Analog input is sampled and the value is stored into input buffer.
// Input buffer is then passed through filter.
// Finally, the resulting output sample is sent to DAC.
void ADC1Int() org 0x2A {                // ADC interrupt handler
unsigned int CurrentValue;
  latd  = portd ^ 0xffff;
  input[inext] = ADCBUF0;                // Fetch sample

  CurrentValue = IIR_Radix( SCALE_B,     //
                            SCALE_A,     //
                            COEFF_B,     // b coefficients of the filter
                            COEFF_A,     // a coefficients of the filter
                            FILTER_ORDER+1,// Filter order + 1
                            input,       // Input buffer
                            BUFFER_SIZE, // Input buffer length
                            output,      // Input buffer
                            inext);      // Current sample

//  CurrentValue = 2048;
  output[inext] = CurrentValue;

  inext = (inext+1) & (BUFFER_SIZE-1);   // inext = (inext + 1) mod BUFFER_SIZE;

  LATC.CS_PIN = 0;                       // CS enable for DAC
  SPI2BUF = 0x3000 | CurrentValue;       // Write CurrentValue to DAC ($3 is required by DAC)
  while (SPI2STAT.F1 == 1);              // Wait for SPI module to finish write
  LATC.LOAD_PIN  = 0;                    // Load data in DAC
  delay_us(2);
  LATC.LOAD_PIN  = 1;                    //
  LATC.CS_PIN    = 1;                    // CS disable for DAC

  IFS0.F11 = 0;                          // Clear AD1IF
} //~

// This is Timer1 interrupt handler.
// It is used to start ADC at
//     periodic intervals.
void Timer1Int() org 0x1A {              // Timer1 interrupt handler
  if (ADCON1.DONE == 1){                 // If ADC is not busy
    ADCON1.SAMP  = 1;                    // Start new sample
  }
 LATD = PORTD ^ 0xFFFF;

  IFS0.F3    = 0;                        // Clear TMR1IF
} //~


// Main program starts here.
// Firstly, hardware peripherals are initialized and then
//   the program goes to an infinite loop, waiting for interrupts.
void main() {
  TRISD = 0;
  // DAC setup
  TRISC.LOAD_PIN = 0;                    // LOAD pin
  TRISC.CS_PIN   = 0;                    // CS pin
  LATC.CS_PIN    = 1;                    // Set CS to inactive
  LATC.LOAD_PIN  = 1;                    // Set LOAD to inactive

  // SPI setup
  Spi2_Init_Advanced(_SPI_MASTER, _SPI_16_BIT,_SPI_PRESCALE_SEC_1, _SPI_PRESCALE_PRI_1,
                     _SPI_SS_DISABLE, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_HIGH,
                     _SPI_ACTIVE_2_IDLE);
  SPI2STATbits.SPIROV = 0;
  SPI2STATbits.SPIEN = 1;

  inext   = 0;                           // Initialize buffer index
  Vector_Set(input, BUFFER_SIZE, 0);     // Clear input buffer
  Vector_Set(output, BUFFER_SIZE, 0);    // Clear output buffer
  
  TRISB   = 0xFFFF;                      // Use PORTB for input signal
  ADCON1  = 0x00E2;                      // Auto-stop sampling, unsigned integer out
  ADCON2  = 0x0000;
  ADCON3  = 0x021A;                      // Sampling time= 3*Tad, minimum Tad selected
  ADPCFG  = 0x0000;                      // Configure PORTB as ADC input port
  ADCHS   = 0x000A;                      // Sample input on RB10
  ADCSSL  = 0;                           // No input scan
  ADPCFG  = 0x0000;                      // Configure PORTB as analog ADC input port

  // Interrupts setup
  IFS0    = 0;
  IFS1    = 0;
  IFS2    = 0;
  INTCON1 = 0x8000;                       // Nested interrupts DISABLED
  INTCON2 = 0;
  IEC0    = 0x0808;                       // Timer1 and ADC interrupts ENABLED
  IPC0.F12= 1;                            // Timer1 interrupt priority level = 1
  IPC2.F13= 1;                            // ADC interrupt priority level = 1

  // Timer1 setup
  PR1     = 250;                          // Sampling ~= 40 kHz. The value of 250 is calculated for 80MHz clock.
  T1CON   = 0x8000;                       // Timer1 ON, internal clock FCY, prescaler 1:1
  ADCON1.F15 = 1;
  ADCON1.SAMP  = 1;
  while (1);                              // Infinite loop,
                                          //   wait for interrupts
} //~



second program:::

Code: Select all


#include "p30fxxxx.h"
#include "common.h"
#include "dsp.h"

extern fractional inputSignal[NUMSAMP];
extern int doFilterFlag;
extern fractional* iPtr;

//Functions and Variables with Global Scope:
void ADC_Init(void);
void __attribute__((__interrupt__)) _ADCInterrupt(void);

volatile unsigned int * adcPtr;

//Functions:
//ADC_Init() is used to configure A/D to convert 16 samples of 1 input
//channel per interrupt. The A/D is set up for a sampling rate of 8KHz
//Timer3 is used to provide sampling time delay.
//The input pin being acquired and converted is AN7.
void ADC_Init(void)
{
        //ADCON1 Register
        //Set up A/D for Automatic Sampling
        //Use Timer3 to provide sampling time
        //Set up A/D conversrion results to be read in 1.15 fractional
        //number format.
        //All other bits to their default state
        ADCON1bits.FORM = 3;
        ADCON1bits.SSRC = 2;
        ADCON1bits.ASAM = 1;

        //ADCON2 Register
        //Set up A/D for interrupting after 16 samples get filled in the buffer
        //All other bits to their default state
        ADCON2bits.SMPI = 15;

        //ADCON3 Register
        //We would like to set up a sampling rate of 8KHz
        //Total Conversion Time= 1/Sampling Rate = 125 microseconds
        //At 29.4 MIPS, Tcy = 33.9 ns = Instruction Cycle Time
        //Tad > 667ns (for -40C to 125C temperature range)
        //We will set up Sampling Time using Timer3 & Tad using ADCS<5:0> bits
        //All other bits to their default state
        //Let's set up ADCS arbitrarily to the maximum possible amount = 63
        //So Tad = Tcy*(ADCS+1)/2 = 1.085 microseconds
        //So, the A/D converter will take 14*Tad periods to convert each sample
        ADCON3bits.ADCS = 63;

        //Next, we will to set up Timer 3 to time-out every 125 microseconds
        //As a result, the module will stop sampling and trigger a conversion
        //on every Timer3 time-out, i.e., 125 microseconds. At that time,
        //the conversion process starts and completes 14*Tad periods later.
        //When the conversion completes, the module starts sampling again
        //However, since Timer3 is already on and counting, about 110
        //microseconds later (=125 microseconds - 14*Tad), Timer3 will expire
        //again. Effectively, the module samples for 110 microseconds and
        //converts for 15 microseconds
        //NOTE: The actual sampling rate realized may be 7998.698 Hz
        //      due to a small round off error. Ensure you provide the
        //      true sampling rate to dsPICworks if you are trying to plot
        //      the sampled or filtered signal.
        TMR3 = 0x0000;
        PR3 = SAMPCOUNT;
        IFS0bits.T3IF = 0;
        IEC0bits.T3IE = 0;

        //ADCHS Register
        //Set up A/D Channel Select Register to convert AN7 on Mux A input
        ADCHS = 0x0007;

        //ADCSSL Register
        //Channel Scanning is disabled. All bits left to their default state
        ADCSSL = 0x0000;

        //ADPCFG Register
        //Set up channels AN7 as analog input and configure rest as digital
        //Recall that we configured all A/D pins as digital when code execution
        //entered main() out of reset
        ADPCFG = 0xFFFF;
        ADPCFGbits.PCFG7 = 0;

        //Clear the A/D interrupt flag bit
        IFS0bits.ADIF = 0;

        //Set the A/D interrupt enable bit
        IEC0bits.ADIE = 1;

        //Turn on the A/D converter
        //This is typically done after configuring other registers
        ADCON1bits.ADON = 1;

        //Start Timer 3
        T3CONbits.TON = 1;
}

//_ADCInterrupt() is the A/D interrupt service routine (ISR).
//The routine must have global scope in order to be an ISR.
//The ISR name is chosen from the device linker script.
void __attribute__((interrupt, no_auto_psv)) _ADCInterrupt(void)
{
        //Clear the Timer3 Interrupt Flag
        IFS0bits.T3IF = 0;

        int i = 0;

        //Clear the A/D Interrupt flag bit or else the CPU will
        //keep vectoring back to the ISR
        IFS0bits.ADIF = 0;

        //Copy the A/D conversion results to variable "inputSignal"
        adcPtr = &ADCBUF0 ;
        for (i=0;i<16;i++)
        {
                *iPtr++ = *adcPtr++;
        }
        if (iPtr > &inputSignal[NUMSAMP]) doFilterFlag = 1;

}

help me here plz am so confused!!!!

thanks in advance

my chip is dspic30f4013
and am using c-language

Post Reply

Return to “mikroC for dsPIC30/33 and PIC24 General”