Dear all,
I'm currently working on a frequency measurement device, wich eventualy measure the frequency of a generator 3 times with a fixed period in between, to determine what the final frequency will be. After that, stuff wil happen to keep the frequency constant (sort of feedback loop). Problem now is, I need a verry high resolution in the pulselength measurement, otherwise the math will be bad. So I tried with micros(), turns out.. resolution of micros() function is 4 us. Bit to bad..
Now I've done a little reading, digging in the datasheet of the atmega 2560 and stuff, cause I want to use Timer5 to count the clockpulses between HIGH state and HIGH state of the measurement pin, to determine the periode 'time' (I know that in order of time, this is not a guaranty of frequency accuracy of 100%, but i'm conserned about the resolution in the first place).
Problem is, that when i set the OCR5A output compare register to a small value (to get beter resolution), results go nuts and arent what they sepose to be (20Hz PWM from the arduino itself in the test).
Can anyone please tell me what I'm doing wrong?
Here is my code:
#include <PWM.h>
#define frequencyOutput 5
#define frequencyInput 3 // this is pin 20
const int uSecInterval = 6;
int32_t frequencyOfPin = 5;
double Freq;
double Frequency_1;
double duration;
int x;
int i;
int finalTime;
int beginTime;
unsigned long TimeDuration;
int startF = 50;
unsigned long Time;
unsigned long EndTime;
volatile unsigned long TimerS;
void setup() {
InitTimersSafe();
SetPinFrequencySafe(frequencyOutput,frequencyOfPin);
pinMode(frequencyOutput, OUTPUT);
pinMode(9,OUTPUT);
Serial.begin(9600);
x= startF;
pinMode(22,INPUT);
noInterrupts(); //disable global interupt
TimerS = 0; //clear increment in ISR
TCCR5A = 0; //clear timer nA register
TCCR5B = 0; //clear timer nB register
TCNT5=0; //Set counter to 0
OCR5A = uSecInterval*16-1; //Output Compare Restister nA (with prescaler one, one pulse =
1/16th microsecond, so topvalue should be this value, to fit in
the amount of microsecond between TimerS_n and TimerS_n+1
TCCR5B |= (1<<CS50) | (1<<WGM52); //Prescaler = 1, CLC
TIMSK5 |= (1<<OCIE5A); //Enable OCR5A interrupt
interrupts(); //enable global interupt
for(i=0;i<5;i++){
Time = TimerS;
delayMicroseconds(50);
EndTime = TimerS;
Serial.println((EndTime-Time)*uSecInterval); //<<this is to check if the timing is a bit right
}
}
ISR(TIMER5_COMPA_vect){
TimerS++;
}
void loop() {
delay(100);
SetPinFrequencySafe(frequencyOutput,x);
beginTime = micros();
analogWrite(frequencyOutput,254);
Frequency_1 = FrequencyMeasure_1(); // this is the call for frequency measurement!
}
double FrequencyMeasure_1(){
restart:
TimerS=0;
switch(digitalRead(22)){
case LOW:
while(digitalRead(22)==LOW){}
Time = TimerS;
while(digitalRead(22)==HIGH){}
while(digitalRead(22)==LOW){}
EndTime = TimerS;
break;
case HIGH:
while(digitalRead(22)==HIGH){}
Time = TimerS;
while(digitalRead(22)==LOW){}
while(digitalRead(22)==HIGH){}
EndTime = TimerS;
break;
}
/*if (EndTime<Time){
goto restart;
}*/
Freq= 1000000/((float)EndTime-(float)Time)/uSecInterval;
//Serial.println(Freq);
return Freq;
}
Tried this with macros() and that worked ok, but not within the resolution I need/want.
Results with uSecInterval = 6 are between 3333 to 3335 pulses from the clock (19998 to 20010 us on 50Hz)
Results with uSecInterval = 2 are between 4964 to 5000 pulses from the clock (9928 to 10000 us on 50Hz, which is totaly wierd..)
Results with uSecInterval = 1 are between 4965 to 5000 pulses from the clock (4965 to 5000 us on 50Hz, which is even wierder..)
Any help will be great!