guitar frequencies

I thought these two posts looked very similar, so I merged them.

Back in my childhood (14 - 15 years old) l tuned a couple of piano's, upright's with a Strobicon. We had some little felt tools that were used to mute the strings that weren't being tuned (3 strings/note) and tuning was simple. I even worked with another guy that was a pipe organ tuner and even though there were several pipes necessary for some voicing we still tuned one note at a time.. Lot of pipes in a 4 manual 17 rank pipe organ.
In my dotage I designed an FSK decoder, several as a matter of fact and it had to process the audio from an AM radio. This places several severe restrictions on what I could do due to noise, co-channel and skip reception. This was compounded by the processor speed of 400 KHz for very low power operation (the whole board with the radio drew 3.2 mA) what I finally did was to accept any 3 crossings in any bit frame that were the right perioid as a valid bit one or zero. I also repeated the message 3 times as I had no ack returned from the receiver.
Perhaps some food for thought?

Bob
{Edit RKJ)

Could you put a pickup on the guitar and pick 1 string at a time?

But you'd have to do more to get it safely into Arduino to output to LCD for visualization.

The issue with a pickup is that unless the rest of the strings are muted they will resonate too the absolute difference between any consecutive two notes is the 12th root of 2 or 1.059463... (20 more places).

Bob

Thanks PaulS and AWOL for the help,

indeed it is part of our project.
the hardware I am using,is microcontroller seeeduino ADK Mega2560 and LMD386 amplifier - when the string is tuned the signal from the guitars string should be amplified and it passed to arduino pin0 , the signal should be again filtered and finally it should be shown the frequency on LCD. the input and the output of the amplifier are connected two coils-with electro-magatics , one input couil and the other is output coil(one coil is as microphone the other coil is making vabrating the string) , the tuning is happen outomatically when the guitars string come very close to the magnatics, one string at a time. the idea is like this link:Messing around with E-bow and bottleneck on a dobro guitar. - YouTube
I attached here the picture of the system. I still need help about coding,
thanks

obs: is that line 87 of the frequency library - ?
but it is behaving like my compiler does'nt recognize c++ code
I am using arduino IDE-

obs: is that line 87 of the frequency library - ?

I like AWOL's analogy.

My car wouldn't start this morning. It's the white one. Can you tell me what is wrong?

You didn't show any code. You didn't post any error messages. You simply expected us to help you fix them.

sorry PaulS
you are right, what I want to try is to re-use the frequency counter library code/ the code on this public domain link:FreqCount Library, for Measuring Frequencies in the 1 kHz to 5 MHz Range
because I think, it is relevant my project after modifying,. I compliled the code, there is always error like this one
thanks
the code is

// Frequency Counter Lib example

/*
  Martin Nawrath KHM LAB3
  Kunsthochschule f¸r Medien Kˆln
  Academy of Media Arts
  http://www.khm.de
  http://interface.khm.de/index.php/labor/experimente/	
 */
#include <FreqCounter.h>


unsigned long frq;
int cnt;
int pinLed=13;

void setup() {
  pinMode(pinLed, OUTPUT);

  Serial.begin(115200);        // connect to the serial port

  Serial.println("Frequency Counter");

}



void loop() {

  // wait if any serial is going on
  FreqCounter::f_comp=10;   // Cal Value / Calibrate with professional Freq Counter
  FreqCounter::start(100);  // 100 ms Gate Time

  while (FreqCounter::f_ready == 0) 

  frq=FreqCounter::f_freq;
  Serial.print(cnt++);
  Serial.print("  Freq: ");
  Serial.println(frq);
  delay(20);
  digitalWrite(pinLed,!digitalRead(pinLed));  // blink Led

}

header file

/*
  FreqCounter.h - Library for a Frequency Counter c.
  Created by Martin Nawrath, KHM Lab3, Dec. 2008
  Released into the public domain.
*/



#ifndef FreqCounter_h
#define FreqCounter_h


#include <avr/interrupt.h>
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

namespace FreqCounter {

	extern unsigned long f_freq;
	extern volatile unsigned char f_ready;
	extern volatile unsigned char f_mlt;
	extern volatile unsigned int f_tics;
	extern volatile unsigned int f_period;
	extern volatile unsigned int f_comp;
	
	void start(int ms);
	
	
}

#endif

There is a difference between
#include <FreqCounter.h>
and

#include "FreqCounter.h"

The difference is where the compiler looks for include files. If one doesn't work, because you have not installed the library as a library, try the other one.

Thanks PoulS

now I changed header file from #include <FreqCounter.h> to
#include "FreqCounter.h"

I can see that was a part of the compile error, but still the compile problem not disappear,
new one is her: on the piture
how to install the library as library ?, sorry my novice questions?
thanks again

Docedison:
The issue with a pickup is that unless the rest of the strings are muted they will resonate too the absolute difference between any consecutive two notes is the 12th root of 2 or 1.059463... (20 more places).

Bob

Sure, you won't get a perfectly clean sine wave. A pickup will also get effect from the guitar body sound box. Yet somehow an A sounds like an A, those resonances add a little tone is all.

You want just the string, do like Les Paul did and get a piece of train track.. or a hardwood 4x4. But then it's not an acoustic guitar.

thanks

I installed the library "frequency Library" and it complied well,

thank you PoulS and other guys in thread :slight_smile:

HI,

is there any help about this thread,guitar frequencies - #15 by system - Programming Questions - Arduino Forum , still I coun't figur out , calculating the frequency of guitar strings???? any hints ?
thanks

Are you trying to visualize the data or calculate the frequency?

You know that the string plucked will be the loudest part of the sound by far?
And that loudest sound is highest amplitude at the peaks?
So if you feed the signal through a resistor of high enough value to the grid of an NPN transistor, only the peaks will turn that on. Blip, blip, blip, count the blips per second and you have what?

Hi GoForSmoke

I just want to visualize the string frequency(guitar string) on LCD.

You've got some code you haven't showed us.

You've using some hardware to get the vibration information that you haven't told us about,

My car still won't start. The seats are leather. Does that help?

Hi PaulS

thanks for help, may be "a strang car again" sorry, I am new for using farum.
the hardware I am using, I explained before here: guitar frequencies - #15 by system - Programming Questions - Arduino Forum
I get some code from this public domain: Tony Chai wrote by Tony Chai
I don,t need to to use servo or tuning peg, indstead I am using electromegnet and coils to vibrate the string, just visualizing frequency. my vibration hardware circuit I put here

here is the code

/*
 * Magic_Tune
 *
 * This program will receive an amplified analog signal, compare the pitch, and control the servo motor while displaying output LEDs
 */


//Libraries required for servo control and usage of the Atmega’s internal timer
 #include 
#include "WProgram.h"

//Global variables to be used
 int x;
 int y;
 int lastx;
 int lasty;
 long timer;
 int idle_timer;
 int threshold;
 int cross_count;
 int in_tune;
 int average_val;
 int pitch_diff;

int upper_bound;
 int lower_bound;
 int avg_cross;
 int avg_counter;
 int avg_upper;
 int avg_lower;
 float a, b;

int timer_divide;
 int divide_by;

int string_select;
 int select_pin_val;

int analogPin = 0; // analog to digital pin for signal input

int led_high = 13; // this LED will show user if a string's pitch is too high
 int led_ok = 12; // this LED will show user if a string's pitch is correct
 int led_low = 11; // this LED will show user if a string's pitch is too low

// these pins will light up to show which string the Atmega is comparing values for
 int led_e4 = 10;
 int led_b3 = 9;
 int led_g3 = 8;
 int led_d3 = 7;
 int led_a2 = 6;
 int led_e2 = 5;

int button_pin = 3; // input pin for user using a button to switch strings
 int servoPin = 2; // control pin for servo motor

void setup()
 {
 // Set up timer 1 to generate an interrupt every 1 microsecond
 TCCR1A = 0x00;
 TCCR1B = (_BV(WGM12) | _BV(CS12));
 OCR1A = .071;
 TIMSK1 = _BV(OCIE1A);

 x = 0;
 lastx = 0;
 y = 0;
 lasty = 0;

 timer = 0;
 cross_count = 0;
 avg_cross = 0;
 avg_counter = 0;
 string_select = 0;

 //Set the input and output pins
 pinMode(button_pin, INPUT);
 pinMode(servoPin, OUTPUT);
 pinMode(led_high, OUTPUT);
 pinMode(led_ok, OUTPUT);
 pinMode(led_low, OUTPUT);
 pinMode(led_e4, OUTPUT);
 pinMode(led_b3, OUTPUT);
 pinMode(led_g3, OUTPUT);
 pinMode(led_d3, OUTPUT);
 pinMode(led_a2, OUTPUT);
 pinMode(led_e2, OUTPUT);

 Serial.begin(9600); // Opens serial port, sets data rate to 9600 bps
 }

// Nothing is done in the Arduino loop, since timing is off.
 void loop()
 { 
}

// Timer function running every microsecond
 ISR(TIMER1_COMPA_vect)
 {
 timer++;
 idle_timer++;

 // Read button press to determine which string is to be detected
 if (timer % 100 == 0)
 {
 select_pin_val = digitalRead(button_pin);
 if (select_pin_val == HIGH)
 {
 string_select = ((string_select + 1) % 6);
 Serial.print("string: ");
 Serial.println(string_select);
 }
 }


 // Depending on which string is selected, the proper variables are set
 switch (string_select)
 {
 case 0:
 digitalWrite(led_e4, LOW); // sets the proper LED on, all else off
 digitalWrite(led_b3, LOW);
 digitalWrite(led_g3, LOW);
 digitalWrite(led_d3, LOW);
 digitalWrite(led_a2, LOW);
 digitalWrite(led_e2, HIGH);
 a = 0.045;
 b = 0.9099;
 threshold = 150;
 upper_bound = 77;
 lower_bound = 33;
 avg_upper = 57;
 in_tune = 55; // This is the “in tune” average of cross counts for the string.
 avg_lower = 53;
 timer_divide= 2000;
 divide_by = 3;
 break;
 case 1:
 digitalWrite(led_e4, LOW); // sets the proper LED on, all else off
 digitalWrite(led_b3, LOW);
 digitalWrite(led_g3, LOW);
 digitalWrite(led_d3, LOW);
 digitalWrite(led_a2, HIGH);
 digitalWrite(led_e2, LOW);
 a = 0.0592;
 b = 0.8816;
 threshold = 150;
 upper_bound = 88;
 lower_bound = 44;
 avg_upper = 67;
 in_tune = 65; // This is the “in tune” average of cross counts for the string.
 avg_lower = 63;
 timer_divide = 2000;
 divide_by = 3;
 break;
 case 2:
 digitalWrite(led_e4, LOW); // sets the proper LED on, all else off
 digitalWrite(led_b3, LOW);
 digitalWrite(led_g3, LOW);
 digitalWrite(led_d3, HIGH);
 digitalWrite(led_a2, LOW);
 digitalWrite(led_e2, LOW);
 a = 0.0797;
 b = 0.8406;
 threshold = 150;
 upper_bound = 117;
 lower_bound = 63;
 avg_upper = 97;
 in_tune = 95; // This is the “in tune” average of cross counts for the string.
 avg_lower = 93;
 timer_divide = 2000;
 divide_by = 3;
 break;

I have to divede the code two parts because I cant put here all- the next is ather part of the code-
see the circuit image

the code continued here

case 3:
 digitalWrite(led_e4, LOW); // sets the proper LED on, all else off
 digitalWrite(led_b3, LOW);
 digitalWrite(led_g3, HIGH);
 digitalWrite(led_d3, LOW);
 digitalWrite(led_a2, LOW);
 digitalWrite(led_e2, LOW);
 a = 0.0730;
 b = 0.8541;
 threshold = 130;
 upper_bound = 50;
 lower_bound = 15;
 avg_upper = 29;
 in_tune = 27; // This is the “in tune” average of cross counts for the string.
 avg_lower = 26;
 timer_divide = 500;
 divide_by = 4;
 break;
 case 4: 
digitalWrite(led_e4, LOW); // sets the proper LED on, all else off
 digitalWrite(led_b3, HIGH);
 digitalWrite(led_g3, LOW);
 digitalWrite(led_d3, LOW);
 digitalWrite(led_a2, LOW);
 digitalWrite(led_e2, LOW); 
a = 0.1270;
 b = 0.7459;
 threshold = 140;
 upper_bound = 50;
 lower_bound = 15;
 avg_upper = 35;
 in_tune = 34; // This is the “in tune” average of cross counts for the string.
 avg_lower = 33;
 timer_divide = 500;
 divide_by = 4;
 break; 
case 5:
 digitalWrite(led_e4, HIGH); // sets the proper LED on, all else off
 digitalWrite(led_b3, LOW);
 digitalWrite(led_g3, LOW);
 digitalWrite(led_d3, LOW);
 digitalWrite(led_a2, LOW);
 digitalWrite(led_e2, LOW);
 a = 0.1648;
 b = 0.6705; 
threshold = 150;
 upper_bound = 60;
 lower_bound = 20;
 avg_upper = 47;
 in_tune = 45; // This is the “in tune” average of cross counts for the string.
 avg_lower = 43;
 timer_divide = 500;
 divide_by = 4;
 break;
 }

 check_crossings();

 // After the string input has been idle for a while, we take the average of a number of cross counts that were in bound.
 if (idle_timer == 10000)
 {
 Serial.println("AVG AVG LOOK HERE AVG AVG");
 average_val = avg_cross / divide_by;
 Serial.println(average_val);

 // If else statements for tuner lights
 if ((average_val < avg_lower) && (average_val > 0))
 {
 // Turn off all string display lights to conserve power
 digitalWrite(led_e4, LOW);
 digitalWrite(led_b3, LOW);
 digitalWrite(led_g3, LOW);
 digitalWrite(led_d3, LOW);
 digitalWrite(led_a2, LOW);
 digitalWrite(led_e2, LOW);

 // Sets the proper tuning LED on, all else off
 digitalWrite(led_high, LOW);
 digitalWrite(led_ok, LOW);
 digitalWrite(led_low, HIGH);

 pitch_diff = in_tune - average_val;
 Serial.print("Pitch Difference Low: ");
 Serial.println(pitch_diff);

 // If the tuning is off by a questionably high amount, count it as an error in reading and do not turn the peg.
 // Otherwise tune the peg for a period of time. This time depends on how far off the read average is.
 if (pitch_diff < 20)
 for(long i = 0; i < pitch_diff * 36000; i++)
 {
 digitalWrite(servoPin, HIGH); // start the pulse
 delayMicroseconds(15); // pulse width
 digitalWrite(servoPin, LOW); // stop the pulse
 }
 }

 // Don't turn the peg if the guitar is in tune.
 else if ((average_val >= avg_lower && average_val <= avg_upper) || (average_val == 0))
 {
 // Sets the proper tuning LED on, all else off
 digitalWrite(led_high, LOW);
 digitalWrite(led_ok, HIGH);
 digitalWrite(led_low, LOW);
 }

 else if (average_val > avg_upper)
 {
 // Turn off all string display lights to conserve power
 digitalWrite(led_e4, LOW);
 digitalWrite(led_b3, LOW);
 digitalWrite(led_g3, LOW);
 digitalWrite(led_d3, LOW);
 digitalWrite(led_a2, LOW);
 digitalWrite(led_e2, LOW);

 // Sets the proper tuning LED on, all else off
 digitalWrite(led_high, HIGH);
 digitalWrite(led_ok, LOW);
 digitalWrite(led_low, LOW);

 pitch_diff = average_val - in_tune;
 Serial.print("Pitch Difference High: ");
 Serial.println(pitch_diff);

 // If the tuning is off by a questionably high amount, count it as an error in reading and do not turn the peg.
 // Otherwise tune the peg for a period of time. This time depends on how far off the read average is.
 if (pitch_diff < 20)
 for(long i = 0; i < pitch_diff * 270000; i++)
 {
 digitalWrite(servoPin, HIGH); // start the pulse
 delayMicroseconds(2); // pulse width
 digitalWrite(servoPin, LOW); // stop the pulse
 }
 }

 // Reset all variables used for pitch detection
 cross_count = 0;
 avg_cross = 0;
 avg_counter = 0;
 }

 // We take the average of cross counts after the first value in bound. We dismiss the first value since it is usually inaccurate
 // for finding a good average.
 if (timer % timer_divide == 0){
 if (cross_count > lower_bound && cross_count < upper_bound) {
 if (avg_counter >= 1 && avg_counter < (divide_by + 1)) {
 avg_cross = avg_cross + cross_count;
 Serial.print("Runnin Avg cross sum: ");
 Serial.println(avg_cross);
 } 
avg_counter++; 
} 
Serial.print("cross_count: ");
 Serial.println(cross_count);
 cross_count = 0;
 }
 }

void check_crossings()
 {
 lastx = x;
 lasty = y;
 x = analogRead(analogPin); // Read the input pin
 y = a * x + a * lastx + b * lasty; // Apply Butterworth filter to eliminate high frequencies

 // If the string crosses it's set threshold, add it to the count. If there are no crossings, the idle timer will begin to run.
 if (lasty > threshold and y < threshold)
 {
 cross_count++;
 idle_timer = 0;
 } 
}
 OCR1A = .071;

Are you sure that you can do this? From what I've read, it looks like OCR1A needs to be a non-zero, integer value.

 Serial.print("string: ");
 Serial.println(string_select);

In an ISR? No.

That code does something. You want it to do something. What either of those somethings is is not clear.

My car has mag wheels. Why won't it start?

That code claims to start Timer1 interrupting every microsecond and then has an ISR routine that:

  • can't possibly execute in less than a microsecond
  • calls Serial.print (as PaulS has pointed out)
  • calls delayMicroseconds(15) inside a loop that is executed a minimum of 36000 times and (if that's not enough silliness) it also calls delayMicroseconds(2) in a loop that executes a minimum of 270000 times.
    It therefore can't possibly be sampling the audio at a consistent rate which would permit it to detect an audio tone (even if the code's detection method could actually work in the first place).

Pete