frequency measurement with small problem

Hi,

This is my first project with Arduino and everything went well, almost 100%... but then...

My project deals with frequency measurement(Thanks to Martin Nawrath Lab3) As the architecture of the ATMEGA chip it provides a special counter and capture unit and the frequency detection is done with this way with high precision.

My actual problem is that after detecting for example three different frequencies the reset (false) function does not work properly.After the first run when all three tone are detected LED goes HIGH as it should be but after that it takes only two tone sample and LED goes HIGH again. Somehow the code remember the last state and the false function does not reset all three flag. I have tried to solve this without success.

Any idea?

 for (i=0;i<3;i++){
   
   if(lfrq >=315 and lfrq <=325 ){ //320
    
    tone1=true; }
    break; 
   }
   
   for (i=0;i<3;i++){
   
   if(lfrq >=365 and lfrq <=375 ){ //370
  
    tone2=true; }
    break;
   
   }
  
   for (i=0;i<3;i++){
     
   if(lfrq >=415 and lfrq <=425 ){ //420
  
    tone3=true; }
    break; 
   } 
   if (tone1==true&&tone2==true&&tone3==true){
        
  digitalWrite(led12,HIGH);
  delay(200); 
  digitalWrite(led12, LOW);
  
  tone1=false;
  tone2=false;
  tone3=false;
            }
                       
       }
   
   }

Probably need to post the whole code. But first Auto Format (ctrl-T). It appears there are too many curly braces in what you posted, so it's almost impossible to tell what control flow is intended or obtained :slight_smile:

it's almost impossible to tell what control flow is intended or obtained

Seconded.

johncc:
Probably need to post the whole code. But first Auto Format (ctrl-T). It appears there are too many curly braces in what you posted, so it's almost impossible to tell what control flow is intended or obtained :slight_smile:

It says "No changes necessary for Auto Format"

So this is whole code with my mods javascript:void(0);

 #include "FreqPeriod.h"

double lfrq;
long int pp;

int led12=12;
int i;
int tone1;
int tone2;
int tone3;



void setup() {


  for (i=0;i<3;i++);
  pinMode(led12,OUTPUT);
  digitalWrite(led12, LOW);


  Serial.begin(115200);
  FreqPeriod::begin();
  Serial.println("FreqPeriod Library Test");
}

void loop() {

  pp=FreqPeriod::getPeriod();
  if (pp ){

    Serial.print("period: ");
    Serial.print(pp);
    Serial.print(" 1/16us  /  frequency: ");

    lfrq= 16000400.0 / pp;
    printDouble(lfrq,6);
    Serial.print(" Hz");
    Serial.println("  "); 

    for (i=0;i<3;i++){

      if(lfrq >=315 and lfrq <=325 ){ //320

        tone1=true; 
      }
      break; 
    }

    for (i=0;i<3;i++){

      if(lfrq >=365 and lfrq <=375 ){ //370

        tone2=true; 
      }
      break;

    }

    for (i=0;i<3;i++){

      if(lfrq >=415 and lfrq <=425 ){ //420

        tone3=true; 
      }
      break; 
    } 
    if (tone1==true&&tone2==true&&tone3==true){

      digitalWrite(led12,HIGH);
      delay(200); 
      digitalWrite(led12, LOW);

      tone1=false;
      tone2=false;
      tone3=false;
    }

  }

}     



//***************************************************************************
void printDouble( double val, byte precision){
  // prints val with number of decimal places determine by precision
  // precision is a number from 0 to 6 indicating the desired decimial places
  // example: lcdPrintDouble( 3.1415, 2); // prints 3.14 (two decimal places)

  if(val < 0.0){
    Serial.print('-');
    val = -val;
  }

  Serial.print (int(val));  //prints the int part
  if( precision > 0) {
    Serial.print("."); // print the decimal point
    unsigned long frac;
    unsigned long mult = 1;
    byte padding = precision -1;
    while(precision--)
      mult *=10;

    if(val >= 0)
      frac = (val - int(val)) * mult;
    else
      frac = (int(val)- val ) * mult;
    unsigned long frac1 = frac;
    while( frac1 /= 10 )
      padding--;
    while(  padding--)
      Serial.print("0");
    Serial.print(frac,DEC) ;
  }
}
for (i=0;i<3;i++);

First problem

if(lfrq >=365 and lfrq <=375 ){ //370

        tone2=true; 
      }
      break;

Another, probably.

AWOL:

for (i=0;i<3;i++);

First problem

if(lfrq >=365 and lfrq <=375 ){ //370

tone2=true;
      }
      break;


Another, probably.

The problem remains the same even if I removed the whole (for loop), LED goes HIGH still after two sample. The meaning (for loop) was ensure an adequate number of samples.

 if(lfrq >=365 and lfrq <=375 ){ //370

        tone2=true;

This this should be OK anyway

Do you know what a "break" does?
Why are you always breaking on the first iteration of the for loop?
If you do that, you may as well not have the loop.

Yeah, all of your for loops in setup() and loop() functions are incorrect and are not doing anything.

But,

you could put a print in to convince yourself that the booleans are getting reset

      tone1=false;
      tone2=false;
      tone3=false;
      Serial.print(tone1);Serial.print(tone2); Serial.println(tone3);

and
what is your output of lfrq at the time that tone3 is improperly going true?

    Serial.print(" 1/16us  /  frequency: ");

backlight:

   if(lfrq >=315 and lfrq <=325 ){ //320

What is 'and' supposed to do?

What is 'and' supposed to do?

Are you being serious?

what is your output of lfrq at the time that tone3 is improperly going true?

    Serial.print(" 1/16us  /  frequency: ");

It says;

period: 43189 1/16us  /  frequency: 370.473968 Hz  
period: 43178 1/16us  /  frequency: 370.568359 Hz  
period: 43179 1/16us  /  frequency: 370.559753 Hz  
period: 43181 1/16us  /  frequency: 370.542602 Hz  
period: 43179 1/16us  /  frequency: 370.559753 Hz  
period: 43181 1/16us  /  frequency: 370.542602 Hz  
period: 108264528 1/16us  /  frequency: 0.147789 Hz  
period: 20586 1/16us  /  frequency: 777.246643 Hz  
period: 38081 1/16us  /  frequency: 420.167541 Hz  
period: 38131 1/16us  /  frequency: 419.616577 Hz  
period: 38039 1/16us  /  frequency: 420.631469 Hz  
period: 38048 1/16us  /  frequency: 420.531951 Hz  
period: 38035 1/16us  /  frequency: 420.675689 Hz  
period: 38040 1/16us  /  frequency: 420.620391 Hz  
period: 38040 1/16us  /  frequency: 420.620391 Hz  
period: 38047 1/16us  /  frequency: 420.542999 Hz  
period: 38050 1/16us  /  frequency: 420.509857 Hz  
period: 38049 1/16us  /  frequency: 420.520904 Hz  
period: 38039 1/16us  /  frequency: 420.631469 Hz  
period: 38047 1/16us  /  frequency: 420.542999 Hz  
period: 38048 1/16us  /  frequency: 420.531951 Hz  
period: 38051 1/16us  /  frequency: 420.498809 Hz  
period: 38029 1/16us  /  frequency: 420.742065 Hz  
period: 38021 1/16us  /  frequency: 420.830596 Hz  
period: 38041 1/16us  /  frequency: 420.609344 Hz

As you can see there is sometimes transition (glitch) on frequency at start but it is out of range and rest of sample is steady.Problem stays same if I add sample frequencies to five or even 7,after second run LED goes high after four for (five) and six for (seven) sample.
I removed for() loop and my code stands now;

#include "FreqPeriod.h"

 double lfrq;
 long int pp;

 int led12=12;
 int tone1;
 int tone2;
 int tone3;
 
 
 
 void setup() {
  

 
  pinMode(led12,OUTPUT);
  digitalWrite(led12, LOW);
 

  Serial.begin(115200);
  FreqPeriod::begin();
  Serial.println("FreqPeriod Library Test");
 }

 void loop() {

  pp=FreqPeriod::getPeriod();
  if (pp ){
  
    Serial.print("period: ");
    Serial.print(pp);
    Serial.print(" 1/16us  /  frequency: ");

    lfrq= 16000400.0 / pp;
    printDouble(lfrq,6);
    Serial.print(" Hz");
    Serial.println("  "); 
  
  
   
   if(lfrq >=315 && lfrq <=325 ){ //320
    
    tone1=true; }
  
   
   if(lfrq >=365 && lfrq <=375 ){ //370
  
    tone2=true; }
   
     
   if(lfrq >=415 && lfrq <=425 ){ //420
  
    tone3=true; }
  
   if (tone1==true&&tone2==true&&tone3==true){
        
  digitalWrite(led12,HIGH);
  delay(200); 
  digitalWrite(led12, LOW);
  
  tone1=false;
  tone2=false;
  tone3=false;
  Serial.print(tone1);Serial.print(tone2); Serial.println(tone3);
  
            }
                       
       }
   
   }     
   
 
 
//***************************************************************************
void printDouble( double val, byte precision){
  // prints val with number of decimal places determine by precision
  // precision is a number from 0 to 6 indicating the desired decimial places
  // example: lcdPrintDouble( 3.1415, 2); // prints 3.14 (two decimal places)

  if(val < 0.0){
    Serial.print('-');
    val = -val;
  }

  Serial.print (int(val));  //prints the int part
  if( precision > 0) {
    Serial.print("."); // print the decimal point
    unsigned long frac;
    unsigned long mult = 1;
    byte padding = precision -1;
    while(precision--)
      mult *=10;

    if(val >= 0)
      frac = (val - int(val)) * mult;
    else
      frac = (int(val)- val ) * mult;
    unsigned long frac1 = frac;
    while( frac1 /= 10 )
      padding--;
    while(  padding--)
      Serial.print("0");
    Serial.print(frac,DEC) ;
  }
}

backlight:
what is your output of lfrq at the time that tone3 is improperly going true?

period: 43189 1/16us  /  frequency: 370.473968 Hz  

period: 43178 1/16us  /  frequency: 370.568359 Hz 
...

The important part is the print of the samples immediately before the led comes when you don't think it should (and when you get the output from Serial.print( tone1 ton2 tone3). Can you capture that, examine, and post?

John

johncc:

backlight:
what is your output of lfrq at the time that tone3 is improperly going true?

period: 43189 1/16us  /  frequency: 370.473968 Hz  

period: 43178 1/16us  /  frequency: 370.568359 Hz 
...

The important part is the print of the samples immediately before the led comes when you don't think it should (and when you get the output from Serial.print( tone1 ton2 tone3). Can you capture that, examine, and post?

John

Hi,

After I added the Serial.print( tone1 tone2 tone3) to code now it says something strange. It sets the first sample of the third frequency (420Hz) like above(before) tone1,tone2,tone3 false(000) Why it is doing that?

period: 43189 1/16us  /  frequency: 370.473968 Hz  
period: 43179 1/16us  /  frequency: 370.559753 Hz  
period: 43193 1/16us  /  frequency: 370.439666 Hz  
period: 43186 1/16us  /  frequency: 370.499694 Hz  
period: 43173 1/16us  /  frequency: 370.611267 Hz  
period: 113674601 1/16us  /  frequency: 0.140756 Hz  
period: 20585 1/16us  /  frequency: 777.284423 Hz  
period: 38078 1/16us  /  frequency: 420.200653 Hz  
000
period: 38045 1/16us  /  frequency: 420.565124 Hz  
period: 38052 1/16us  /  frequency: 420.487762 Hz  
period: 38031 1/16us  /  frequency: 420.719940 Hz  
period: 38046 1/16us  /  frequency: 420.554077 Hz  
period: 38034 1/16us  /  frequency: 420.686767 Hz  
period: 38037 1/16us  /  frequency: 420.653564 Hz  
period: 38029 1/16us  /  frequency: 420.742065 Hz  
period: 38047 1/16us  /  frequency: 420.542999 Hz  
period: 38044 1/16us  /  frequency: 420.576171 Hz  
period: 38036 1/16us  /  frequency: 420.664642 Hz  
period: 38036 1/16us  /  frequency: 420.664642 Hz  
period: 38044 1/16us  /  frequency: 420.576171 Hz  
period: 38047 1/16us  /  frequency: 420.542999 Hz  
period: 38046 1/16us  /  frequency: 420.554077 Hz  
period: 38035 1/16us  /  frequency: 420.675689 Hz  
period: 38040 1/16us  /  frequency: 420.620391 Hz  
period: 38038 1/16us  /  frequency: 420.642517 Hz

backlight:
After I added the Serial.print( tone1 tone2 tone3) to code now it says something strange. It sets the first sample of the third frequency (420Hz) like above(before) tone1,tone2,tone3 false(000) Why it is doing that?

period: 43189 1/16us  /  frequency: 370.473968 Hz  

period: 43179 1/16us  /  frequency: 370.559753 Hz 
period: 43193 1/16us  /  frequency: 370.439666 Hz 
period: 43186 1/16us  /  frequency: 370.499694 Hz 
period: 43173 1/16us  /  frequency: 370.611267 Hz 
period: 113674601 1/16us  /  frequency: 0.140756 Hz 
period: 20585 1/16us  /  frequency: 777.284423 Hz 
period: 38078 1/16us  /  frequency: 420.200653 Hz 
000
period: 38045 1/16us  /  frequency: 420.565124 Hz 
period: 38052 1/16us  /  frequency: 420.487762 Hz 
...lots more

I'm not sure if I understand your question, but...(working backwards)
The 000 prints out when you have just reset all three flags to false, hence 000.
Right before that the led blinked for about .2 seconds.
Right before you set them to false all three were true, since it entered the if(tone1==tone2==tone3==true) code
Right before that was the first time tone3 was true because it was the first 420.
Sometime before that it had already seen 320 and 370 (we assume this but it's prior to your posted log)

By "Right before that" I mean micro maybe nano seconds.

So far I don't see anything amiss? Were you not expecting that there should be a 420mhz coming across at that time? (I have no idea about that library or where these frequencies are coming from or generated :slight_smile: )

John

Any idea?

The code makes zero sense.

For example, I reformatted the first piece like this:

 for (i=0;i<3;i++){
   
   if(lfrq >=315 and lfrq <=325 ){ //320
    
      tone1=true; 
   }
   break; 
  }

What exactly did you expect it to do?

The code he is currently using is in Reply #10, have a look...

   if(lfrq >=315 && lfrq <=325 ){ //320
    
    tone1=true; }
  
   
   if(lfrq >=365 && lfrq <=375 ){ //370
  
    tone2=true; }
   
     
   if(lfrq >=415 && lfrq <=425 ){ //420
  
    tone3=true; }
  
   if (tone1==true&&tone2==true&&tone3==true){
        
  digitalWrite(led12,HIGH);
  delay(200); 
  digitalWrite(led12, LOW);
  
  tone1=false;
  tone2=false;
  tone3=false;
  Serial.print(tone1);Serial.print(tone2); Serial.println(tone3);
  
            }

I would use more parenthesis to be sure of operation order and just for clarity and use the AutoFormat tool also for clarity.

That last line of code above... how about printing "flags reset"?

I looked at the library

  FreqPeriod 
  Counter1 unit capturing analog comparator event measuring period length of analog signal on input AIN1 
  AIN0 set to VCC/2 by resistors
  pin5 used as output for comparator feedback
  Analog comparator interrupt service is used to calculate period length
  Timer1 overflow interrupt service used to count overflow events

I don't speak AVR-interrupt-port-speak though. Could there be a problem/conflict with his writing to LED on Arduino pin 12? He says it always misbehaves on the "second time around".

Backlight, what kind of Arduino do you have exactly?

John

GoForSmoke:
I would use more parenthesis to be sure of operation order and just for clarity

Clarity, ok. But which operation order are you unsure of?

That last line of code above... how about printing "flags reset"?

"000" is Backlightian for "flags reset". Scan from the top of the thread for that backstory :slight_smile:

and use the AutoFormat tool also for clarity.

Agree with that. Here, I am involved enough already I will do it for him/you

#include "FreqPeriod.h"

double lfrq;
long int pp;

int led12 = 12;
int tone1;
int tone2;
int tone3;

void setup() {
	pinMode(led12, OUTPUT);
	digitalWrite(led12, LOW);

	Serial.begin(115200);
	FreqPeriod::begin();
	Serial.println("FreqPeriod Library Test");
}

void loop() {
	pp = FreqPeriod::getPeriod();
	if (pp) {
		Serial.print("period: ");
		Serial.print(pp);
		Serial.print(" 1/16us  /  frequency: ");

		lfrq = 16000400.0 / pp;
		printDouble(lfrq, 6);
		Serial.print(" Hz");
		Serial.println("  ");

		if (lfrq >= 315 && lfrq <= 325) { //320
			tone1 = true;
		}

		if (lfrq >= 365 && lfrq <= 375) { //370
			tone2 = true;
		}

		if (lfrq >= 415 && lfrq <= 425) { //420
			tone3 = true;
		}

		if (tone1 == true && tone2 == true && tone3 == true) {
			digitalWrite(led12, HIGH);
			delay(200);
			digitalWrite(led12, LOW);

			tone1 = false;
			tone2 = false;
			tone3 = false;
			Serial.print(tone1);
			Serial.print(tone2);
			Serial.println(tone3);
		}
	}
}

//***************************************************************************
void printDouble(double val, byte precision) {
	// prints val with number of decimal places determine by precision
	// precision is a number from 0 to 6 indicating the desired decimial places
	// example: lcdPrintDouble( 3.1415, 2); // prints 3.14 (two decimal places)

	if (val < 0.0) {
		Serial.print('-');
		val = -val;
	}

	Serial.print(int(val));  //prints the int part
	if (precision > 0) {
		Serial.print("."); // print the decimal point
		unsigned long frac;
		unsigned long mult = 1;
		byte padding = precision - 1;
		while (precision--)
			mult *= 10;

		if (val >= 0)
			frac = (val - int(val)) * mult;
		else
			frac = (int(val) - val) * mult;
		unsigned long frac1 = frac;
		while (frac1 /= 10)
			padding--;
		while (padding--)
			Serial.print("0");
		Serial.print(frac, DEC);
	}
}

period: 43173 1/16us / frequency: 370.611267 Hz
period: 113674601 1/16us / frequency: 0.140756 Hz
period: 20585 1/16us / frequency: 777.284423 Hz
period: 38078 1/16us / frequency: 420.200653 Hz
000
period: 38045 1/16us / frequency: 420.565124 Hz
period: 38052 1/16us / frequency: 420.487762 Hz
...lots more

The 000 prints out when you have just reset all three flags to false, hence 000.
Right before that the led blinked for about .2 seconds.
Right before you set them to false all three were true, since it entered the if(tone1==tone2==tone3==true) code
Right before that was the first time tone3 was true because it was the first 420.
Sometime before that it had already seen 320 and 370

OK

I think I understand now how the code works. Whether it would be possible that it toggle tone3 to back true right after all three flags has gone false.I mean that (period: 38045 1/16us / frequency: 420.565124 Hz) right after 000 (false) fires tone3 flag true and after that when second run comes, it needs only freq 370 and freq 320 to light up LED.
How I can prevent this toggle, my actual need is still three sample every round?

I added Serial .print to read tone3=true and I think it toggles back.What do you think?

 if(lfrq >=415 && lfrq <=425 ){ //420
  
    tone3=true; }
  Serial.print(tone3); // This is for testing purpose only
   if (tone1==true&&tone2==true&&tone3==true){
        
  digitalWrite(led12,HIGH);
  delay(200); 
  digitalWrite(led12, LOW);
  
  tone1=false;
  tone2=false;
  tone3=false;
  /*Serial.print(tone1);Serial.print(tone2);*/ Serial.println(tone3);

Now it says;

0period: 43188 1/16us  /  frequency: 370.482543 Hz  
0period: 43186 1/16us  /  frequency: 370.499694 Hz  
0period: 43171 1/16us  /  frequency: 370.628418 Hz  
0period: 83224463 1/16us  /  frequency: 0.192255 Hz  
0period: 20585 1/16us  /  frequency: 777.284423 Hz  
0period: 38081 1/16us  /  frequency: 420.167541 Hz  
10
period: 38045 1/16us  /  frequency: 420.565124 Hz  
1period: 38049 1/16us  /  frequency: 420.520904 Hz  
1period: 38034 1/16us  /  frequency: 420.686767 Hz  
1period: 38047 1/16us  /  frequency: 420.542999 Hz  
1period: 38036 1/16us  /  frequency: 420.664642 Hz