0
\$\begingroup\$

for the school project I must measure frequency with Arduino Atmega2560 (or some other microcontroller). The Idea is to have timer interrupt set to 1 second and external square signal (frequency) connected to pin interrupt.. Each interrupt on pin increment counter for 1.. Every second (timer interrupt) the frequency is calculated ant counter is reset to 0. The frequency I must measure vary from 2-11 kHz..Can this be done?

regards

\$\endgroup\$
  • \$\begingroup\$ what is your clock frequency, and interrupt latency? \$\endgroup\$ – Sean Houlihane Nov 2 '16 at 7:54
  • 2
    \$\begingroup\$ Gut feeling: easily. For higher frequencies it might be better to use a counter/timer to count the pulses directly. \$\endgroup\$ – Wouter van Ooijen Nov 2 '16 at 8:03
  • \$\begingroup\$ I think the clock frequency is 12Mhz or 16Mhz (must verify).. \$\endgroup\$ – Ferguson Nov 2 '16 at 8:13
  • 2
    \$\begingroup\$ You can measure frequencies all the way up to 8 MHz (perhaps even up to 16 MHz, I can't remember) by using timer/counter 2 as an externally clocked counter. \$\endgroup\$ – jms Nov 2 '16 at 9:11
1
\$\begingroup\$

The Arduino ATMega2650 is listed as having a clock speed of 16MHz, meaning that it should be able to handle this at least in terms of instruction cycles. If you look at the datasheet (P.39) for the actual ATMega2650 chip it appears the I/O clock runs at the same speed as the CPU clock.

There is also this forum post where someone found the maximum digital write speed to be around 100kHz.

I'd say go for it. The chip should be able to handle this. The only place you might run into issues is if you try to do too much in your 1 second timer interrupt, but if all you are doing is returning the counter value then resetting you should be fine.

\$\endgroup\$
0
\$\begingroup\$

Should this be ok?

Little explanation.. if a signal is prenest on pin 2 the method readtemp() is called and counter is incremented.. Every one second the interrupt service routine is called. In this routine I check if two secconds are passed and if yes then the frequency is calculated, counter is set to 0.. In the main loop I check if the flag bData is true and if yes then the temperature is calculated and send over serial port to pc..

#include <SPI.h>
#include <Ethernet.h>
#include <Math.h>

const byte interruptPinTemp = 2;
const byte interruptPinSlanost = 3;

//konstante 
const double g = 4.85442486e-003;
const double h = 6.77300393e-004;
const double i = 2.65502731e-005;
const double j = 2.06782794e-006;
const double f = 1000.0;

volatile int cnt = 0;
volatile int cnt1 = 0;

int timer1_counter;

boolean bData = false;

volatile int dvesek = 1;

void setup() {

  Serial.begin(9600);       
  noInterrupts();           

  pinMode(interruptPinTemp, INPUT_PULLUP);
  pinMode(interruptPinSlanost, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(interruptPinTemp), readTemp, CHANGE);

  TCCR1A = 0;
  TCCR1B = 0;
  timer1_counter = 34286;   // preload timer 65536-16MHz/256/2Hz

  TCNT1 = timer1_counter;   // preload timer
  TCCR1B |= (1 << CS12);    // 256 prescaler
  TIMSK1 |= (1 << TOIE1);   // enable timer overflow interrupt
  interrupts();
}

//Timer interrupt na 1 sekundo
ISR(TIMER1_OVF_vect)        // interrupt service routine
{
  TCNT1 = timer1_counter;   // preload timer

  if (dvesek++ == 2)
  {
    cnt1 = cnt / 2 ;               
    bData = true;             
    cnt = 0;
    dvesek = 1;
  }

}

void loop() {
  // if bData is available... print it on serial port....
  if (bData == true)
  {
    bData = false;
    Serial.println(calcTemp(cnt1), 3);
  }

}

void readTemp() {
  cnt++;
}



//get temperature from measured frequency...
double calcTemp(double frekvenca)
{
  double logRes = log(f / frekvenca);
  return 1.0 / (g + (h * logRes) + (i * pow(logRes, 2.0)) + (j * pow(logRes, 3.0))) - 273.15;
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.