Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

External input for the timer1 to generate an interrupt when the counter reaches the maximum #38

Open
rtek1000 opened this issue May 22, 2019 · 4 comments

Comments

@rtek1000
Copy link

I would like to make a frequency meter for up to 500khz (or more if possible), I would like to try via external input for the timer1 (16 bits, should give a 7 restarts). It seems that it is possible to generate an interrupt when the counter reaches the maximum (when it should restart the count).

I've been looking at the source code, but it seems like there's no such kind of setup, do you have any examples?

Thank you.

@rtek1000
Copy link
Author

Note: Atmega328

@rtek1000
Copy link
Author

rtek1000 commented May 22, 2019

I have found some codes (I need to test at 500kHz):
(need a jumper from D3 to D5)

//#include <TimerOne.h>

const int led = LED_BUILTIN;  // the pin with a LED

void setup(void)
{
  pinMode(led, OUTPUT);
  //Timer1.initialize(150000);
  //Timer1.attachInterrupt(blinkLED); // blinkLED to run every 0.15 seconds

  TIMSK1 |= (1 << TOIE1);             // interrupt TIMER1 on
  
  TCCR1A = 0;                         //normal OC1A OC1B off
  TCCR1B = 0;                         //clear register
  TCCR1B = 0;                         //clear register
  // external clock on pin4 rising edge
  //TCCR1B |= (1<<CS12) | (1<<CS11) | (1<<CS10);
  // external clock on pin4 falling edge
  TCCR1B |= (1 << CS12) | (1 << CS11) | (0 << CS10);

  TCNT1 = 0;                          //clear register
  Serial.begin(9600);

  pinMode(5, INPUT_PULLUP);

  pinMode(3, OUTPUT);
  analogWrite(3, 128);

  TCCR2B = TCCR2B & B11111000 | B00000001; // for PWM frequency of 31372.55 Hz
}

unsigned long blinkCount = 0; // use volatile for shared variables

//void blinkLED(void)
ISR(TIMER1_OVF_vect)                              //interrupção do TIMER1 
{
  blinkCount++;  // increase when overflows

  digitalWrite(led, !digitalRead(led));
}

uint32_t millis1;
uint32_t calcMed = 0;

// The main program will print the blink count
// to the Arduino Serial Monitor
void loop(void)
{

  calcMed = (blinkCount * 65536) + TCNT1;
  blinkCount = 0;
  TCNT1 = 0;

  // 5000ms for overflow a few times
  calcMed /= 5; // 5s (5000ms) freq=1s/pulses

  Serial.print("Freq = ");

  Serial.println(calcMed);

  // 5000ms for overflow a few times (PWM at 31khz)
  while ((millis1 + 5000) > millis()) {

  }

  millis1 = millis();
}

Sources:
https://www.robotshop.com/community/forum/t/arduino-101-timers-and-interrupts/13072
https://www.embarcados.com.br/timers-do-atmega328-no-arduino/
https://forum.arduino.cc/index.php?topic=169100.0
https://etechnophiles.com/change-frequency-pwm-pins-arduino-uno/

@rtek1000
Copy link
Author

D3 at 232khz!!!

//#include <TimerOne.h>

const int led = LED_BUILTIN;  // the pin with a LED

void setup(void)
{
  pinMode(led, OUTPUT);
  //Timer1.initialize(150000);
  //Timer1.attachInterrupt(blinkLED); // blinkLED to run every 0.15 seconds

  TIMSK1 |= (1 << TOIE1);             // interrupt TIMER1 on

  TCCR1A = 0;                         //normal OC1A OC1B off
  TCCR1B = 0;                         //clear register
  TCCR1B = 0;                         //clear register
  // external clock on pin4 rising edge
  //TCCR1B |= (1<<CS12) | (1<<CS11) | (1<<CS10);
  // external clock on pin4 falling edge
  TCCR1B |= (1 << CS12) | (1 << CS11) | (0 << CS10);

  TCNT1 = 0;                          //clear register
  Serial.begin(9600);

  pinMode(5, INPUT_PULLUP);

  //  pinMode(3, OUTPUT);
  //  analogWrite(3, 128);

  TCCR2B = TCCR2B & B11111000 | B00000001; // for PWM frequency of 31372.55 Hz

  pinMode(3, OUTPUT); // output pin for OCR2B, this is Arduino pin number

  // In the next line of code, we:
  // 1. Set the compare output mode to clear OC2A and OC2B on compare match.
  //    To achieve this, we set bits COM2A1 and COM2B1 to high.
  // 2. Set the waveform generation mode to fast PWM (mode 3 in datasheet).
  //    To achieve this, we set bits WGM21 and WGM20 to high.
  TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);

  // In the next line of code, we:
  // 1. Set the waveform generation mode to fast PWM mode 7 —reset counter on
  //    OCR2A value instead of the default 255. To achieve this, we set bit
  //    WGM22 to high.
  // 2. Set the prescaler divisor to 1, so that our counter will be fed with
  //    the clock's full frequency (16MHz). To achieve this, we set CS20 to
  //    high (and keep CS21 and CS22 to low by not setting them).
  TCCR2B = _BV(WGM22) | _BV(CS20);

  // OCR2A holds the top value of our counter, so it acts as a divisor to the
  // clock. When our counter reaches this, it resets. Counting starts from 0.
  // Thus 63 equals to 64 divs.
  OCR2A = 63;
  // This is the duty cycle. Think of it as the last value of the counter our
  // output will remain high for. Can't be greater than OCR2A of course. A
  // value of 0 means a duty cycle of 1/64 in this case.
  OCR2B = 0;
}

unsigned long blinkCount = 0; // use volatile for shared variables

//void blinkLED(void)
ISR(TIMER1_OVF_vect)                              //interrupção do TIMER1
{
  blinkCount++;  // increase when overflows

  digitalWrite(led, !digitalRead(led));
}

uint32_t millis1;
uint32_t calcMed = 0;

// The main program will print the blink count
// to the Arduino Serial Monitor
void loop(void)
{

  calcMed = (blinkCount * 65536) + TCNT1;
  blinkCount = 0;
  TCNT1 = 0;

  // 5000ms for overflow a few times
  //  calcMed /= 1; // 1s (5000ms) freq=1s/pulses

  Serial.print("Freq = ");

  Serial.println(calcMed);

  // 1000ms for overflow a few times (D3 at 232khz)
  while ((millis1 + 1000) > millis()) {
    _delay_us(5);
    if ( OCR2B < 63 )
      OCR2B += 5;
    else
      OCR2B = 0;
  }

  millis1 = millis();
}

@rtek1000
Copy link
Author

Note: It worked well with about 450khz (I do not have 500khz at the moment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant