Go Down

Topic: Detecting and Responding to High Frequency Audio (Read 3 times) previous topic - next topic

MarkT

Its worth trying - you still have to amplify the audio signal enough and make sure the signal of interest has a greater amplitude than background noise...
[ I won't respond to messages, use the forum please ]

grizzlby

#11
Jul 10, 2012, 02:56 am Last Edit: Jul 10, 2012, 03:02 am by grizzlby Reason: 1
Alright. Now i have this simple transistor pre-amp set up using a 2N4401



and it's giving me surprisingly good AnalogRead results considering how poorly the previous op-amp circuit worked. A "quiet" environment tends towards 450 and doesn't fluctuate more than ~30 in either direction.

I have also successfully put together a 5v to trim pot circuit to control my reference voltage for the comparator interrupt so that I can set the zero-crossing right around the 490 mark.

The problem is that when I attempt to run the code found here
Code: [Select]
// Count zero crossings using analog comparator
// atmega328p:
//   Uses pin 7 as the anacomp -ve input (AIN1)
//   Uses pin 6 as the anacomp +ve input (AIN0)
// attiny85:
//   Uses pin 1 as AIN1
//   Uses pin 0 as AIN0

#ifdef __AVR_ATtiny85__
#define AIN1 1
#define AIN0 0
#else
#define AIN1 7
#define AIN0 6
#endif

#define SAMPLE_WINDOW_SIZE 5
#define SAMPLE_MILLIS 50

volatile unsigned int crossings;
volatile unsigned int crossing_counts[SAMPLE_WINDOW_SIZE];
unsigned char timerLoadValue;
unsigned char latency;
unsigned char n;
int timer;
volatile unsigned long timer2;
volatile char sample_ready;
long oldmicro;
int diags;
int oldfreq;

#define TIMER_CLOCK_FREQ 16000000.0 //2MHz for /8 prescale from 16MHz

#ifdef __AVR_ATtiny85__
// TBD: Will need to use timer 1 or timer 0 for ATTiny
#error ATTiny clock code not yet written
#endif

//Setup Timer2.
//Configures the 8-Bit Timer2 to generate an interrupt
//at the specified frequency.
//Returns the timer load value which must be loaded into TCNT2
//inside your ISR routine.
//See the example usage below.
unsigned char SetupTimer2(float timeoutFrequency){
 unsigned char result; //The timer load value.
 
 
 /* We need to work out what divisor of the chip clock can be
    used to get an 8-bit counter preload value that represents
    the requested frequency.

     timer preload_val = scaled_freq / requested_freq
 =>  scaled_freq = clock_freq / scaler
 =>  preload_val = clock_freq / scaler / requested_freq
 =>  256 > clock_freq / scaler / requested_freq
 =>  clock_freq / scaler < 256 * requested_freq
 =>  1 / scaler < 256 * requested_freq / clock_freq
 =>  scaler > clock_freq / (256 * requested_freq)
   */

 Serial.print("clock/requested:");
 Serial.println(TIMER_CLOCK_FREQ / timeoutFrequency);

 int min_scaler = TIMER_CLOCK_FREQ / (256 * timeoutFrequency);
 Serial.print("Min scaler:");
 Serial.println(min_scaler);  
 
 // Need to convert min_scaler into a power-of-2 value to use.
 // Allowable values are actually 1, 8, 32, 64, 128, 256, 1024 -
 // see data sheet, section 18.10.
 int scaler = 1;
 while ((scaler < min_scaler) && (scaler < 1024))
 {
   scaler <<= 1;
   // skip disallowed values
   if ((scaler == 2) || (scaler == 4) || (scaler == 16) || (scaler == 512))
   {
     scaler <<= 1;
   }
 }
 
 if (scaler < min_scaler)
 {
   // Output a warning.
   Serial.println("Requested timer frequency too low - unable to find a suitable divider");
 }
 else
 {
   Serial.print("Chosen prescaler:");
   Serial.println(scaler);
 }
 
 long scaled_freq = TIMER_CLOCK_FREQ / scaler;      

 // Convert the scaler value into register settings
 switch (scaler)
 {
   case 1:
     TCCR2B = 0b00000001;
     break;
   case 8:
     TCCR2B = 0b00000010;
     break;
   case 32:
     TCCR2B = 0b00000011;
     break;
   case 64:
     TCCR2B = 0b00000100;
     break;
   case 128:
     TCCR2B = 0b00000101;
     break;
   case 256:
     TCCR2B = 0b00000110;
     break;
   case 1024:
     TCCR2B = 0b00000111;
     break;
   default:
     Serial.print("Unrecognised scaler: ");
     Serial.println(scaler);
     break;
 }  
 
 //Calculate the timer load value
 result=(int)((256.0-(scaled_freq/timeoutFrequency))+0.5);

 //Timer2 Settings: Timer mode 0
 TCCR2A = 0;

 //Timer2 Overflow Interrupt Enable
 TIMSK2 = 1<<TOIE2;

 //load the timer for its first cycle
 TCNT2=result;

 Serial.print("Timer2 reload value:");
 Serial.println(result);
 return(result);
}
 
void setup()
{
 Serial.begin(57600);
 
 crossings = 0;
 n = 0;
 timer = 0;
 timer2 = 0;
 sample_ready = 0;
 diags = 0;
 oldfreq = 0;
 
 // Set up the comparator.
 pinMode(AIN0, INPUT);
 pinMode(AIN1, INPUT);
 // ACI : Ana Comp Interrupt flag - writing a 1 clears it, hardware autoclears it when calling ISR
 // ACIE : Ana Comp Int Enable
 // ACIS1, ACIS0 : Ana Comp Int mode select:
 //   0      0     Int on output toggle
 //   0      1     Reserved
 //   1      0     Int on falling output edge
 //   0      1     Int on rising output edge
 // (See section 16 of ATTiny85 datasheet)
 ACSR = 0 | (1 << ACI) | (1 << ACIE) | (1 << ACIS1);  // Enable interrupts; falling edge mode.
 
 // Set up a timer interrupt.
 timerLoadValue = SetupTimer2(1000);
}

void loop()
{
 // Calculate average crossings and output once we have a full sample window.
 // (This is indicated by the timer ISR setting sample_ready == true.
 while (!sample_ready);
 
 // Reset so that we'll wait again on the next loop.
 sample_ready = 0;
 
 // Grab a copy of the data as calculation could take a while.
 int copy[SAMPLE_WINDOW_SIZE];
 memcpy(copy, (const void *)crossing_counts, sizeof(crossing_counts));

 // Debugging : Print contents of the copy[] array every 10 cycles.
 /*
 diags ++;
 if (diags % 10 == 0)
 {
   for (int ii = 0; ii < SAMPLE_WINDOW_SIZE; ii++)
   {
     Serial.print(copy[ii]);
     Serial.print(',');
   }
   Serial.println("\x08.");
 }
 */
 
 long avg_count = 0;
 for (int ii = 0; ii < SAMPLE_WINDOW_SIZE; ii++)
 {
   avg_count += copy[ii];
 }
 avg_count *= (1000 / SAMPLE_MILLIS) / SAMPLE_WINDOW_SIZE;  
 
 
 /* Debugging : check that the interval between full samples is
    as expected:  
 long micro = micros();
 long microdiff = micro - oldmicro;
 oldmicro = micro;

 Serial.print(microdiff);
 Serial.print(' ');
 */
 
 // Filter noise.  If we're within 100Hz of our previous value,
 // then assume that we're reading a steady tone.
 if ((abs(avg_count - oldfreq) < 100) && (avg_count != 0))
 {
   Serial.println(avg_count);
 }
 oldfreq = avg_count;
}

ISR(ANALOG_COMP_vect)
{
 crossings ++;
}

//Timer2 overflow interrupt vector handler, called once per ms.
ISR(TIMER2_OVF_vect) {
 timer++;
//  timer2++;
 
 // Sample input freq every 100ms
 if (timer == SAMPLE_MILLIS)
 {
   crossing_counts[n++] = crossings;
   timer = 0;
   crossings = 0;
   if (n == SAMPLE_WINDOW_SIZE)
   {
     n = 0;
     sample_ready = 1;
   }
 }

 //Capture the current timer value. This is how much error we
 //have due to interrupt latency and the work in this function
 latency=TCNT2;

 //Reload the timer and correct for latency.
 TCNT2=latency+timerLoadValue;
}


it slowly prints out unintelligible characters such as:
" ¯ÌarÌúÄpÂ0 Dz?²?ù???Åñ?ûÉ?ó²Éó?ÉøÉóûáÉÍ?àÉÉÉ?Dz?áñ?óÁ????ÉûáûÉÉÉóÉ?ÉÉÉÍÍüÆóÇÆÆÅñÅÌ?#773¢'¦¢¢¢¢?'"

I don't expect my found code to work perfectly, but I'm also not sure where this strange output is coming from. Any ideas as to what's happening?

grizzlby

the gibberish was due to baud rate of serial data transmission. the code from my previous post is now working effectively to print out the frequency of a generated tone from my phone. there's a certain amount of troubleshooting to be done about finding the best combination of audio input circuit + reference voltage, but beyond that the rest of my project is trivial. thanks.

karan2012singh

i have a two pin microphone...and i want that microphone listens to my clap,and then arduino process this audio to do some action.... plzz help,how to connect and how to do that....

karan2012singh


Go Up