Custom PWM frequency on SAMD21 based hardware - VGavara/arduino-TB6612FNG GitHub Wiki
Table of contents
Abstract
This document exposes the integration of the library SAMD21_turbo_PWM into Arduino_TB6612FNG in order to support driving motors using a custom PWM frequency.
Background
When driving DC motors with PWM, a careful frequency customization greatly improves both performance and motor life (1). Frequencies in the range of kiloHertz, specially above the human sonic limit (20kHz) are desirable.
Though the PWM frequency on Arduinos can be customized, it requires deep knowledges on each specific Arduino hardware platform. That implies using specific, hardware-dependant libraries when dealing with PWM frequency customization.
The default PWM frequency on SAMD21-based Arduinos is fixed to 732Hz, whereas the max switching frequency of Toshiba TB6612FNG driver is 100kHz. Therefore there is an important difference (99,3kHz) between the generator PWM frequency and the driver absolute maximum switching value.
Based on that previously exposed, supporting PWM frequency customization at Motor
class level is both feasible and desirable. For that purpose, specific hardware libraries exist and can be used, though the scope of this document only covers the frequency customization on SAMD21 based Arduinos by using the library SAMD21_turbo_PWM.
Applying frequency customization
Customizing the frequency
The SAMD21_turbo_PWM library uses the Processor Generic Clock as PWM source, what means using a base frequency of 48Mhz. As exposed in 2 and 3, this source can be connected to different Timers/Counters for Control (TCC) that are in charge of generating the desired PWM frequency and duty cycle based on the user configuration. Specifically, the PWM frequency in kHz is defined by the formula:
Where:
- GCLK is the Generic Clock frequency, in kHz. Since SAMD21_turbo_PWM uses the Processor Generic Clock as source (48MHz), this value is 48000kHz.
- N is the prescaler value.
- PER is the PERIOD register value. Depending on specific conditions out of the scope of this document, the PER register can have a size of 16 or 24 bits, what means that in the worst case (16 bits) it can take values from 0 to 65535.
For the specific need of customizing the frequency for driving a motor via a Toshiba TB6612FNG, N can be set constant to its minimum value (1) while PER can range from 240 (PWM frequency = 100 kHz, ie, the max. TB6612FNG switching frequency) to 32768 (PWM frequency = 732 Hz, ie, the default Arduino frequency). This value can be stored in 16 bits, that is the smaller size for the PER register, so there is no need of constraining it based on the register size.
PWM duty cycle resolution
PER value also determines the PWM duty cycle resolution. The standard PWM resolution on Arduinos is 256 steps, what means that it can take values from 0 to 255. On the other hand, the maximum resolution managed by the SAMD21_turbo_PWM library is 1000. Therefore we must choose PER values that range between the Arduino standard PWM resolution (256) and, at least, the SAMD21_turbo_PWM library resolution (1000).
The custom PWM duty cycle resolution on SAMD21 Arduinos is based on the formula:
With the above PER value range (240-32768), the PWM resolution would range from 256 steps at 100kHz (the default Arduino PWM resolution) to above 1024 steps for frequencies below 23,4kHz (above the maximum SAMD21_turbo_PWM library), as shown in this table:
Resolution | Higher Frequency (kHz) | Lower Frequency (kHz) |
---|---|---|
256 | 100 | 96,1 |
512 | 95,7 | 47 |
1024 | 46,9 | 23,5 |
>=2048 | 23,4 | 0,7 |
Calculating PER given a user frequency
The above formula calculates the PWM frequency given a PER value. If the PER value must be calculated given a PWM frequency, this formula must be used:
... being PWMFreq the desired PWM frequency, in kHz. The result must be rounded to get an integer PER value. Using this formula, the PWM frequency calculation can be abstracted to the user and, instead of setting it based on a PER value, the PER value can be calculated from a PWM frequency.
PWM pins
As previously said regarding custom PWM, the frequency source can be connected to different Timers/Counters for Control (TCC) that are in charge of generating the desired PWM frequency and duty cycle based on the user configuration. In practical terms, the used TCC also determines what Arduino pins can be used as PWM source.
The SAMD21_turbo_PWM library can work with TCC0, TCC1 and TCC2, what determines the potential PWM source pins depending on the Arduino board (4):
Board | TCC | PWM source pins |
---|---|---|
Nano 33 IoT | 0 | 5, 6, 8, 12 |
1 | 4, 7 | |
2 | 11, 13 | |
Zero | 0 | 3, 4, 10, 12 |
1 | 8, 9 | |
2 | 11, 13 | |
MKR series | 0 | 4, 5, 6, 7 |
1 | 2, 3 | |
2 | 8, 9 |
Therefore, given a PWM pin and the specific Arduino board model the TCC can be set. That allows inhibiting the user of setting the desired TCC and, instead, just asking for the source PWM pin and then setting the TCC by using the table above.