-1

i don't know how to manipulate arduino uno or mega registers and timers to be close to 75kHz output frequency. Could you help please ?

1
  • 1
    output frequency from where to where? Commented Dec 13, 2022 at 7:00

2 Answers 2

3

First you have to compute, from your desired frequency, the number of CPU cycles per period of the signal:

F_CPU / 75 kHz = 16,000 kHz / 75 kHz ≈ 213.33

Since the timers can only count up to an integer, the closest you can get is 213 CPU cycles. The frequency you get will then be

F_CPU / 213 = 16,000 kHz / 213 ≈ 75.12 kHz

Now you can configure a timer. I find that the easiest is to use a so called “fast PWM” mode. Choose one of those modes where the TOP value can be set with a register, and set it to one unit less than the desired period: the timer will then repeatedly count from 0 to 212.

Here is an example using channel A of Timer 1 on an Arduino Uno. The output is on digital pin 9 = OC1A = PB1:

// Configure Timer 1 for PWM @ 75.12 kHz.
DDRB  |= PB1;         // set OC1A = PB1 as output
TCCR1A = 0;           // clear the settings of the Arduino core
TCCR1B = 0;           // ...ditto
TCNT1  = 0;           // clear the timer
TCCR1A = _BV(COM1A1)  // non-inverting PWM on OC1A
       | _BV(WGM11);  // mode 14: fast PWM, TOP = ICR1
TCCR1B = _BV(WGM12)   // ...ditto
       | _BV(WGM13)   // ...ditto
       | _BV(CS10);   // clock at F_CPU
ICR1   = 213 - 1;     // period = 213 CPU cycles = 13.3125 us
OCR1A  = 213/2 - 1;   // duty cycle ~ 50%

You can easily adapt this to any timer on the Uno or Mega. Just avoid Timer 0 if you are going to use the Arduino timekeeping functions.

0

I think the answer given by Edgar Bonet is the right one, all things considered, and I up-voted it for that reason.

For S&G, I want to add the following:

  1. The easiest way is to simply use the tone(GPIO,Frequency); command - and there are caveats. BUT, the frequency argument is an unsigned int so the fastest frequency is 65535Hz - it will do you no good for 75kHz.

Using a frequency counter and an UNO (crystal), tone(10,65535); the output was 65556/8 Hz. On a Pro Mini 5V (ceramic resonator as I recall), it was 65540 Hz.

  1. Again, for S&G, I tried this code (and adjusted the number of NOPs) to get as close as I could to 75kHz:

void setup() { pinMode(10, OUTPUT); }

void loop() {
here:
  digitalWrite(10, HIGH);
  delayMicroseconds(3);
  __asm__("nop\n\t");
  __asm__("nop\n\t");
  __asm__("nop\n\t");
  __asm__("nop\n\t");
  __asm__("nop\n\t");
  __asm__("nop\n\t");
  __asm__("nop\n\t");
  digitalWrite(10, LOW);
  delayMicroseconds(3);
  __asm__("nop\n\t");
  __asm__("nop\n\t");
  __asm__("nop\n\t");
  __asm__("nop\n\t");
  __asm__("nop\n\t");
  __asm__("nop\n\t");
  __asm__("nop\n\t");
  goto here;
}

The output on the UNO was 75004/6 Hz - not too bad. On the Pro Mini, the best I could do was 74986 Hz.

Of course, we are talking about square waves.

2
  • Note that: 1. You can replace delayMicroseconds() and the train of nop with a single call to _delay_us(). This macro has single cycle resolution: _delay_us(3.4375) delays by exactly 55 CPU cycles with a 16 MHz clock. 2. This approach works better with interrupts disabled. Otherwise you get a small glitch on every timer interrupt. BTW: what does “S&G” mean? Commented Dec 13, 2022 at 20:11
  • urbandictionary.com/define.php?term=S%26G picked up the expression for someplace a long time ago :) Commented Dec 13, 2022 at 20:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.