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
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
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) ;
}
}
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.
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.
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) ;
}
}
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?
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?
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?
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 )
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?
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);