Hi, I made a board based on SAMD21, which is basically a crystaless Zero.
It turns out that to power from a USB battery pack, I need to periodically increase the current consumption > 50mA. My goal is to find a safe way to do this without adding more components onto the board.
What I've done so far:
Baseline with 48MHz DFLL oscillator + I2S, I2C, USB peripheral = 22mA
Outputting max voltage to DAC pin (not connected to anything) = 35mA
I can't seem to increase the draw beyond this point. Anyone has other suggestions?
You could try firing up the SAMD21's 96MHz Fractional Digital Phase Locked Loop (FDPLL96M), then route this clock source to any unused TCCx/TC3 timers, all of which are capable of running at this higher speed:
// SAMD21: Connect the 96MHz DPLL to the TCCx timers
void setup()
{
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable the generic clock
//GCLK_CLKCTRL_GEN_GCLK1 | // Select GCLK1 using the OSC32K internal 32k oscillator for CRYSTALLESS operation
GCLK_CLKCTRL_GEN_GCLK2 | // Select GCLK2 using the OSCULP32K ultra low power 32k oscillator
GCLK_CLKCTRL_ID_FDPLL; // Connect GCLK2 to GCLK_DPLL input
SYSCTRL->DPLLCTRLB.reg = SYSCTRL_DPLLCTRLB_REFCLK_GCLK; // Select GCLK_DPLL as the clock source
SYSCTRL->DPLLRATIO.reg = SYSCTRL_DPLLRATIO_LDRFRAC(11) | // Generate a 96MHz DPLL clock source from the external 32kHz crystal
SYSCTRL_DPLLRATIO_LDR(2928); // Frequency = 32.768kHz * (2928 + 1 + 11/16) = 96MHz
SYSCTRL->DPLLCTRLA.reg = SYSCTRL_DPLLCTRLA_ENABLE; // Enable the Digital Phase Locked Loop (DPLL)
while (!SYSCTRL->DPLLSTATUS.bit.LOCK); // Wait for the DPLL to achieve lock
GCLK->GENDIV.reg = GCLK_GENDIV_DIV(1) | // Divide the 96MHz clock source by divisor 1: 96MHz/1=96MHz
GCLK_GENDIV_ID(4); // Select Generic Clock (GCLK) 4
GCLK->GENCTRL.reg = GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW
GCLK_GENCTRL_GENEN | // Enable the generic clock
GCLK_GENCTRL_SRC_FDPLL | // Set the clock source to FDPLL96M at 96MHz
GCLK_GENCTRL_ID(4); // Select GCLK4
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable the generic clock
GCLK_CLKCTRL_GEN_GCLK4 | // Select GCLK4
GCLK_CLKCTRL_ID_TCC0_TCC1; // Connect GCLK4 to TCC0 and TCC1
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable the generic clock
GCLK_CLKCTRL_GEN_GCLK4 | // Select GCLK4
GCLK_CLKCTRL_ID_TCC2_TC3; // Connect GCLK4 to TCC2 and TC3
TCC0->PER.reg = 0xFFFF; // Set the frequency of the PWM on TCC0
while(TCC0->SYNCBUSY.bit.PER); // Wait for synchronization
TCC1->PER.reg = 0xFFFF; // Set the frequency of the PWM on TCC1
while(TCC1->SYNCBUSY.bit.PER); // Wait for synchronization
TCC2->PER.reg = 0xFFFF; // Set the frequency of the PWM on TCC2
while(TCC2->SYNCBUSY.bit.PER); // Wait for synchronization
TCC0->CTRLA.bit.ENABLE = 1; // Enable TCC0
while (TCC0->SYNCBUSY.bit.ENABLE); // Wait for synchronization
TCC1->CTRLA.bit.ENABLE = 1; // Enable TCC1
while (TCC1->SYNCBUSY.bit.ENABLE); // Wait for synchronization
TCC2->CTRLA.bit.ENABLE = 1; // Enable TCC2
while (TCC2->SYNCBUSY.bit.ENABLE); // Wait for synchronization
}
void loop() {}
Note that the generic clock divider should remain set to 1 at this higher frequency.