Go Down

Topic: Filter library test (Read 25047 times) previous topic - next topic

AdaZus

please check attached picture: ;)

AdaZus

#16
May 15, 2014, 01:52 pm Last Edit: May 15, 2014, 02:06 pm by AdaZus Reason: 1
Hello,
now I wrote a sketch like described in my previous posts.
Switch a LED on if amplitude from filtered signal reaches an arbitrary level:

Code: [Select]
// Arduino Signal Filtering and LED on if filter amplitude reaches an arbitrary threshold.
// 2014

// Arduino Signal Filtering Library
// Copyright 2012-2013 Jeroen Doggen (jeroendoggen@gmail.com)
//http://jeroendoggen.github.io/Arduino-signal-filtering-library/
//http://www.schwietering.com/jayduino/filtuino/


#include <SignalFilter.h>  // Filter Library
SignalFilter Filter;

//const int analogPin = A0;    // pin that the sensor is attached to
const int ledPin = 13;         // pin that the LED is attached to
const int threshold = 1000;    // an arbitrary threshold level that's in the range of the analog input


unsigned long time_start;    // variable for time measurement start
unsigned long time_sampl;    // variable for time measurement sample


unsigned int data1;     
unsigned int data2;     

int incomingByte = 0;


void setup()
{

  pinMode(ledPin, OUTPUT);     // initialize the LED pin as an output:
  Serial.begin(9600);
  Filter.begin();
  Filter.setFilter('c');       // filter settings: c=Cebycheff  b= Bessel
  Filter.setOrder(2);          // filter settings: order 1 or 2
       
}
/*
      Filter characteristics are stored in: “SignalFilter.cpp”.
      Current filter settings and code: for “c” “2”

  /// runChebyshev: Low Pass; 2nt Order; cutoff =300Hz; sampling=5000Hz; long type 8bit;
  “-1bit saturation” enabled;
                        _v[0] = _v[1];
_v[1] = _v[2];
long tmp = ((((data * 3009876L) >>  6) //= (   2.2425325955e-2 * x)
+ ((_v[0] * -3295982L) >> 1) //+( -0.7858234574*v[0])
+ (_v[1] * 3557026L) //+(  1.6961221536*v[1])
)+1048576) >> 21; // round and downshift fixed point /2097152

_v[2]= (short)tmp;
return (short)((
(_v[0] + _v[2])
+2 * _v[1])); // 2^ 
*/


void loop()
{
   
  //Read Analog Input... you can connect accelerometer, gyro, temperature sensor, microphone etc to the channel
 
// int data1 = analogRead(analogPin);
  data1 = analogRead(0);       //Read Analog channels
  data2 = Filter.run(data1);   //Read the filtered signal


  time_start = micros();               //time measurement
   data1 = analogRead(0);              // for Analog Pin A0
   data2 = Filter.run(data1);          // for filter calculation
   time_sampl = micros() - time_start; //time measurement math
 
 
 
  if (Serial.available() > 0) {
    incomingByte = Serial.read();
    if (incomingByte == 'm') {         // enter and sent "m" in serial monitor window and read time in microsec for Filter.run(data1) and analog read
    Serial.print("Time Sample = ");
    Serial.println(time_sampl, DEC);
        }
      }
     
/*
http://arduino.cc/en/Tutorial/IfStatement
the variable called analogValue is used to store the data collected from a Analog Pin A0.
This data is then compared to a threshold value.
If the analog value is found to be above the set threshold the LED connected to digital pin 13 is turned on.
If analogValue is found to be < threshold, the LED remains off. */
     
      // read the value of the microphone:
      // int analogValue = analogRead(analogPin);

  // if the filter value is high enough, turn on the LED:
  if (data2 > threshold) {
    digitalWrite(ledPin, HIGH);
  }
  else {
    digitalWrite(ledPin,LOW);
  }
     
   // print the analog value:
   // Serial.print("In: ");
   // Serial.print(data1);
   // Serial.print(" - Out: ");
   // Serial.println(data2);
   // delay(500);        // delay in between reads for stability
     
         
}   



To check if the sketch works, firstly I did some test directly on A0. I set threshold level to 1000 and it works fine: If I speak in the microphone the LED turns on, if not the LED remains dark.
Then I made tests with the filtered signal. Insert data2 instead of data1 at code:
  if (data2 > threshold) {
    digitalWrite(ledPin, HIGH);…..
but now the LED switches on and off randomly!  :(
I think the filter gives out incorrect numbers. But before I`m goning to check this I have another question:
Are the input signals correctly for filter computation? 
Because the microphone gives out a value off ca. 512 (1024/2) if it`s quite, and when it's loud a signal of 1024 or 0. In the microphone circuit is implemented a DC offset. So the microphone waves doesn't oscillate around 0V but around 2,5V. See also:
http://www.instructables.com/id/Arduino-Audio-Input/step4/DC-Offset/
Here the schematic, of my microphone:
https://www.sparkfun.com/datasheets/BreakoutBoards/Amplified-Mic-Electret-v14.pdf
a plot from Maxy-B:
http://de.tinypic.com/view.php?pic=slscnt&s=7#.U3SmqSga670
(see also comments on: https://www.sparkfun.com/products/9964)
This should be correct because you can work whit the whole wave of the input signal.
But are these signals also ok for filter calculation?

Magician

Quote
Are the input signals correctly for filter computation?

Good question, you should subtract DC offset. Other things, declare data1 and data2 as signed. And you don't need time measurements anymore, otherwise you are reading input twice.
Code: [Select]
// int data1 = analogRead(analogPin);    <-- int, not unsigned int !
  data1 = analogRead(0) -512;       //Read Analog channels
  data2 = Filter.run(data1);   //Read the filtered signal

AdaZus

Hello Magician, thank you very much for the support! Now it works!
I tested it with a sweep from 0-1000Hz. LED on until ca. 400Hz (threshold= 512). LED off, for all frequencies above. I set cut off at 300Hz, the LED switches off only at 400Hz. I think this can have to do with the filter curve and the characteristics which defines them… Chebyshev or Bessel; order...
Here the code:

Code: [Select]
// Arduino Signal Filtering Test
// Turn a LED on if filter amplitude reaches an arbitrary threshold.
// 2014 

// Arduino Signal Filtering Library
// Copyright 2012-2013 Jeroen Doggen (jeroendoggen@gmail.com)
//http://jeroendoggen.github.io/Arduino-signal-filtering-library/
//http://www.schwietering.com/jayduino/filtuino/


#include <SignalFilter.h>  // Filter Library
SignalFilter Filter;

const int ledPin = 13;        // pin that the LED is attached to
const int threshold = 512;    // an arbitrary threshold level that's in the range of the analog input

/* Variable for time measurement
unsigned long time_start;    // variable for time measurement start
unsigned long time_sampl;    // variable for time measurement sample
int incomingByte = 0;        // sets incoming Byte to 0
*/

int data1;     // variable for Analog In
int data2;     // variable for filter


void setup()
{
  pinMode(ledPin, OUTPUT);     // initialize the LED pin as an output:
// Serial.begin(9600);        // used only printing (debugging)
  Filter.begin();
  Filter.setFilter('c');       // filter settings: c=Cebycheff  b= Bessel
  Filter.setOrder(2);          // filter settings: order 1 or 2     
}

/*
      Filter characteristics are stored in: "SignalFilter.cpp".
      Current filter settings and code: for "c" "2"

  /// runChebyshev: Low Pass; 2nt Order; cutoff =300Hz; sampling=5000Hz; long type 8bit;
  "-1bit saturation" enabled;
                        _v[0] = _v[1];
_v[1] = _v[2];
long tmp = ((((data * 3009876L) >>  6) //= (   2.2425325955e-2 * x)
+ ((_v[0] * -3295982L) >> 1) //+( -0.7858234574*v[0])
+ (_v[1] * 3557026L) //+(  1.6961221536*v[1])
)+1048576) >> 21; // round and downshift fixed point /2097152

_v[2]= (short)tmp;
return (short)((
(_v[0] + _v[2])
+2 * _v[1])); // 2^ 
*/


void loop()
{
// Read Analog Input... you can connect accelerometer, gyro, temperature sensor, microphone etc to the channel
 
  data1 = analogRead(0)-512;      //Read Analog channel (value of microphone) and substract DC-Offset from Microphone "BOB-09964"
  data2 = Filter.run(data1);      //Read the filtered signal
 
/*
http://arduino.cc/en/Tutorial/IfStatement
the variable called data1 is used to store the data collected from a Analog Pin A0.
This data is then compared to a threshold value.
If the the value is found to be above the set threshold the LED connected to digital pin 13 is turned on.
If analogValue is found to be < threshold, the LED remains off. */


  // if the filter value is high enough, turn on the LED:
  if (data2 > threshold) {
    digitalWrite(ledPin, HIGH);
  }
  else {
    digitalWrite(ledPin,LOW);
  }
   
   /* time measurement for debugging:

   time_start = micros();               //time measurement
   data1 = analogRead(0);              // for Analog Pin A0
   data2 = Filter.run(data1);          // for filter calculation
   time_sampl = micros() - time_start; //time measurement math
 
  if (Serial.available() > 0) {
    incomingByte = Serial.read();
    if (incomingByte == 'm') {         // enter and sent "m" in serial monitor window and read time in microsec for Filter.run(data1) and analog read
    Serial.print("Time Sample = ");
    Serial.println(time_sampl, DEC);
        }
      } */
}   


If you see further errors or if you have improvement suggestions please write me.
Now I'm going to implement a BandPassFilter. Let's see if I can make it! ;)   

AdaZus

#19
May 16, 2014, 06:29 pm Last Edit: May 16, 2014, 06:31 pm by AdaZus Reason: 1
Hello, I have a further question now:
Beside the filter I want also generate sine-waves (0Hz-500Hz) with the Arduino.
I thought I could use one of these methods:
DDS
http://interface.khm.de/index.php/lab/experiments/arduino-dds-sinewave-generator/
DAC (Digital Analog Converter)
http://www.instructables.com/id/Arduino-Audio-Output/?ALLSTEPS
http://makezine.com/projects/make-35/advanced-arduino-sound-synthesis/
but they are maybe to heavy for the microcontroller (slow sample rate). I did some tests and the filter didn’t work anymore.
What do you think, it’s principally possible to use a filter and generate sine-waves simultaneously?
I found also this Audio Shield:
https://learn.adafruit.com/adafruit-wave-shield-audio-shield-for-arduino/design
Maybe that’s a good solution because it works “asynchronously as an interrupt, so the Arduino can perform tasks while the audio is playing.”

What do you think about? Do you know maybe other methods to generate sine-waves which don’t overload the microcontroller?

Magician

Quote
What do you think, it's principally possible to use a filter and generate sine-waves simultaneously?

Sure, it's possible. 500 Hz is quite low freq.,
Quote
I did some tests and the filter didn't work anymore.
It happenes, when two subfunction interfere with each other.

AdaZus

Quote
It happenes, when two subfunction interfere with each other.


I did a little bit of research in the last 2 days. I don't know if I'm right, but I think a good solution to run two subroutines (subfunction) in a like simultaneous way is the use of interrupts:
http://www.instructables.com/answers/How-do-you-run-more-than-one-subroutine-at-the-sam/
I tried to understand how this project works:
http://makezine.com/projects/make-35/advanced-arduino-sound-synthesis/
"We use timer2 to regularly interrupt the CPU and call a special function to load…"
So they are already using interrupts and the processor should have enough time to calculate filter.
Consideration this I did further tests with this sketch and the filter sketch merged together:
Code: [Select]
// Arduino:
// Generating sine waves
//http://makezine.com/projects/make-35/advanced-arduino-sound-synthesis/
// Filter
// Turn a LED on if filter amplitude reaches an arbitrary threshold.
// 2014 

// Arduino Signal Filtering Library
// Copyright 2012-2013 Jeroen Doggen (jeroendoggen@gmail.com)
//http://jeroendoggen.github.io/Arduino-signal-filtering-library/
//http://www.schwietering.com/jayduino/filtuino/

// and generate a Sinewave
/******** Load AVR timer interrupt macros ********/
//http://makezine.com/projects/make-35/advanced-arduino-sound-synthesis/


#include <avr/interrupt.h>  // library for Sinewave

//Sine wave parameters
#define PI2     6.283185  // 2 * PI - saves calculating it later
#define AMP     127       // Multiplication factor for the sine wave
#define OFFSET  128       // Offset shifts wave to just positive values

// Lookup table
#define LENGTH  256  // The length of the waveform lookup table
byte wave[LENGTH];   // Storage for the waveform




#include <SignalFilter.h>  // Filter Library
SignalFilter Filter;

const int ledPin = 13;        // pin that the LED is attached to
const int threshold = 480;    // an arbitrary threshold level that's in the range of the analog input

/* // Variable for time measurement
unsigned long time_start;     // variable for time measurement start
unsigned long time_sampl;     // variable for time measurement sample
int incomingByte = 0;         // sets incoming Byte to 0 */


int data1;     // variable for Analog In
int data2;     // variable for filter


void setup()
{
 
// Filter Parameters
  pinMode(ledPin, OUTPUT);      // initialize the LED pin as an output:
  /* Serial.begin(9600);        // used only for printing (debugging) */
  Filter.begin();
  Filter.setFilter('c');       // filter settings: c=Cebycheff  b= Bessel
  Filter.setOrder(2);          // filter settings: order 1 or 2   


// Sinewave Parameters
// Populate the waveform lookup table with a sine wave
  for (int i=0; i<LENGTH; i++) {          // Step across wave table
    float v = (AMP*sin((PI2/LENGTH)*i));  // Calculate current entry
    wave[i] = int(v+OFFSET);              // Store value as integer
  }
 
  // Set timer1 for 8-bit fast PWM output
  pinMode(9, OUTPUT);       // Make timer's PWM pin an output
  TCCR1B  = (1 << CS10);    // Set prescaler to full 16MHz
  TCCR1A |= (1 << COM1A1);  // PWM pin to go low when TCNT1=OCR1A
  TCCR1A |= (1 << WGM10);   // Put timer into 8-bit fast PWM mode
  TCCR1B |= (1 << WGM12);

  // Set up timer 2 to call ISR
  TCCR2A = 0;               // We need no options in control register A
  TCCR2B = (1 << CS21);     // Set prescaller to divide by 8
  TIMSK2 = (1 << OCIE2A);   // Set timer to call ISR when TCNT2 = OCRA2
  OCR2A = 32;               // sets the frequency of the generated wave (32=246.94Hz)
  sei();                    // Enable interrupts to generate waveform!
 
}


/*
      Filter characteristics are stored in: "SignalFilter.cpp".
      Current filter settings and code: for "c" "2"

/// runChebyshev: Bandpass 220Hz; 1. Order; lower corner=215Hz; upper corner=225Hz; sampling=5000Hz; long type 8bit; enabled "-1 bit saturation";
_v[0] = _v[1];
_v[1] = _v[2];
long tmp = ((((data * 3360365L) >>  8) //= (   6.2591678898e-3 * x)
+ ((_v[0] * -4141801L) >> 1) //+( -0.9874824279*v[0])
+ (_v[1] * 4009861L) //+(  1.9120508347*v[1])
)+1048576) >> 21; // round and downshift fixed point /2097152

_v[2]= (short)tmp;
return (short)((
(_v[2] - _v[0]))); // 2^
*/


void loop()
{
// Read Analog Input... you can connect accelerometer, gyro, temperature sensor, microphone etc to the channel
 
  data1 = analogRead(0)-512;      //Read Analog channel (value of microphone) and substract DC-Offset from microphone "BOB-09964"
  data2 = Filter.run(data1);      //Read the filtered signal
 

// http://arduino.cc/en/Tutorial/IfStatement

  // if the filter value is high enough, turn on the LED:
  if (data2 > threshold) {
    digitalWrite(ledPin, HIGH);
  }
  else {
    digitalWrite(ledPin,LOW);
  }
   
   /*
    // time measurement for debugging:
   time_start = micros();               //time measurement
   data1 = analogRead(0);              // for Analog Pin A0
   data2 = Filter.run(data1);          // for filter calculation
   time_sampl = micros() - time_start; //time measurement math
 
  if (Serial.available() > 0) {
    incomingByte = Serial.read();
    if (incomingByte == 'm') {         // enter and sent "m" in serial monitor window and read time in microsec for Filter.run(data1) and analog read
    Serial.print("Time Sample = ");
    Serial.println(time_sampl, DEC);
        }
      }*/   
}   

  //Called every time TCNT2 = OCR2A
ISR(TIMER2_COMPA_vect) {  // Called each time TCNT2 == OCR2A
  static byte index=0;    // Points to successive entries in the wavetable
  OCR1AL = wave[index++]; // Update the PWM output
  asm("NOP;NOP");         // Fine tuning
  TCNT2 = 6;              // Timing to compensate for time spent in ISR
}



AdaZus

As filter I used a Bandpassfilter where a frequency of 220Hz should pass. I set the lower cut off frequency at 215Hz and the upper cut off frequency at 225Hz (more details in the posted sketchs).
The good news is that the sketch works, but instead that pass my desired frequency of 220Hz, passes a frequency of 275Hz.
To exclude errors I did also tests with my Filter-LED sketch:
Code: [Select]
// Arduino Signal Filtering Test
// Turn a LED on if filter amplitude reaches an arbitrary threshold.
// 2014 

// Arduino Signal Filtering Library
// Copyright 2012-2013 Jeroen Doggen (jeroendoggen@gmail.com)
//http://jeroendoggen.github.io/Arduino-signal-filtering-library/
//http://www.schwietering.com/jayduino/filtuino/


#include <SignalFilter.h>  // Filter Library
SignalFilter Filter;

const int ledPin = 13;        // pin that the LED is attached to
const int threshold = 512;    // an arbitrary threshold level that's in the range of the analog input

/* // Variable for time measurement
unsigned long time_start;    // variable for time measurement start
unsigned long time_sampl;    // variable for time measurement sample
int incomingByte = 0;        // sets incoming Byte to 0
*/

int data1;     // variable for Analog In
int data2;     // variable for filter


void setup()
{
  pinMode(ledPin, OUTPUT);     // initialize the LED pin as an output:
// Serial.begin(9600);        // used only printing (debugging)
  Filter.begin();
  Filter.setFilter('c');       // filter settings: c=Cebycheff  b= Bessel
  Filter.setOrder(2);          // filter settings: order 1 or 2     
}

/*
      Filter characteristics are stored in: "SignalFilter.cpp".
      Current filter settings and code: for "c" "2"

/// runChebyshev: Band Pass 220Hz; 1. Order; lower corner =215Hz; upper corner 225Hz; sampling=5000Hz; long type 8bit; enabled "-1 bit saturation";
_v[0] = _v[1];
_v[1] = _v[2];
long tmp = ((((data * 3360365L) >>  8) //= (   6.2591678898e-3 * x)
+ ((_v[0] * -4141801L) >> 1) //+( -0.9874824279*v[0])
+ (_v[1] * 4009861L) //+(  1.9120508347*v[1])
)+1048576) >> 21; // round and downshift fixed point /2097152

_v[2]= (short)tmp;
return (short)((
(_v[2] - _v[0]))); // 2^
*/


void loop()
{
// Read Analog Input... you can connect accelerometer, gyro, temperature sensor, microphone etc to the channel
 
  data1 = analogRead(0)-512;      //Read Analog channel (value of microphone) and substract DC-Offset from Microphone "BOB-09964"
  data2 = Filter.run(data1);      //Read the filtered signal
 
/*
http://arduino.cc/en/Tutorial/IfStatement
the variable called data1 is used to store the data collected from a Analog Pin A0.
This data is then compared to a threshold value.
If the the value is found to be above the set threshold the LED connected to digital pin 13 is turned on.
If analogValue is found to be < threshold, the LED remains off. */


  // if the filter value is high enough, turn on the LED:
  if (data2 > threshold) {
    digitalWrite(ledPin, HIGH);
  }
  else {
    digitalWrite(ledPin,LOW);
  }
   
   /* // time measurement for debugging:

   time_start = micros();               //time measurement
   data1 = analogRead(0);              // for Analog Pin A0
   data2 = Filter.run(data1);          // for filter calculation
   time_sampl = micros() - time_start; //time measurement math
 
  if (Serial.available() > 0) {
    incomingByte = Serial.read();
    if (incomingByte == 'm') {         // enter and sent "m" in serial monitor window and read time in microsec for Filter.run(data1) and analog read
    Serial.print("Time Sample = ");
    Serial.println(time_sampl, DEC);
        }
      } */
}   

But also there nearly the same problem: 220Hz doesn't pass but a frequency of 306Hz?!  :~
Do you understand this bug? Are there maybe more variables from filter depends?

Magician

Quote
But also there nearly the same problem: 220Hz doesn't pass but a frequency of 306Hz?!
Probably, your sampling rate isn't defined at 5 kHz, but vary above the spec.
Do you have a scope? If not, i could suggest to use your PC as a freq. meter, set one digital pin as output, and drive it high/low in the loop. Than using audacity or something else, use PC sound card to measure freq. Don't forget to attenuate a voltage from the pin with resistive divider, and put a DC blocking cap

AdaZus

Quote
Probably, your sampling rate isn't defined at 5 kHz, but vary above the spec.

Yes, you are right! :)
I have a digital oscilloscope and did the measurement how as suggested by you. Here the sketch:
Code: [Select]
// Arduino Signal Filtering Test
// Turn a LED on if filter amplitude reaches an arbitrary threshold.
// 2014 

// Arduino Signal Filtering Library
// Copyright 2012-2013 Jeroen Doggen (jeroendoggen@gmail.com)
//http://jeroendoggen.github.io/Arduino-signal-filtering-library/
//http://www.schwietering.com/jayduino/filtuino/


#include <SignalFilter.h>  // Filter Library
SignalFilter Filter;

int Pin8 = 8;   // for sampling measurement

const int ledPin = 13;        // pin that the LED is attached to
const int threshold = 512;    // an arbitrary threshold level that's in the range of the analog input

/* // Variable for time measurement
unsigned long time_start;    // variable for time measurement start
unsigned long time_sampl;    // variable for time measurement sample
int incomingByte = 0;        // sets incoming Byte to 0
*/

int data1;     // variable for Analog In
int data2;     // variable for filter


void setup()
{
  pinMode(Pin8, OUTPUT);        // for sampling measurement
  pinMode(ledPin, OUTPUT);     // initialize the LED pin as an output:
// Serial.begin(9600);        // used only printing (debugging)
  Filter.begin();
  Filter.setFilter('c');       // filter settings: c=Cebycheff  b= Bessel
  Filter.setOrder(2);          // filter settings: order 1 or 2     
}

/*
      Filter characteristics are stored in: "SignalFilter.cpp".
      Current filter settings and code: for "c" "2"

/// runChebyshev: Band Pass 220Hz; 1. Order; lower corner =215Hz; upper corner 225Hz; sampling=5000Hz; long type 8bit; enabled "-1 bit saturation";
_v[0] = _v[1];
_v[1] = _v[2];
long tmp = ((((data * 3360365L) >>  8) //= (   6.2591678898e-3 * x)
+ ((_v[0] * -4141801L) >> 1) //+( -0.9874824279*v[0])
+ (_v[1] * 4009861L) //+(  1.9120508347*v[1])
)+1048576) >> 21; // round and downshift fixed point /2097152

_v[2]= (short)tmp;
return (short)((
(_v[2] - _v[0]))); // 2^
*/


void loop()
{
// Read Analog Input... you can connect accelerometer, gyro, temperature sensor, microphone etc to the channel
 
  data1 = analogRead(0)-512;      //Read Analog channel (value of microphone) and substract DC-Offset from Microphone "BOB-09964"
  data2 = Filter.run(data1);      //Read the filtered signal
 
/*
http://arduino.cc/en/Tutorial/IfStatement
the variable called data1 is used to store the data collected from a Analog Pin A0.
This data is then compared to a threshold value.
If the the value is found to be above the set threshold the LED connected to digital pin 13 is turned on.
If analogValue is found to be < threshold, the LED remains off. */


  // if the filter value is high enough, turn on the LED:
  if (data2 > threshold) {
    digitalWrite(ledPin, HIGH);
  }
  else {
    digitalWrite(ledPin,LOW);
  }
   

    digitalWrite(Pin8, HIGH);  // PIN Output High Sample Measurement
    digitalWrite(Pin8, LOW);   // PIN Output Low Sample Measurement
   
   
   /* // time measurement for debugging:

   time_start = micros();               //time measurement
   data1 = analogRead(0);              // for Analog Pin A0
   data2 = Filter.run(data1);          // for filter calculation
   time_sampl = micros() - time_start; //time measurement math
 
  if (Serial.available() > 0) {
    incomingByte = Serial.read();
    if (incomingByte == 'm') {         // enter and sent "m" in serial monitor window and read time in microsec for Filter.run(data1) and analog read
    Serial.print("Time Sample = ");
    Serial.println(time_sampl, DEC);
        }
      } */
}   

It gives me a frequency between 6,350 KHz and 6,579KHz (attachment).
On my other sketch (filter and sine wave) the sample rate is about 5,9KHz
Are there possibilities to control the sampling frequency?

Magician

Perhaps, TimerOne library could help.

AdaZus

I'll check it out.
Many thanks for your precious tips!

mrburnette


Quote
http://coolarduino.wordpress.com/2012/06/28/stereo-audio-vu-meter-on-arduino/
sadly doesn`t exist anymore.

Right, virus eats it up completely
[/quote]


Is the attached the article that got wiped?  From some FFT research I was doing last year.

Ray

AdaZus

Hello, I suppose… Magician posted it here http://forum.arduino.cc/index.php?PHPSESSID=h35fsns7ltuls6qpoe2pki8bs4&/topic,164915
Quote
IMHO, there is nothing better than FFT for band pass filtering, explained here:
http://coolarduino.wordpress.com/2012/06/28/stereo-audio-vu-meter-on-arduino/


When I have more time I will read the article.
Thankz for your post!! :)

AdaZus

Hello,
now I did some tests with the TimerOne-Library:
Firstly I set the sampling rate at my "filtered data triggers a LED" sketch:
Code: [Select]
// Arduino Signal Filtering Test
// Turn a LED on if filter amplitude reaches an arbitrary threshold and whit a defined sampling rate
// June 2014 

// Arduino Signal Filtering Library
// Copyright 2012-2013 Jeroen Doggen (jeroendoggen@gmail.com)
// http://jeroendoggen.github.io/Arduino-signal-filtering-library/
// http://www.schwietering.com/jayduino/filtuino/

// Timer 1 Library for a defined sampling rate
// http://playground.arduino.cc/Code/Timer1



#include <TimerOne.h>
#include <SignalFilter.h>  // Filter Library
SignalFilter Filter;

int Pin8 = 8;   // for sampling measurement

const int ledPin = 13;        // pin that the LED is attached to
const int threshold = 400;    // an arbitrary threshold level that's in the range of the analog input


int data1;     // variable for Analog In
int data2;     // variable for filter


void setup()
{
  pinMode(Pin8, OUTPUT);        // for sampling rate measurement
  pinMode(ledPin, OUTPUT);      // initialize the LED pin as an output:

  Filter.begin();
  Filter.setFilter('c');       // filter settings: c=Cebycheff  b= Bessel
  Filter.setOrder(2);          // filter settings: order 1 or 2   

  Timer1.initialize(200); // set a timer of length 200 microseconds (1.000.000/200 = 5000Hz)
  Timer1.attachInterrupt( timerIsr ); // attach the service routine here 
}

/*
      Filter characteristics are stored in: "SignalFilter.cpp".
      Current filter settings and code: for "c" "2"


/// runChebyshev: Band Pass 220Hz; 1. Order; lower corner =215Hz; upper corner 225Hz; sampling=5000Hz; long type 8bit; enabled "-1 bit saturation";
_v[0] = _v[1];
_v[1] = _v[2];
long tmp = ((((data * 3360365L) >>  8) //= (   6.2591678898e-3 * x)
+ ((_v[0] * -4141801L) >> 1) //+( -0.9874824279*v[0])
+ (_v[1] * 4009861L) //+(  1.9120508347*v[1])
)+1048576) >> 21; // round and downshift fixed point /2097152

_v[2]= (short)tmp;
return (short)((
(_v[2] - _v[0]))); // 2^
*/

void loop()
{
  // Main code loop
  // TODO: Put your regular (non-ISR) logic here
}

void timerIsr()
{
// Read Analog Input... you can connect accelerometer, gyro, temperature sensor, microphone etc to the channel
 
  data1 = analogRead(0)-512;      //Read Analog channel (value of microphone) and substract DC-Offset from Microphone "BOB-09964"
  data2 = Filter.run(data1);      //Read the filtered signal
 
/*
http://arduino.cc/en/Tutorial/IfStatement
the variable called data1 is used to store the data collected from a Analog Pin A0.
This data is then compared to a threshold value.
If the value is found to be above the set threshold the LED connected to digital pin 13 is turned on.
If analogValue is found to be < threshold, the LED remains off. */


  // if the filter value is high enough, turn on the LED:
  if (data2 > threshold) {
    digitalWrite(ledPin, HIGH);
  }
  else {
    digitalWrite(ledPin,LOW);
  }
   

digitalWrite(Pin8, HIGH);  // PIN Output High for sampling rate measurement
digitalWrite(Pin8, LOW);   // PIN Output Low for sampling rate measurement

}   

It works fine! :) At PIN8 I measured a sampling rate of 5000Hz. This was the sampling rate I programmed. And also the filter works now. The in the filter code generator appointed frequency of 220Hz passes now.
But then I tried the same whit my other sketch, were simultaneously I want produce a tone and it didn't work. I measured a sampling rate of 6250Hz:
Code: [Select]
// Arduino:
// Generating sine waves
// Filter
// Turn a LED on if filter amplitude reaches an arbitrary threshold
// try to set the sampling rate with TimerOne-Library
// 2014 

// and generate a Sinewave
/******** Load AVR timer interrupt macros ********/
// http://makezine.com/projects/make-35/advanced-arduino-sound-synthesis/


// Arduino Signal Filtering Library
// Copyright 2012-2013 Jeroen Doggen (jeroendoggen@gmail.com)
// http://jeroendoggen.github.io/Arduino-signal-filtering-library/
// http://www.schwietering.com/jayduino/filtuino/


// IF Statement LED ON
// http://arduino.cc/en/Tutorial/IfStatement


// Timer 1 Library for a defined sampling rate
// http://playground.arduino.cc/Code/Timer1


int Pin8 = 8;   // for sampling rate measurement

#include <TimerOne.h>  //include library for set timer1 and sampling rate
#include <avr/interrupt.h>  // library for Sinewave

//Sine wave parameters
#define PI2     6.283185  // 2 * PI - saves calculating it later
#define AMP     127       // Multiplication factor for the sine wave
#define OFFSET  128       // Offset shifts wave to just positive values

// Lookup table
#define LENGTH  256  // The length of the waveform lookup table
byte wave[LENGTH];   // Storage for the waveform


#include <SignalFilter.h>  // Filter Library
SignalFilter Filter;

const int ledPin = 13;        // pin that the LED is attached to
const int threshold = 480;    // an arbitrary threshold level that's in the range of the analog input


int data1;     // variable for Analog In
int data2;     // variable for filter


void setup()
{
  pinMode(Pin8, OUTPUT);        // for sampling measurement
// Filter Parameters
  pinMode(ledPin, OUTPUT);      // initialize the LED pin as an output:
// digitalWrite(ledPin, ledState); 
 
  Timer1.initialize(200); // set a timer of length 200 microseconds (1.000.000/200 = 5000Hz) this will be your samplerate
  Timer1.attachInterrupt( timerIsr ); // attach the service routine here

  Filter.begin();
  Filter.setFilter('c');       // filter settings: c=Cebycheff  b= Bessel
  Filter.setOrder(2);          // filter settings: order 1 or 2   


// Sinewave Parameters
// Populate the waveform lookup table with a sine wave
  for (int i=0; i<LENGTH; i++) {          // Step across wave table
    float v = (AMP*sin((PI2/LENGTH)*i));  // Calculate current entry
    wave[i] = int(v+OFFSET);              // Store value as integer
  }
 
  // Set timer1 for 8-bit fast PWM output
  pinMode(9, OUTPUT);       // Make timer's PWM pin an output
  TCCR1B  = (1 << CS10);    // Set prescaler to full 16MHz
  TCCR1A |= (1 << COM1A1);  // PWM pin to go low when TCNT1=OCR1A
  TCCR1A |= (1 << WGM10);   // Put timer into 8-bit fast PWM mode
  TCCR1B |= (1 << WGM12);

  // Set up timer 2 to call ISR
  TCCR2A = 0;               // We need no options in control register A
  TCCR2B = (1 << CS21);     // Set prescaller to divide by 8
  TIMSK2 = (1 << OCIE2A);   // Set timer to call ISR when TCNT2 = OCRA2
  OCR2A = 32;               // sets the frequency of the generated wave (32=246.94Hz)
  sei();                    // Enable interrupts to generate waveform!
 
}

/*
      Filter characteristics are stored in: "SignalFilter.cpp".
      Current filter settings and code: for "c" "2"


/// runChebyshev: Band Pass 220Hz; 1. Order; lower corner =215Hz; upper corner 225Hz; sampling=5000Hz; long type 8bit; enabled "-1 bit saturation";
_v[0] = _v[1];
_v[1] = _v[2];
long tmp = ((((data * 3360365L) >>  8) //= (   6.2591678898e-3 * x)
+ ((_v[0] * -4141801L) >> 1) //+( -0.9874824279*v[0])
+ (_v[1] * 4009861L) //+(  1.9120508347*v[1])
)+1048576) >> 21; // round and downshift fixed point /2097152

_v[2]= (short)tmp;
return (short)((
(_v[2] - _v[0]))); // 2^
*/

void loop()
{
  // Main code loop
  // TODO: Put your regular (non-ISR) logic here

}

void timerIsr()

{
// Read Analog Input... you can connect accelerometer, gyro, temperature sensor, microphone etc to the channel
 
  data1 = analogRead(0)-512;      //Read Analog channel (value of microphone) and substract DC-Offset from microphone "BOB-09964"
  data2 = Filter.run(data1);      //Read the filtered signal
 

  // if the filter value is high enough, turn on the LED:
  if (data2 > threshold) {
    digitalWrite(ledPin, HIGH);
    }
  else {
      digitalWrite(ledPin, LOW);
      }
   
     
    digitalWrite(Pin8, HIGH);  // PIN Output High Sample Measurement
    digitalWrite(Pin8, LOW);   // PIN Output Low Sample Measurement   
}   

  //Called every time TCNT2 = OCR2A
ISR(TIMER2_COMPA_vect) {  // Called each time TCNT2 == OCR2A
  static byte index=0;    // Points to successive entries in the wavetable
  OCR1AL = wave[index++]; // Update the PWM output
  asm("NOP;NOP");         // Fine tuning
  TCNT2 = 6;              // Timing to compensate for time spent in ISR
}


Maybe the problem is that Timer1 is also used by the tone generator.
If that's really the problem how can I regulate the sampling rate?
Any suggestions? 


Go Up