0

mbed LPC マイクロコントローラーを使用してギターをチューニングしようとしています。プロジェクトの例については、以下のリンクがあります。 https://developer.mbed.org/users/adurand/notebook/guitar-tuner/

しかし、私はそれにいくつかの問題を抱えています。最初に、各弦の必要な周波数で任意波形発生器を使用してギター入力をシミュレートしています。増幅回路も同じように構成されています。また、Nokia の代わりに Mbed LCD を使用するようにコードを変更しました。オシロスコープを使用して、Mbed の AnalogueIn p20 に入る出力が増幅され、正しい周波数であることを検証しました。これは私が問題を抱えているところです。

コードは次のとおりです (Andrew Durand の功績による):

#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 は「高すぎる」、「低すぎる」、および波線を交互に表示します。私が最高のコーダーではないことを最初に認めます。これは、夏に向けて実際に取り組む予定です。コードに重大な問題があるか、比較的単純な問題である可能性があります。すべての入力を歓迎します。

注: ブレッドボードのデバウンス回路は接続していません。使用していない Nokia LCD に接続されています。代わりに mbed アプリケーション ボードのジョイスティックを使用して、目的の文字列を 1 ~ 6 の間で変更できます。それは大丈夫ですか?それとも、極めて重要なデバウンス回路ですか? 再度、感謝します。

4

1 に答える 1

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

于 2016-04-26T17:32:56.117 に答える