Using nPM1300 Battery Charger and Power Rails
- 1 1. Overview
- 2 2. SOM-nRF9151 Power Architecture
- 3 3. Configuring nPM1300 PMIC in Zephyr BSP
- 4 4. Controlling nPM1300 PMIC in User Application
- 5 5. Validating nPM1300 PMIC Operations
1. Overview
This application note describes how to configure nPM1300 PMIC in Zephyr BSP and use it in the user application.
2. SOM-nRF9151 Power Architecture
The power architecture of the nRF9151 SOM is based on the NORDIC Semiconductor nPM1300 PMIC, which has several power and system management features:
System regulator (SYSREG) of the PMIC supplies main power rail VSYS from:
VBUS (VIN from an AC wall adapter or a USB port- if/when they are present);
Battery (VBAT_C): when a battery is connected but VIN (VBUS) isn’t present;
The VSYS voltage is 4V-5.5V when it is supplied from the VIN (VBUS) (+5V power is present) and 3.2V-4.4V when it is supplied from the Battery/VBAT_C (+5V power isn’t present)
Two 200mA BUCK regulators:
§ BUCK2 (VOUT2) @ 3.0V is used on the SOM and broken out to the SOM interface connectors;
§ BUCK1 is disabled by default, may be enabled and configured by software to a 1.0V-3.0V output voltage. It is available on SOM interface connectors;
Two LDO/Load Switches :
§ LDO1/LSW1 gets power from the BUCK1 output. LDO1/LSW1 is disabled by default, may be enabled and configured by software to a 1.0V-3.0V output voltage. It is available on the SOM interface connectors;
§ LDO2/LSW2 isn’t used in the nRF9151 SOM
SYSREG provide the following features:
Operating voltage up to 5.5 V
Overvoltage protection to 22 V
Undervoltage detection
USB port detection and a current limiter to comply with the USB specification
Provides VBUSOUT voltage
In the nRF9151 SOM, the nPM1300 supplies VBUSOUT voltage on the SOM interface connectors when VIN (VBUS) voltage is present. VBUSOUT provides overvoltage and undervoltage protection for safe connection to external devices.
The nPM1300 supports the USB PD Configuration Channel functionality.
The PMIC VIN (VBUS) input current limiter manages VIN (VBUS) current limitation and charger detection for USB Type-C compatible chargers. The VIN (VBUS) current limit value is configurable by software.
The PMIC battery charger is suitable for general purpose applications with lithium-ion (Li-ion), lithium-polymer (Li-poly), and lithium iron phosphate (LiFePO4) batteries.
nPM1300 supports charging up to 800 mA and delivers up to 500 mA of adjustable regulated voltage.
For more details about the SOM-NRF9151 hardware and power architecture refer to https://voxelbotics.atlassian.net/wiki/x/GQAcKw.
3. Configuring nPM1300 PMIC in Zephyr BSP
The nPM1300 PMIC device is declared in nrf9151som_nrf9151_ns.dts
as a child node of the i2c1
bus:
&i2c1 {
status = "okay";
...
npm1300_pmic: pmic@6b {
compatible = "nordic,npm1300";
reg = <0x6b>;
status = "okay";
host-int-gpios = <&gpio0 10 0>;
pmic-int-pin = <0>;
...
};
};
This node configures the following parameters:
Parameter | Value | Description |
---|---|---|
|
| Enables the |
|
| nPM1300 slave address on the I2C bus, which will be used by the driver to communicate with the PMIC. |
|
| Host SoC GPIO, that will be used for PMIC interrupts. |
|
| nPM1300 interrupt pin. |
3.1. Configuring nPM1300 Battery Charger
The nPM1300 Battery Charger device is declared in nrf9151som_nrf9151_ns.dts
as a child node of the npm1300_pmic
device:
npm1300_pmic: pmic@6b {
compatible = "nordic,npm1300";
...
npm1300_charger: charger {
compatible = "nordic,npm1300-charger";
term-microvolt = <4200000>;
term-current-percent= <10>;
current-microamp = <500000>;
dischg-limit-microamp = <1340000>;
vbus-limit-microamp = <1200000>;
dietemp-stop-millidegrees = <95000>;
dietemp-resume-millidegrees = <80000>;
thermistor-ohms = <10000>;
thermistor-beta = <3435>;
charging-enable;
};
...
};
The devicetree node configures the following parameters:
Parameter | Value | Description |
---|---|---|
|
| Enables the |
|
| Charge termination voltage in uV. The battery charging mode will switch to constant voltage charge once the battery voltage reaches this value. |
|
| Termination current, as a percentage of current-microamp. Charge completes when the charge current falls below this value. |
|
| Charge current in uA. |
|
| Battery discharge current limit in uA. |
|
| VBUS current limit in uA. |
|
| Battery charging stops when the nPM1300 chip temperature reaches this threshold (in milli-degrees). |
|
| If stopped, battery charging will resume when the nPM1300 chip temperature drops below this threshold (in milli-degrees). |
|
| Thermistor nominal resistance type in ohms. |
|
| Beta value of selected thermistor. |
|
| Enable charging. |
The battery parameters are defined for EEMB LP653042 820 mAh battery:
If another battery is used, the parameters should be changed accordingly.
3.2. Configuring nPM1300 Voltage Regulators
The nPM1300 regulator device is declared in nrf9151som_nrf9151_ns.dts
as a child node of the npm1300_pmic
device:
npm1300_pmic: pmic@6b {
compatible = "nordic,npm1300";
...
npm1300_regulators: regulators {
compatible = "nordic,npm1300-regulator";
status = "okay";
/* limits are set to min/max allowed values */
npm1300_buck1: BUCK1 {
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3000000>;
};
npm1300_ldsw1: LDO1 {
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3000000>;
regulator-initial-mode = <NPM1300_LDSW_MODE_LDSW>;
regulator-allowed-modes = <NPM1300_LDSW_MODE_LDSW>;
};
};
...
};
The devicetree node configures the following parameters and subnodes:
Parameter | Value | Description |
---|---|---|
|
| Enables the |
| ||
|
| Smallest voltage consumers may set. |
|
| Largest voltage consumers may set. |
| ||
|
| Smallest voltage consumers may set. |
|
| Largest voltage consumers may set. |
|
| Initial operating mode. |
|
| List of operating modes that software is allowed to configure for the regulator at run-time. |
4. Controlling nPM1300 PMIC in User Application
4.1. Using nPM1300 Battery Charger
4.1.1. nPM1300 Battery Charger C-binding API
The Customized Asset Tracker v2 application implements the following C-binding helper API for nPM1300 battery charger, defined in pmic_charger.*
and pmic_soc.*
files:
Function | Description | Comments |
| ||
| Get battery voltage from PMIC charger driver. |
Returns 0 on success, or a negative error code on failure. |
| Get battery current from PMIC charger driver. |
Returns 0 on success, or a negative error code on failure. |
| Get battery temperature from PMIC charger driver. |
Returns 0 on success, or a negative error code on failure. |
| Read PMIC charger status register. |
Returns 0 on success, or a negative error code on failure. |
| Read PMIC charger error register. |
Returns 0 on success, or a negative error code on failure. |
| Clear PMIC charger error register. | Returns 0 on success, or a negative error code on failure. |
| Check if charging is enabled. |
Returns 0 on success, or a negative error code on failure. |
| ||
| Calculate battery State of Charge (SoC). |
Returns 0 on success, or a negative error code on failure. |
| Monitor battery State of Charge (SoC). | Schedules a system workqueue task that will periodically update the battery State of Charge. Returns 0 on success, or a negative error code on failure. |
| Emulate battery State of Charge (SoC). |
|
4.1.2. nPM1300 Battery Charger Threads and Tasks
The Customized Asset Tracker v2 application provides a Zephyr system workqueue task that updates the battery State of Charge with 1 minute period and generates an appropriate event, which is distributed by the Application Event Manager and handled by other modules. Refer to Using nPM1300 Battery Charger and Power Rails | 3.4. PMIC Events for details about PMIC events.
4.1.3. nPM1300 Battery Charger Shell Commands
The Customized Asset Tracker v2 application provides a set of Zephyr shell commands for nPM1300 battery charger, defined in the pmic_charger.c
file:
Command | Parameters | Comments |
|
| Prints out the battery charger parameters to the serial console in the following format: pmic_charger status
Battery charging: <enabled|disabled>
Battery voltage: <voltage> V
Battery current: <current> mA
Battery temp: <temperature>
Battery SoC: <SoC>
<Charge status>
<Errors> |
|
| Emulate VBUS events. |
|
| Emulate battery SoC. |
4.2. Controlling nPM1300 Voltage Regulators
4.2.1. nPM1300 Voltage Regulators C-binding API
The Customized Asset Tracker v2 application implements the following C-binding helper API for nPM1300 voltage regulator, defined in pmic_regulator.*
files:
Function | Description | Comments |
| Deinitialize PMIC voltage regulators. |
|
| Enable a specific regulator. |
Returns zero on success, otherwise a negative error code is returned. |
| Disable a specific regulator. |
|
| Check if regulator is enabled. |
Returns true if regulator is enabled, false otherwise.. |
4.2.2. nPM1300 Voltage Regulators Shell Commands
The Customized Asset Tracker v2 application provides a set of Zephyr shell commands for nPM1300 voltage regulator, defined in the pmic_regulator.c
file:
Command | Parameters | Comments |
|
| Prints out the BUCK1 and LDSW1 parameters to the serial console in the following format: uart:~$ pmic_regulator status
Regulator: BUCK1 status: <enabled|disabled>, voltage: <voltage> V
Regulator: LDSW1 status: <enabled|disabled>, voltage: <voltage> V |
|
| Enable a specific regulator. |
|
| Disable a specific regulator. |
4.3. Enabling and Handling PMIC Interrupts
4.3.1. nPM1300 Interrupts C-binding API
The Customized Asset Tracker v2 application implements the following C-binding helper API for nPM1300 interrupts, defined in pmic_irq.*
files:
Function | Description | Comments |
| Enable PMIC interrupts and configure IRQ handler. | Zero on success, otherwise a negative error code is returned. |
| Disable PMIC interrupts and remove IRQ handler. | |
| Send PMIC event. |
Refer to Using nPM1300 Battery Charger and Power Rails | 3.4. PMIC Events for details about PMIC events. |
4.3.2. nPM1300 Interrupt Events
The Customized Asset Tracker v2 application configures the following PMIC interrupts through the mfd_npm1300.c
driver:
Interrupt | Description |
| Charging completed. |
| Charging error. |
| The battery is connected to the SOM-NRF9151 baseboard and VBAT voltage is detected. |
| The battery is diconnected from the SOM-NRF9151 baseboard . |
| The battery voltage dropped below 95% of the charge termination voltage while the device is connected to a power source with a USB-C cable. Recharge is needed. |
| The device has been connected to a power source with a USB-C cable and VBUS voltage is detected. |
| The device has been disconnected from a power source. |
4.3.3. nPM1300 Interrupts Configuration and Handling
The Customized Asset Tracker v2 application configures and handles PMIC interrupts the following way:
PMIC interrupts are configured at Zephyr boot by calling
pmic_irq_enable()
insetup()
function, defined inutil_module.c
.pmic_irq.c
file defines the PMIC interrupt handler, which generates an appropriate PMIC event when the interrupt is triggered. Refer to Using nPM1300 Battery Charger and Power Rails | 3.4. PMIC Events for details about PMIC events.
4.4. PMIC Events
The Customized Asset Tracker v2 application defines PMIC event types and data structures in the pmic_module_event.*
files:
Event | Description |
| Charging completed. |
| Charging error. |
| The battery is connected to the SOM-NRF9151 baseboard and VBAT voltage is detected. |
| The battery is diconnected from the SOM-NRF9151 baseboard . |
| The battery voltage dropped below 95% of the charge termination voltage while the device is connected to a power source with a USB-C cable. Recharge is needed. |
| The device has been connected to a power source with a USB-C cable and VBUS voltage is detected. |
| The device has been disconnected from a power source. |
| Battery SoC value is >= 100% |
| Battery SoC value is < 100% and >= 90% |
| Battery SoC value is < 90% |
| Battery SoC value has been updated |
The PMIC event data structure has the following definition:
/** @brief PMIC event. */
struct pmic_module_event {
/** PMIC module application event header. */
struct app_event_header header;
/** PMIC module event type. */
enum pmic_module_event_type type;
union {
struct pmic_module_status status;
uint8_t soc;
} data;
};
The pmic_module_status
data structure used in pmic_module_event
has the following definition:
struct pmic_module_status {
bool battery_detected;
bool vbus_detected;
enum pmic_module_charge_status charge_status;
};
pmic_module_charge_status
is defined as follows:
enum pmic_module_charge_status {
PMIC_CHARGE_COMPLETED,
PMIC_CHARGE_IN_PROGRESS,
PMIC_CHARGE_ERROR
};
The PMIC events are sent by calling pmic_irq_send_event()
, which subsequently calls APP_EVENT_SUBMIT()
. The PMIC events are then processed and distributed to the event subscribers by the Application Event Manager.
Other application modules can receive PMIC events by defining an event handler and calling APP_EVENT_SUBSCRIBE(MODULE, pmic_module_event);
4.5. Sending PMIC Data to nRF Cloud
The PMIC data is being collected and sent to the nRF Cloud by the sensor and data modules, defined in sensor_module.c
and data_module.c
:
When the sensor module receives
APP_EVT_DATA_GET
, it calls thebattery_data_get()
function to collect PMIC data that should be sent to nRF Cloud.battery_data_get()
reads the battery SoC by callingpmic_soc_get()
, then it generates thesensor_module_event
, which contains the battery SoC, timestamp andSENSOR_EVT_FUEL_GAUGE_READY
event type.The data module receives the
sensor_module_event
from the sensor module and enqueues the PMIC data to be sent to nRF Cloud.
The battery data is being sent to the nRF Cloud in JSON format via MQTT transport:
{
"appId": "BATTERY", // "Application" name. Some application data can be processed by nRF Cloud and displayed as graphs on the device page.
"messageType": "DATA",
"ts": 1743101787576, // Device timestamp in seconds
"data": "98" // Battery SoC level
},
After receiving the message from the device, nRF Cloud converts it into the following JSON structure:
{
"topic": "prod/8ac47cbc-cc7f-43d0-bb92-de294d73db3e/m/d/50343959-3733-4b54-80f4-0c0bb0646d4c/d2c",
"deviceId": "50343959-3733-4b54-80f4-0c0bb0646d4c", // Device UUID
"receivedAt": "2025-03-27T18:58:20.771Z", // nRF Cloud timestamp indicating when the message has been received. May differ from the device timestamp
"message": {
"appId": "BATTERY",
"messageType": "DATA",
"ts": 1743101787576,
"data": "98"
},
"tenantId": "8ac47cbc-cc7f-43d0-bb92-de294d73db3e"
},
The event and data structures used by the sensor and data modules have the following definitions:
/** @brief Sensor module event. */
struct sensor_module_event {
/** Sensor module application event header. */
struct app_event_header header;
/** Sensor module event type. */
enum sensor_module_event_type type;
union {
/** Variable that contains sensor readings. */
struct sensor_module_data sensors;
/** Variable that contains acceleration data. */
struct sensor_module_accel_data accel;
/** Variable that contains impact data. */
struct sensor_module_impact_data impact;
/** Variable that contains battery level data. */
struct sensor_module_batt_lvl_data bat;
/** Module ID, used when acknowledging shutdown requests. */
uint32_t id;
/** Code signifying the cause of error. */
int err;
} data;
};
/** @brief Structure used to provide battery level. */
struct sensor_module_batt_lvl_data {
/** Uptime when the data was sampled. */
int64_t timestamp;
/** Battery level in percentage. */
int battery_level;
};
/** @brief Structure containing battery data published to cloud. */
struct cloud_data_battery {
/** Battery fuel gauge percentage. */
uint16_t bat;
/** Battery data timestamp. UNIX milliseconds. */
int64_t bat_ts;
/** Flag signifying that the data entry is to be encoded. */
bool queued : 1;
5. Validating nPM1300 PMIC Operations
5.1. Validating nPM1300 Charger Operations
Put Jumpers on the JP1 and JP2 headers on the SOM-NRF9151-BSB board.
Plug the battery into P3 on SOM-NRF9151 board.
Power up the board from the USB Type-C.
Verify that the board has successfully booted up, by checking that the boot-up messages appear on the SOM-NRF9151 console.
Issue the
pmic_charger status
command to read the charger status:uart:~$ pmic_charger status Battery charging: enabled Battery voltage: 4.20 V Battery current: 108.00 mA Battery temp: 24.79 Constant voltage charge No error
Verify that charging is enabled and the application prints valid values indicating a successful charging process to the SOM-NRF9151 console:
If battery charging started successfully, charging status will change depending on battery voltage and current levels:
Trickle charge
: Battery voltage <= 2.9V. Charging current should be ≈30 mA.Constant current charge
: 2.9V > Battery voltage < 4.2V. Charging current should be ≈300 mA.Constant voltage charge
: Battery voltage = 4.2V. Charging current should gradually decrease to 0 mA.Charging completed
: Battery voltage = 4.2V and battery current < 20 mA.
If the device is not able to start or continue charging the battery, the
pmic_charger status
command will print one of the following status messages:Battery not detected
: Battery is not present or not connected properly.Charging paused, high battery temp
: Charging paused due to high battery temperature and should continue after the battery cools down.Trickle charge error
: An error has occurred during trickle charge.Charge timeout
: Normal charging (Constant Current and Constant Voltage) time has exceeded 7 hours.Trickle charge timeout
: Battery voltage didn’t reach trickle charge threshold (2.9V) in 10 minutes.
Wait until the battery is fully charged. Estimated charge time from 0% to 100% is 2.5-3 hours.
Check charging status using
pmic_charger status
command and verify that battery charging is completed:uart:~$ pmic_charger status Battery charging: enabled Battery voltage: 4.20 V Battery current: 0.00 mA Battery temp: 25.38 Charging completed No error
5.2. Validating nPM1300 Voltage Regulators
From the serial console, issue the following commands to read the BUCK1_OUT and VLS1_OUT status:
uart:~$ pmic_regulator status Regulator: BUCK1 status: disabled, voltage: 3.00 V Regulator: LDSW1 status: disabled, voltage: 3.00 V
Issue the following commands to enable the BUCK1_OUT power rail and VLS1_OUT load switch:
uart:~$ pmic_regulator enable BUCK1 [00:00:28.139,953] <inf> pmic_regulator: Regulator BUCK1 enabled uart:~$ pmic_regulator enable LDSW1 [00:00:31.384,113] <inf> pmic_regulator: Regulator LDSW1 enabled
Read the BUCK1_OUT and VLS1_OUT status again:
uart:~$ pmic_regulator status Regulator: BUCK1 status: enabled, voltage: 3.00 V Regulator: LDSW1 status: enabled, voltage: 3.00 V
Check voltage on the following test points:
Measure voltage on BUCK1_OUT/P2.9 on the baseboard. The voltage should be in the 2.8V…3.2V range.
Measure voltage on VLS1_OUT/P2.11 on the baseboard. The voltage should be in the 2.8V…3.2V range.
Disable the the BUCK1_OUT power rail and VLS1_OUT load switch:
uart:~$ pmic_regulator enable BUCK1 [00:01:43.581,237] <inf> pmic_regulator: Regulator BUCK1 disabled uart:~$ pmic_regulator enable LDSW1 [00:01:51.213,841] <inf> pmic_regulator: Regulator LDSW1 disabled
Check voltage on the following test points:
Measure voltage on BUCK1_OUT/P2.9 on the baseboard. The voltage should be 0V.
Measure voltage on VLS1_OUT/P2.11 on the baseboard. The voltage should be 0V.
5.3. Validating nPM1300 PMIC Interrupts
Plug the battery into the P3 connector on SOM-NRF9151 baseboard.
Power up the board from the USB Type-C.
Power up the board and verify that the board has successfully booted up, by checking that the boot-up messages appear on the SOM-NRF9151 console:
... [00:00:00.306,945] <inf> pmic_irq: Battery event: Start *** Booting nRF Connect SDK v2.8.0-e3db2104b81d *** *** Using Zephyr OS v3.7.99-78e3b9740208 *** ...
Disconnect the battery and verify that the “Battery removed“ is printed to the console periodically:
... [00:03:14.603,149] <inf> pmic_irq: Battery event: Battery removed [00:03:15.104,919] <inf> pmic_irq: Battery event: Battery removed [00:03:15.607,666] <inf> pmic_irq: Battery event: Battery removed [00:03:16.110,412] <inf> pmic_irq: Battery event: Battery removed ...
Connect the battery back and verify that the “Battery detected“ is printed once to the console instead of:
[00:03:17.461,120] <inf> pmic_irq: Battery event: Battery detected
5.4. Validating nPM1300 PMIC Integration with nRF Cloud
Check the board
uuid
from the nRF9151 console (it is assumed that the nRF Device provisioning procedure has been performed earlier):uart:~$ nrf_provisioning uuid 50343959-3733-4c71-806b-202470cee0bf
Check that the board has successfully connected to the cloud over LTE:
[00:00:02.824,615] <inf> app_event_manager: MODEM_EVT_LTE_CONNECTING [00:00:04.110,168] <inf> app_event_manager: MODEM_EVT_LTE_CELL_UPDATE [00:00:15.095,916] <inf> app_event_manager: MODEM_EVT_LTE_CONNECTED [00:00:15.236,907] <inf> app_event_manager: CLOUD_EVT_CONNECTING [00:00:15.237,426] <inf> app_event_manager: MODEM_EVT_LTE_PSM_UPDATE [00:00:15.237,915] <inf> app_event_manager: DATA_EVT_DATE_TIME_OBTAINED [00:00:22.080,871] <inf> net_mqtt: Connect completed
Login to the nRF Cloud and go to the DEVICE MANAGEMENT / Devices page. Find the board by the
uuid
ID and open the board page.Click the Manage Cards button and check the Device Data checkbox so that the Device Data card is displayed on the board page.
In the Device Data card, check the Last connected attribute to make sure that the board has recently connected to the cloud.
From the nRF9151 console, confirm that the Battery sensor has been read successfully:
[00:00:27.001,281] <inf> app_event_manager: SENSOR_EVT_FUEL_GAUGE_READY
Wait 110 seconds for the device data to be updated on the cloud. The default timeout of 110 seconds can be reduced for convenience: click the View Config button, then Edit Configuration. If activeMode is false then the timeout is no greater than movementResolution, otherwise, it is no greater than activeWaitTime.
From the nRF9151 console, confirm that the device data have been sent to the cloud:
[00:02:16.997,283] <inf> app_event_manager: DATA_EVT_DATA_READY [00:02:17.002,197] <inf> app_event_manager: DATA_EVT_DATA_SEND_BATCH [00:02:17.002,868] <inf> app_event_manager: CLOUD_EVT_DATA_SEND_QOS
In the Device Data card on the nRF Cloud, verify that the Battery attribute has just been updated and has a proper value:
Click the Show Battery card icon to see the graphical representation of the battery values on the time scale:
Click the View historical data icon and select appropriate time interval to see the battery status history: