如何根据频率转换arduino的数字输出

时间:2015-07-13 08:33:36

标签: audio arduino android-sensors arduino-uno

我正在使用模拟输出声音传感器模块,其中传感器模块的输出连接到arduino,可以看到arduino正在进行Ato D转换并显示0到1023范围内的整数。

但我需要计算传感器测量声音的频率。

所以你能帮助我,从这个Ato D转换后的arduino值来计算频率。

2 个答案:

答案 0 :(得分:0)

你真的不需要ADC转换吗?您需要做的就是检测输入的上升沿然后计算它们。由于您的传感器将输出低 - 高 - 低序列,并且由于Arduino将在一定电压下注册为高电平,因此应该足够了。

此代码将从连接到电路板上数字引脚8的输入开始测量高达200 kHz左右:

// Input: Pin D8 

volatile boolean first;
volatile boolean triggered;
volatile unsigned long overflowCount;
volatile unsigned long startTime;
volatile unsigned long finishTime;

// timer overflows (every 65536 counts)
ISR (TIMER1_OVF_vect) 
{
  overflowCount++;
}  // end of TIMER1_OVF_vect

ISR (TIMER1_CAPT_vect)
  {
  // grab counter value before it changes any more
  unsigned int timer1CounterValue;
  timer1CounterValue = ICR1;  // see datasheet, page 117 (accessing 16-bit registers)
  unsigned long overflowCopy = overflowCount;

  // if just missed an overflow
  if ((TIFR1 & bit (TOV1)) && timer1CounterValue < 0x7FFF)
    overflowCopy++;

  // wait until we noticed last one
  if (triggered)
    return;

  if (first)
    {
    startTime = (overflowCopy << 16) + timer1CounterValue;
    first = false;
    return;  
    }

  finishTime = (overflowCopy << 16) + timer1CounterValue;
  triggered = true;
  TIMSK1 = 0;    // no more interrupts for now
  }  // end of TIMER1_CAPT_vect

void prepareForInterrupts ()
  {
  noInterrupts ();  // protected code
  first = true;
  triggered = false;  // re-arm for next time
  // reset Timer 1
  TCCR1A = 0;
  TCCR1B = 0;

  TIFR1 = bit (ICF1) | bit (TOV1);  // clear flags so we don't get a bogus interrupt
  TCNT1 = 0;          // Counter to zero
  overflowCount = 0;  // Therefore no overflows yet

  // Timer 1 - counts clock pulses
  TIMSK1 = bit (TOIE1) | bit (ICIE1);   // interrupt on Timer 1 overflow and input capture
  // start Timer 1, no prescaler
  TCCR1B =  bit (CS10) | bit (ICES1);  // plus Input Capture Edge Select (rising on D8)
  interrupts ();
  }  // end of prepareForInterrupts


void setup () 
  {
  Serial.begin(115200);       
  Serial.println("Frequency Counter");
  // set up for interrupts
  prepareForInterrupts ();   
  } // end of setup

void loop () 
  {
  // wait till we have a reading
  if (!triggered)
    return;

  // period is elapsed time
  unsigned long elapsedTime = finishTime - startTime;
  // frequency is inverse of period, adjusted for clock period
  float freq = F_CPU / float (elapsedTime);  // each tick is 62.5 ns at 16 MHz

  Serial.print ("Took: ");
  Serial.print (elapsedTime);
  Serial.print (" counts. ");

  Serial.print ("Frequency: ");
  Serial.print (freq);
  Serial.println (" Hz. ");

  // so we can read it  
  delay (500);

  prepareForInterrupts ();   
}   // end of loop

Timers and counters上的更多讨论和信息。

答案 1 :(得分:0)

正如我在另一个帖子中建议的那样,最好的是

  1. 过滤
  2. AMPLIFY
  3. 应用阈值
  4. 测量边缘之间的时间
  5. 步骤1,2,3可以用软件执行,但在硬件中执行它们要好得多。第四步是Nick Gammon的解决方案......但你必须首先在HW中完成1,2,3步骤,否则你会收到很多“嘈杂”的读数