Go Down

Topic: Reading A Frequency (Read 7834 times) previous topic - next topic

sigilwig444

Oct 09, 2015, 03:15 am Last Edit: Oct 09, 2015, 03:16 am by sigilwig444
Hi there! I've been working on this project for a little while now and can seem to get it to work... I can't determine if my problem is in my wiring or my code... I normally would give up at this point but it's a pretty important project... Anyhow, I'll add what I'm using for wiring and post my code here also, you guys can take a look and see if you can see any problems... Basically I'm trying to get a frequency just as some type of tuner would from a microphone... Whenever I try to run the code it reads in the serial monitor "0.00 hz"

Find Wiring Here: http://postimg.org/image/6990p484l/

Code: [Select]

boolean clipping = 0;

//data storage variables
byte newData = 0;
byte prevData = 0;

//freq variables
unsigned int timer = 0;//counts period of wave
unsigned int period;
int frequency;

void setup(){
 
  Serial.begin(9600);
 
  pinMode(13,OUTPUT);//led indicator pin
 
  cli();//diable interrupts
 
  //set up continuous sampling of analog pin 0
 
  //clear ADCSRA and ADCSRB registers
  ADCSRA = 0;
  ADCSRB = 0;
 
  ADMUX |= (1 << REFS0); //set reference voltage
  ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only
 
  ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz
  ADCSRA |= (1 << ADATE); //enabble auto trigger
  ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete
  ADCSRA |= (1 << ADEN); //enable ADC
  ADCSRA |= (1 << ADSC); //start ADC measurements
 
  sei();//enable interrupts
}

ISR(ADC_vect) {//when new ADC value ready

  prevData = newData;//store previous value
  newData = ADCH;//get value from A0
  if (prevData < 127 && newData >=127){//if increasing and crossing midpoint
    period = timer;//get period
    timer = 0;//reset timer
  }
 
 
  if (newData == 0 || newData == 1023){//if clipping
    PORTB |= B00100000;//set pin 13 high- turn on clipping indicator led
    clipping = 1;//currently clipping
  }
 
  timer++;//increment timer at rate of 38.5kHz
}

void loop(){
  if (clipping){//if currently clipping
    PORTB &= B11011111;//turn off clippng indicator led
    clipping = 0;
  }

  frequency = 38462/period;//timer rate/period
  //print results
  Serial.print(frequency);
  Serial.println(" hz");
 
  delay(100);
}

sigilwig444


el_supremo

Quote
frequency = 38462/period;//timer rate/period
I think at least part of your problem is in this statement. 38462 is too big to fit in a 16-bit integer (which is what the compiler will use unless you tell it otherwise) so it will be truncated and end up with a value of 5694.

Try:
Quote
frequency = 38462L/period;//timer rate/period
This forces 38462 to be a 32-bit integer. The division might work out better, but it still depends upon what values 'period' can have.

Pete
Don't send me technical questions via Private Message.

sigilwig444

I think at least part of your problem is in this statement. 38462 is too big to fit in a 16-bit integer (which is what the compiler will use unless you tell it otherwise) so it will be truncated and end up with a value of 5694.

Try:
This forces 38462 to be a 32-bit integer. The division might work out better, but it still depends upon what values 'period' can have.

Pete
It currently displays -1 hz... I'm still not sure if it's my wiring or code...

tmd3

I'm still not sure if it's my wiring or code
I haven't checked the code.  There's definitely something peculiar about the wiring.  The analog input looks to be connected to a voltage divider with 10K resistors, and the divider looks to be connected between 5V and GND.  No matter what, that will provide a voltage of 2.5 volts.  I'm not sure what you're measuring here.

I can't tell where the input is.  There's something funny about the two capacitors, too - it looks to me that they're in series.  Is that what you intended?

I also can't find any description of the troubleshooting that you've already done, and what the outcome was.  I can't tell what input you used to get an output value of 1 Hz.

There seems to be a lot of information missing here.  Can you illuminate?

sigilwig444

I haven't checked the code.  There's definitely something peculiar about the wiring.  The analog input looks to be connected to a voltage divider with 10K resistors, and the divider looks to be connected between 5V and GND.  No matter what, that will provide a voltage of 2.5 volts.  I'm not sure what you're measuring here.

I can't tell where the input is.  There's something funny about the two capacitors, too - it looks to me that they're in series.  Is that what you intended?

I also can't find any description of the troubleshooting that you've already done, and what the outcome was.  I can't tell what input you used to get an output value of 1 Hz.

There seems to be a lot of information missing here.  Can you illuminate?
I don't know too much about wiring... I'm taking a schematic from this project. I paid someone on fiverr.com to convert it to a fritzing image since I'm not too good with schmatics... I wired it up and tried to use it and that's where I am now... What else would you like to know?

Grumpy_Mike

Quote
I paid someone on fiverr.com to convert it to a fritzing image since I'm not too good with schmatics.
You were had.
Mind you the circuit is up to the normal instructable standards, that is crap. So you have a bad job of a bad circuit.

Remove C2. Replace the reed switch with a real switch, use a double pole switch to switch the -ve supply as well as the +ve one. On the audio input put a 10uF cap and two 10K resistors like on the audio input of the Arduino.

Check the hardware is working by just printing out the value from A0 as fast as you can. When it is working you should see a reading about 512 and steady with no audio. With audio that value will go up and down from the steady value. Until this works there is no point in trying any more software.

Its3darchitecturals


Grumpy_Mike

Very bad manners to bump a post especially one that is not your own.
If you have a question just ask it, all the information on this topic has been covered. Bad schematic implemented incorrectly.

sigilwig444

You were had.
Mind you the circuit is up to the normal instructable standards, that is crap. So you have a bad job of a bad circuit.

Remove C2. Replace the reed switch with a real switch, use a double pole switch to switch the -ve supply as well as the +ve one. On the audio input put a 10uF cap and two 10K resistors like on the audio input of the Arduino.

Check the hardware is working by just printing out the value from A0 as fast as you can. When it is working you should see a reading about 512 and steady with no audio. With audio that value will go up and down from the steady value. Until this works there is no point in trying any more software.
I'm sorry, this is an old thread now, but was a project that I didn't have time to think about for a while... Anyhow, I'm ready to do some more work, but I'm not sure what you're telling me to do... Could you explain more on what I need to do? Thanks!

Grumpy_Mike

Well I can only repeat what I said, you have to say what you don't understand and then I will try and explain that bit.

pjrc

#11
Dec 31, 2015, 01:28 pm Last Edit: Dec 31, 2015, 01:43 pm by Paul Stoffregen
Would you believe just in the last few days a similar conversation has been happening over on the forum for Teensy?

But before that, I should mention the FreqMeasure library.  (full disclosure, I'm the author of FreqMeasure and the maker of Teensy)  Your original code uses the ADC, but it simply looks for the signal to be above or below a fixed threshold.  If you build this with a circuit, using a voltage comparator chip, or transistors, or just feed the signal to a digital pin and how the pin's input threshold is approx what you need, you can use the FreqMeasure library.  FreqMeasure is very reliable and accurate.  Well, it's at least as accurate as your board's crystal.

However, FreqMeasure using a digital pin, or your original approach of low vs high on a fixed threshold depends on the signal not having much harmonic content.  If strong harmonics are present, odds are good the signal will cross the low/high threshold multiple times per cycle.

With that in mind, here's the recent conversation:

https://forum.pjrc.com/threads/32252-Different-Range-FFT-Algorithm/page2

Thanks to Collin Duffy's contribution, and the researchers who came up with the YIN algorithm (Alain de Cheveigne and Hideki Kawahara), you can pretty easily connect your sound to either an ADC pin or the Teensy Audio Shield and use the new note frequency object to analyze it.  The YIN algorithm is pretty good at finding the fundamental frequency of your sound, even if strong harmonics are present.

The Teensy Audio Library now has an example, which you open with File > Examples > Audio > Analysis > NoteFrequency (this is only available when Teensy is selected in the Tools > Boards menu).  The example plays a guitar sound sample and also analyzes it for the frequency, which prints to the Arduino Serial Monitor.  This example makes trying the YIN algorithm about as easy as possible.  Just open the example, upload it to your Teensy 3.2, and open the serial monitor.  You can connect a computer speaker or stereo to the DAC pin to hear the sound it's analyzing.  You can uncomment code to play other notes, to see & hear it work on other guitar strings.  The bass guitar sounds have strong harmonics which are traditionally very tough to analyze.  The YIN algorithm does it very well.

At the moment this stuff is all only on github.  It'll be released in Teensyduino 1.27 in a few days.  This code will only work on Teensy 3.1 & 3.2.  The YIN algorithm requires a lot of computation, so there's really no hope of it ever working in real-time on Arduino Uno.  But if you do have compatible hardware, this new feature should make these traditionally very difficult note detection projects pretty easy!



sigilwig444

Well I can only repeat what I said, you have to say what you don't understand and then I will try and explain that bit.
Sorry for not elaborating more...

Quote
Remove C2. Replace the reed switch with a real switch, use a double pole switch to switch the -ve supply as well as the +ve one. On the audio input put a 10uF cap and two 10K resistors like on the audio input of the Arduino.
What is C2? What is the reed switch? What's a double pole switch and the -ve supply and the +ve supply? Where is the audio input? Maybe if you could tell me where things are on my fritzing image would be helpful?

Thank you Paul for your input, but I think I'm going to worry about wiring first, and then I'll worry about the code... Once I do get the wiring down though, I will look into your FreqMeasure library... Just a little bit longer!

Grumpy_Mike

On the wiring diagram the capacitors are numbered, one of them is numbered C2.

The reed switch is the switch that is activated by a magnet and is shown as a pair of contacts.

A double pole switch is two sets of contacts that switch form one input to the other through the action of a single throw, or change of switch position.

The supply is the battery it has two ends the positive or +Ve end and the negative or -Ve end.

The audio input is any analogue input on your Arduino.

If you really do not know these things then your project is way too complex for you and you should do some turptorial examples first.

pjrc

You should buy the Arduino Starter Kit and use it first.

Go Up