Arduino uno, interrupt like code

Hi everyone, thank you for support.

Problem: I am building frequency counter with small T. I am using pin 5 is timer. I need to run part of code(for reading frequency) immediately when signal on pin 5 occurs. I do know that i can use attach interrupt only for pin 2 and 3 instead of 5. The problem is than the frequency pulse has only 30 ms and the code is not fast enough to catch it correctly - i am sending 20 MHz T=30 ms but it catches only half of signal ergo it displays F=10 MHz.

I hope that its is clear.

Thanks, Svato

Not clear to me.

How does 30mS and 20MHz feature in the same sentence, those frequencies/times are orders of magnitude apart.

And what's a "small T"?

FWIW if you poll pin 5 in a VERY tight loop you can react faster than an interrupt.

Hi everyone,
thank you for support.

Problem: I am building frequency counter with small T. I am using pin 5 is timer. I need to run part of code(for reading frequency) immediately when signal on pin 5 occurs. I do know that i can use attach interrupt only for pin 2 and 3 instead of 5. The problem is than the frequency pulse has only 30 ms and the code is not fast enough to catch it correctly - i am sending 20 MHz T=30 ms but it catches only half of signal ergo it displays F=10 MHz.

I hope that its is clear.

Thanks,
Svato

30 ms is an eternity in Arduino time. My crystal ball says that the problem is on line 42 of the code that you didn’t show us. A schematic or wiring diagram could help also.

To post code and/or error messages:

  1. Use CTRL-T in the Arduino IDE to autoformat your code.
  2. Paste the autoformatted code between code tags (the </> button)
    so that we can easily see and deal with your code.
  3. Paste the complete error message between code tags (the </> button)
    so that we can easily see and deal with your messages.

Before posting again, you should read the three locked topics at the top of the Programming Questions forum, and any links to which these posts point.

Good Luck!

T is period and the length of 20 MHz pulse is only for 30 ms , i need to catch its frequency in that small amount of time

You are not going to be able to read a 20MHz pulse on a 16Mhz processor.

Using the external clock source (pin5) on Timer 1 is the way to go, and counting the pulses over 30ms is not the problem. Nick Gammon has benchmarked the external clock source frequency counter to 8 MHz, with his Frequency Counter Sketch for Atmega 328 .

i am sending 20 MHz T=30 ms but it catches only half of signal ergo it displays F=10 MHz.

What Arduino and code are you using to capture 10MHz?

cattledog: You are not going to be able to read a 20MHz pulse on a 16Mhz processor.

Actually, it may be possible using timer 2 configured for asynchronous operation.

Please do not cross-post. Threads merged.

Hi,

Thank you, I am using divider so frequency range is no a problem. Code is simple:

while (FreqCounter::f_ready == 0) {  // wait until counter ready
      frq = FreqCounter::f_freq; // read result
    }

    frq = frq - (frq * 0.00034);
    frq = frq * 100 * 80;
    if (frq > 0) {
      buff = frq;
    }
    frq = buff;
  }

this is what basically reads input from digital pin 5.

The main problem is that I am also displaying it on display and when input occurs during that time, it is not able to catch it. I need something what enables me to priorly read input from pin 5 immediately when it occurs so I will catch all pulses.

U8GLIB_PCD8544 u8g(4, 3, A4, 2, A5);  // CLK=4, DIN=3, CE=A4, DC=2, RST=A5


float logarithm, output, frq, a, b, battery, buff, buffa, buffb;
unsigned int select;
String string, jednotky, fwd, bwd;

void setup() {
  pinMode(9, OUTPUT);
  //pinMode(A1, INPUT);
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);

  digitalWrite(9, HIGH);
  delay(500);
  pinMode(9, INPUT);
  analogWrite(6, 5);

  Serial.begin(57600);
}

void loop() {
  select = digitalRead(9);
  //battery = analogRead(A1);
  //battery = battery / 100;
  a = analogRead(A2);
  a = a / 200;
  b = analogRead(A3);
  b = b / 200;

  if (a > 0) {
    buffa = a;
  }
  a = buffa;
  
  if (b > 0) {
    buffb = b;
  }
  b = buffb;

  fwd = "FWD: " + String(float(a), 3) + " V";
  bwd = "BWD: " + String(float(b), 3) + " V";

  if (digitalRead(5) == HIGH) {
    FreqCounter::f_comp = 1;            // Set compensation to 12
    FreqCounter::start(10);

    while (FreqCounter::f_ready == 0) {  // wait until counter ready
      frq = FreqCounter::f_freq; // read result
    }

    frq = frq - (frq * 0.00034);
    frq = frq * 100 * 80;
    if (frq > 0) {
      buff = frq;
    }
    frq = buff;
  }

  delay(10);  // Start counting with gatetime of 100ms/10/100/1000
  logarithm = log10(frq);


  if (logarithm < 3) {
    jednotky = " Hz";
    output = frq;
  } else if ( logarithm < 6 && logarithm >= 3) {
    jednotky = " KHz";
    output = frq / 1000;
  } else if ( logarithm < 9 && logarithm >= 6) {
    jednotky = " MHz";
    output = frq / 1000000;
  } else if ( logarithm < 12  && logarithm >= 9) {
    jednotky = " GHz";
    output = frq / 1000000000;
  } else if ( logarithm < 15  && logarithm >= 12) {
    jednotky = " THz";
    output = frq / 1000000000000;
  }
  string = "F: " + String(float(output), 3) + jednotky;
  u8g.firstPage();
  do {
    draw();
  } while ( u8g.nextPage() );
}


void draw() {
  u8g.setFont(u8g_font_profont12);  // select font
  u8g.setPrintPos(0, 24);   // put string of display at position X, Y;
  u8g.print(string);
  u8g.setFont(u8g_font_profont11);
  u8g.setPrintPos(0, 40);
  u8g.print(fwd);
  u8g.setPrintPos(0, 48);
  u8g.print(bwd);
  //  u8g.setPrintPos(45, 8);
  //  u8g.print(String(battery));


}

Svato:
I need something what enables me to priority read input from pin 5 immediately when it occurs so I will catch all pulses.

Not going to happen.

https://www.pjrc.com/teensy/td_libs_FreqCount.html

FreqCount: best for 1 kHz to 8 MHz

well i had no problem to read it correctly but only if FreqCount Library code started before or in the exact time the pulse was there. I am using 10ms option so the reading was correct i had just problem with triggering it of in the right time.

You are not going to be able to read a 20MHz pulse on a 16Mhz processor.

Actually, it may be possible using timer 2 configured for asynchronous operation.

I don't think so. The "asynchronous clock" for timer2 comes in on the same pin that the 16MHz resonator is connected to on an Arduino, which is "not available" to the user...

Thank you, I am using divider so frequency range is no a problem

You appear to be using a library called FreqCounter which is here https://codebender.cc/library/FreqCounter#FreqCounter.cpp

OK, you are not trying to measure 20MHz directly, and you are using a library. You should have told us this in your first post.

The main problem is that I am also displaying it on display and when input occurs during that time, it is not able to catch it. I need something what enables me to priorly read input from pin 5 immediately when it occurs so I will catch all pulses.

Your issue appears to be that uglib8 and the tft display are blocking the frequency reading. I doubt that you will be able to get a randomly frequency reading to interrupt the display draw, but I am not knowledgeable about uglib8.

You should probably not be updating the display every time through loop, but rather coordinating with updated frequency information.

Please tell us more about the frequency signal source? Is it continuous? Is it intermittant? What triggers the signal? Is it random?

westfw: I don't think so.

I agree for that reason and another.

As far as I can tell, it is impossible for a m328 to capture a frequency higher than the processor's frequency. Pin synchronizers get in the way.

Yes, I'm pretty sure the sync circuit for each pin is essentially a latch driven by the system clock, so no way it can see faster signals and it may even mean that you can only see freq up to half the system clock.

I think for 20MHz you need an external prescaler.

[Solved]

I was able to use interrupts although I was using freq counter lib. Check- http://playground.arduino.cc/Main/PinChangeInt it's handful to know about this possibility, when talking about interrupts.

Problem: I was trying to catch 30ms pulse of 50 MHz frequency. Yes I am using divider (prescaler) , so as you have said you can count frequency up to 8 MHz using your board. Because I had such small amount of time for detection (30 ms) I wanted to start in the exact time pulse has started. That's why I needed something like interrupt.

I am using software interrupts so they do not cross with hardware interrupts used by freq counter lib.

Thank you for your support :)