Battery Operation Environment for Raspberry Pi Pico Part 2

Friday, August 27, 2021

Raspberry Pi Pico

t f B! P L

This is the sequel to Battery Operation Environment for Raspberry Pi Pico Part 1.

Description of External Additional Circuits

Breadboard Test Circuit

The external additional circuits will be explained based on a breadboard test circuit that does not use SMD components.

Battery Charger Connection: P-ch MOS-FET (T1)

Battery Charger Connection: P-ch MOS-FET

Part 1, in order to use battery power when USB power is not connected and to supply USB power to the DC/DC converter side while charging the battery when USB power is connected, as described in pico-datasheet.pdf, a P-ch MOS-FET (T1) is placed based on the recommendation. In the typical usage of a high-side switch, the source (S) is connected to the supply side and the drain (D) to the load side (this is how T5 is used in this schematic). However, connecting it this way in this section would cause a problem because the body diode of the MOS-FET would allow current to flow back from the USB side to the battery charger side when USB power is connected. This P-ch MOS-FET operates so that current flows from the drain (D) side to the source (S) side when ON. The advantage of using a P-ch MOS-FET instead of a single diode here is that no forward voltage drop of the diode occurs when the FET is ON. It is also interesting that the source (S) side voltage, which serves as the reference for the gate (G) voltage, is provided from the drain (D) side to the source (S) side through the body diode. To verify that current is actually flowing from the drain (D) side to the source (S) side, you can compare the VSYS voltage during battery-powered operation with the VSYS voltage when the gate (G) is floated from VBUS and shorted to the source (S) side. (Assuming a battery voltage of 3.7V, in the latter case where power is supplied only through the body diode, VSYS drops to approximately 3.2V.)

DC/DC Converter 3V3_EN Control (T2)

DC/DC Converter 3V3_EN Control (T2)

Since the drain (D) of T2 is connected to 3V3_EN on the Raspberry Pi Pico board, the DC/DC converter is OFF when T2 is ON, and the DC/DC converter is ON when T2 is OFF. In other words, focusing only on the section outlined in blue in the figure above, the DC/DC converter is OFF with T2 ON when power is supplied. When POWER_SW (SW2) is pressed in this state, T2 turns OFF and the DC/DC converter turns ON. Therefore, POWER_SW (SW2) serves the role of turning ON the DC/DC converter from stand-by state to start the RP2040. Since POWER_SW (SW2) is also connected to GP21, it also serves as a GPIO input after the RP2040 has started. R1 100Kohm is placed to prevent the input voltage to GP21 from exceeding 3.3V. R6 100Kohm is placed to prevent the pull-up voltage for GP21 from dropping too low during battery operation. Since the GP21 periphery operates on a delicate balance like this, the RP2040's internal pull-up and pull-down for GP21 itself must be kept OFF.

Maintaining DC/DC Converter ON State (T3, T4)

Maintaining DC/DC Converter ON State (T3, T4)

Once the DC/DC converter is turned ON by POWER_SW (SW2) and the RP2040 starts, turning ON POWER_KEEP (GP19) from the software side causes T3 to turn ON → T2 to turn OFF, allowing the DC/DC converter to remain ON even after POWER_SW (SW2) is released, and from that point on, control is handled by the software side.
Alternatively, even when USB power is connected while in stand-by state, T4 turns ON → T2 turns OFF, and the DC/DC converter ON state is maintained. When considering this as a battery-operated device, having the power always turn ON when USB power is connected (i.e., when charging) is not desirable behavior. However, without this arrangement, the RP2040 cannot remain ON during program rewriting, which would be problematic. Therefore, when USB power is connected for charging, a separate Charge state is provided to notify the user that charging is in progress, and then the device immediately enters dormant state, thus maintaining the RP2040 ON while keeping the device in a non-operating state.
The reason why the gate (G) of T4 is connected after voltage division by R4 and R5 (100Kohm each) is related to the Schottky barrier diode D1 mounted on the Raspberry Pi Pico board.
D1 in the figure above serves to prevent reverse current flow from VSYS to VBUS, while a Schottky barrier diode is used to minimize the forward voltage drop when current flows from VBUS to VSYS during USB power operation. However, since the reverse current (leakage current) of a Schottky barrier diode is an order of magnitude larger than that of a regular diode, approximately 0.8V appears on the VBUS side when only battery power is used. If this voltage were connected directly to the gate (G) of T4, it would be sufficient to turn the FET ON, resulting in undesired operation. Therefore, when VBUS is approximately 0.8V, voltage division is performed using R4 and R5 (100Kohm each) before connecting to the gate (G) of T4, so that the gate voltage is sufficiently lower than the threshold voltage.

Peripheral Power Control (T5)

Peripheral Power Control (T5)

T5 is used as a standard P-ch MOS-FET high-side switch. Peripheral power is supplied when PERI_POWER (GP20) is Low, and peripheral power is cut off when PERI_POWER (GP20) is High.

Description of Components Used

Battery Charger (TP4056 Project)

TP4056 Project

The module shown in the photo above, called the TP4056 Project, was used as the battery charger. Either microB or typeC USB type is acceptable. They can be obtained inexpensively from Amazon, Aliexpress, etc. As a precaution, make sure to use a type with overcurrent and over-discharge protection functions, not one that only supports charging. The charging-only type differs from the module in the photo above in that it has only one IC component mounted and has only two terminal systems: 5V input and battery connection terminals, so it can be easily identified.

P-ch MOSFET

For the P-ch MOSFETs T1 and T5, since they are used for power line control, please use ones with sufficiently low ON resistance (less than 0.1 ohm) and adequate current capacity (3A or more). Also, since the gate threshold voltage must allow the FET to fully turn ON at the battery voltage, please use ones with a low threshold voltage (2.5V or less). During verification here, no suitable non-SMD components were found, so the SMD component IRLML6401 was used.
IRLML6401 (mounted on breakout board)

N-ch MOSFET

For the N-ch MOSFETs T2, T3, and T4, since they are used only for signal control, small-signal types are acceptable. During verification here, the SMD component IRLML2502 and the non-SMD component 2N7000 were used.

Description of Sample Program

https://github.com/elehobica/pico_battery_op
The sample program above will be explained below.

USB Power Connection Detection

Whether USB power is connected (in this project, whether charging is in progress) can be determined simply by reading the value of GPIO24 using the connection on the Raspberry Pi Pico board.
bool pm_usb_power_detected()
{
    return gpio_get(PIN_USB_POWER_DETECT);
}
Additionally, when the RP2040 is started from stand-by state, it can be determined whether it was started by the Power switch or by USB power being connected. Therefore, if the device was started by USB power being connected, it proceeds directly to enter the Charge state.
    if (pm_usb_power_detected()) {
        power_state = ChargeState;
    } else {
        power_state = NormalState;
    }

Maintaining Power-On State

After the RP2040 has started, calling pm_set_power_keep(true) maintains the power-on state. Also, calling pm_set_power_keep(false) transitions to stand-by state if USB power is not connected.
void pm_set_power_keep(bool value)
{
    gpio_put(PIN_POWER_KEEP, value);
}

Transition to and Recovery from Dormant State

The program for transition to and recovery from dormant state is as follows.
void pm_enter_dormant_and_wake()
{
    // === [1] Preparation for dormant ===
    bool psm = gpio_get(PIN_DCDC_PSM_CTRL);
    gpio_put(PIN_DCDC_PSM_CTRL, 0); // PFM mode for better efficiency
    stdio_usb_deinit(); // terminate usb cdc
 
    // === [2] goto dormant then wake up ===
    uint32_t ints = save_and_disable_interrupts(); // (+a)
    _preserve_clock_before_sleep(); // (+c)
    //--
    sleep_run_from_xosc();
    sleep_goto_dormant_until_pin(PIN_POWER_SW, true, false); // dormant until fall edge detected
    //--
    _recover_clock_after_sleep(); // (-c)
    restore_interrupts(ints); // (-a)
 
    // === [3] treatments after wake up ===
    _start_serial();
    gpio_put(PIN_DCDC_PSM_CTRL, psm); // recover PWM mode
}
The following preparations are performed before transitioning to dormant state.
  • Save the DC/DC PSM setting and then set to efficiency-oriented PFM mode
  • Terminate USB CDC
  • Save the interrupt enable state and then disable interrupts
  • Save the clock settings
 
If the DC/DC PSM mode is set to PWM mode (which prioritizes ripple quality), efficiency appears to degrade at low loads, so it needs to be operated in PFM mode.
Regarding USB CDC, if init is called again after returning from dormant, the interrupt vectors end up being double-registered, resulting in an abnormal processing load state. The code to terminate USB CDC is not included in the standard pico-sdk, so it was prepared independently. (lib/my_pico_stdio_usb/stdio_usb.c)
void stdio_usb_deinit(void) {
    stdio_set_driver_enabled(&stdio_usb, false);
    if ((bool) alarm_id) {
        cancel_alarm(alarm_id);
    }
    irq_set_enabled(PICO_STDIO_USB_LOW_PRIORITY_IRQ, false);
    irq_remove_handler(PICO_STDIO_USB_LOW_PRIORITY_IRQ, low_priority_worker_irq);
}
It appears that if interrupts are enabled when transitioning to dormant, wake up may not work properly when using PWM.
For clock setting save → restore, the following article was referenced. https://ghubcoder.github.io/posts/awaking-the-pico/
The wake up condition is specified in the order of pin specification, level/edge specification, and polarity specification. In this case, it is specified as follows, so it is set to edge-triggered, falling, and wake up occurs on the falling edge of PIN_POWER_SW.
sleep_goto_dormant_until_pin(PIN_POWER_SW, true, false);
The following recovery processing is performed after wake up.
  • Restore clock settings
  • Restore interrupt enable state
  • Resume UART serial and USB CDC
  • Restore DC/DC PSM setting
 
Overall, the transition to dormant was accomplished without issues, but restoring the original state after wake up required considerable trial and error. Testing needs to be done according to the usage state of various RP2040 resources before entering dormant, and even with this sample, there may still be insufficient points depending on the application being used.

Peripheral Power Control

To turn ON peripheral power, call pm_set_peripheral_power(true). Since the GP20 pin is used as open-drain, it is driven only when outputting Low.
void pm_set_peripheral_power(bool value)
{
    // Open Drain, Active Low
    if (value) {
        gpio_put(PIN_PERI_POWER_ENB, 0);
        gpio_set_dir(PIN_PERI_POWER_ENB, GPIO_OUT); 
    } else {
        gpio_put(PIN_PERI_POWER_ENB, 0);
        gpio_set_dir(PIN_PERI_POWER_ENB, GPIO_IN); 
    }
}
This concludes the description of the battery operation environment for Raspberry Pi Pico.

About Me

My photo
Electronics, programming & audio

Featured Post

Synchronizing Radio-Controlled Clocks with Raspberry Pi Pico W (JJY Standard Radio Wave Emulator)

As a Raspberry Pi Pico W application, I built a JJY emulator for radio-controlled clocks (for time synchronization) with minimal peripheral...

QooQ