Skip to main content
Arduino

Return to Revisions

2 of 2
Copy edited (e.g. ref. <http://en.wikipedia.org/wiki/Hertz#SI_multiples>, <http://arduino.cc/en/Main/ArduinoBoardUno>, <https://en.wikipedia.org/wiki/Interrupt_handler>, <https://en.wikipedia.org/wiki/ATmega328>, and <http://english.stackexchange.com/questions/15953>).

It is indeed possible to generate a 56 kHz signal with an Arduino timer.

A timer actually can be seen as a special register, in the MCU, that holds a value (starting at 0) that gets incremented at a frequency that is the MCU clock frequency (16 MHz on Arduino Uno), possibility divided by a factor called prescaler. When that value reaches a limit, called Compare Match, that you specify, then two things happen:

  • The timer register value is reset to 0.
  • One ISR (interrupt service routine) callback function gets called (you can define it to point to your own code).

The idea is to use that ISR to change the output of a logical pin every time it is called (HIGH, then LOW, then HIGH...).

Now, in order to generate a 56 kHz square wave, you'll need your ISR to be called 56000 * 2 times per second (* 2 because you need to change the output value twice per period).

You can choose the prescaler value you want for a timer among the following list:

  • 1 (clock frequency is not divided, hence 16 MHz)
  • 8 (clock frequency is divided by 8, hence 2 MHz)
  • 64
  • 256
  • 1024

There are two sizes of timers/counters on Arduino Uno (they are called timer/counter actually): 8 bits and 16 bits.

On Arduino Uno (ATmega328P), you have three timers overall, but some may be used by the Arduino core library or other libraries used in your sketches (you'll have to check that by yourself):

  • timer0 (8-bit)
  • timer1 (16-bit)
  • timer2 (8-bit): this one has more prescaling options (1, 8, 32, 64, 128, 256, and 1024)

Now you need to generate a 56 kHz wave from 16 MHz, hence, without prescaling, you would need to count to:

16000000 / (56000 * 2) - 1 = 141.857 (- 1 because a timer counts from 0 to this value and resets only after it has been reached)

From this calculation, we can draw two observations:

  1. 141.857 is not an integer and thus you won't be able to generate a wave of exactly 56 kHz.
  2. Without prescaling, you need a 16-bit timer as 285 is not representable as an 8-bit unsigned integer.

From now you have two options:

  1. Use a 16-bit timer (timer1), use prescaler = 1, and select 142 as the Compare Match; that will give you the following frequency: 16000000 / (2 * (142 + 1)) = 55944 Hz
  2. Use an 8-bit timer (timer0), use prescaler = 8, and select 17 as the Compare Match; that will give less precision with the following frequency: 16000000 / (8 * 2 * (17 + 1)) = 55555 Hz which is still within the required range.

Now, regarding how to write your sketch for that, I advise you to check out this instructable which is very complete and very interesting to read.

Of course, the ATmega328P complete datasheet is also important if you want to understand, in the slightest details, what you are doing.

Some important notes:

  • An ISR is executed with disabled interrupts and must thus be as short as possible. In particular, there are several functions from the Arduino library that shall not be called from an ISR.
  • Arduino Uno clock is not very accurate (it uses a ceramic resonator instead of a quartz, which would have been much more accurate), so this means the output frequency will shift further.
jfpoilpret
  • 9.2k
  • 7
  • 38
  • 54

AltStyle によって変換されたページ (->オリジナル) /