Square wave generator and frequency meter

i also changed my generator code a little and it helped alot, from the time that clock waits to change output i substracted time it takes to make this whole isr function.

Then re-post that one also...

New generator code

unsigned long waveHz = 100000;
unsigned int exacttime, numofovf;
volatile unsigned int timeovf;
unsigned long waveTime;

void setup() {

  pinMode(2, OUTPUT);
  waveTime = (1.0/(waveHz*2.0))*16000000;
  numofovf = waveTime/65536;
  exacttime = waveTime-(numofovf*65536UL);
  if(exacttime>38){
    exacttime = exacttime-38;
  } else {
    exacttime = 65535-38+exacttime;
    numofovf = numofovf - 1;
  }
  cli();          
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;
  OCR1A = exacttime;           
  TCCR1B |= (1 << CS10);       
  TIMSK1 |= (1 << OCIE1A);
  TIMSK1 |= (1 << TOIE1); 
  sei();  
}

void loop() {
}

ISR(TIMER1_COMPA_vect){
  if(timeovf == numofovf){
    TCNT1 = 0;
    timeovf = 0;
    PORTD ^= bit(2);
  }
  
}

ISR(TIMER1_OVF_vect){
  timeovf++;
}

New freq meter code

unsigned int timervalue, overflows, timeovf;
float hz;
unsigned long timeofrev;
void setup() {
  // put your setup code here, to run once:
  pinMode(2, INPUT);
  pinMode(LED_BUILTIN, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(2), rpmcheck, RISING);
  Serial.begin(115200);
  cli();          
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;
  TCCR1B |= (1 << CS10);    
  TIMSK1 |= (1 << TOIE1); 
  sei();  
}

void loop() {
  cli();
  timeofrev = overflows*65535UL+timervalue;
  sei();
  hz = 16000000/timeofrev;
  Serial.println(hz, 2);
  delay(500);
}

ISR(TIMER1_OVF_vect){
  timeovf++;
}

void rpmcheck() {
  timervalue = TCNT1;
  TCNT1 = 0;
  overflows = timeovf;
  timeovf = 0;
}

There is no documentation or inline comments of any significance. Can you explain in a paragraph or two, how this thing works? I'm focusing on the freq meter now...

Just one detail, variables shared between the main program and ISR must be declared using the 'volatile' keyword.

You seem to be expecting 'timervalue' to hold the residual fractional part of the timed interval. But it isn't updated when you use it. It's only updated when timer 1 fires. You do that in the timer 1 ISR.

TLDR;It basically counts how much ticks of TIMER1 it took from 1 rising edge on pin D2 to another rising etge there, and then calcualtes freqency based on that tick number.

So, expected input on pin D2 is a square wave of any frequency. TIMER1 is set just to count, and interrupt on overflow is set to on.
On overflow interrupt it just increments value of timeovf - to know how much times the timer overflowed. Now there is interrupt attached on rising edge of pin D2. So when pin D2 changes from LOW to HIGH function rpm check is called. What rpmcheck function does, is basically store current value of TIMER1 into variable "timervalue", then erase TIMER1, then store current value of overflows into variable "overflows" and erase overflows. Now based on those two variables("timervalue" and "overflows") - we can calculate how much timer1 ticks it took for the 1 wave cycle. Since TIMER1 is 16Mhz we can calculate how much time it took for 1 wave cycle to happen and then calculate frequency from that - based on this tick value that we stored in rpmcheck function.

What do you think the value of TCNT1 is, at the moment when a Timer 1 interrupt fires?

Also i changed variables to volatile

volatile unsigned int timervalue, overflows, timeovf;
float hz;
unsigned long timeofrev;
void setup() {
  // put your setup code here, to run once:
  pinMode(2, INPUT);
  pinMode(LED_BUILTIN, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(2), rpmcheck, RISING);
  Serial.begin(115200);
  cli();          
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;
  TCCR1B |= (1 << CS10);    
  TIMSK1 |= (1 << TOIE1); 
  sei();  
}

void loop() {
  cli();
  timeofrev = overflows*65535UL+timervalue;
  sei();
  hz = 16000000/timeofrev;
  Serial.println(hz, 2);
  delay(500);
}

ISR(TIMER1_OVF_vect){
  timeovf++;
}

void rpmcheck() {
  timervalue = TCNT1;
  TCNT1 = 0;
  overflows = timeovf;
  timeovf = 0;
}

I guess its 0 or 65535.

Correct. That is your problem right there.

Where?

Because then 'timervalue' can only ever be 65535 or 0.

Why is that?

because the only time you ever assign a value to 'timervalue' is when timer 1 fires... try a serial debug print of 'timervalue'...

And thats a false claim, i assign value to timervalue when i get interrupt on pin D2 not when timer1 overflows.
In timer1 overflow ISR is only 1 line of code:

ISR(TIMER1_OVF_vect){
  timeovf++;
}

Oh, I see.. okay, rethinking.

Also i think wavegenerator is the wrong function, because when i plug freq meter to pin which has analogWrite on it it gives me exactly 490hz or 980hz depending on pin which i use for analogWrite.

...at least we got some basic interrupt protocol fixed...

try

  hz = 16000000.0/timeofrev;

Wave generator set to 50000hz. Still quite off and a lot of fluctuations. Thats what gives freq meter output after this change:

51446.94
51282.05
52980.13
53156.14
51282.05
51446.94
53156.14
49230.77
51118.21
51282.05
51282.05
51282.05

You've got two unknowns. You need to use some known good frequency source. Or else, apply the output from your generator, to a known good frequency meter.