Help with AudioFrequencyMeter for Arduino Zero

Hello everybody.

I’m new to the forum so please, excuse me if I break some rules.

I have an issue trying to use this library “AudioFrequencyMeter.h” it seems that the function getFrequency() can’t work outside the loop but I don’t have any ideas on how to solve this

I’ll leave my code over here

#include <AudioFrequencyMeter.h>
#include <PID_v1.h>
#define NOTE_A4  440.000

AudioFrequencyMeter meter;

  const int MotorCW = 6;
  const int MotorCCW = 7;
  const int PWM = 3;
  const int frecPIN = A0;
  const int Enable = 2;
  double Setpoint, Input, Output;
  int out=0;
  float frequency = 0;
  String NOTE;
  PID PID1(&Input, &Output, &Setpoint, 2,5,3, DIRECT); //my gains are just random numbers (I will work on this later)

void setup()
{
  pinMode(MotorCW, OUTPUT);
  pinMode(MotorCCW, OUTPUT);
  pinMode(Enable, OUTPUT);
  pinMode(frecPIN, INPUT);
  Serial.begin(115200);
  
  PID1.SetMode(AUTOMATIC);
  PID1.SetSampleTime(5000);
  PID1.SetOutputLimits(1,2);
  
  meter.setBandwidth(30, 5000);
  meter.setAmplitudeThreshold(0.3);
  meter.begin(A0, 45000);
void loop()
{
  Serial.println("Ingrese la nota deseada junto con la octava (A4, AS4)");
  while(Serial.available()<=0);
  {
    NOTE=Serial.readString();
    Serial.println("LA NOTA ES: ");
    Serial.println(NOTE);
     if(NOTE=="A4")
    {
      Setpoint=NOTE_A4;
      delay(500);
      obtenerfreq();
      delay(300);
      movemotor();
      delay(500);
    }
  }
}
float obtenerfreq()
{
  Serial.println("Obteniendo frecuencia");
  Serial.println("Frecuencia de Setpoint: ");
  Serial.println(Setpoint);
  for(int b=0; b<10000;b++)
  {
    frequency=meter.getFrequency();
    Serial.println(frequency);
  }
  Serial.print("Frecuencia de la cuerda: ");
  Serial.print(frequency);
  Serial.println(" Hz");
  if(frequency>0)
  {
    return frequency;
  }
  else
  {
    Serial.println("NO LECTURA");
  }
}

int movemotor()
{
  Serial.println("Calculando movimiento de motor");
  Input=Setpoint-frequency;
  PID1.Compute();
  Serial.println("OUTPUT PID");
  Serial.println(Output);
  delay(500);
  if(Output<=1)
  {
    digitalWrite(Enable,HIGH);
    analogWrite(MotorCW,100);
    digitalWrite(MotorCCW,LOW);
    Serial.println("a contrario");
  }
  if(Output>1)
  {
    digitalWrite(Enable,HIGH);
    digitalWrite(MotorCW,LOW);
    analogWrite(MotorCCW,100);
    Serial.println("manecillas de reloj");
  }
}

This is used with an Arduino Zero and is for a piano tuner; a school project, deadline is coming soon and I have done a lot of research on this subject but I couldn’t find why function “obtenerfreq()” is not reading the frequency.

Thank you!

That code won't compile. There is a missing right brace } at the end of the setup function but other code might be missing too.

Pete

I will leave the code but without the 88 notes (sorry for the mistake while copying)

#include <AudioFrequencyMeter.h>
#include <PID_v1.h>


#define NOTE_A4  440.000


AudioFrequencyMeter meter;

  const int MotorCW = 6;
  const int MotorCCW = 7;
  const int PWM = 3;
  const int frecPIN = A0;
  const int Enable = 2;
  double Setpoint, Input, Output;
  int out=0;
  float frequency = 0;
  String NOTE;
  PID PID1(&Input, &Output, &Setpoint, 2,5,3, DIRECT);
  
void setup()
{
  pinMode(MotorCW, OUTPUT);
  pinMode(MotorCCW, OUTPUT);
  pinMode(Enable, OUTPUT);
  pinMode(frecPIN, INPUT);
  Serial.begin(115200);
  
  PID1.SetMode(AUTOMATIC);
  PID1.SetSampleTime(5000);
  PID1.SetOutputLimits(1,2);
  
  meter.setBandwidth(30, 5000);
  meter.setAmplitudeThreshold(0.3);
  meter.begin(A0, 45000);
      
}

void loop()
{
  Serial.println("Ingrese la nota deseada junto con la octava (A4, AS4)");
  while(Serial.available()<=0);
  {
    NOTE=Serial.readString();
    Serial.println("LA NOTA ES: ");
    Serial.println(NOTE);
     if(NOTE=="A4")
    {
      Setpoint=NOTE_A4;
      delay(500);
      obtenerfreq();
      delay(300);
      movemotor();
      delay(500);
    }   
  }
}


float obtenerfreq()
{
  Serial.println("Obteniendo frecuencia");
  Serial.println("Frecuencia de Setpoint: ");
  Serial.println(Setpoint);
  for(int b=0; b<10000;b++)
  {
    frequency=meter.getFrequency();
    Serial.println(frequency);
  }
  Serial.print("Frecuencia de la cuerda: ");
  Serial.print(frequency);
  Serial.println(" Hz");
  if(frequency>0)
  {
    return frequency;
  }
  else
  {
    Serial.println("NO LECTURA");
  }
}

int movemotor()
{
  Serial.println("Calculando movimiento de motor");
  Input=Setpoint-frequency;
  PID1.Compute();
  Serial.println("OUTPUT PID");
  Serial.println(Output);
  delay(500);
  if(Output<=1)
  {
    digitalWrite(Enable,HIGH);
    analogWrite(MotorCW,100);
    digitalWrite(MotorCCW,LOW);
    Serial.println("a contrario");
  }
  if(Output>1)
  {
    digitalWrite(Enable,HIGH);
    digitalWrite(MotorCW,LOW);
    analogWrite(MotorCCW,100);
    Serial.println("manecillas de reloj");
  }
}

What is the motor used for? This code looks to me like it was originally written as a guitar tuner. I don’t know much about tuning a piano but I don’t think this would be at all useful. Each note on a piano can consist of one (at the bass end), two, or three (at the treble end) strings. That code will be useless for any of the notes which have two or more strings - unless the piano has already been tuned, which defeats the whole purpose.
On top of that, the AudioFrequencyMeter library uses a simple zero-crossing method to determine the period of the wave. The waveform from a piano (or a guitar) is not just one frequency. It is a mix of frequencies and the zero-crossing method can’t reliably determine the pitch of such a waveform.

Which microphone are you using and how do you have it wired to the Zero?

Pete

el_supremo:
What is the motor used for?

The motor is attached to the pins of the piano strings.

el_supremo:
This code looks to me like it was originally written as a guitar tuner. I don't know much about tuning a piano but I don't think this would be at all useful. Each note on a piano can consist of one (at the bass end), two, or three (at the treble end) strings. That code will be useless for any of the notes which have two or more strings - unless the piano has already been tuned, which defeats the whole purpose.

I'm aware about the one, two and three strings. The strings are tuned one by one.

el_supremo:
On top of that, the AudioFrequencyMeter library uses a simple zero-crossing method to determine the period of the wave. The waveform from a piano (or a guitar) is not just one frequency. It is a mix of frequencies and the zero-crossing method can't reliably determine the pitch of such a waveform.

Which microphone are you using and how do you have it wired to the Zero?

I have tried the example on that library that comes on the Arduino page ( https://www.arduino.cc/en/Tutorial/SimpleAudioFrequencyMeter ) and when I play the note A4, the frequency read on the serial monitor, is 440. And with other notes, the frequency reading is correct.

And I'm using the module KY-037 (KY-037 High Sensitivity Sound Detection Module for Arduino AVR PIC | eBay) wired with the A0 output.

  meter.setAmplitudeThreshold(0.3);

This might be the problem. The library uses an integer here so you will have set the threshold to zero. I suggest that you change it to

  meter.setAmplitudeThreshold(30);

which is the default value. If it doesn't help, you'll have to experiment to get a working value.

Pete

Thank you.
Tomorrow I'll be testing that change and I will post the update.

el_supremo Thank you very much for your observation

The program is working just fine now

I just have to adjust the gains of the PID and the output will be just what I need
thank you very much!

Excellent. I'm glad that got it working.

Pete