2016-04-26 54 views
0

我试图用mbed LPC微调器来调整吉他。 下面有一个关于该项目的例子的链接。 https://developer.mbed.org/users/adurand/notebook/guitar-tuner/Mbed吉他调谐器代码问题?

但是,我遇到了一些问题。首先,我使用任意波形发生器以每个串的所需频率模拟吉他输入。放大器电路构造相同。我也改变了代码,以利用Mbed LCD而不是诺基亚。我使用示波器来验证进入Mbed的AnalogueIn p20的输出是否被放大并且频率正确。这是我遇到问题的地方。

下面是代码(以信誉安德鲁·杜兰德):

#include "mbed.h" 
#include "adc.h" 
#include "C12832.h" 
#include <math.h> 
#define PI 3.1415 
#define SAMPLE_RATE 24000 

InterruptIn button1(p12); 
C12832 lcd(p5, p7, p6, p8, p11); 
DigitalOut myled1(LED1); 
DigitalOut myled2(LED2); 
DigitalOut myled3(LED3); 

//LCD and Other Random Variables 
int string_select = 0; 
float high, high1, in_tune, in_tune1, in_tune2, in_tune3, 
low, low1, note, low_mod, high_mod; 
char* key; 
int Counter = 0; 
int Buffer[6000]; 

float goertzelFilter(int samples[], float freq, int N) { 
    float s_prev = 0.0; 
    float s_prev2 = 0.0; 
    float coeff,normalizedfreq,power,s; 
    int i; 
    normalizedfreq = freq/SAMPLE_RATE; 
    coeff = 2*cos(2*PI*normalizedfreq); 
    for (i=0; i<N; i++) { 
     s = samples[i] + coeff * s_prev - s_prev2; 
     s_prev2 = s_prev; 
     s_prev = s; 
    } 
    power = s_prev2*s_prev2+s_prev*s_prev-coeff*s_prev*s_prev2; 
    return power; 
} 

ADC adc(SAMPLE_RATE, 1); 

void sample_audio(int chan, uint32_t value) { 
    Buffer[Counter] = adc.read(p20); 
    Counter += 1; 
} 

void button1_pressed() { 
    string_select++; 
    if (string_select > 5) string_select = 0; 
} 

int main() { 
    //Interupt for Switching Strings 
    button1.mode(PullDown); 
    button1.rise(&button1_pressed); 

    while (1) { 

     switch (string_select) { 
      case 0: 
       note = 82; 
       key= "E2"; 
       break; 
      case 1: 
       note = 110; 
       key= "A2"; 
       break; 
      case 2: 
       note = 147; 
       key= "D3"; 
       break; 
      case 3: 
       note = 196; 
       key= "G3"; 
       break; 
      case 4: 
       note = 247; 
       key= "B3"; 
       break; 
      case 5: 
       note = 330; 
       key= "E4"; 
       break; 
     } 

     //Prepare for burst mode on all ADC pins and set up interrupt handler (using ADC library from Simon Blandford 
     adc.append(sample_audio); 
     adc.startmode(0,0); 
     adc.burst(1); 
     adc.setup(p20,1); 

     //start the interrupt and wait for about 4096 samples 
     adc.interrupt_state(p20,1); 
     wait(.2); 

     //Finsh up - Unset pin 20 
     adc.interrupt_state(p20,0); 
     adc.setup(p20,0); 
     int actual_rate = adc.actual_sample_rate(); 

     //for debugging tell the terminal sample rate and how many samples we took 
     printf("Requested max sample rate is %u, actual max sample rate is %u.\n", 
       SAMPLE_RATE, actual_rate); 
     printf("We did %i samples\n",Counter); 

high = 0; 
low = 0; 
for (int i=3; i<46; i+=3) { 
    high1 = goertzelFilter(Buffer, (note + i), Counter); 
    if (high1 > high) high=high1; 
} 
for (int i=3; i<46; i+=3) { 
    low1 = goertzelFilter(Buffer, (note - i), Counter); 
    if (low1 > low) low=low1; 
} 
     in_tune1 = goertzelFilter(Buffer, (note+1), Counter); 
     in_tune2 = goertzelFilter(Buffer, note, Counter); 
     in_tune3 = goertzelFilter(Buffer, (note-1), Counter); 

     if ((in_tune1 > in_tune2) && (in_tune1 > in_tune3)) in_tune = in_tune1; 
     else if ((in_tune2 > in_tune1) && (in_tune2 > in_tune3)) in_tune = in_tune2; 
     else in_tune = in_tune3; 
     printf("high = %.2f, low = %.2f, in_tune = %.2f", high, low, in_tune); 
     high_mod = high/in_tune; 
     low_mod = low/in_tune; 
     if ((high_mod > .8)&&(low_mod > .8)) { 
      myled1 = 0; 
      myled2 = 0; 
      myled3 = 0; 
     } 
       if ((high_mod < .8)&&(low_mod > .8)) { 
      myled1 = 0; 
      myled2 = 0; 
      myled3 = 0; 
     } 
     if ((high > in_tune) && (low < in_tune)) {   //Guitar string is at correct frequency 
      myled1 = 0; 
      myled2 = 1; 
      myled3 = 0; 

     } else if (high > in_tune) {      // String is higher than the desired frequency 
      myled1 = 1; 
      myled2 = 0; 
      myled3 = 0; 

     } else if (low < in_tune){      // String is below that of the desired frequency 
      myled1 = 0; 
      myled2 = 0; 
      myled3 = 1; 

     } else {          // Else no input, display squiggles 
      myled1 = 0; 
      myled2 = 0; 
      myled3 = 0; 
     } 

     // Display on the LCD 
     lcd.cls(); 
     lcd.locate(0,0); 
     lcd.printf("Tuning String: %i", (6-string_select)); 
     lcd.locate(0,11); 
     lcd.printf("%s at %i Hz",key, (int) note); 
     lcd.locate(0,23); 
     if (myled2) lcd.printf("In Tune!");    // if myled2 is on, guitar is in tune 
     else if (myled3) lcd.printf("Too Low ");   // if myled3 is on, guitar is lower than desired tone 
     else if (myled1) lcd.printf("Too High");   // if myled1 is on, guitar is higher than desired tone 
     else lcd.printf("No Input Detected");      // corresponds to led case 4 - no guitar input present 

     Counter = 0; 

    } 



} 

现在,当我编译程序,邮件打印。然而,LED在“太高”,“太低”和波形之间交替。我会第一个承认我不是最好的编码器,我真的会在夏天工作。代码可能存在一个非常重要的问题,或者它可能相对简单。所有的投入都赞赏。

注意:我没有连接面包板上的去抖电路 - 它连接到我没有使用的诺基亚LCD上。我可以使用mbed应用程序板上的操纵杆改变所需的字符串,在1-6之间。可以吗?还是至关重要的去抖电路? 再次感谢。

回答

1

指找到low环路是(几乎)相同,在这种代码发现high循环:

high = 0; 
low = 0; 
for (int i=3; i<46; i+=3) { 
    high1 = goertzelFilter(Buffer, (note + i), Counter); 
    if (high1 > high) high=high1; 
} 
for (int i=3; i<46; i+=3) { 
    low1 = goertzelFilter(Buffer, (note - i), Counter); 
    if (low1 > low) low=low1; 
} 

我建议low部分应该是这样的

low = FLT_MAX; 
for (int i=3; i<46; i+=3) { 
    low1 = goertzelFilter(Buffer, (note - i), Counter); 
    if (low1 < low) low=low1; 
} 

..尽管我可能会误以为low的预期用途。

+0

我该如何定义FLT_MAX? – jvnlendm

+0

'#include '顺便说一句我看你也是用'printf'所以'#include '也是。 –

+0

...或将“低”设置为其他不可行的高价值。 –