This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Guitar Tuner



Hi,

I would like to use my TM4C129 as a guitar tuner using it ADC port. I also trying to use Systick handler.  I have tryed this code, but it doesnt work properly, it doesnt detect inputc frequency well.

Could anyone help me?

Thanks

#include <stdint.h>
#include "driverlib\systick.h" 
#include "driverlib\systick.c" 
#include "driverlib/sysctl.h"
#include "driverlib/adc.h"

unsigned long start_times[10];
unsigned long stop_times[10];
int long Vin;
int datoA;
float frecuencia;
float pendiente;
float tiempo;
int contador;

#define TickerPeriod 1363

#define ADCpin1 7


void setup()
{

SysTickDisable(); // Deshabilita SysTick durante la configuracion
SysTickPeriodSet(TickerPeriod); // Define el periodo del contador. Al llegar a cero genera la intrrupcion
SysTickIntRegister(&Ticker); // Se vincula a la ISR de la interrupción causada por el SysTick
SysTickIntEnable(); // Se habilita la interrupción del SysTick
SysTickEnable(); // Se habilita el SysTick, después de haber sido configurado
IntMasterEnable(); // Se habilitan todas las interrupciones

Serial.begin(9600);

//ADC configuration
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); //enables a peripheral 
ROM_ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0); // Configures the trigger source and priority of a sample sequence.
ROM_ADCHardwareOversampleConfigure(ADC0_BASE,0); //Configures the hardware oversampling factor of the ADC.
ROM_ADCSequenceEnable(ADC0_BASE, 3); //enables a sample sequence. 
ROM_ADCIntClear(ADC0_BASE, 3); //Clears sample sequence interrupt source.



}

void loop()
{


frecuencia = (120000/TickerPeriod)*tiempo;
if (contador = 10)
{
Serial.print("\nADC = "); 
Serial.print(Vin);
Serial.print("\tTiempo captura = "); 
Serial.print(stop_times[1] - start_times[1]);
Serial.print("\tPendiente = "); 
Serial.print(pendiente);
Serial.print("\tFrecuencia = "); 
Serial.print(frecuencia);

contador = 0;
}

}


void Ticker() 
{
start_times[1] = micros();

Vin = analogRead1(ADCpin1);
pendiente = Vin - datoA;

datoA = Vin;


if (pendiente > 1 && Vin > 2000)
{
tiempo++;
}
if (Vin < 2047)
{
tiempo = 0;
}

if(pendiente < 0 && Vin > 2000)
{
tiempo = 0;
}
contador++;
stop_times[1] = micros();
}


uint16_t analogRead1(uint8_t pin) {

uint16_t value[1];
uint32_t channel = digitalPinToADCIn(pin);


ROM_ADCSequenceStepConfigure(ADC0_BASE, 3, 0, channel | ADC_CTL_IE | ADC_CTL_END); // This function configures the ADC for one step of a sample sequence.
if (channel == NOT_ON_ADC) 
{ //invalid ADC pin
return 0;
}
ROM_ADCProcessorTrigger(ADC0_BASE, 3); // Causes a processor trigger for a sample sequence.
while(!ROM_ADCIntStatus(ADC0_BASE, 3, false))
{ //Gets the current interrupt status.
}
ROM_ADCIntClear(ADC0_BASE, 3); //Clears sample sequence interrupt source.
ROM_ADCSequenceDataGet(ADC0_BASE, 3, (unsigned long*) value); //Gets the captured data for a sample sequence.
return value[0];
}

  • I suspect that it would prove wise for you to (first) confirm that your ADC set-up is correct by introducing low impedance, known, stable, "w/in ADC spec" voltages to your selected ADC pins. If this test/verify does not succeed - all further efforts must fail.

    Further - have you investigated how the (many) existing "tuners" perform that task? It would seem that "off-chip(MCU)" detection of the frequency components - and then presentation of that digital signal to the MCU's Timer(s) would, "Speed, Ease & Enhance" your development...
  • The ADC setup might be correct cos it detect different voltage levels. I have tested it with a potenciometer and a variable frequency circuit made with a 555 timer. I have tested pins 7 and 27, and correctly works.

    I'm using a KY-038 microphone to detect the guitar tone, so i suspect problems could be caused by the offset of the microphone or by the, maybe, gain, i didnt find any schematich so i dont know it gain value.

    Im triyng to detect frequency in a way similar to this, is quite similar to apply Bolzano's theorem (intermediate value theorem). 

    http://www.instructables.com/id/Arduino-Frequency-Detection/

  • Alvaro,

    You have a nice mission there. Allow me to make a few comments to help this one, and also for future posts:

    1) It's not likely that anyone will analyze your whole code... and even if so, then when posting, please use the "Insert Code with SyntaxHighlighter" button, so that your code gets at least properly idented.

    2) The approach of analyzing frequency detecting the changes is not wrong, but might be a bit weak... There are several other inflections on the sound you are producing (harmonics, noise, what not). Even the pure signal would cause a lot of misread direction changes, particularly near the top and low edges (that little "almost horizontal" part can be a whole rollercoaster if seen with more resolution).

    3) I don't see in your code (again, just pasting the text makes it too tiring to search for anything) the part where you'd apply the "intelligence" to figure out the frequency. Did you actually do it?

    4) As for your doubt about the mic signal level, there's only one solution: look at the signal on an oscilloscope, and see if it ranges within the expected analog input of the uC's ADC.

    5) And to make life interesting, look at FFT transform functions in C, try to embed one in your TM4C, and you will obtain a whole "map" of frequencies coming out of your instrument. The dominant one will be your (probably off-tune) note.

    Saludos y suerte!

  • Like #2 awarded, Bruno...

    Note too that it always pays to (speeds/eases) investigate the methods of (successful) others.    Inventing the wheel (from scratch) is a sure path to needless delay, dead-ends & disappointment...

    Often the real world over-whelms, "text-book theory" - the success of (others) may indicate that (their) theory has (withstood) reality...

  • To add my two cents here:

    Like others, I have trouble understanding the purpose of the code you presented. At first glance, it looks like you try to discern frequency by the zero-crossing method. That works with mains voltage, but not with an real-world audio signal. The latter, like a guitar tone, containing several frequencies and harmonics. Fourier analysis (FFT) is, as Bruno pointed out, more appropriate. That requires some more consideration about tuning precision, FFT block size and core performance.

    Note too that it always pays to (speeds/eases) investigate the methods of (successful) others.    Inventing the wheel (from scratch) is a sure path to needless delay, dead-ends & disappointment...

    While I agree with you, there is another side. Or, as Frank Zappa said: "Without deviation from the norm, no progress is possible." Working examples (done by experts) are a great guide to learn how it could be done. However, I always encourage my kids (and others) to try their own ideas, instead of memorizing their teachers (often unproven) words. Learning by doing (even if failing) is most often more effective than dozens of theoretical lectures.

    To express my opinion about teachers, I'd like to cite some one else here (can't remember his name): "Those who can, do. Those who can't, teach. And those who can't teach, administer".

  • f. m. said:
    I always encourage my kids (and others) to try their own ideas, instead of memorizing their teachers (often unproven) words. Learning by doing (even if failing...

    I fully salute this, f.m.   And you will note that I placed NO limits upon poster's imagination, direction, proceedings.    Yet - investigation most always proves of high value - and it is (again & again) proven that man (most often) effectively advances via "small tweaks & improvements" - not from a (completely blank) sheet of paper.   Perhaps there's not so much "another" side - instead I propose a "broader" side...

    Usually - a successful design will - at minimum - identify & deal w/the "basics."   Such observation & notation by the reader tends to eliminate (at least reduce) "gaping holes" which otherwise are (too often) the "norm."

    Suspect that you/I/others agree that investigation is, "Just one (ideally early) step" and that further, "thought, experimentation, & modeling" lead to the best results.

    Following your example, "He who does NOT study history is condemned to repeat it!"   Avoidance of known/predictable, "bad effects" - while welcoming "good effects/methods" - proves most valuable.    And that's the "job" of proper investigation...

  • Bruno Saraiva said:

    2) The approach of analyzing frequency detecting the changes is not wrong, but might be a bit weak... There are several other inflections on the sound you are producing (harmonics, noise, what not). Even the pure signal would cause a lot of misread direction changes, particularly near the top and low edges (that little "almost horizontal" part can be a whole rollercoaster if seen with more resolution).

    3) I don't see in your code (again, just pasting the text makes it too tiring to search for anything) the part where you'd apply the "intelligence" to figure out the frequency. Did you actually do it?

    4) As for your doubt about the mic signal level, there's only one solution: look at the signal on an oscilloscope, and see if it ranges within the expected analog input of the uC's ADC.

    5) And to make life interesting, look at FFT transform functions in C, try to embed one in your TM4C, and you will obtain a whole "map" of frequencies coming out of your instrument. The dominant one will be your (probably off-tune) note.

    2) I tried other code which detect ramps and positive semicicles instead of zero crossing, but it doesnt work too. This is my first time i work with microcontrolers and i a bit lost, so maybe it is configuration problem.

    3) The idea it is to count the time the signal slope is positive and over the offtset produced by the micropone, then it times by the frecuency of the systick interrupt

    4) I have tested it, it has around 1Vpp with the zero in 2Vcc offset, 

    5) I tried the fix_fft function by Tom Roberts, but it gives me wrong frequencies. I use a square signal and seems to sample very fast so it only detects high or low level instead some periods to calculate the sginal's frequency

    Is there any fft function from TI i could call directly?

  • Poster Investigation - kicked to the curb! (off-loaded to others...)