On Arduino due PWM frequency
I just got myself a couple of Arduino Due boards. While they were released almost two years ago, I have not really got a chance to look at these until quite recently. Arduino Due is based on Atmel’s ATSAM3x8E 32-bit ARM Cortext-M3 processor. The processor core runs at 84 MHz, which is significantly faster than its 8-bit AVR counterpart ATmega328p which runs at 16 MHz. For an ATmega328p, the highest achievable PWM frequency is 8Mhz (square wave), so we should be able to generate much higher frequency signals on an Arduino Due. But how high can we go? Let’s find out.
If you use the bit-banging method (e.g. pin toggling), the highest achievable output frequency is actually quite abysmal. For example, the following code on Due generates a 200.7 kHz square wave on pin 8 (compiled with Arduino 1.5.7):
The Arduino code base is not very efficient and this code is actually not much faster than the same code on an ATmega328p (126.2 kHz for comparison, compiled with Arduino 1.0.5). By the way, the reason a while loop is used inside the loop() function is that the loop function has some extra instructions for checking the serial port. So if we did not use the while loop, extra instructions would be executed after outputting a LOW, causing the duty cycle to change and lowering the overall waveform frequency. This overhead is not very noticeable on ATmega328p (116.9 kHz without the while loop versus 126.2 kHz with the loop). But on Arduino Due, this difference is much more drastic. If the while loop is removed, the output frequency will drop to 145.4 kHz which is a 30% degradation from 200.7 kHz!
Of course, we can improve the code efficiency above quite a bit by using direct port manipulation. If we replace the digitalWrite with the following code, we will get an output square wave on pin 8 of roughly 16.8 Mhz. This is a huge improvement over the meager 200.7 kHz with digitalWrite.
We can do even better if we use the dedicated hardware (e.g. via PWM controller) to generate our waveform rather than big-banging with software. But before doing that, let’s take a look at how the the 84 Mhz clock frequency is obtained on the Due.
In /arduino-1.5.7/hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam3xa/source/system_sam3xa.c you will find the following definitions:
For more detail: On Arduino due PWM frequency
JLCPCB – Prototype 10 PCBs for $2 + 2 days Lead Time
China’s Largest PCB Prototype Enterprise, 300,000+ Customers & 10,000+ Online Orders Per Day
Inside a huge PCB factory: https://www.youtube.com/watch?v=_XCznQFV-Mw
This Post / Project can also be found using search terms:
- pwm frequency code for arduino pdf