Initial commit of Arduino libraries

This commit is contained in:
Sam
2025-05-23 10:47:41 +10:00
commit 5bfce5fc3e
2476 changed files with 1108481 additions and 0 deletions

View File

@@ -0,0 +1,403 @@
/*
MIT License
Copyright (c) 2022 lewis he
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
! WARN:
Please do not run the example without knowing the external load voltage of the PMU,
it may burn your external load, please check the voltage setting before running the example,
if there is any loss, please bear it by yourself
*/
#ifndef XPOWERS_NO_ERROR
#error "Running this example is known to not damage the device! Please go and uncomment this!"
#endif
// Defined using AXP192
#define XPOWERS_CHIP_AXP192
#include <Wire.h>
#include <Arduino.h>
#include "XPowersLib.h"
#ifndef CONFIG_PMU_SDA
#define CONFIG_PMU_SDA 21
#endif
#ifndef CONFIG_PMU_SCL
#define CONFIG_PMU_SCL 22
#endif
#ifndef CONFIG_PMU_IRQ
#define CONFIG_PMU_IRQ 35
#endif
bool pmu_flag = 0;
XPowersPMU power;
const uint8_t i2c_sda = CONFIG_PMU_SDA;
const uint8_t i2c_scl = CONFIG_PMU_SCL;
const uint8_t pmu_irq_pin = CONFIG_PMU_IRQ;
void setFlag(void)
{
pmu_flag = true;
}
void setup()
{
Serial.begin(115200);
bool result = power.begin(Wire, AXP192_SLAVE_ADDRESS, i2c_sda, i2c_scl);
if (result == false) {
Serial.println("power is not online..."); while (1)delay(50);
}
Serial.printf("getID:0x%x\n", power.getChipID());
// Set the minimum system operating voltage inside the PMU,
// below this value will shut down the PMU
// Range: 2600~3300mV
power.setSysPowerDownVoltage(2700);
// Set the minimum common working voltage of the PMU VBUS input,
// below this value will turn off the PMU
power.setVbusVoltageLimit(XPOWERS_AXP192_VBUS_VOL_LIM_4V5);
// Turn off USB input current limit
power.setVbusCurrentLimit(XPOWERS_AXP192_VBUS_CUR_LIM_OFF);
// DC1 700~3500mV, IMAX=1.2A
power.setDC1Voltage(3300);
Serial.printf("DC1 :%s Voltage:%u mV \n", power.isEnableDC1() ? "+" : "-", power.getDC1Voltage());
// DC2 700~2750 mV, IMAX=1.6A;
power.setDC2Voltage(700);
Serial.printf("DC2 :%s Voltage:%u mV \n", power.isEnableDC2() ? "+" : "-", power.getDC2Voltage());
// DC3 700~3500 mV,IMAX=0.7A;
power.setDC3Voltage(3300);
Serial.printf("DC3 :%s Voltage:%u mV \n", power.isEnableDC3() ? "+" : "-", power.getDC3Voltage());
//LDO2 1800~3300 mV, 100mV/step, IMAX=200mA
power.setLDO2Voltage(1800);
//LDO3 1800~3300 mV, 100mV/step, IMAX=200mA
power.setLDO3Voltage(1800);
//LDOio 1800~3300 mV, 100mV/step, IMAX=50mA
power.setLDOioVoltage(3300);
// Enable PMU output channel
// power.enableDC1();
power.enableDC2();
power.enableDC3();
power.enableLDO2();
power.enableLDO3();
power.enableLDOio();
Serial.println("DCDC=======================================================================");
Serial.printf("DC1 :%s Voltage:%u mV \n", power.isEnableDC1() ? "ENABLE" : "DISABLE", power.getDC1Voltage());
Serial.printf("DC2 :%s Voltage:%u mV \n", power.isEnableDC2() ? "ENABLE" : "DISABLE", power.getDC2Voltage());
Serial.printf("DC3 :%s Voltage:%u mV \n", power.isEnableDC3() ? "ENABLE" : "DISABLE", power.getDC3Voltage());
Serial.println("LDO=======================================================================");
Serial.printf("LDO2: %s Voltage:%u mV\n", power.isEnableLDO2() ? "ENABLE" : "DISABLE", power.getLDO2Voltage());
Serial.printf("LDO3: %s Voltage:%u mV\n", power.isEnableLDO3() ? "ENABLE" : "DISABLE", power.getLDO3Voltage());
Serial.printf("LDOio: %s Voltage:%u mV\n", power.isEnableLDOio() ? "ENABLE" : "DISABLE", power.getLDOioVoltage());
Serial.println("==========================================================================");
// Set the time of pressing the button to turn off
power.setPowerKeyPressOffTime(XPOWERS_AXP192_POWEROFF_4S);
uint8_t opt = power.getPowerKeyPressOffTime();
Serial.print("PowerKeyPressOffTime:");
switch (opt) {
case XPOWERS_AXP192_POWEROFF_4S: Serial.println("4 Second");
break;
case XPOWERS_AXP192_POWEROFF_65: Serial.println("6 Second");
break;
case XPOWERS_AXP192_POWEROFF_8S: Serial.println("8 Second");
break;
case XPOWERS_AXP192_POWEROFF_10S: Serial.println("10 Second");
break;
default:
break;
}
// Set the button power-on press time
power.setPowerKeyPressOnTime(XPOWERS_POWERON_128MS);
opt = power.getPowerKeyPressOnTime();
Serial.print("PowerKeyPressOnTime:");
switch (opt) {
case XPOWERS_POWERON_128MS: Serial.println("128 Ms");
break;
case XPOWERS_POWERON_512MS: Serial.println("512 Ms");
break;
case XPOWERS_POWERON_1S: Serial.println("1 Second");
break;
case XPOWERS_POWERON_2S: Serial.println("2 Second");
break;
default:
break;
}
Serial.println("===========================================================================");
// It is necessary to disable the detection function of the TS pin on the board
// without the battery temperature detection function, otherwise it will cause abnormal charging
power.disableTSPinMeasure();
// power.enableTemperatureMeasure();
// power.disableTemperatureMeasure();
// Enable internal ADC detection
power.enableBattDetection();
power.enableVbusVoltageMeasure();
power.enableBattVoltageMeasure();
power.enableSystemVoltageMeasure();
/*
The default setting is CHGLED is automatically controlled by the PMU.
- XPOWERS_CHG_LED_OFF,
- XPOWERS_CHG_LED_BLINK_1HZ,
- XPOWERS_CHG_LED_BLINK_4HZ,
- XPOWERS_CHG_LED_ON,
- XPOWERS_CHG_LED_CTRL_CHG,
* */
power.setChargingLedMode(XPOWERS_CHG_LED_OFF);
pinMode(pmu_irq_pin, INPUT);
attachInterrupt(pmu_irq_pin, setFlag, FALLING);
// Disable all interrupts
power.disableIRQ(XPOWERS_AXP192_ALL_IRQ);
// Clear all interrupt flags
power.clearIrqStatus();
// Enable the required interrupt function
power.enableIRQ(
XPOWERS_AXP192_BAT_INSERT_IRQ | XPOWERS_AXP192_BAT_REMOVE_IRQ | //BATTERY
XPOWERS_AXP192_VBUS_INSERT_IRQ | XPOWERS_AXP192_VBUS_REMOVE_IRQ | //VBUS
XPOWERS_AXP192_PKEY_SHORT_IRQ | XPOWERS_AXP192_PKEY_LONG_IRQ | //POWER KEY
XPOWERS_AXP192_BAT_CHG_DONE_IRQ | XPOWERS_AXP192_BAT_CHG_START_IRQ | //CHARGE
// XPOWERS_AXP192_PKEY_NEGATIVE_IRQ | XPOWERS_AXP192_PKEY_POSITIVE_IRQ | //POWER KEY
XPOWERS_AXP192_TIMER_TIMEOUT_IRQ //Timer
);
// Set constant current charge current limit
power.setChargerConstantCurr(XPOWERS_AXP192_CHG_CUR_280MA);
// Set stop charging termination current
power.setChargerTerminationCurr(XPOWERS_AXP192_CHG_ITERM_LESS_10_PERCENT);
// Set charge cut-off voltage
power.setChargeTargetVoltage(XPOWERS_AXP192_CHG_VOL_4V2);
// Cache writes and reads, as long as the PMU remains powered, the data will always be stored inside the PMU
Serial.println("Write pmu data buffer .");
uint8_t data[XPOWERS_AXP192_DATA_BUFFER_SIZE] = {1, 2, 3, 4, 5, 6};
power.writeDataBuffer(data, XPOWERS_AXP192_DATA_BUFFER_SIZE);
memset(data, 0, XPOWERS_AXP192_DATA_BUFFER_SIZE);
Serial.print("Read pmu data buffer :");
power.readDataBuffer(data, XPOWERS_AXP192_DATA_BUFFER_SIZE);
for (int i = 0; i < XPOWERS_AXP192_DATA_BUFFER_SIZE; ++i) {
Serial.print(data[i]);
Serial.print(",");
}
Serial.println();
// Set the timing after one minute, the isWdtExpireIrq will be triggered in the loop interrupt function
power.setTimerout(1);
}
void printPMU()
{
Serial.print("isCharging:"); Serial.println(power.isCharging() ? "YES" : "NO");
Serial.print("isDischarge:"); Serial.println(power.isDischarge() ? "YES" : "NO");
Serial.print("isVbusIn:"); Serial.println(power.isVbusIn() ? "YES" : "NO");
Serial.print("getBattVoltage:"); Serial.print(power.getBattVoltage()); Serial.println("mV");
Serial.print("getVbusVoltage:"); Serial.print(power.getVbusVoltage()); Serial.println("mV");
Serial.print("getSystemVoltage:"); Serial.print(power.getSystemVoltage()); Serial.println("mV");
Serial.print("getTemperature:"); Serial.print(power.getTemperature()); Serial.println("*C");
if (power.isBatteryConnect()) {
Serial.print("getBatteryPercent:"); Serial.print(power.getBatteryPercent()); Serial.println("%");
}
Serial.println();
}
void enterPmuSleep(void)
{
// Set sleep flag
power.enableSleep();
power.disableDC2();
power.disableDC3();
power.disableLDO2();
power.disableLDO3();
// Finally, turn off the power of the control chip
power.disableDC1();
}
void loop()
{
if (pmu_flag) {
pmu_flag = false;
// Get PMU Interrupt Status Register
uint32_t status = power.getIrqStatus();
Serial.print("STATUS => HEX:");
Serial.print(status, HEX);
Serial.print(" BIN:");
Serial.println(status, BIN);
if (power.isAcinOverVoltageIrq()) {
Serial.println("isAcinOverVoltageIrq");
}
if (power.isAcinInserIrq()) {
Serial.println("isAcinInserIrq");
}
if (power.isAcinRemoveIrq()) {
Serial.println("isAcinRemoveIrq");
}
if (power.isVbusOverVoltageIrq()) {
Serial.println("isVbusOverVoltageIrq");
}
if (power.isVbusInsertIrq()) {
Serial.println("isVbusInsertIrq");
}
if (power.isVbusRemoveIrq()) {
Serial.println("isVbusRemoveIrq");
}
if (power.isVbusLowVholdIrq()) {
Serial.println("isVbusLowVholdIrq");
}
if (power.isBatInsertIrq()) {
Serial.println("isBatInsertIrq");
}
if (power.isBatRemoveIrq()) {
Serial.println("isBatRemoveIrq");
}
if (power.isBattEnterActivateIrq()) {
Serial.println("isBattEnterActivateIrq");
}
if (power.isBattExitActivateIrq()) {
Serial.println("isBattExitActivateIrq");
}
if (power.isBatChargeStartIrq()) {
Serial.println("isBatChargeStartIrq");
}
if (power.isBatChargeDoneIrq()) {
Serial.println("isBatChargeDoneIrq");
}
if (power.isBattTempHighIrq()) {
Serial.println("isBattTempHighIrq");
}
if (power.isBattTempLowIrq()) {
Serial.println("isBattTempLowIrq");
}
if (power.isChipOverTemperatureIrq()) {
Serial.println("isChipOverTemperatureIrq");
}
if (power.isChargingCurrentLessIrq()) {
Serial.println("isChargingCurrentLessIrq");
}
if (power.isDC1VoltageLessIrq()) {
Serial.println("isDC1VoltageLessIrq");
}
if (power.isDC2VoltageLessIrq()) {
Serial.println("isDC2VoltageLessIrq");
}
if (power.isDC3VoltageLessIrq()) {
Serial.println("isDC3VoltageLessIrq");
}
if (power.isPekeyShortPressIrq()) {
Serial.println("isPekeyShortPress");
// enterPmuSleep();
//CHG LED mode test
uint8_t m = power.getChargingLedMode();
Serial.print("getChargingLedMode:");
Serial.println(m++);
m %= XPOWERS_CHG_LED_CTRL_CHG;
Serial.printf("setChargingLedMode:%u", m);
power.setChargingLedMode(m);
}
if (power.isPekeyLongPressIrq()) {
Serial.println("isPekeyLongPress");
}
if (power.isNOEPowerOnIrq()) {
Serial.println("isNOEPowerOnIrq");
}
if (power.isNOEPowerDownIrq()) {
Serial.println("isNOEPowerDownIrq");
}
if (power.isVbusEffectiveIrq()) {
Serial.println("isVbusEffectiveIrq");
}
if (power.isVbusInvalidIrq()) {
Serial.println("isVbusInvalidIrq");
}
if (power.isVbusSessionIrq()) {
Serial.println("isVbusSessionIrq");
}
if (power.isVbusSessionEndIrq()) {
Serial.println("isVbusSessionEndIrq");
}
if (power.isLowVoltageLevel2Irq()) {
Serial.println("isLowVoltageLevel2Irq");
}
if (power.isWdtExpireIrq()) {
Serial.println("isWdtExpire");
printPMU();
// Clear the timer state and continue to the next timer
power.clearTimerFlag();
}
if (power.isGpio2EdgeTriggerIrq()) {
Serial.println("isGpio2EdgeTriggerIrq");
}
if (power.isGpio1EdgeTriggerIrq()) {
Serial.println("isGpio1EdgeTriggerIrq");
}
if (power.isGpio0EdgeTriggerIrq()) {
Serial.println("isGpio0EdgeTriggerIrq");
}
// Clear PMU Interrupt Status Register
power.clearIrqStatus();
}
delay(10);
}

View File

@@ -0,0 +1,403 @@
/*
MIT License
Copyright (c) 2022 lewis he
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
! WARN:
Please do not run the example without knowing the external load voltage of the PMU,
it may burn your external load, please check the voltage setting before running the example,
if there is any loss, please bear it by yourself
*/
#ifndef XPOWERS_NO_ERROR
#error "Running this example is known to not damage the device! Please go and uncomment this!"
#endif
#define XPOWERS_CHIP_AXP202
#include <Wire.h>
#include <Arduino.h>
#include "XPowersLib.h"
#ifndef CONFIG_PMU_SDA
#define CONFIG_PMU_SDA 21
#endif
#ifndef CONFIG_PMU_SCL
#define CONFIG_PMU_SCL 22
#endif
#ifndef CONFIG_PMU_IRQ
#define CONFIG_PMU_IRQ 35
#endif
bool pmu_flag = 0;
XPowersPMU power;
const uint8_t i2c_sda = CONFIG_PMU_SDA;
const uint8_t i2c_scl = CONFIG_PMU_SCL;
const uint8_t pmu_irq_pin = CONFIG_PMU_IRQ;
void setFlag(void)
{
pmu_flag = true;
}
void setup()
{
Serial.begin(115200);
bool result = power.begin(Wire, AXP202_SLAVE_ADDRESS, i2c_sda, i2c_scl);
if (result == false) {
Serial.println("power is not online..."); while (1)delay(50);
}
Serial.printf("getID:0x%x\n", power.getChipID());
// Set the minimum system operating voltage inside the PMU,
// below this value will shut down the PMU
// Range: 2600~3300mV
power.setSysPowerDownVoltage(2700);
// Set the minimum common working voltage of the PMU VBUS input,
// below this value will turn off the PMU
power.setVbusVoltageLimit(XPOWERS_AXP202_VBUS_VOL_LIM_4V5);
// Turn off USB input current limit
power.setVbusCurrentLimit(XPOWERS_AXP202_VBUS_CUR_LIM_OFF);
// DC2 700~3500 mV, IMAX=1.6A;
power.setDC2Voltage(700);
// DC3 700~3500 mV,IMAX=0.7A;
power.setDC3Voltage(3300);
//LDO2 1800~3300 mV, 100mV/step, IMAX=200mA
power.setLDO2Voltage(1800);
//LDO3 700~2275 mV, 100mV/step, IMAX=200mA
power.setLDO3Voltage(1800);
/* LDO4 Range:
1250, 1300, 1400, 1500, 1600, 1700, 1800, 1900,
2000, 2500, 2700, 2800, 3000, 3100, 3200, 3300
*/
power.setLDO4Voltage(3300);
//LDOio 1800~3300 mV, 100mV/step, IMAX=50mA
power.setLDOioVoltage(3300);
// Enable power output channel
power.enableDC2();
// power.enableDC3();
power.enableLDO2();
power.enableLDO3();
power.enableLDO4();
power.enableLDOio();
Serial.println("DCDC=======================================================================");
Serial.printf("DC2 :%s Voltage:%u mV \n", power.isEnableDC2() ? "ENABLE" : "DISABLE", power.getDC2Voltage());
Serial.printf("DC3 :%s Voltage:%u mV \n", power.isEnableDC3() ? "ENABLE" : "DISABLE", power.getDC3Voltage());
Serial.println("LDO=======================================================================");
Serial.printf("LDO2: %s Voltage:%u mV\n", power.isEnableLDO2() ? "ENABLE" : "DISABLE", power.getLDO2Voltage());
Serial.printf("LDO3: %s Voltage:%u mV\n", power.isEnableLDO3() ? "ENABLE" : "DISABLE", power.getLDO3Voltage());
Serial.printf("LDO4: %s Voltage:%u mV\n", power.isEnableLDO4() ? "ENABLE" : "DISABLE", power.getLDO4Voltage());
Serial.printf("LDOio: %s Voltage:%u mV\n", power.isEnableLDOio() ? "ENABLE" : "DISABLE", power.getLDOioVoltage());
Serial.println("==========================================================================");
// Set the time of pressing the button to turn off
power.setPowerKeyPressOffTime(XPOWERS_AXP202_POWEROFF_4S);
uint8_t opt = power.getPowerKeyPressOffTime();
Serial.print("PowerKeyPressOffTime:");
switch (opt) {
case XPOWERS_AXP202_POWEROFF_4S: Serial.println("4 Second");
break;
case XPOWERS_AXP202_POWEROFF_65: Serial.println("6 Second");
break;
case XPOWERS_AXP202_POWEROFF_8S: Serial.println("8 Second");
break;
case XPOWERS_AXP202_POWEROFF_10S: Serial.println("10 Second");
break;
default:
break;
}
// Set the button power-on press time
power.setPowerKeyPressOnTime(XPOWERS_POWERON_128MS);
opt = power.getPowerKeyPressOnTime();
Serial.print("PowerKeyPressOnTime:");
switch (opt) {
case XPOWERS_POWERON_128MS: Serial.println("128 Ms");
break;
case XPOWERS_POWERON_512MS: Serial.println("512 Ms");
break;
case XPOWERS_POWERON_1S: Serial.println("1 Second");
break;
case XPOWERS_POWERON_2S: Serial.println("2 Second");
break;
default:
break;
}
Serial.println("===========================================================================");
// It is necessary to disable the detection function of the TS pin on the board
// without the battery temperature detection function, otherwise it will cause abnormal charging
power.disableTSPinMeasure();
// power.enableTemperatureMeasure();
// power.disableTemperatureMeasure();
// Enable internal ADC detection
power.enableBattDetection();
power.enableVbusVoltageMeasure();
power.enableBattVoltageMeasure();
power.enableSystemVoltageMeasure();
/*
The default setting is CHGLED is automatically controlled by the PMU.
- XPOWERS_CHG_LED_OFF,
- XPOWERS_CHG_LED_BLINK_1HZ,
- XPOWERS_CHG_LED_BLINK_4HZ,
- XPOWERS_CHG_LED_ON,
- XPOWERS_CHG_LED_CTRL_CHG,
* */
power.setChargingLedMode(XPOWERS_CHG_LED_OFF);
pinMode(pmu_irq_pin, INPUT);
attachInterrupt(pmu_irq_pin, setFlag, FALLING);
// Disable all interrupts
power.disableIRQ(XPOWERS_AXP202_ALL_IRQ);
// Clear all interrupt flags
power.clearIrqStatus();
// Enable the required interrupt function
power.enableIRQ(
XPOWERS_AXP202_BAT_INSERT_IRQ | XPOWERS_AXP202_BAT_REMOVE_IRQ | //BATTERY
XPOWERS_AXP202_VBUS_INSERT_IRQ | XPOWERS_AXP202_VBUS_REMOVE_IRQ | //VBUS
XPOWERS_AXP202_PKEY_SHORT_IRQ | XPOWERS_AXP202_PKEY_LONG_IRQ | //POWER KEY
XPOWERS_AXP202_BAT_CHG_DONE_IRQ | XPOWERS_AXP202_BAT_CHG_START_IRQ | //CHARGE
// XPOWERS_AXP202_PKEY_NEGATIVE_IRQ | XPOWERS_AXP202_PKEY_POSITIVE_IRQ | //POWER KEY
XPOWERS_AXP202_TIMER_TIMEOUT_IRQ //Timer
);
// Set constant current charge current limit
power.setChargerConstantCurr(XPOWERS_AXP202_CHG_CUR_280MA);
// Set stop charging termination current
power.setChargerTerminationCurr(XPOWERS_AXP202_CHG_ITERM_LESS_10_PERCENT);
// Set charge cut-off voltage
power.setChargeTargetVoltage(XPOWERS_AXP202_CHG_VOL_4V2);
// Cache writes and reads, as long as the PMU remains powered, the data will always be stored inside the PMU
Serial.println("Write pmu data buffer .");
uint8_t data[XPOWERS_AXP202_DATA_BUFFER_SIZE] = {1, 2, 3, 4, 5, 6};
power.writeDataBuffer(data, XPOWERS_AXP202_DATA_BUFFER_SIZE);
memset(data, 0, XPOWERS_AXP202_DATA_BUFFER_SIZE);
Serial.print("Read pmu data buffer :");
power.readDataBuffer(data, XPOWERS_AXP202_DATA_BUFFER_SIZE);
for (int i = 0; i < XPOWERS_AXP202_DATA_BUFFER_SIZE; ++i) {
Serial.print(data[i]);
Serial.print(",");
}
Serial.println();
// Set the timing after one minute, the isWdtExpireIrq will be triggered in the loop interrupt function
power.setTimerout(1);
}
void printPMU()
{
Serial.print("isCharging:"); Serial.println(power.isCharging() ? "YES" : "NO");
Serial.print("isDischarge:"); Serial.println(power.isDischarge() ? "YES" : "NO");
Serial.print("isVbusIn:"); Serial.println(power.isVbusIn() ? "YES" : "NO");
Serial.print("getBattVoltage:"); Serial.print(power.getBattVoltage()); Serial.println("mV");
Serial.print("getVbusVoltage:"); Serial.print(power.getVbusVoltage()); Serial.println("mV");
Serial.print("getSystemVoltage:"); Serial.print(power.getSystemVoltage()); Serial.println("mV");
Serial.print("getTemperature:"); Serial.print(power.getTemperature()); Serial.println("*C");
if (power.isBatteryConnect()) {
Serial.print("getBatteryPercent:"); Serial.print(power.getBatteryPercent()); Serial.println("%");
}
Serial.println();
}
void enterPmuSleep(void)
{
// Set sleep flag
power.enableSleep();
power.disableDC2();
power.disableLDO2();
power.disableLDO3();
// Finally, turn off the power of the control chip
power.disableDC3();
}
void loop()
{
if (pmu_flag) {
pmu_flag = false;
// Get power Interrupt Status Register
uint32_t status = power.getIrqStatus();
Serial.print("STATUS => HEX:");
Serial.print(status, HEX);
Serial.print(" BIN:");
Serial.println(status, BIN);
if (power.isAcinOverVoltageIrq()) {
Serial.println("isAcinOverVoltageIrq");
}
if (power.isAcinInserIrq()) {
Serial.println("isAcinInserIrq");
}
if (power.isAcinRemoveIrq()) {
Serial.println("isAcinRemoveIrq");
}
if (power.isVbusOverVoltageIrq()) {
Serial.println("isVbusOverVoltageIrq");
}
if (power.isVbusInsertIrq()) {
Serial.println("isVbusInsertIrq");
}
if (power.isVbusRemoveIrq()) {
Serial.println("isVbusRemoveIrq");
}
if (power.isVbusLowVholdIrq()) {
Serial.println("isVbusLowVholdIrq");
}
if (power.isBatInsertIrq()) {
Serial.println("isBatInsertIrq");
}
if (power.isBatRemoveIrq()) {
Serial.println("isBatRemoveIrq");
}
if (power.isBattEnterActivateIrq()) {
Serial.println("isBattEnterActivateIrq");
}
if (power.isBattExitActivateIrq()) {
Serial.println("isBattExitActivateIrq");
}
if (power.isBatChargeStartIrq()) {
Serial.println("isBatChargeStartIrq");
}
if (power.isBatChargeDoneIrq()) {
Serial.println("isBatChargeDoneIrq");
}
if (power.isBattTempHighIrq()) {
Serial.println("isBattTempHighIrq");
}
if (power.isBattTempLowIrq()) {
Serial.println("isBattTempLowIrq");
}
if (power.isChipOverTemperatureIrq()) {
Serial.println("isChipOverTemperatureIrq");
}
if (power.isChargingCurrentLessIrq()) {
Serial.println("isChargingCurrentLessIrq");
}
if (power.isDC1VoltageLessIrq()) {
Serial.println("isDC1VoltageLessIrq");
}
if (power.isDC2VoltageLessIrq()) {
Serial.println("isDC2VoltageLessIrq");
}
if (power.isDC3VoltageLessIrq()) {
Serial.println("isDC3VoltageLessIrq");
}
if (power.isPekeyShortPressIrq()) {
Serial.println("isPekeyShortPress");
// enterPmuSleep();
//CHG LED mode test
uint8_t m = power.getChargingLedMode();
Serial.print("getChargingLedMode:");
Serial.println(m++);
m %= XPOWERS_CHG_LED_CTRL_CHG;
Serial.printf("setChargingLedMode:%u", m);
power.setChargingLedMode(m);
}
if (power.isPekeyLongPressIrq()) {
Serial.println("isPekeyLongPress");
}
if (power.isNOEPowerOnIrq()) {
Serial.println("isNOEPowerOnIrq");
}
if (power.isNOEPowerDownIrq()) {
Serial.println("isNOEPowerDownIrq");
}
if (power.isVbusEffectiveIrq()) {
Serial.println("isVbusEffectiveIrq");
}
if (power.isVbusInvalidIrq()) {
Serial.println("isVbusInvalidIrq");
}
if (power.isVbusSessionIrq()) {
Serial.println("isVbusSessionIrq");
}
if (power.isVbusSessionEndIrq()) {
Serial.println("isVbusSessionEndIrq");
}
if (power.isLowVoltageLevel2Irq()) {
Serial.println("isLowVoltageLevel2Irq");
}
if (power.isWdtExpireIrq()) {
Serial.println("isWdtExpire");
printPMU();
// Clear the timer state and continue to the next timer
power.clearTimerFlag();
}
if (power.isGpio2EdgeTriggerIrq()) {
Serial.println("isGpio2EdgeTriggerIrq");
}
if (power.isGpio1EdgeTriggerIrq()) {
Serial.println("isGpio1EdgeTriggerIrq");
}
if (power.isGpio0EdgeTriggerIrq()) {
Serial.println("isGpio0EdgeTriggerIrq");
}
// Clear power Interrupt Status Register
power.clearIrqStatus();
}
delay(10);
}

View File

@@ -0,0 +1,183 @@
/*
MIT License
Copyright (c) 2022 lewis he
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
! WARN:
Please do not run the example without knowing the external load voltage of the PMU,
it may burn your external load, please check the voltage setting before running the example,
if there is any loss, please bear it by yourself
*/
#ifndef XPOWERS_NO_ERROR
#error "Running this example is known to not damage the device! Please go and uncomment this!"
#endif
// Defined using AXP2102
#define XPOWERS_CHIP_AXP2101
#include <Wire.h>
#include <Arduino.h>
#include "XPowersLib.h"
#ifndef CONFIG_PMU_SDA
#define CONFIG_PMU_SDA 15
#endif
#ifndef CONFIG_PMU_SCL
#define CONFIG_PMU_SCL 7
#endif
#ifndef CONFIG_PMU_IRQ
#define CONFIG_PMU_IRQ 6
#endif
XPowersPMU power;
const uint8_t i2c_sda = CONFIG_PMU_SDA;
const uint8_t i2c_scl = CONFIG_PMU_SCL;
const uint8_t pmu_irq_pin = CONFIG_PMU_IRQ;
bool pmu_flag = false;
bool adc_switch = false;
void setFlag(void)
{
pmu_flag = true;
}
void adcOn()
{
power.enableTemperatureMeasure();
// Enable internal ADC detection
power.enableBattDetection();
power.enableVbusVoltageMeasure();
power.enableBattVoltageMeasure();
power.enableSystemVoltageMeasure();
}
void adcOff()
{
power.disableTemperatureMeasure();
// Enable internal ADC detection
power.disableBattDetection();
power.disableVbusVoltageMeasure();
power.disableBattVoltageMeasure();
power.disableSystemVoltageMeasure();
}
void setup()
{
Serial.begin(115200);
bool result = power.begin(Wire, AXP2101_SLAVE_ADDRESS, i2c_sda, i2c_scl);
if (result == false) {
Serial.println("PMU is not online..."); while (1)delay(50);
}
// Force add pull-up
pinMode(pmu_irq_pin, INPUT_PULLUP);
attachInterrupt(pmu_irq_pin, setFlag, FALLING);
power.disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
// Clear all interrupt flags
power.clearIrqStatus();
// Enable the required interrupt function
power.enableIRQ(
XPOWERS_AXP2101_PKEY_SHORT_IRQ //POWER KEY
);
/*
The default setting is CHGLED is automatically controlled by the PMU.
- XPOWERS_CHG_LED_OFF,
- XPOWERS_CHG_LED_BLINK_1HZ,
- XPOWERS_CHG_LED_BLINK_4HZ,
- XPOWERS_CHG_LED_ON,
- XPOWERS_CHG_LED_CTRL_CHG,
* */
power.setChargingLedMode(XPOWERS_CHG_LED_ON);
//Default turn on adc
adcOn();
}
void loop()
{
if (pmu_flag) {
pmu_flag = false;
// Get PMU Interrupt Status Register
power.getIrqStatus();
if (power.isPekeyShortPressIrq()) {
if (adc_switch) {
adcOn(); Serial.println("Enable ADC\n\n\n");
} else {
adcOff(); Serial.println("Disable ADC\n\n\n");
}
adc_switch = !adc_switch;
}
// Clear power Interrupt Status Register
power.clearIrqStatus();
}
Serial.print("power Temperature:"); Serial.print(power.getTemperature()); Serial.println("*C");
Serial.print("isCharging:"); Serial.println(power.isCharging() ? "YES" : "NO");
Serial.print("isDischarge:"); Serial.println(power.isDischarge() ? "YES" : "NO");
Serial.print("isStandby:"); Serial.println(power.isStandby() ? "YES" : "NO");
Serial.print("isVbusIn:"); Serial.println(power.isVbusIn() ? "YES" : "NO");
Serial.print("isVbusGood:"); Serial.println(power.isVbusGood() ? "YES" : "NO");
Serial.print("getChargerStatus:");
uint8_t charge_status = power.getChargerStatus();
if (charge_status == XPOWERS_AXP2101_CHG_TRI_STATE) {
Serial.println("tri_charge");
} else if (charge_status == XPOWERS_AXP2101_CHG_PRE_STATE) {
Serial.println("pre_charge");
} else if (charge_status == XPOWERS_AXP2101_CHG_CC_STATE) {
Serial.println("constant charge");
} else if (charge_status == XPOWERS_AXP2101_CHG_CV_STATE) {
Serial.println("constant voltage");
} else if (charge_status == XPOWERS_AXP2101_CHG_DONE_STATE) {
Serial.println("charge done");
} else if (charge_status == XPOWERS_AXP2101_CHG_STOP_STATE) {
Serial.println("not charge");
}
// After the ADC detection is turned off, the register will return to the last reading. The PMU will not refresh the data register
Serial.print("getBattVoltage:"); Serial.print(power.getBattVoltage()); Serial.println("mV");
Serial.print("getVbusVoltage:"); Serial.print(power.getVbusVoltage()); Serial.println("mV");
Serial.print("getSystemVoltage:"); Serial.print(power.getSystemVoltage()); Serial.println("mV");
// The battery percentage may be inaccurate at first use, the PMU will automatically
// learn the battery curve and will automatically calibrate the battery percentage
// after a charge and discharge cycle
if (power.isBatteryConnect()) {
Serial.print("getBatteryPercent:"); Serial.print(power.getBatteryPercent()); Serial.println("%");
}
// Serial.println();
delay(1000);
}

View File

@@ -0,0 +1,174 @@
/*
MIT License
Copyright (c) 2024 lewis he
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
! WARN:
Please do not run the example without knowing the external load voltage of the PMU,
it may burn your external load, please check the voltage setting before running the example,
if there is any loss, please bear it by yourself
*/
#ifndef XPOWERS_NO_ERROR
#error "Running this example is known to not damage the device! Please go and uncomment this!"
#endif
// Defined using AXP2102
#define XPOWERS_CHIP_AXP2101
#include <Wire.h>
#include <Arduino.h>
#include "XPowersLib.h"
#ifndef CONFIG_PMU_SDA
#define CONFIG_PMU_SDA 21
#endif
#ifndef CONFIG_PMU_SCL
#define CONFIG_PMU_SCL 22
#endif
#ifndef CONFIG_PMU_IRQ
#define CONFIG_PMU_IRQ 35
#endif
XPowersPMU power;
bool pmu_flag = false;
uint8_t curIndex = 4;
void setFlag(void)
{
pmu_flag = true;
}
void printChargerConstantCurr()
{
const uint16_t currTable[] = {
0, 0, 0, 0, 100, 125, 150, 175, 200, 300, 400, 500, 600, 700, 800, 900, 1000
};
uint8_t val = power.getChargerConstantCurr();
Serial.printf("Setting Charge Target Current - VAL:%u CURRENT:%u\n", val, currTable[val]);
}
void setup()
{
Serial.begin(115200);
//Start while waiting for Serial monitoring
while (!Serial);
delay(3000);
Serial.println();
bool res = power.begin(Wire, AXP2101_SLAVE_ADDRESS, CONFIG_PMU_SDA, CONFIG_PMU_SCL);
if (!res) {
Serial.println("Failed to initialize power.....");
while (1) {
delay(5000);
}
}
// Set power interrupt
pinMode(CONFIG_PMU_IRQ, INPUT);
attachInterrupt(CONFIG_PMU_IRQ, setFlag, FALLING);
// Disable all interrupts
power.disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
// Enable the required interrupt function
power.enableIRQ(
XPOWERS_AXP2101_BAT_INSERT_IRQ | XPOWERS_AXP2101_BAT_REMOVE_IRQ | //BATTERY
XPOWERS_AXP2101_VBUS_INSERT_IRQ | XPOWERS_AXP2101_VBUS_REMOVE_IRQ | //VBUS
XPOWERS_AXP2101_PKEY_SHORT_IRQ | XPOWERS_AXP2101_PKEY_LONG_IRQ | //POWER KEY
XPOWERS_AXP2101_BAT_CHG_DONE_IRQ | XPOWERS_AXP2101_BAT_CHG_START_IRQ //CHARGE
);
// Clear all interrupt flags
power.clearIrqStatus();
// Set the minimum common working voltage of the PMU VBUS input,
// below this value will turn off the power
power.setVbusVoltageLimit(XPOWERS_AXP2101_VBUS_VOL_LIM_4V36);
// Set the maximum current of the PMU VBUS input,
// higher than this value will turn off the PMU
power.setVbusCurrentLimit(XPOWERS_AXP2101_VBUS_CUR_LIM_1500MA);
// Set VSY off voltage as 2600mV , Adjustment range 2600mV ~ 3300mV
power.setSysPowerDownVoltage(2600);
// Set the precharge charging current
power.setPrechargeCurr(XPOWERS_AXP2101_PRECHARGE_50MA);
// Set constant current charge current limit
power.setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_200MA);
// Set stop charging termination current
power.setChargerTerminationCurr(XPOWERS_AXP2101_CHG_ITERM_25MA);
// Set charge cut-off voltage
power.setChargeTargetVoltage(XPOWERS_AXP2101_CHG_VOL_4V1);
/*
The default setting is CHGLED is automatically controlled by the PMU.
- XPOWERS_CHG_LED_OFF,
- XPOWERS_CHG_LED_BLINK_1HZ,
- XPOWERS_CHG_LED_BLINK_4HZ,
- XPOWERS_CHG_LED_ON,
- XPOWERS_CHG_LED_CTRL_CHG,
* */
power.setChargingLedMode(XPOWERS_CHG_LED_OFF);
// Set cell battery voltage to 3.3V
power.setButtonBatteryChargeVoltage(3300);
// Enable cell battery charge function
power.enableButtonBatteryCharge();
// Print default setting current
printChargerConstantCurr();
}
void loop()
{
if (pmu_flag) {
pmu_flag = false;
// Get PMU Interrupt Status Register
power.getIrqStatus();
if (power.isPekeyShortPressIrq()) {
// Set constant current charge current limit
// For setting a current greater than 500mA, the VBUS power supply must be sufficient. If the input is lower than 5V, the charging current will be below 500mA.
if (!power.setChargerConstantCurr(curIndex)) {
Serial.println("Setting Charger Constant Current Failed!");
}
printChargerConstantCurr();
Serial.println("===========================");
curIndex++;
curIndex %= (XPOWERS_AXP2101_CHG_CUR_1000MA + 1);
if (curIndex == 0) {
curIndex = 3;
}
// Toggle CHG led
power.setChargingLedMode(power.getChargingLedMode() != XPOWERS_CHG_LED_OFF ? XPOWERS_CHG_LED_OFF : XPOWERS_CHG_LED_ON);
}
// Clear PMU Interrupt Status Register
power.clearIrqStatus();
}
delay(200);
}

View File

@@ -0,0 +1,326 @@
/*
MIT License
Copyright (c) 2022 lewis he
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
! WARN:
Please do not run the example without knowing the external load voltage of the PMU,
it may burn your external load, please check the voltage setting before running the example,
if there is any loss, please bear it by yourself
*/
#ifndef XPOWERS_NO_ERROR
#error "Running this example is known to not damage the device! Please go and uncomment this!"
#endif
// Defined using AXP2102
#define XPOWERS_CHIP_AXP2101
#include <Wire.h>
#include <Arduino.h>
#include "XPowersLib.h"
#ifndef CONFIG_PMU_SDA
#define CONFIG_PMU_SDA 21
#endif
#ifndef CONFIG_PMU_SCL
#define CONFIG_PMU_SCL 22
#endif
#ifndef CONFIG_PMU_IRQ
#define CONFIG_PMU_IRQ 35
#endif
bool pmu_flag = 0;
XPowersPMU power;
const uint8_t i2c_sda = CONFIG_PMU_SDA;
const uint8_t i2c_scl = CONFIG_PMU_SCL;
const uint8_t pmu_irq_pin = CONFIG_PMU_IRQ;
void setFlag(void)
{
pmu_flag = true;
}
void setup()
{
Serial.begin(115200);
bool result = power.begin(Wire, AXP2101_SLAVE_ADDRESS, i2c_sda, i2c_scl);
if (result == false) {
Serial.println("power is not online..."); while (1)delay(50);
}
Serial.printf("getID:0x%x\n", power.getChipID());
// Set the minimum common working voltage of the PMU VBUS input,
// below this value will turn off the PMU
power.setVbusVoltageLimit(XPOWERS_AXP2101_VBUS_VOL_LIM_4V36);
// Set the maximum current of the PMU VBUS input,
// higher than this value will turn off the PMU
power.setVbusCurrentLimit(XPOWERS_AXP2101_VBUS_CUR_LIM_1500MA);
// Get the VSYS shutdown voltage
uint16_t vol = power.getSysPowerDownVoltage();
Serial.printf("-> getSysPowerDownVoltage:%u\n", vol);
// Set VSY off voltage as 2600mV , Adjustment range 2600mV ~ 3300mV
power.setSysPowerDownVoltage(2600);
// It is necessary to disable the detection function of the TS pin on the board
// without the battery temperature detection function, otherwise it will cause abnormal charging
power.disableTSPinMeasure();
// power.enableTemperatureMeasure();
// Enable internal ADC detection
power.enableBattDetection();
power.enableVbusVoltageMeasure();
power.enableBattVoltageMeasure();
power.enableSystemVoltageMeasure();
/*
The default setting is CHGLED is automatically controlled by the PMU.
- XPOWERS_CHG_LED_OFF,
- XPOWERS_CHG_LED_BLINK_1HZ,
- XPOWERS_CHG_LED_BLINK_4HZ,
- XPOWERS_CHG_LED_ON,
- XPOWERS_CHG_LED_CTRL_CHG,
* */
power.setChargingLedMode(XPOWERS_CHG_LED_CTRL_CHG);
// Force add pull-up
pinMode(pmu_irq_pin, INPUT_PULLUP);
attachInterrupt(pmu_irq_pin, setFlag, FALLING);
// Disable all interrupts
power.disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
// Clear all interrupt flags
power.clearIrqStatus();
// Enable the required interrupt function
power.enableIRQ(
XPOWERS_AXP2101_BAT_INSERT_IRQ | XPOWERS_AXP2101_BAT_REMOVE_IRQ | //BATTERY
XPOWERS_AXP2101_VBUS_INSERT_IRQ | XPOWERS_AXP2101_VBUS_REMOVE_IRQ | //VBUS
XPOWERS_AXP2101_PKEY_SHORT_IRQ | XPOWERS_AXP2101_PKEY_LONG_IRQ | //POWER KEY
XPOWERS_AXP2101_BAT_CHG_DONE_IRQ | XPOWERS_AXP2101_BAT_CHG_START_IRQ | //CHARGE
XPOWERS_AXP2101_WARNING_LEVEL1_IRQ | XPOWERS_AXP2101_WARNING_LEVEL2_IRQ //Low battery warning
// XPOWERS_AXP2101_PKEY_NEGATIVE_IRQ | XPOWERS_AXP2101_PKEY_POSITIVE_IRQ | //POWER KEY
);
// Set the precharge charging current
power.setPrechargeCurr(XPOWERS_AXP2101_PRECHARGE_200MA);
// Set stop charging termination current
power.setChargerTerminationCurr(XPOWERS_AXP2101_CHG_ITERM_25MA);
// Set constant current charge current limit
if (!power.setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_1000MA)) {
Serial.println("Setting Charger Constant Current Failed!");
}
const uint16_t currTable[] = {
0, 0, 0, 0, 100, 125, 150, 175, 200, 300, 400, 500, 600, 700, 800, 900, 1000
};
uint8_t val = power.getChargerConstantCurr();
Serial.print("Setting Charge Target Current : ");
Serial.println(currTable[val]);
// Set charge cut-off voltage
power.setChargeTargetVoltage(XPOWERS_AXP2101_CHG_VOL_4V2);
const uint16_t tableVoltage[] = {
0, 4000, 4100, 4200, 4350, 4400, 255
};
val = power.getChargeTargetVoltage();
Serial.print("Setting Charge Target Voltage : ");
Serial.println(tableVoltage[val]);
// Set the power level to be lower than 15% and send an interrupt to the host`
power.setLowBatWarnThreshold(10);
// Set the power level to be lower than 5% and turn off the power supply
power.setLowBatShutdownThreshold(5);
/*
Turn on the learning battery curve,
And write the learned battery curve into the ROM
*/
power.fuelGaugeControl(true, true);
Serial.println();
delay(5000);
}
void printPMU()
{
Serial.println("---------------------------------------------------------------------------------------------------------");
Serial.println("Satus1 Satus2 CHARG DISC STBY VBUSIN VGOOD VBAT VBUS VSYS Percentage CHG_STATUS");
Serial.println("(Bin) (Bin) (bool) (bool) (bool) (bool) (bool) (mV) (mV) (mV) (%) (str) ");
Serial.println("---------------------------------------------------------------------------------------------------------");
uint16_t statusVal = power.status();
Serial.print("0b"); Serial.print(statusVal >> 8, BIN); Serial.print("\t");
Serial.print("0b"); Serial.print(statusVal & 0xFF, BIN); Serial.print("\t");
Serial.print(power.isCharging() ? "YES" : "NO "); Serial.print("\t");
Serial.print(power.isDischarge() ? "YES" : "NO "); Serial.print("\t");
Serial.print(power.isStandby() ? "YES" : "NO "); Serial.print("\t");
Serial.print(power.isVbusIn() ? "YES" : "NO "); Serial.print("\t");
Serial.print(power.isVbusGood() ? "YES" : "NO "); Serial.print("\t");
Serial.print(power.getBattVoltage()); Serial.print("\t");
Serial.print(power.getVbusVoltage()); Serial.print("\t");
Serial.print(power.getSystemVoltage()); Serial.print("\t");
// The battery percentage may be inaccurate at first use, the PMU will automatically
// learn the battery curve and will automatically calibrate the battery percentage
// after a charge and discharge cycle
Serial.print(power.getBatteryPercent()); Serial.print("\t");
uint8_t charge_status = power.getChargerStatus();
if (charge_status == XPOWERS_AXP2101_CHG_TRI_STATE) {
Serial.println("tri_charge");
} else if (charge_status == XPOWERS_AXP2101_CHG_PRE_STATE) {
Serial.println("pre_charge");
} else if (charge_status == XPOWERS_AXP2101_CHG_CC_STATE) {
Serial.println("constant charge(CC)");
} else if (charge_status == XPOWERS_AXP2101_CHG_CV_STATE) {
Serial.println("constant voltage(CV)");
} else if (charge_status == XPOWERS_AXP2101_CHG_DONE_STATE) {
Serial.println("charge done");
} else if (charge_status == XPOWERS_AXP2101_CHG_STOP_STATE) {
Serial.println("not charge");
}
Serial.println();
}
uint32_t printTime = 0;
void loop()
{
if (millis() > printTime) {
printTime = millis() + 2000;
printPMU();
}
if (pmu_flag) {
pmu_flag = false;
// Get PMU Interrupt Status Register
uint32_t status = power.getIrqStatus();
Serial.print("STATUS => HEX:");
Serial.print(status, HEX);
Serial.print(" BIN:");
Serial.println(status, BIN);
if (power.isDropWarningLevel2Irq()) {
Serial.println("isDropWarningLevel2");
}
if (power.isDropWarningLevel1Irq()) {
Serial.println(" >>>> isDropWarningLevel1 <<<<");
power.shutdown();
}
if (power.isGaugeWdtTimeoutIrq()) {
Serial.println("isWdtTimeout");
}
if (power.isBatChargerOverTemperatureIrq()) {
Serial.println("isBatChargeOverTemperature");
}
if (power.isBatWorkOverTemperatureIrq()) {
Serial.println("isBatWorkOverTemperature");
}
if (power.isBatWorkUnderTemperatureIrq()) {
Serial.println("isBatWorkUnderTemperature");
}
if (power.isVbusInsertIrq()) {
Serial.println("isVbusInsert");
uint8_t val = power.getVbusCurrentLimit();
Serial.print("Get Vbus Current Limit = "); Serial.println(val);
}
if (power.isVbusRemoveIrq()) {
Serial.println("isVbusRemove");
uint8_t val = power.getVbusCurrentLimit();
Serial.print("Get Vbus Current Limit = "); Serial.println(val);
}
if (power.isBatInsertIrq()) {
Serial.println("isBatInsert");
}
if (power.isBatRemoveIrq()) {
Serial.println("isBatRemove");
}
if (power.isPekeyShortPressIrq()) {
Serial.println("isPekeyShortPress");
}
if (power.isPekeyLongPressIrq()) {
Serial.println("isPekeyLongPress");
}
if (power.isPekeyNegativeIrq()) {
Serial.println("isPekeyNegative");
}
if (power.isPekeyPositiveIrq()) {
Serial.println("isPekeyPositive");
}
if (power.isWdtExpireIrq()) {
Serial.println("isWdtExpire");
}
if (power.isLdoOverCurrentIrq()) {
Serial.println("isLdoOverCurrentIrq");
}
if (power.isBatfetOverCurrentIrq()) {
Serial.println("isBatfetOverCurrentIrq");
}
if (power.isBatChargeDoneIrq()) {
Serial.println("isBatChargeDone");
}
if (power.isBatChargeStartIrq()) {
Serial.println("isBatChargeStart");
}
if (power.isBatDieOverTemperatureIrq()) {
Serial.println("isBatDieOverTemperature");
}
if (power.isChargeOverTimeoutIrq()) {
Serial.println("isChargeOverTimeout");
}
if (power.isBatOverVoltageIrq()) {
Serial.println("isBatOverVoltage");
}
// Clear PMU Interrupt Status Register
power.clearIrqStatus();
}
delay(10);
}

View File

@@ -0,0 +1,512 @@
/*
MIT License
Copyright (c) 2022 lewis he
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
! WARN:
Please do not run the example without knowing the external load voltage of the PMU,
it may burn your external load, please check the voltage setting before running the example,
if there is any loss, please bear it by yourself
*/
#ifndef XPOWERS_NO_ERROR
#error "Running this example is known to not damage the device! Please go and uncomment this!"
#endif
// Defined using AXP2102
#define XPOWERS_CHIP_AXP2101
#include <Wire.h>
#include <Arduino.h>
#include "XPowersLib.h"
#ifndef CONFIG_PMU_SDA
#define CONFIG_PMU_SDA 21
#endif
#ifndef CONFIG_PMU_SCL
#define CONFIG_PMU_SCL 22
#endif
#ifndef CONFIG_PMU_IRQ
#define CONFIG_PMU_IRQ 35
#endif
bool pmu_flag = 0;
XPowersPMU power;
const uint8_t i2c_sda = CONFIG_PMU_SDA;
const uint8_t i2c_scl = CONFIG_PMU_SCL;
const uint8_t pmu_irq_pin = CONFIG_PMU_IRQ;
void setFlag(void)
{
pmu_flag = true;
}
void setup()
{
Serial.begin(115200);
bool result = power.begin(Wire, AXP2101_SLAVE_ADDRESS, i2c_sda, i2c_scl);
if (result == false) {
Serial.println("power is not online..."); while (1)delay(50);
}
Serial.printf("getID:0x%x\n", power.getChipID());
// Set the minimum common working voltage of the PMU VBUS input,
// below this value will turn off the PMU
power.setVbusVoltageLimit(XPOWERS_AXP2101_VBUS_VOL_LIM_4V36);
// Set the maximum current of the PMU VBUS input,
// higher than this value will turn off the PMU
power.setVbusCurrentLimit(XPOWERS_AXP2101_VBUS_CUR_LIM_1500MA);
// Get the VSYS shutdown voltage
uint16_t vol = power.getSysPowerDownVoltage();
Serial.printf("-> getSysPowerDownVoltage:%u\n", vol);
// Set VSY off voltage as 2600mV , Adjustment range 2600mV ~ 3300mV
power.setSysPowerDownVoltage(2600);
vol = power.getSysPowerDownVoltage();
Serial.printf("-> getSysPowerDownVoltage:%u\n", vol);
// DC1 IMAX=2A
// 1500~3400mV,100mV/step,20steps
power.setDC1Voltage(3300);
Serial.printf("DC1 : %s Voltage:%u mV \n", power.isEnableDC1() ? "+" : "-", power.getDC1Voltage());
// DC2 IMAX=2A
// 500~1200mV 10mV/step,71steps
// 1220~1540mV 20mV/step,17steps
power.setDC2Voltage(1000);
Serial.printf("DC2 : %s Voltage:%u mV \n", power.isEnableDC2() ? "+" : "-", power.getDC2Voltage());
// DC3 IMAX = 2A
// 500~1200mV,10mV/step,71steps
// 1220~1540mV,20mV/step,17steps
// 1600~3400mV,100mV/step,19steps
power.setDC3Voltage(3300);
Serial.printf("DC3 : %s Voltage:%u mV \n", power.isEnableDC3() ? "+" : "-", power.getDC3Voltage());
// DCDC4 IMAX=1.5A
// 500~1200mV,10mV/step,71steps
// 1220~1840mV,20mV/step,32steps
power.setDC4Voltage(1000);
Serial.printf("DC4 : %s Voltage:%u mV \n", power.isEnableDC4() ? "+" : "-", power.getDC4Voltage());
// DC5 IMAX=2A
// 1200mV
// 1400~3700mV,100mV/step,24steps
power.setDC5Voltage(3300);
Serial.printf("DC5 : %s Voltage:%u mV \n", power.isEnableDC5() ? "+" : "-", power.getDC5Voltage());
//ALDO1 IMAX=300mA
//500~3500mV, 100mV/step,31steps
power.setALDO1Voltage(3300);
//ALDO2 IMAX=300mA
//500~3500mV, 100mV/step,31steps
power.setALDO2Voltage(3300);
//ALDO3 IMAX=300mA
//500~3500mV, 100mV/step,31steps
power.setALDO3Voltage(3300);
//ALDO4 IMAX=300mA
//500~3500mV, 100mV/step,31steps
power.setALDO4Voltage(3300);
//BLDO1 IMAX=300mA
//500~3500mV, 100mV/step,31steps
power.setBLDO1Voltage(3300);
//BLDO2 IMAX=300mA
//500~3500mV, 100mV/step,31steps
power.setBLDO2Voltage(3300);
//CPUSLDO IMAX=30mA
//500~1400mV,50mV/step,19steps
power.setCPUSLDOVoltage(1000);
//DLDO1 IMAX=300mA
//500~3400mV, 100mV/step,29steps
power.setDLDO1Voltage(3300);
//DLDO2 IMAX=300mA
//500~1400mV, 50mV/step,2steps
power.setDLDO2Voltage(3300);
// power.enableDC1();
power.enableDC2();
power.enableDC3();
power.enableDC4();
power.enableDC5();
power.enableALDO1();
power.enableALDO2();
power.enableALDO3();
power.enableALDO4();
power.enableBLDO1();
power.enableBLDO2();
power.enableCPUSLDO();
power.enableDLDO1();
power.enableDLDO2();
Serial.println("DCDC=======================================================================");
Serial.printf("DC1 : %s Voltage:%u mV \n", power.isEnableDC1() ? "+" : "-", power.getDC1Voltage());
Serial.printf("DC2 : %s Voltage:%u mV \n", power.isEnableDC2() ? "+" : "-", power.getDC2Voltage());
Serial.printf("DC3 : %s Voltage:%u mV \n", power.isEnableDC3() ? "+" : "-", power.getDC3Voltage());
Serial.printf("DC4 : %s Voltage:%u mV \n", power.isEnableDC4() ? "+" : "-", power.getDC4Voltage());
Serial.printf("DC5 : %s Voltage:%u mV \n", power.isEnableDC5() ? "+" : "-", power.getDC5Voltage());
Serial.println("ALDO=======================================================================");
Serial.printf("ALDO1: %s Voltage:%u mV\n", power.isEnableALDO1() ? "+" : "-", power.getALDO1Voltage());
Serial.printf("ALDO2: %s Voltage:%u mV\n", power.isEnableALDO2() ? "+" : "-", power.getALDO2Voltage());
Serial.printf("ALDO3: %s Voltage:%u mV\n", power.isEnableALDO3() ? "+" : "-", power.getALDO3Voltage());
Serial.printf("ALDO4: %s Voltage:%u mV\n", power.isEnableALDO4() ? "+" : "-", power.getALDO4Voltage());
Serial.println("BLDO=======================================================================");
Serial.printf("BLDO1: %s Voltage:%u mV\n", power.isEnableBLDO1() ? "+" : "-", power.getBLDO1Voltage());
Serial.printf("BLDO2: %s Voltage:%u mV\n", power.isEnableBLDO2() ? "+" : "-", power.getBLDO2Voltage());
Serial.println("CPUSLDO====================================================================");
Serial.printf("CPUSLDO: %s Voltage:%u mV\n", power.isEnableCPUSLDO() ? "+" : "-", power.getCPUSLDOVoltage());
Serial.println("DLDO=======================================================================");
Serial.printf("DLDO1: %s Voltage:%u mV\n", power.isEnableDLDO1() ? "+" : "-", power.getDLDO1Voltage());
Serial.printf("DLDO2: %s Voltage:%u mV\n", power.isEnableDLDO2() ? "+" : "-", power.getDLDO2Voltage());
Serial.println("===========================================================================");
// Set the time of pressing the button to turn off
power.setPowerKeyPressOffTime(XPOWERS_POWEROFF_4S);
uint8_t opt = power.getPowerKeyPressOffTime();
Serial.print("PowerKeyPressOffTime:");
switch (opt) {
case XPOWERS_POWEROFF_4S: Serial.println("4 Second");
break;
case XPOWERS_POWEROFF_6S: Serial.println("6 Second");
break;
case XPOWERS_POWEROFF_8S: Serial.println("8 Second");
break;
case XPOWERS_POWEROFF_10S: Serial.println("10 Second");
break;
default:
break;
}
// Set the button power-on press time
power.setPowerKeyPressOnTime(XPOWERS_POWERON_128MS);
opt = power.getPowerKeyPressOnTime();
Serial.print("PowerKeyPressOnTime:");
switch (opt) {
case XPOWERS_POWERON_128MS: Serial.println("128 Ms");
break;
case XPOWERS_POWERON_512MS: Serial.println("512 Ms");
break;
case XPOWERS_POWERON_1S: Serial.println("1 Second");
break;
case XPOWERS_POWERON_2S: Serial.println("2 Second");
break;
default:
break;
}
Serial.println("===========================================================================");
bool en;
// DCDC 120%(130%) high voltage turn off PMIC function
en = power.getDCHighVoltagePowerDownEn();
Serial.print("getDCHighVoltagePowerDownEn:");
Serial.println(en ? "ENABLE" : "DISABLE");
// DCDC1 85% low voltage turn off PMIC function
en = power.getDC1LowVoltagePowerDownEn();
Serial.print("getDC1LowVoltagePowerDownEn:");
Serial.println(en ? "ENABLE" : "DISABLE");
// DCDC2 85% low voltage turn off PMIC function
en = power.getDC2LowVoltagePowerDownEn();
Serial.print("getDC2LowVoltagePowerDownEn:");
Serial.println(en ? "ENABLE" : "DISABLE");
// DCDC3 85% low voltage turn off PMIC function
en = power.getDC3LowVoltagePowerDownEn();
Serial.print("getDC3LowVoltagePowerDownEn:");
Serial.println(en ? "ENABLE" : "DISABLE");
// DCDC4 85% low voltage turn off PMIC function
en = power.getDC4LowVoltagePowerDownEn();
Serial.print("getDC4LowVoltagePowerDownEn:");
Serial.println(en ? "ENABLE" : "DISABLE");
// DCDC5 85% low voltage turn off PMIC function
en = power.getDC5LowVoltagePowerDownEn();
Serial.print("getDC5LowVoltagePowerDownEn:");
Serial.println(en ? "ENABLE" : "DISABLE");
// power.setDCHighVoltagePowerDown(true);
// power.setDC1LowVoltagePowerDown(true);
// power.setDC2LowVoltagePowerDown(true);
// power.setDC3LowVoltagePowerDown(true);
// power.setDC4LowVoltagePowerDown(true);
// power.setDC5LowVoltagePowerDown(true);
// It is necessary to disable the detection function of the TS pin on the board
// without the battery temperature detection function, otherwise it will cause abnormal charging
power.disableTSPinMeasure();
// power.enableTemperatureMeasure();
// Enable internal ADC detection
power.enableBattDetection();
power.enableVbusVoltageMeasure();
power.enableBattVoltageMeasure();
power.enableSystemVoltageMeasure();
/*
The default setting is CHGLED is automatically controlled by the PMU.
- XPOWERS_CHG_LED_OFF,
- XPOWERS_CHG_LED_BLINK_1HZ,
- XPOWERS_CHG_LED_BLINK_4HZ,
- XPOWERS_CHG_LED_ON,
- XPOWERS_CHG_LED_CTRL_CHG,
* */
power.setChargingLedMode(XPOWERS_CHG_LED_OFF);
// Force add pull-up
pinMode(pmu_irq_pin, INPUT_PULLUP);
attachInterrupt(pmu_irq_pin, setFlag, FALLING);
// Disable all interrupts
power.disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
// Clear all interrupt flags
power.clearIrqStatus();
// Enable the required interrupt function
power.enableIRQ(
XPOWERS_AXP2101_BAT_INSERT_IRQ | XPOWERS_AXP2101_BAT_REMOVE_IRQ | //BATTERY
XPOWERS_AXP2101_VBUS_INSERT_IRQ | XPOWERS_AXP2101_VBUS_REMOVE_IRQ | //VBUS
XPOWERS_AXP2101_PKEY_SHORT_IRQ | XPOWERS_AXP2101_PKEY_LONG_IRQ | //POWER KEY
XPOWERS_AXP2101_BAT_CHG_DONE_IRQ | XPOWERS_AXP2101_BAT_CHG_START_IRQ //CHARGE
// XPOWERS_AXP2101_PKEY_NEGATIVE_IRQ | XPOWERS_AXP2101_PKEY_POSITIVE_IRQ | //POWER KEY
);
// Set the precharge charging current
power.setPrechargeCurr(XPOWERS_AXP2101_PRECHARGE_50MA);
// Set constant current charge current limit
power.setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_200MA);
// Set stop charging termination current
power.setChargerTerminationCurr(XPOWERS_AXP2101_CHG_ITERM_25MA);
// Set charge cut-off voltage
power.setChargeTargetVoltage(XPOWERS_AXP2101_CHG_VOL_4V1);
// Set the watchdog trigger event type
power.setWatchdogConfig(XPOWERS_AXP2101_WDT_IRQ_TO_PIN);
// Set watchdog timeout
power.setWatchdogTimeout(XPOWERS_AXP2101_WDT_TIMEOUT_4S);
// Enable watchdog to trigger interrupt event
power.enableWatchdog();
// power.disableWatchdog();
// Enable Button Battery charge
power.enableButtonBatteryCharge();
// Set Button Battery charge voltage
power.setButtonBatteryChargeVoltage(3300);
}
void printPMU()
{
Serial.print("isCharging:"); Serial.println(power.isCharging() ? "YES" : "NO");
Serial.print("isDischarge:"); Serial.println(power.isDischarge() ? "YES" : "NO");
Serial.print("isStandby:"); Serial.println(power.isStandby() ? "YES" : "NO");
Serial.print("isVbusIn:"); Serial.println(power.isVbusIn() ? "YES" : "NO");
Serial.print("isVbusGood:"); Serial.println(power.isVbusGood() ? "YES" : "NO");
Serial.print("getChargerStatus:");
uint8_t charge_status = power.getChargerStatus();
if (charge_status == XPOWERS_AXP2101_CHG_TRI_STATE) {
Serial.println("tri_charge");
} else if (charge_status == XPOWERS_AXP2101_CHG_PRE_STATE) {
Serial.println("pre_charge");
} else if (charge_status == XPOWERS_AXP2101_CHG_CC_STATE) {
Serial.println("constant charge");
} else if (charge_status == XPOWERS_AXP2101_CHG_CV_STATE) {
Serial.println("constant voltage");
} else if (charge_status == XPOWERS_AXP2101_CHG_DONE_STATE) {
Serial.println("charge done");
} else if (charge_status == XPOWERS_AXP2101_CHG_STOP_STATE) {
Serial.println("not charge");
}
Serial.print("getBattVoltage:"); Serial.print(power.getBattVoltage()); Serial.println("mV");
Serial.print("getVbusVoltage:"); Serial.print(power.getVbusVoltage()); Serial.println("mV");
Serial.print("getSystemVoltage:"); Serial.print(power.getSystemVoltage()); Serial.println("mV");
// The battery percentage may be inaccurate at first use, the PMU will automatically
// learn the battery curve and will automatically calibrate the battery percentage
// after a charge and discharge cycle
if (power.isBatteryConnect()) {
Serial.print("getBatteryPercent:"); Serial.print(power.getBatteryPercent()); Serial.println("%");
}
Serial.println();
}
void enterPmuSleep(void)
{
// Set the wake-up source to PWRKEY
power.wakeupControl(XPOWERS_AXP2101_WAKEUP_IRQ_PIN_TO_LOW, true);
// Set sleep flag
power.enableSleep();
power.disableDC2();
power.disableDC3();
power.disableDC4();
power.disableDC5();
power.disableALDO1();
power.disableALDO2();
power.disableALDO3();
power.disableALDO4();
power.disableBLDO1();
power.disableBLDO2();
power.disableCPUSLDO();
power.disableDLDO1();
power.disableDLDO2();
// Finally, turn off the power of the control chip
power.disableDC1();
}
void loop()
{
if (pmu_flag) {
pmu_flag = false;
// Get PMU Interrupt Status Register
uint32_t status = power.getIrqStatus();
Serial.print("STATUS => HEX:");
Serial.print(status, HEX);
Serial.print(" BIN:");
Serial.println(status, BIN);
if (power.isDropWarningLevel2Irq()) {
Serial.println("isDropWarningLevel2");
}
if (power.isDropWarningLevel1Irq()) {
Serial.println("isDropWarningLevel1");
}
if (power.isGaugeWdtTimeoutIrq()) {
Serial.println("isWdtTimeout");
}
if (power.isBatChargerOverTemperatureIrq()) {
Serial.println("isBatChargeOverTemperature");
}
if (power.isBatWorkOverTemperatureIrq()) {
Serial.println("isBatWorkOverTemperature");
}
if (power.isBatWorkUnderTemperatureIrq()) {
Serial.println("isBatWorkUnderTemperature");
}
if (power.isVbusInsertIrq()) {
Serial.println("isVbusInsert");
}
if (power.isVbusRemoveIrq()) {
Serial.println("isVbusRemove");
}
if (power.isBatInsertIrq()) {
Serial.println("isBatInsert");
}
if (power.isBatRemoveIrq()) {
Serial.println("isBatRemove");
}
if (power.isPekeyShortPressIrq()) {
Serial.println("isPekeyShortPress");
// enterPmuSleep();
Serial.print("Read pmu data buffer .");
uint8_t data[4] = {0};
power.readDataBuffer(data, XPOWERS_AXP2101_DATA_BUFFER_SIZE);
for (int i = 0; i < 4; ++i) {
Serial.print(data[i]);
Serial.print(",");
}
Serial.println();
}
if (power.isPekeyLongPressIrq()) {
Serial.println("isPekeyLongPress");
Serial.println("write pmu data buffer .");
uint8_t data[4] = {1, 2, 3, 4};
power.writeDataBuffer(data, XPOWERS_AXP2101_DATA_BUFFER_SIZE);
}
if (power.isPekeyNegativeIrq()) {
Serial.println("isPekeyNegative");
}
if (power.isPekeyPositiveIrq()) {
Serial.println("isPekeyPositive");
}
if (power.isWdtExpireIrq()) {
Serial.println("isWdtExpire");
printPMU();
}
if (power.isLdoOverCurrentIrq()) {
Serial.println("isLdoOverCurrentIrq");
}
if (power.isBatfetOverCurrentIrq()) {
Serial.println("isBatfetOverCurrentIrq");
}
if (power.isBatChargeDoneIrq()) {
Serial.println("isBatChargeDone");
}
if (power.isBatChargeStartIrq()) {
Serial.println("isBatChargeStart");
}
if (power.isBatDieOverTemperatureIrq()) {
Serial.println("isBatDieOverTemperature");
}
if (power.isChargeOverTimeoutIrq()) {
Serial.println("isChargeOverTimeout");
}
if (power.isBatOverVoltageIrq()) {
Serial.println("isBatOverVoltage");
}
// Clear PMU Interrupt Status Register
power.clearIrqStatus();
}
delay(10);
}

View File

@@ -0,0 +1,206 @@
/*
MIT License
Copyright (c) 2022 lewis he
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
! WARN:
Please do not run the example without knowing the external load voltage of the PMU,
it may burn your external load, please check the voltage setting before running the example,
if there is any loss, please bear it by yourself
*/
#ifndef XPOWERS_NO_ERROR
#error "Running this example is known to not damage the device! Please go and uncomment this!"
#endif
// Defined using AXP2102
#define XPOWERS_CHIP_AXP2101
#include <Wire.h>
#include <Arduino.h>
#include "XPowersLib.h"
#ifndef CONFIG_PMU_SDA
#define CONFIG_PMU_SDA 21
#endif
#ifndef CONFIG_PMU_SCL
#define CONFIG_PMU_SCL 22
#endif
#ifndef CONFIG_PMU_IRQ
#define CONFIG_PMU_IRQ 35
#endif
bool pmu_flag = 0;
XPowersPMU power;
const uint8_t i2c_sda = CONFIG_PMU_SDA;
const uint8_t i2c_scl = CONFIG_PMU_SCL;
const uint8_t pmu_irq_pin = CONFIG_PMU_IRQ;
void setFlag(void)
{
pmu_flag = true;
}
void setup()
{
Serial.begin(115200);
bool result = power.begin(Wire, AXP2101_SLAVE_ADDRESS, i2c_sda, i2c_scl);
if (result == false) {
Serial.println("power is not online..."); while (1)delay(50);
}
Serial.printf("getID:0x%x\n", power.getChipID());
// Force add pull-up
pinMode(pmu_irq_pin, INPUT_PULLUP);
attachInterrupt(pmu_irq_pin, setFlag, FALLING);
// Disable all interrupts
power.disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
// Print interrupt register
power.printIntRegister(&Serial);
// Clear all interrupt flags
power.clearIrqStatus();
// Enable the required interrupt function
// power.enableIRQ(
// XPOWERS_AXP2101_BAT_INSERT_IRQ | XPOWERS_AXP2101_BAT_REMOVE_IRQ | //BATTERY
// XPOWERS_AXP2101_VBUS_INSERT_IRQ | XPOWERS_AXP2101_VBUS_REMOVE_IRQ | //VBUS
// XPOWERS_AXP2101_PKEY_SHORT_IRQ | XPOWERS_AXP2101_PKEY_LONG_IRQ | //POWER KEY
// XPOWERS_AXP2101_BAT_CHG_DONE_IRQ | XPOWERS_AXP2101_BAT_CHG_START_IRQ //CHARGE
// // XPOWERS_AXP2101_PKEY_NEGATIVE_IRQ | XPOWERS_AXP2101_PKEY_POSITIVE_IRQ | //POWER KEY
// );
power.enableIRQ(XPOWERS_AXP2101_BAT_NOR_UNDER_TEMP_IRQ);
// Print AXP2101 interrupt control register
power.printIntRegister(&Serial);
power.enableIRQ(XPOWERS_AXP2101_PKEY_SHORT_IRQ | XPOWERS_AXP2101_PKEY_NEGATIVE_IRQ);
// Print AXP2101 interrupt control register
power.printIntRegister(&Serial);
power.enableIRQ(XPOWERS_AXP2101_BAT_OVER_VOL_IRQ);
// Print AXP2101 interrupt control register
power.printIntRegister(&Serial);
// delay(30000);
}
void loop()
{
if (pmu_flag) {
pmu_flag = false;
// Get PMU Interrupt Status Register
uint32_t status = power.getIrqStatus();
Serial.print("STATUS => HEX:");
Serial.print(status, HEX);
Serial.print(" BIN:");
Serial.println(status, BIN);
if (power.isDropWarningLevel2Irq()) {
Serial.println("isDropWarningLevel2");
}
if (power.isDropWarningLevel1Irq()) {
Serial.println("isDropWarningLevel1");
}
if (power.isGaugeWdtTimeoutIrq()) {
Serial.println("isWdtTimeout");
}
if (power.isBatChargerOverTemperatureIrq()) {
Serial.println("isBatChargeOverTemperature");
}
if (power.isBatWorkOverTemperatureIrq()) {
Serial.println("isBatWorkOverTemperature");
}
if (power.isBatWorkUnderTemperatureIrq()) {
Serial.println("isBatWorkUnderTemperature");
}
if (power.isVbusInsertIrq()) {
Serial.println("isVbusInsert");
}
if (power.isVbusRemoveIrq()) {
Serial.println("isVbusRemove");
}
if (power.isBatInsertIrq()) {
Serial.println("isBatInsert");
}
if (power.isBatRemoveIrq()) {
Serial.println("isBatRemove");
}
if (power.isPekeyShortPressIrq()) {
Serial.println("isPekeyShortPress");
}
if (power.isPekeyLongPressIrq()) {
Serial.println("isPekeyLongPress");
}
if (power.isPekeyNegativeIrq()) {
Serial.println("isPekeyNegative");
}
if (power.isPekeyPositiveIrq()) {
Serial.println("isPekeyPositive");
}
if (power.isWdtExpireIrq()) {
Serial.println("isWdtExpire");
}
if (power.isLdoOverCurrentIrq()) {
Serial.println("isLdoOverCurrentIrq");
}
if (power.isBatfetOverCurrentIrq()) {
Serial.println("isBatfetOverCurrentIrq");
}
if (power.isBatChargeDoneIrq()) {
Serial.println("isBatChargeDone");
}
if (power.isBatChargeStartIrq()) {
Serial.println("isBatChargeStart");
}
if (power.isBatDieOverTemperatureIrq()) {
Serial.println("isBatDieOverTemperature");
}
if (power.isChargeOverTimeoutIrq()) {
Serial.println("isChargeOverTimeout");
}
if (power.isBatOverVoltageIrq()) {
Serial.println("isBatOverVoltage");
}
// Clear PMU Interrupt Status Register
power.clearIrqStatus();
// Print AXP2101 interrupt control register
power.printIntRegister(&Serial);
}
delay(10);
}

View File

@@ -0,0 +1,283 @@
/*
MIT License
Copyright (c) 2024 lewis he
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
! WARN:
Please do not run the example without knowing the external load voltage of the PMU,
it may burn your external load, please check the voltage setting before running the example,
if there is any loss, please bear it by yourself
*/
#ifndef XPOWERS_NO_ERROR
#error "Running this example is known to not damage the device! Please go and uncomment this!"
#endif
// Defined using AXP2102
#define XPOWERS_CHIP_AXP2101
#include <Wire.h>
#include <Arduino.h>
#include "XPowersLib.h"
#ifndef CONFIG_PMU_SDA
#define CONFIG_PMU_SDA 21
#endif
#ifndef CONFIG_PMU_SCL
#define CONFIG_PMU_SCL 22
#endif
#ifndef CONFIG_PMU_IRQ
#define CONFIG_PMU_IRQ 35
#endif
bool pmu_flag = 0;
XPowersPMU power;
const uint8_t i2c_sda = CONFIG_PMU_SDA;
const uint8_t i2c_scl = CONFIG_PMU_SCL;
const uint8_t pmu_irq_pin = CONFIG_PMU_IRQ;
static uint32_t interval = 0;
void setFlag(void)
{
pmu_flag = true;
}
void setup()
{
Serial.begin(115200);
bool result = power.begin(Wire, AXP2101_SLAVE_ADDRESS, i2c_sda, i2c_scl);
if (result == false) {
Serial.println("power is not online..."); while (1)delay(50);
}
Serial.printf("getID:0x%x\n", power.getChipID());
// Set the minimum common working voltage of the PMU VBUS input,
// below this value will turn off the PMU
power.setVbusVoltageLimit(XPOWERS_AXP2101_VBUS_VOL_LIM_4V36);
// Set the maximum current of the PMU VBUS input,
// higher than this value will turn off the PMU
power.setVbusCurrentLimit(XPOWERS_AXP2101_VBUS_CUR_LIM_1500MA);
// Get the VSYS shutdown voltage
uint16_t vol = power.getSysPowerDownVoltage();
Serial.printf("-> getSysPowerDownVoltage:%u\n", vol);
// Set VSYS off voltage as 2600mV , Adjustment range 2600mV ~ 3300mV
power.setSysPowerDownVoltage(2600);
vol = power.getSysPowerDownVoltage();
Serial.printf("-> getSysPowerDownVoltage:%u\n", vol);
Serial.println("DCDC=======================================================================");
Serial.printf("DC1 : %s Voltage:%u mV \n", power.isEnableDC1() ? "+" : "-", power.getDC1Voltage());
Serial.printf("DC2 : %s Voltage:%u mV \n", power.isEnableDC2() ? "+" : "-", power.getDC2Voltage());
Serial.printf("DC3 : %s Voltage:%u mV \n", power.isEnableDC3() ? "+" : "-", power.getDC3Voltage());
Serial.printf("DC4 : %s Voltage:%u mV \n", power.isEnableDC4() ? "+" : "-", power.getDC4Voltage());
Serial.printf("DC5 : %s Voltage:%u mV \n", power.isEnableDC5() ? "+" : "-", power.getDC5Voltage());
Serial.println("ALDO=======================================================================");
Serial.printf("ALDO1: %s Voltage:%u mV\n", power.isEnableALDO1() ? "+" : "-", power.getALDO1Voltage());
Serial.printf("ALDO2: %s Voltage:%u mV\n", power.isEnableALDO2() ? "+" : "-", power.getALDO2Voltage());
Serial.printf("ALDO3: %s Voltage:%u mV\n", power.isEnableALDO3() ? "+" : "-", power.getALDO3Voltage());
Serial.printf("ALDO4: %s Voltage:%u mV\n", power.isEnableALDO4() ? "+" : "-", power.getALDO4Voltage());
Serial.println("BLDO=======================================================================");
Serial.printf("BLDO1: %s Voltage:%u mV\n", power.isEnableBLDO1() ? "+" : "-", power.getBLDO1Voltage());
Serial.printf("BLDO2: %s Voltage:%u mV\n", power.isEnableBLDO2() ? "+" : "-", power.getBLDO2Voltage());
Serial.println("CPUSLDO====================================================================");
Serial.printf("CPUSLDO: %s Voltage:%u mV\n", power.isEnableCPUSLDO() ? "+" : "-", power.getCPUSLDOVoltage());
Serial.println("DLDO=======================================================================");
Serial.printf("DLDO1: %s Voltage:%u mV\n", power.isEnableDLDO1() ? "+" : "-", power.getDLDO1Voltage());
Serial.printf("DLDO2: %s Voltage:%u mV\n", power.isEnableDLDO2() ? "+" : "-", power.getDLDO2Voltage());
Serial.println("===========================================================================");
// Enable internal ADC detection
power.enableBattDetection();
power.enableVbusVoltageMeasure();
power.enableBattVoltageMeasure();
power.enableSystemVoltageMeasure();
power.enableTemperatureMeasure();
/*
The default setting is CHGLED is automatically controlled by the PMU.
- XPOWERS_CHG_LED_OFF,
- XPOWERS_CHG_LED_BLINK_1HZ,
- XPOWERS_CHG_LED_BLINK_4HZ,
- XPOWERS_CHG_LED_ON,
- XPOWERS_CHG_LED_CTRL_CHG,
* */
power.setChargingLedMode(XPOWERS_CHG_LED_CTRL_CHG);
// Force add pull-up
pinMode(pmu_irq_pin, INPUT_PULLUP);
attachInterrupt(pmu_irq_pin, setFlag, FALLING);
// Disable all interrupts
power.disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
// Clear all interrupt flags
power.clearIrqStatus();
// Enable the required interrupt function
power.enableIRQ(
XPOWERS_AXP2101_BAT_INSERT_IRQ | XPOWERS_AXP2101_BAT_REMOVE_IRQ | //BATTERY
XPOWERS_AXP2101_VBUS_INSERT_IRQ | XPOWERS_AXP2101_VBUS_REMOVE_IRQ | //VBUS
XPOWERS_AXP2101_PKEY_SHORT_IRQ | XPOWERS_AXP2101_PKEY_LONG_IRQ | //POWER KEY
XPOWERS_AXP2101_BAT_CHG_DONE_IRQ | XPOWERS_AXP2101_BAT_CHG_START_IRQ | //CHARGE
XPOWERS_AXP2101_WARNING_LEVEL1_IRQ | XPOWERS_AXP2101_WARNING_LEVEL2_IRQ // LOW BATTER
);
// Get the default low pressure warning percentage setting
uint8_t low_warn_per = power.getLowBatWarnThreshold();
Serial.printf("Default low battery warning threshold is %d percentage\n", low_warn_per);
//
// setLowBatWarnThreshold Range: 5% ~ 20%
// The following data is obtained from actual testing , Please see the description below for the test method.
// 20% ~= 3.7v
// 15% ~= 3.6v
// 10% ~= 3.55V
// 5% ~= 3.5V
// 1% ~= 3.4V
power.setLowBatWarnThreshold(5); // Set to trigger interrupt when reaching 5%
// Get the low voltage warning percentage setting
low_warn_per = power.getLowBatWarnThreshold();
Serial.printf("Set low battery warning threshold is %d percentage\n", low_warn_per);
// Get the default low voltage shutdown percentage setting
uint8_t low_shutdown_per = power.getLowBatShutdownThreshold();
Serial.printf("Default low battery shutdown threshold is %d percentage\n", low_shutdown_per);
// setLowBatShutdownThreshold Range: 0% ~ 15%
// The following data is obtained from actual testing , Please see the description below for the test method.
// 15% ~= 3.6v
// 10% ~= 3.55V
// 5% ~= 3.5V
// 1% ~= 3.4V
power.setLowBatShutdownThreshold(1); // Set to trigger interrupt when reaching 1%
// Get the low voltage shutdown percentage setting
low_shutdown_per = power.getLowBatShutdownThreshold();
Serial.printf("Set low battery shutdown threshold is %d percentage\n", low_shutdown_per);
/*
*
* Measurement methods:
* 1. Connect the battery terminal to a voltage stabilizing source
* 2. Set voltage test voltage
* 3. Press PWR to boot
* 4. Read the serial output voltage percentage
*
* If a voltage regulator is connected during testing and the voltage is slowly reduced,
* the voltage percentage will not change immediately. It will take a while to slowly decrease.
* In actual production, it needs to be adjusted according to the actual situation.
* * * */
}
void loop()
{
if (millis() > interval) {
interval = millis() + 3000;
Serial.print("getBattVoltage:"); Serial.print(power.getBattVoltage()); Serial.println("mV");
Serial.print("getVbusVoltage:"); Serial.print(power.getVbusVoltage()); Serial.println("mV");
Serial.print("getSystemVoltage:"); Serial.print(power.getSystemVoltage()); Serial.println("mV");
// The battery percentage may be inaccurate at first use, the PMU will automatically
// learn the battery curve and will automatically calibrate the battery percentage
// after a charge and discharge cycle
if (power.isBatteryConnect()) {
Serial.print("getBatteryPercent:"); Serial.print(power.getBatteryPercent()); Serial.println("%");
}
Serial.println();
}
if (pmu_flag) {
pmu_flag = false;
// Get PMU Interrupt Status Register
uint32_t status = power.getIrqStatus();
Serial.print("STATUS => HEX:");
Serial.print(status, HEX);
Serial.print(" BIN:");
Serial.println(status, BIN);
// When the set low-voltage battery percentage warning threshold is reached,
// set the threshold through getLowBatWarnThreshold( 5% ~ 20% )
if (power.isDropWarningLevel2Irq()) {
Serial.println("The voltage percentage has reached the low voltage warning threshold!!!");
}
// When the set low-voltage battery percentage shutdown threshold is reached
// set the threshold through setLowBatShutdownThreshold()
if (power.isDropWarningLevel1Irq()) {
int i = 4;
while (i--) {
Serial.printf("The voltage percentage has reached the low voltage shutdown threshold and will shut down in %d seconds.\n", i);
}
// Turn off all power supplies, leaving only the RTC power supply. The RTC power supply cannot be turned off.
power.shutdown();
}
if (power.isVbusInsertIrq()) {
Serial.println("isVbusInsert");
}
if (power.isVbusRemoveIrq()) {
Serial.println("isVbusRemove");
}
if (power.isBatInsertIrq()) {
Serial.println("isBatInsert");
}
if (power.isBatRemoveIrq()) {
Serial.println("isBatRemove");
}
if (power.isPekeyShortPressIrq()) {
Serial.println("isPekeyShortPress");
}
if (power.isPekeyLongPressIrq()) {
Serial.println("isPekeyLongPress");
}
// Clear PMU Interrupt Status Register
power.clearIrqStatus();
}
delay(10);
}

View File

@@ -0,0 +1,170 @@
/*
MIT License
Copyright (c) 2022 lewis he
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
! WARN:
Please do not run the example without knowing the external load voltage of the PMU,
it may burn your external load, please check the voltage setting before running the example,
if there is any loss, please bear it by yourself
*/
//! @note In the experiment on T-SIM7080-ESP32, the power consumption is about 900uA after setting the PMU to sleep,
//! and 1mA if it is not set to sleep. After setting the PMU to sleep, it can save about 100uA consumption current
#ifndef XPOWERS_NO_ERROR
#error "Running this example is known to not damage the device! Please go and uncomment this!"
#endif
// Defined using AXP2102
#define XPOWERS_CHIP_AXP2101
#include <Wire.h>
#include <Arduino.h>
#include "XPowersLib.h"
#ifndef CONFIG_PMU_SDA
#define CONFIG_PMU_SDA 15
#endif
#ifndef CONFIG_PMU_SCL
#define CONFIG_PMU_SCL 7
#endif
#ifndef CONFIG_PMU_IRQ
#define CONFIG_PMU_IRQ 6
#endif
XPowersPMU power;
const uint8_t i2c_sda = CONFIG_PMU_SDA;
const uint8_t i2c_scl = CONFIG_PMU_SCL;
const uint8_t pmu_irq_pin = CONFIG_PMU_IRQ;
bool pmu_flag = false;
bool adc_switch = false;
void setFlag(void)
{
pmu_flag = true;
}
void setup()
{
Serial.begin(115200);
bool result = power.begin(Wire, AXP2101_SLAVE_ADDRESS, i2c_sda, i2c_scl);
if (result == false) {
Serial.println("PMU is not online..."); while (1)delay(50);
}
// Force add pull-up
pinMode(pmu_irq_pin, INPUT_PULLUP);
attachInterrupt(pmu_irq_pin, setFlag, FALLING);
// Close other IRQs
power.disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
// Clear all interrupt flags
power.clearIrqStatus();
// Enable the required interrupt function
power.enableIRQ(
XPOWERS_AXP2101_PKEY_SHORT_IRQ //POWER KEY
);
// Turn on the charging indicator light as a power-on indicator
power.setChargingLedMode(XPOWERS_CHG_LED_ON);
// Enable chip temperature detection
power.enableTemperatureMeasure();
}
void loop()
{
if (pmu_flag) {
pmu_flag = false;
// Get PMU Interrupt Status Register
power.getIrqStatus();
if (power.isPekeyShortPressIrq()) {
// Turn off the charging indicator to save power
power.setChargingLedMode(XPOWERS_CHG_LED_OFF);
// Turn off ADC data monitoring to save power
power.disableTemperatureMeasure();
// Enable internal ADC detection
power.disableBattDetection();
power.disableVbusVoltageMeasure();
power.disableBattVoltageMeasure();
power.disableSystemVoltageMeasure();
// Enable PMU sleep
power.enableSleep();
// Reserve the MCU chip power supply, LilyGo AXP2101 usually uses DC as ESP power supply
// power.enableDC1();
// Turn off the power output of other channels
power.disableDC2();
power.disableDC3();
power.disableDC4();
power.disableDC5();
power.disableALDO1();
power.disableALDO2();
power.disableALDO3();
power.disableALDO4();
power.disableBLDO1();
power.disableBLDO2();
power.disableCPUSLDO();
power.disableDLDO1();
power.disableDLDO2();
// Clear PMU Interrupt Status Register
power.clearIrqStatus();
// Send IRQ wakeup command
power.enableWakeup();
#if !CONFIG_IDF_TARGET_ESP32S3
Serial.println("Please implement the MCU sleep method");
#else
// Set ESP32 to wake up externally
esp_sleep_enable_ext0_wakeup((gpio_num_t )pmu_irq_pin, LOW);
// Enable ESP32 sleep
esp_deep_sleep_start();
#endif
Serial.println("Here never prints . ");
}
}
// When not sleeping, print PMU temperature
Serial.print("power Temperature:"); Serial.print(power.getTemperature()); Serial.println("*C");
delay(1000);
}

View File

@@ -0,0 +1,354 @@
/*
MIT License
Copyright (c) 2022 lewis he
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
! WARN:
Please do not run the example without knowing the external load voltage of the PMU,
it may burn your external load, please check the voltage setting before running the example,
if there is any loss, please bear it by yourself
*/
#ifndef XPOWERS_NO_ERROR
#error "Running this example is known to not damage the device! Please go and uncomment this!"
#endif
// Defined using AXP2102
#define XPOWERS_CHIP_AXP2101
#include <Wire.h>
#include <Arduino.h>
#include "XPowersLib.h"
XPowersPMU power;
#ifndef CONFIG_PMU_SDA
#define CONFIG_PMU_SDA 21
#endif
#ifndef CONFIG_PMU_SCL
#define CONFIG_PMU_SCL 22
#endif
#ifndef CONFIG_PMU_IRQ
#define CONFIG_PMU_IRQ 35
#endif
const uint8_t i2c_sda = CONFIG_PMU_SDA;
const uint8_t i2c_scl = CONFIG_PMU_SCL;
const uint8_t pmu_irq_pin = CONFIG_PMU_IRQ;
uint16_t targetVol;
uint16_t vol = 0;
void setup()
{
Serial.begin(115200);
bool result = power.begin(Wire, AXP2101_SLAVE_ADDRESS, i2c_sda, i2c_scl);
if (result == false) {
Serial.println("power is not online..."); while (1)delay(50);
}
Serial.println("AXP2101 Power Output Test.");
power.disableDC2();
power.disableDC3();
power.disableDC4();
power.disableDC5();
power.disableALDO1();
power.disableALDO2();
power.disableALDO3();
power.disableALDO4();
power.disableBLDO1();
power.disableBLDO2();
power.disableCPUSLDO();
power.disableDLDO1();
power.disableDLDO2();
// DC1 IMAX=2A
// 1500~3400mV,100mV/step,20steps
vol = 1500;
for (int i = 0; i < 20; ++i) {
power.setDC1Voltage(vol);
vol += 100;
Serial.printf("DC1 :%s Voltage:%u mV \n", power.isEnableDC1() ? "ENABLE" : "DISABLE", power.getDC1Voltage());
}
// DC2 IMAX=2A
// 500~1200mV 10mV/step,71steps
vol = 500;
for (int i = 0; i < 71; ++i) {
power.setDC2Voltage(vol);
delay(1);
targetVol = power.getDC2Voltage();
Serial.printf("[%d]DC2 :%s Voltage:%u mV \n", i, power.isEnableDC2() ? "ENABLE" : "DISABLE", targetVol );
if (targetVol != vol)Serial.println(">>> FAILED!");
vol += 10;
}
// DC2 IMAX=2A
// 1220~1540mV 20mV/step,17steps
vol = 1220;
for (int i = 0; i < 17; ++i) {
power.setDC2Voltage(vol);
delay(1);
targetVol = power.getDC2Voltage();
Serial.printf("[%u]DC2 :%s Voltage:%u mV \n", i, power.isEnableDC2() ? "ENABLE" : "DISABLE", targetVol );
if (targetVol != vol)Serial.println(">>> FAILED!");
vol += 20;
}
// DC3 IMAX = 2A
// 500~1200mV,10mV/step,71steps
vol = 500;
for (int i = 0; i < 71; ++i) {
power.setDC3Voltage(vol);
delay(1);
targetVol = power.getDC3Voltage();
Serial.printf("[%u]DC3 :%s Voltage:%u mV \n", i, power.isEnableDC3() ? "ENABLE" : "DISABLE", targetVol );
if (targetVol != vol)Serial.println(">>> FAILED!");
vol += 10;
}
// DC3 IMAX = 2A
// 1220~1540mV,20mV/step,17steps
vol = 1220;
for (int i = 0; i < 17; ++i) {
power.setDC3Voltage(vol);
delay(1);
targetVol = power.getDC3Voltage();
Serial.printf("[%u]DC3 :%s Voltage:%u mV \n", i, power.isEnableDC3() ? "ENABLE" : "DISABLE", targetVol );
if (targetVol != vol)Serial.println(">>> FAILED!");
vol += 20;
}
// DC3 IMAX = 2A
// 1600~3400mV,100mV/step,19steps
vol = 1600;
for (int i = 0; i < 19; ++i) {
power.setDC3Voltage(vol);
delay(1);
targetVol = power.getDC3Voltage();
Serial.printf("[%u]DC3 :%s Voltage:%u mV \n", i, power.isEnableDC3() ? "ENABLE" : "DISABLE", targetVol );
if (targetVol != vol)Serial.println(">>> FAILED!");
vol += 100;
}
// DCDC4 IMAX=1.5A
// 500~1200mV,10mV/step,71steps
vol = 500;
for (int i = 0; i < 71; ++i) {
power.setDC4Voltage(vol);
delay(1);
targetVol = power.getDC4Voltage();
Serial.printf("[%u]DC4 :%s Voltage:%u mV \n", i, power.isEnableDC4() ? "ENABLE" : "DISABLE", targetVol );
if (targetVol != vol)Serial.println(">>> FAILED!");
vol += 10;
}
// DCDC4 IMAX=1.5A
// 1220~1840mV,20mV/step,32steps
vol = 1220;
for (int i = 0; i < 32; ++i) {
power.setDC4Voltage(vol);
delay(1);
targetVol = power.getDC4Voltage();
Serial.printf("[%u]DC4 :%s Voltage:%u mV \n", i, power.isEnableDC4() ? "ENABLE" : "DISABLE", targetVol );
if (targetVol != vol)Serial.println(">>> FAILED!");
vol += 20;
}
// DC5 IMAX=2A
// 1200mV
power.setDC5Voltage(1200);
targetVol = power.getDC5Voltage();
Serial.printf("[0]DC5 :%s Voltage:%u mV \n", power.isEnableDC5() ? "ENABLE" : "DISABLE", targetVol );
// DC5 IMAX=2A
// 1400~3700mV,100mV/step,24steps
vol = 1400;
for (int i = 0; i < 24; ++i) {
power.setDC5Voltage(vol);
delay(1);
targetVol = power.getDC5Voltage();
Serial.printf("[%u]DC5 :%s Voltage:%u mV \n", i, power.isEnableDC5() ? "ENABLE" : "DISABLE", targetVol );
if (targetVol != vol)Serial.println(">>> FAILED!");
vol += 100;
}
//ALDO1 IMAX=300mA
//500~3500mV, 100mV/step,31steps
vol = 500;
for (int i = 0; i < 31; ++i) {
power.setALDO1Voltage(vol);
delay(1);
targetVol = power.getALDO1Voltage();
Serial.printf("[%u]ALDO1 :%s Voltage:%u mV \n", i, power.isEnableALDO1() ? "ENABLE" : "DISABLE", targetVol );
if (targetVol != vol)Serial.println(">>> FAILED!");
vol += 100;
}
//ALDO2 IMAX=300mA
//500~3500mV, 100mV/step,31steps
vol = 500;
for (int i = 0; i < 31; ++i) {
power.setALDO2Voltage(vol);
delay(1);
targetVol = power.getALDO2Voltage();
Serial.printf("[%u]ALDO2 :%s Voltage:%u mV \n", i, power.isEnableALDO2() ? "ENABLE" : "DISABLE", targetVol );
if (targetVol != vol)Serial.println(">>> FAILED!");
vol += 100;
}
//ALDO3 IMAX=300mA
//500~3500mV, 100mV/step,31steps
vol = 500;
for (int i = 0; i < 31; ++i) {
power.setALDO3Voltage(vol);
delay(1);
targetVol = power.getALDO3Voltage();
Serial.printf("[%u]ALDO3 :%s Voltage:%u mV \n", i, power.isEnableALDO3() ? "ENABLE" : "DISABLE", targetVol );
if (targetVol != vol)Serial.println(">>> FAILED!");
vol += 100;
}
//ALDO4 IMAX=300mA
//500~3500mV, 100mV/step,31steps
vol = 500;
for (int i = 0; i < 31; ++i) {
power.setALDO4Voltage(vol);
delay(1);
targetVol = power.getALDO4Voltage();
Serial.printf("[%u]ALDO4 :%s Voltage:%u mV \n", i, power.isEnableALDO4() ? "ENABLE" : "DISABLE", targetVol );
if (targetVol != vol)Serial.println(">>> FAILED!");
vol += 100;
}
//BLDO1 IMAX=300mA
//500~3500mV, 100mV/step,31steps
vol = 500;
for (int i = 0; i < 31; ++i) {
power.setBLDO1Voltage(vol);
delay(1);
targetVol = power.getBLDO1Voltage();
Serial.printf("[%u]BLDO1 :%s Voltage:%u mV \n", i, power.isEnableBLDO1() ? "ENABLE" : "DISABLE", targetVol );
if (targetVol != vol)Serial.println(">>> FAILED!");
vol += 100;
}
//BLDO2 IMAX=300mA
//500~3500mV, 100mV/step,31steps
vol = 500;
for (int i = 0; i < 31; ++i) {
power.setBLDO2Voltage(vol);
delay(1);
targetVol = power.getBLDO2Voltage();
Serial.printf("[%u]BLDO2 :%s Voltage:%u mV \n", i, power.isEnableBLDO2() ? "ENABLE" : "DISABLE", targetVol );
if (targetVol != vol)Serial.println(">>> FAILED!");
vol += 100;
}
//CPUSLDO IMAX=30mA
//500~1400mV,50mV/step,19steps
vol = 500;
for (int i = 0; i < 19; ++i) {
power.setCPUSLDOVoltage(vol);
delay(1);
targetVol = power.getCPUSLDOVoltage();
Serial.printf("[%u]CPUSLDO :%s Voltage:%u mV \n", i, power.isEnableCPUSLDO() ? "ENABLE" : "DISABLE", targetVol );
if (targetVol != vol)Serial.println(">>> FAILED!");
vol += 50;
}
//DLDO1 IMAX=300mA
//500~3400mV, 100mV/step,29steps
vol = 500;
for (int i = 0; i < 29; ++i) {
power.setDLDO1Voltage(vol);
delay(1);
targetVol = power.getDLDO1Voltage();
Serial.printf("[%u]DLDO1 :%s Voltage:%u mV \n", i, power.isEnableDLDO1() ? "ENABLE" : "DISABLE", targetVol );
if (targetVol != vol)Serial.println(">>> FAILED!");
vol += 100;
}
//DLDO2 IMAX=300mA
//500~1400mV, 50mV/step,2steps
vol = 500;
for (int i = 0; i < 29; ++i) {
power.setDLDO2Voltage(vol);
delay(1);
targetVol = power.getDLDO2Voltage();
Serial.printf("[%u]DLDO2 :%s Voltage:%u mV \n", i, power.isEnableDLDO2() ? "ENABLE" : "DISABLE", targetVol );
if (targetVol != vol)Serial.println(">>> FAILED!");
vol += 100;
}
/*
! WARN:
Please do not run the example without knowing the external load voltage of the PMU,
it may burn your external load, please check the voltage setting before running the example,
if there is any loss, please bear it by yourself
*/
// power.enableDC1();
// power.enableDC2();
// power.enableDC3();
// power.enableDC4();
// power.enableDC5();
// power.enableALDO1();
// power.enableALDO2();
// power.enableALDO3();
// power.enableALDO4();
// power.enableBLDO1();
// power.enableBLDO2();
// power.enableCPUSLDO();
// power.enableDLDO1();
// power.enableDLDO2();
}
void loop()
{
delay(10);
}

View File

@@ -0,0 +1,176 @@
/**
* @file BQ25896_Example.ino
* @author Lewis He (lewishe@outlook.com)
* @license MIT
* @copyright Copyright (c) 2024 Shenzhen Xin Yuan Electronic Technology Co., Ltd
* @date 2024-06-04
*
*/
#define XPOWERS_CHIP_BQ25896
#include <XPowersLib.h>
XPowersPPM PPM;
#ifndef CONFIG_PMU_SDA
#define CONFIG_PMU_SDA 0
#endif
#ifndef CONFIG_PMU_SCL
#define CONFIG_PMU_SCL 1
#endif
#ifndef CONFIG_PMU_IRQ
#define CONFIG_PMU_IRQ 28
#endif
const uint8_t i2c_sda = CONFIG_PMU_SDA;
const uint8_t i2c_scl = CONFIG_PMU_SCL;
const uint8_t pmu_irq_pin = CONFIG_PMU_IRQ;
uint32_t cycleInterval;
bool pmu_irq = false;
void setup()
{
Serial.begin(115200);
while (!Serial);
bool result = PPM.init(Wire, i2c_sda, i2c_scl, BQ25896_SLAVE_ADDRESS);
if (result == false) {
while (1) {
Serial.println("PPM is not online...");
delay(50);
}
}
// Set the minimum operating voltage. Below this voltage, the PPM will protect
PPM.setSysPowerDownVoltage(3300);
// Set input current limit, default is 500mA
PPM.setInputCurrentLimit(3250);
Serial.printf("getInputCurrentLimit: %d mA\n", PPM.getInputCurrentLimit());
// Disable current limit pin
PPM.disableCurrentLimitPin();
// Set the charging target voltage, Range:3840 ~ 4608mV ,step:16 mV
PPM.setChargeTargetVoltage(4208);
// Set the precharge current , Range: 64mA ~ 1024mA ,step:64mA
PPM.setPrechargeCurr(64);
// The premise is that Limit Pin is disabled, or it will only follow the maximum charging current set by Limi tPin.
// Set the charging current , Range:0~5056mA ,step:64mA
PPM.setChargerConstantCurr(1024);
// Get the set charging current
PPM.getChargerConstantCurr();
Serial.printf("getChargerConstantCurr: %d mA\n", PPM.getChargerConstantCurr());
// To obtain voltage data, the ADC must be enabled first
PPM.enableMeasure();
// Turn on charging function
// If there is no battery connected, do not turn on the charging function
PPM.enableCharge();
// Turn off charging function
// If USB is used as the only power input, it is best to turn off the charging function,
// otherwise the VSYS power supply will have a sawtooth wave, affecting the discharge output capability.
// PPM.disableCharge();
// The OTG function needs to enable OTG, and set the OTG control pin to HIGH
// After OTG is enabled, if an external power supply is plugged in, OTG will be turned off
// PPM.enableOTG();
// PPM.disableOTG();
// pinMode(OTG_ENABLE_PIN, OUTPUT);
// digitalWrite(OTG_ENABLE_PIN, HIGH);
pinMode(pmu_irq_pin, INPUT_PULLUP);
attachInterrupt(pmu_irq_pin, []() {
pmu_irq = true;
}, FALLING);
}
void loop()
{
if (pmu_irq) {
pmu_irq = false;
// Get PPM interrupt status
PPM.getFaultStatus();
Serial.print("-> [");
Serial.print(millis() / 1000);
Serial.print("] ");
if (PPM.isWatchdogFault()) {
Serial.println("Watchdog Fault");
} else if (PPM.isBoostFault()) {
Serial.println("Boost Fault");
} else if (PPM.isChargeFault()) {
Serial.println("Charge Fault");
} else if (PPM.isBatteryFault()) {
Serial.println("Batter Fault");
} else if (PPM.isNTCFault()) {
Serial.print("NTC Fault:");
Serial.print(PPM.getNTCStatusString());
Serial.print(" Percentage:");
Serial.print(PPM.getNTCPercentage()); Serial.println("%");
} else {
/*
* When the battery is removed, INT will send an interrupt every 100ms. If the battery is not connected,
* you can use PPM.disableCharge() to turn off the charging function.
* */
// PPM.disableCharge();
Serial.println("Battery remove");
}
}
/*
* Obtaining the battery voltage and battery charging status does not directly read the register,
* but determines whether the charging current register is normal.
* If read directly, the reading will be inaccurate.
* The premise for obtaining these two states is that the NTC temperature measurement circuit is normal.
* If the NTC detection is abnormal, it will return 0
* * */
if (millis() > cycleInterval) {
Serial.printf("CHG TARGET VOLTAGE :%04dmV CURRENT:%04dmA PER_CHARGE_CUR %04dmA\n",
PPM.getChargeTargetVoltage(), PPM.getChargerConstantCurr(), PPM.getPrechargeCurr());
Serial.printf("VBUS:%s %04dmV VBAT:%04dmV VSYS:%04dmV\n", PPM.isVbusIn() ? "Connected" : "Disconnect",
PPM.getVbusVoltage(),
PPM.getBattVoltage(),
PPM.getSystemVoltage());
Serial.printf("BUS STATE:%d STR:%s\n", PPM.getBusStatus(), PPM.getBusStatusString());
Serial.printf("CHG STATE:%d STR:%s CURRENT:%04dmA\n", PPM.chargeStatus(), PPM.getChargeStatusString(), PPM.getChargeCurrent());
Serial.printf("[%lu]", millis() / 1000);
Serial.println("----------------------------------------------------------------------------------");
cycleInterval = millis() + 1000;
}
}

View File

@@ -0,0 +1,71 @@
/**
* @file BQ25896_Shutdown_Example.ino
* @author Lewis He (lewishe@outlook.com)
* @license MIT
* @copyright Copyright (c) 2024 Shenzhen Xin Yuan Electronic Technology Co., Ltd
* @date 2024-06-04
*
*/
#define XPOWERS_CHIP_BQ25896
#include <XPowersLib.h>
XPowersPPM PPM;
#ifndef CONFIG_PMU_SDA
#define CONFIG_PMU_SDA 0
#endif
#ifndef CONFIG_PMU_SCL
#define CONFIG_PMU_SCL 1
#endif
#ifndef CONFIG_PMU_IRQ
#define CONFIG_PMU_IRQ 28
#endif
const uint8_t i2c_sda = CONFIG_PMU_SDA;
const uint8_t i2c_scl = CONFIG_PMU_SCL;
const uint8_t pmu_irq_pin = CONFIG_PMU_IRQ;
uint32_t cycleInterval;
uint32_t countdown = 10;
void setup()
{
Serial.begin(115200);
while (!Serial);
bool result = PPM.init(Wire, i2c_sda, i2c_scl, BQ25896_SLAVE_ADDRESS);
if (result == false) {
while (1) {
Serial.println("PPM is not online...");
delay(1000);
}
}
}
void loop()
{
if (millis() > cycleInterval) {
Serial.printf("%d\n", countdown);
if (!(countdown--)) {
Serial.println("Shutdown .....");
// The shutdown function can only be used when the battery is connected alone,
// and cannot be shut down when connected to USB.
// It can only be powered on in the following two ways:
// 1. Press the PPM/QON button
// 2. Connect to USB
PPM.shutdown();
countdown = 10000;
}
cycleInterval = millis() + 1000;
}
}

View File

@@ -0,0 +1,8 @@
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
set(EXTRA_COMPONENT_DIRS ../../../XPowersLib)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(XPowersLib_Example)

View File

@@ -0,0 +1,10 @@
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := XPowersLib_Example
EXTRA_COMPONENT_DIRS = ../../../XPowersLib
include $(IDF_PATH)/make/project.mk

View File

@@ -0,0 +1,73 @@
# XPowersLib Example
### Prerequisites
Please put XPowersLib and esp-idf in the same level directory, after configuring the esp-idf environment variable, enter `XPowersLib/examples/ESP_IDF_Example` and run the idf.py command directly
### Configure the Project
Open the project configuration menu (`idf.py menuconfig`).
In the `XPowers Configuration` menu:
* Select the PMU Type in the `PMU_Type` option.
* In `PMU SCL GPIO Num` select the clock pin to connect to the PMU,the default is 22
* In `PMU SDAGPIO Num` select the data pin connected to the PMU,the default is 21
* Select the interrupt pin connected to the PMU in `PMU Interrupt Pin`, the default is 35
## How to Use Example
Before project configuration and build, be sure to set the correct chip target using `idf.py set-target <chip_name>`.
### Build and Flash
Run `idf.py -p PORT flash monitor` to build, flash and monitor the project.
(To exit the serial monitor, type ``Ctrl-]``.)
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
## Example Output
The output information is to configure the output voltage and enable status of the PMU
```
I (345) mian: I2C initialized successfully
I (355) AXP2101: Init PMU SUCCESS!
I (385) AXP2101: DCDC=======================================================================
I (385) AXP2101: DC1 :ENABLE Voltage:3300 mV
I (385) AXP2101: DC2 :DISABLE Voltage:900 mV
I (395) AXP2101: DC3 :ENABLE Voltage:3300 mV
I (395) AXP2101: DC4 :DISABLE Voltage:1100 mV
I (405) AXP2101: DC5 :DISABLE Voltage:1200 mV
I (405) AXP2101: ALDO=======================================================================
I (415) AXP2101: ALDO1:ENABLE Voltage:1800 mV
I (425) AXP2101: ALDO2:ENABLE Voltage:2800 mV
I (425) AXP2101: ALDO3:ENABLE Voltage:3300 mV
I (435) AXP2101: ALDO4:ENABLE Voltage:3000 mV
I (435) AXP2101: BLDO=======================================================================
I (445) AXP2101: BLDO1:ENABLE Voltage:3300 mV
```
## Build process example
Assuming you don't have esp-idf yet
```
mkdir -p ~/esp
cd ~/esp
git clone --recursive https://github.com/espressif/esp-idf.git
git clone https://github.com/lewisxhe/XPowersLib.git
cd esp-idf
./install.sh
. ./export.sh
cd ..
cd XPowersLib/examples/ESP_IDF_Example
idf.py menuconfig
idf.py build
idf.py -b 921600 flash
idf.py monitor
```

View File

@@ -0,0 +1,5 @@
idf_component_register(SRCS "main.cpp"
"port_axp192.cpp"
"port_axp2101.cpp"
"port_i2c.cpp"
INCLUDE_DIRS ".")

View File

@@ -0,0 +1,59 @@
menu "XPowersLib Configuration"
choice PMU_Type
prompt "XPowers chip type"
default XPOWERS_CHIP_AXP2101 if IDF_TARGET_ESP32
default XPOWERS_CHIP_AXP192
help
Defines the default peripheral for xpowers example
config XPOWERS_CHIP_AXP2101
bool "Xpowers AXP2101"
config XPOWERS_CHIP_AXP192
bool "Xpowers AXP192"
endchoice
choice I2C_COMMUNICATION_METHOD
prompt "XPowersLIb read and write methods"
default I2C_COMMUNICATION_METHOD_BUILTIN_RW
help
Define XPowersLIb read and write methods
config I2C_COMMUNICATION_METHOD_BUILTIN_RW
bool "Implemented using built-in read and write methods"
config I2C_COMMUNICATION_METHOD_CALLBACK_RW
bool "Implemented using read and write callback methods"
endchoice
config I2C_MASTER_PORT_NUM
int "PMU I2C Port Number"
default 1
help
Port number for I2C Master device.
config I2C_MASTER_FREQUENCY
int "Master Frequency"
default 100000
help
I2C Speed of Master device.
config PMU_I2C_SCL
int "PMU SCL GPIO Num"
default 22
help
GPIO number for I2C PMU clock line.
config PMU_I2C_SDA
int "PMU SDA GPIO Num"
default 21
help
GPIO number for I2C PMU data line.
config PMU_INTERRUPT_PIN
int "PMU Interrupt Pin"
default 35
help
PMU interrupt pin.
endmenu

View File

@@ -0,0 +1,4 @@
#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

View File

@@ -0,0 +1,90 @@
#include <stdio.h>
#include <cstring>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "sdkconfig.h"
#include "freertos/queue.h"
#define PMU_INPUT_PIN (gpio_num_t)CONFIG_PMU_INTERRUPT_PIN /*!< axp power chip interrupt Pin*/
#define PMU_INPUT_PIN_SEL (1ULL<<PMU_INPUT_PIN)
/*
! WARN:
Please do not run the example without knowing the external load voltage of the PMU,
it may burn your external load, please check the voltage setting before running the example,
if there is any loss, please bear it by yourself
*/
#ifndef XPOWERS_NO_ERROR
#error "Running this example is known to not damage the device! Please go and uncomment this!"
#endif
static const char *TAG = "mian";
extern esp_err_t pmu_init();
extern esp_err_t i2c_init(void);
extern void pmu_isr_handler();
static void pmu_handler_task(void *);
static QueueHandle_t gpio_evt_queue = NULL;
static void IRAM_ATTR pmu_irq_handler(void *arg)
{
uint32_t gpio_num = (uint32_t) arg;
xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}
static void irq_init()
{
gpio_config_t io_conf;
io_conf.intr_type = GPIO_INTR_NEGEDGE;
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pin_bit_mask = PMU_INPUT_PIN_SEL;
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
gpio_config(&io_conf);
gpio_set_intr_type(PMU_INPUT_PIN, GPIO_INTR_NEGEDGE);
//install gpio isr service
gpio_install_isr_service(0);
//hook isr handler for specific gpio pin
gpio_isr_handler_add(PMU_INPUT_PIN, pmu_irq_handler, (void *) PMU_INPUT_PIN);
}
extern "C" void app_main(void)
{
//create a queue to handle gpio event from isr
gpio_evt_queue = xQueueCreate(5, sizeof(uint32_t));
// Register PMU interrupt pins
irq_init();
#if CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW || \
((ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_XPOWERS_ESP_IDF_NEW_API))
ESP_ERROR_CHECK(i2c_init());
ESP_LOGI(TAG, "I2C initialized successfully");
#endif
ESP_ERROR_CHECK(pmu_init());
xTaskCreate(pmu_handler_task, "App/pwr", 4 * 1024, NULL, 10, NULL);
ESP_LOGI(TAG, "Run...");
}
static void pmu_handler_task(void *args)
{
uint32_t io_num;
while (1) {
if (xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
pmu_isr_handler();
}
}
}

View File

@@ -0,0 +1,325 @@
#include <stdio.h>
#include <cstring>
#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_err.h"
#ifdef CONFIG_XPOWERS_CHIP_AXP192
#define XPOWERS_CHIP_AXP192
#include "XPowersLib.h"
static const char *TAG = "AXP192";
XPowersPMU power;
extern int pmu_register_read(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len);
extern int pmu_register_write_byte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len);
esp_err_t pmu_init()
{
//* Implemented using read and write callback methods, applicable to other platforms
#if CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
ESP_LOGI(TAG, "Implemented using read and write callback methods");
if (power.begin(AXP192_SLAVE_ADDRESS, pmu_register_read, pmu_register_write_byte)) {
ESP_LOGI(TAG, "Init PMU SUCCESS!");
} else {
ESP_LOGE(TAG, "Init PMU FAILED!");
return ESP_FAIL;
}
#endif
//* Use the built-in esp-idf communication method
#if CONFIG_I2C_COMMUNICATION_METHOD_BUILTIN_RW
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_XPOWERS_ESP_IDF_NEW_API)
ESP_LOGI(TAG, "Implemented using built-in read and write methods (Use higher version >= 5.0 API)");
// * Using the new API of esp-idf 5.x, you need to pass the I2C BUS handle,
// * which is useful when the bus shares multiple devices.
extern i2c_master_bus_handle_t bus_handle;
if (power.begin(bus_handle, AXP192_SLAVE_ADDRESS)) {
ESP_LOGI(TAG, "Init PMU SUCCESS!");
} else {
ESP_LOGE(TAG, "Init PMU FAILED!");
return false;
}
#else
ESP_LOGI(TAG, "Implemented using built-in read and write methods (Use lower version < 5.0 API)");
if (power.begin((i2c_port_t)CONFIG_I2C_MASTER_PORT_NUM, AXP192_SLAVE_ADDRESS, CONFIG_PMU_I2C_SDA, CONFIG_PMU_I2C_SCL)) {
ESP_LOGI(TAG, "Init PMU SUCCESS!");
} else {
ESP_LOGE(TAG, "Init PMU FAILED!");
return false;
}
#endif //ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)
#endif //CONFIG_I2C_COMMUNICATION_METHOD_BUILTIN_RW
ESP_LOGI(TAG, "getID:0x%x", power.getChipID());
// Set the minimum system operating voltage inside the PMU,
// below this value will shut down the PMU
// Range: 2600~3300mV
power.setSysPowerDownVoltage(2700);
// Set the minimum common working voltage of the PMU VBUS input,
// below this value will turn off the PMU
power.setVbusVoltageLimit(XPOWERS_AXP192_VBUS_VOL_LIM_4V5);
// Turn off USB input current limit
power.setVbusCurrentLimit(XPOWERS_AXP192_VBUS_CUR_LIM_OFF);
// DC1 700~3500mV, IMAX=1.2A
power.setDC1Voltage(3300);
ESP_LOGI(TAG, "DC1 :%s Voltage:%u mV ", power.isEnableDC1() ? "ENABLE" : "DISABLE", power.getDC1Voltage());
// DC2 700~2750mV, IMAX=1.6A;
power.setDC2Voltage(700);
ESP_LOGI(TAG, "DC2 :%s Voltage:%u mV ", power.isEnableDC2() ? "ENABLE" : "DISABLE", power.getDC2Voltage());
// DC3 700~3500mV,IMAX=0.7A;
power.setDC3Voltage(3300);
ESP_LOGI(TAG, "DC3 :%s Voltage:%u mV ", power.isEnableDC3() ? "ENABLE" : "DISABLE", power.getDC3Voltage());
//LDO2 1800~3300V, 100mV/step, IMAX=200mA
power.setLDO2Voltage(1800);
//LDO3 1800~3300V, 100mV/step, IMAX=200mA
power.setLDO3Voltage(1800);
//LDOio 1800~3300V, 100mV/step, IMAX=50mA
power.setLDOioVoltage(3300);
// Enable power output channel
// power.enableDC1();
power.enableDC2();
power.enableDC3();
power.enableLDO2();
power.enableLDO3();
power.enableLDOio();
ESP_LOGI(TAG, "DCDC=======================================================================\n");
ESP_LOGI(TAG, "DC1 :%s Voltage:%u mV \n", power.isEnableDC1() ? "ENABLE" : "DISABLE", power.getDC1Voltage());
ESP_LOGI(TAG, "DC2 :%s Voltage:%u mV \n", power.isEnableDC2() ? "ENABLE" : "DISABLE", power.getDC2Voltage());
ESP_LOGI(TAG, "DC3 :%s Voltage:%u mV \n", power.isEnableDC3() ? "ENABLE" : "DISABLE", power.getDC3Voltage());
ESP_LOGI(TAG, "LDO=======================================================================\n");
ESP_LOGI(TAG, "LDO2: %s Voltage:%u mV\n", power.isEnableLDO2() ? "ENABLE" : "DISABLE", power.getLDO2Voltage());
ESP_LOGI(TAG, "LDO3: %s Voltage:%u mV\n", power.isEnableLDO3() ? "ENABLE" : "DISABLE", power.getLDO3Voltage());
ESP_LOGI(TAG, "LDOio: %s Voltage:%u mV\n", power.isEnableLDOio() ? "ENABLE" : "DISABLE", power.getLDOioVoltage());
ESP_LOGI(TAG, "==========================================================================\n");
// Set the time of pressing the button to turn off
power.setPowerKeyPressOffTime(XPOWERS_POWEROFF_4S);
uint8_t opt = power.getPowerKeyPressOffTime();
ESP_LOGI(TAG, "PowerKeyPressOffTime:");
switch (opt) {
case XPOWERS_POWEROFF_4S: ESP_LOGI(TAG, "4 Second");
break;
case XPOWERS_POWEROFF_6S: ESP_LOGI(TAG, "6 Second");
break;
case XPOWERS_POWEROFF_8S: ESP_LOGI(TAG, "8 Second");
break;
case XPOWERS_POWEROFF_10S: ESP_LOGI(TAG, "10 Second");
break;
default:
break;
}
// Set the button power-on press time
power.setPowerKeyPressOnTime(XPOWERS_POWERON_128MS);
opt = power.getPowerKeyPressOnTime();
ESP_LOGI(TAG, "PowerKeyPressOnTime:");
switch (opt) {
case XPOWERS_POWERON_128MS: ESP_LOGI(TAG, "128 Ms");
break;
case XPOWERS_POWERON_512MS: ESP_LOGI(TAG, "512 Ms");
break;
case XPOWERS_POWERON_1S: ESP_LOGI(TAG, "1 Second");
break;
case XPOWERS_POWERON_2S: ESP_LOGI(TAG, "2 Second");
break;
default:
break;
}
ESP_LOGI(TAG, "===========================================================================");
// It is necessary to disable the detection function of the TS pin on the board
// without the battery temperature detection function, otherwise it will cause abnormal charging
power.disableTSPinMeasure();
// power.enableTemperatureMeasure();
// power.disableTemperatureMeasure();
// Enable internal ADC detection
power.enableBattDetection();
power.enableVbusVoltageMeasure();
power.enableBattVoltageMeasure();
power.enableSystemVoltageMeasure();
/*
The default setting is CHGLED is automatically controlled by the PMU.
- XPOWERS_CHG_LED_OFF,
- XPOWERS_CHG_LED_BLINK_1HZ,
- XPOWERS_CHG_LED_BLINK_4HZ,
- XPOWERS_CHG_LED_ON,
- XPOWERS_CHG_LED_CTRL_CHG,
* */
power.setChargingLedMode(XPOWERS_CHG_LED_OFF);
// Disable all interrupts
power.disableIRQ(XPOWERS_AXP192_ALL_IRQ);
// Clear all interrupt flags
power.clearIrqStatus();
// Enable the required interrupt function
power.enableIRQ(
XPOWERS_AXP192_BAT_INSERT_IRQ | XPOWERS_AXP192_BAT_REMOVE_IRQ | //BATTERY
XPOWERS_AXP192_VBUS_INSERT_IRQ | XPOWERS_AXP192_VBUS_REMOVE_IRQ | //VBUS
XPOWERS_AXP192_PKEY_SHORT_IRQ | XPOWERS_AXP192_PKEY_LONG_IRQ | //POWER KEY
XPOWERS_AXP192_BAT_CHG_DONE_IRQ | XPOWERS_AXP192_BAT_CHG_START_IRQ | //CHARGE
// XPOWERS_AXP192_PKEY_NEGATIVE_IRQ | XPOWERS_AXP192_PKEY_POSITIVE_IRQ | //POWER KEY
XPOWERS_AXP192_TIMER_TIMEOUT_IRQ //Timer
);
// Set constant current charge current limit
power.setChargerConstantCurr(XPOWERS_AXP192_CHG_CUR_280MA);
// Set stop charging termination current
power.setChargerTerminationCurr(XPOWERS_AXP192_CHG_ITERM_LESS_10_PERCENT);
// Set charge cut-off voltage
power.setChargeTargetVoltage(XPOWERS_AXP192_CHG_VOL_4V2);
// Cache writes and reads, as long as the PMU remains powered, the data will always be stored inside the PMU
ESP_LOGI(TAG, "Write pmu data buffer .");
uint8_t data[XPOWERS_AXP192_DATA_BUFFER_SIZE] = {1, 2, 3, 4, 5, 6};
power.writeDataBuffer(data, XPOWERS_AXP192_DATA_BUFFER_SIZE);
memset(data, 0, XPOWERS_AXP192_DATA_BUFFER_SIZE);
ESP_LOGI(TAG, "Read pmu data buffer :");
power.readDataBuffer(data, XPOWERS_AXP192_DATA_BUFFER_SIZE);
ESP_LOG_BUFFER_HEX(TAG, data, XPOWERS_AXP192_DATA_BUFFER_SIZE);
// Set the timing after one minute, the isWdtExpireIrq will be triggered in the loop interrupt function
power.setTimerout(1);
return ESP_OK;
}
void pmu_isr_handler()
{
// Get PMU Interrupt Status Register
power.getIrqStatus();
if (power.isAcinOverVoltageIrq()) {
ESP_LOGI(TAG, "isAcinOverVoltageIrq");
}
if (power.isAcinInserIrq()) {
ESP_LOGI(TAG, "isAcinInserIrq");
}
if (power.isAcinRemoveIrq()) {
ESP_LOGI(TAG, "isAcinRemoveIrq");
}
if (power.isVbusOverVoltageIrq()) {
ESP_LOGI(TAG, "isVbusOverVoltageIrq");
}
if (power.isVbusInsertIrq()) {
ESP_LOGI(TAG, "isVbusInsertIrq");
}
if (power.isVbusRemoveIrq()) {
ESP_LOGI(TAG, "isVbusRemoveIrq");
}
if (power.isVbusLowVholdIrq()) {
ESP_LOGI(TAG, "isVbusLowVholdIrq");
}
if (power.isBatInsertIrq()) {
ESP_LOGI(TAG, "isBatInsertIrq");
}
if (power.isBatRemoveIrq()) {
ESP_LOGI(TAG, "isBatRemoveIrq");
}
if (power.isBattEnterActivateIrq()) {
ESP_LOGI(TAG, "isBattEnterActivateIrq");
}
if (power.isBattExitActivateIrq()) {
ESP_LOGI(TAG, "isBattExitActivateIrq");
}
if (power.isBatChargeStartIrq()) {
ESP_LOGI(TAG, "isBatChargeStartIrq");
}
if (power.isBatChargeDoneIrq()) {
ESP_LOGI(TAG, "isBatChargeDoneIrq");
}
if (power.isBattTempHighIrq()) {
ESP_LOGI(TAG, "isBattTempHighIrq");
}
if (power.isBattTempLowIrq()) {
ESP_LOGI(TAG, "isBattTempLowIrq");
}
if (power.isChipOverTemperatureIrq()) {
ESP_LOGI(TAG, "isChipOverTemperatureIrq");
}
if (power.isChargingCurrentLessIrq()) {
ESP_LOGI(TAG, "isChargingCurrentLessIrq");
}
if (power.isDC1VoltageLessIrq()) {
ESP_LOGI(TAG, "isDC1VoltageLessIrq");
}
if (power.isDC2VoltageLessIrq()) {
ESP_LOGI(TAG, "isDC2VoltageLessIrq");
}
if (power.isDC3VoltageLessIrq()) {
ESP_LOGI(TAG, "isDC3VoltageLessIrq");
}
if (power.isPekeyShortPressIrq()) {
ESP_LOGI(TAG, "isPekeyShortPress");
// enterPmuSleep();
}
if (power.isPekeyLongPressIrq()) {
ESP_LOGI(TAG, "isPekeyLongPress");
}
if (power.isNOEPowerOnIrq()) {
ESP_LOGI(TAG, "isNOEPowerOnIrq");
}
if (power.isNOEPowerDownIrq()) {
ESP_LOGI(TAG, "isNOEPowerDownIrq");
}
if (power.isVbusEffectiveIrq()) {
ESP_LOGI(TAG, "isVbusEffectiveIrq");
}
if (power.isVbusInvalidIrq()) {
ESP_LOGI(TAG, "isVbusInvalidIrq");
}
if (power.isVbusSessionIrq()) {
ESP_LOGI(TAG, "isVbusSessionIrq");
}
if (power.isVbusSessionEndIrq()) {
ESP_LOGI(TAG, "isVbusSessionEndIrq");
}
if (power.isLowVoltageLevel2Irq()) {
ESP_LOGI(TAG, "isLowVoltageLevel2Irq");
}
if (power.isWdtExpireIrq()) {
ESP_LOGI(TAG, "isWdtExpire");
// Clear the timer state and continue to the next timer
power.clearTimerFlag();
}
if (power.isGpio2EdgeTriggerIrq()) {
ESP_LOGI(TAG, "isGpio2EdgeTriggerIrq");
}
if (power.isGpio1EdgeTriggerIrq()) {
ESP_LOGI(TAG, "isGpio1EdgeTriggerIrq");
}
if (power.isGpio0EdgeTriggerIrq()) {
ESP_LOGI(TAG, "isGpio0EdgeTriggerIrq");
}
// Clear PMU Interrupt Status Register
power.clearIrqStatus();
}
#endif /*CONFIG_XPOWERS_AXP192_CHIP_AXP192*/

View File

@@ -0,0 +1,263 @@
#include <stdio.h>
#include <cstring>
#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_err.h"
#ifdef CONFIG_XPOWERS_CHIP_AXP2101
#define XPOWERS_CHIP_AXP2101
#include "XPowersLib.h"
static const char *TAG = "AXP2101";
static XPowersPMU power;
extern int pmu_register_read(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len);
extern int pmu_register_write_byte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len);
esp_err_t pmu_init()
{
//* Implemented using read and write callback methods, applicable to other platforms
#if CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
ESP_LOGI(TAG, "Implemented using read and write callback methods");
if (power.begin(AXP2101_SLAVE_ADDRESS, pmu_register_read, pmu_register_write_byte)) {
ESP_LOGI(TAG, "Init PMU SUCCESS!");
} else {
ESP_LOGE(TAG, "Init PMU FAILED!");
return ESP_FAIL;
}
#endif
//* Use the built-in esp-idf communication method
#if CONFIG_I2C_COMMUNICATION_METHOD_BUILTIN_RW
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_XPOWERS_ESP_IDF_NEW_API)
ESP_LOGI(TAG, "Implemented using built-in read and write methods (Use higher version >= 5.0 API)");
// * Using the new API of esp-idf 5.x, you need to pass the I2C BUS handle,
// * which is useful when the bus shares multiple devices.
extern i2c_master_bus_handle_t bus_handle;
if (power.begin(bus_handle, AXP2101_SLAVE_ADDRESS)) {
ESP_LOGI(TAG, "Init PMU SUCCESS!");
} else {
ESP_LOGE(TAG, "Init PMU FAILED!");
return false;
}
#else
ESP_LOGI(TAG, "Implemented using built-in read and write methods (Use lower version < 5.0 API)");
if (power.begin((i2c_port_t)CONFIG_I2C_MASTER_PORT_NUM, AXP2101_SLAVE_ADDRESS, CONFIG_PMU_I2C_SDA, CONFIG_PMU_I2C_SCL)) {
ESP_LOGI(TAG, "Init PMU SUCCESS!");
} else {
ESP_LOGE(TAG, "Init PMU FAILED!");
return false;
}
#endif //ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)
#endif //CONFIG_I2C_COMMUNICATION_METHOD_BUILTIN_RW
//Turn off not use power channel
power.disableDC2();
power.disableDC3();
power.disableDC4();
power.disableDC5();
power.disableALDO1();
power.disableALDO2();
power.disableALDO3();
power.disableALDO4();
power.disableBLDO1();
power.disableBLDO2();
power.disableCPUSLDO();
power.disableDLDO1();
power.disableDLDO2();
//ESP32s3 Core VDD
power.setDC3Voltage(3300);
power.enableDC3();
//Extern 3.3V VDD
power.setDC1Voltage(3300);
power.enableDC1();
// CAM DVDD 1500~1800
power.setALDO1Voltage(1800);
// power.setALDO1Voltage(1500);
power.enableALDO1();
// CAM DVDD 2500~2800
power.setALDO2Voltage(2800);
power.enableALDO2();
// CAM AVDD 2800~3000
power.setALDO4Voltage(3000);
power.enableALDO4();
// PIR VDD 3300
power.setALDO3Voltage(3300);
power.enableALDO3();
// OLED VDD 3300
power.setBLDO1Voltage(3300);
power.enableBLDO1();
// MIC VDD 33000
power.setBLDO2Voltage(3300);
power.enableBLDO2();
ESP_LOGI(TAG, "DCDC=======================================================================\n");
ESP_LOGI(TAG, "DC1 : %s Voltage:%u mV \n", power.isEnableDC1() ? "+" : "-", power.getDC1Voltage());
ESP_LOGI(TAG, "DC2 : %s Voltage:%u mV \n", power.isEnableDC2() ? "+" : "-", power.getDC2Voltage());
ESP_LOGI(TAG, "DC3 : %s Voltage:%u mV \n", power.isEnableDC3() ? "+" : "-", power.getDC3Voltage());
ESP_LOGI(TAG, "DC4 : %s Voltage:%u mV \n", power.isEnableDC4() ? "+" : "-", power.getDC4Voltage());
ESP_LOGI(TAG, "DC5 : %s Voltage:%u mV \n", power.isEnableDC5() ? "+" : "-", power.getDC5Voltage());
ESP_LOGI(TAG, "ALDO=======================================================================\n");
ESP_LOGI(TAG, "ALDO1: %s Voltage:%u mV\n", power.isEnableALDO1() ? "+" : "-", power.getALDO1Voltage());
ESP_LOGI(TAG, "ALDO2: %s Voltage:%u mV\n", power.isEnableALDO2() ? "+" : "-", power.getALDO2Voltage());
ESP_LOGI(TAG, "ALDO3: %s Voltage:%u mV\n", power.isEnableALDO3() ? "+" : "-", power.getALDO3Voltage());
ESP_LOGI(TAG, "ALDO4: %s Voltage:%u mV\n", power.isEnableALDO4() ? "+" : "-", power.getALDO4Voltage());
ESP_LOGI(TAG, "BLDO=======================================================================\n");
ESP_LOGI(TAG, "BLDO1: %s Voltage:%u mV\n", power.isEnableBLDO1() ? "+" : "-", power.getBLDO1Voltage());
ESP_LOGI(TAG, "BLDO2: %s Voltage:%u mV\n", power.isEnableBLDO2() ? "+" : "-", power.getBLDO2Voltage());
ESP_LOGI(TAG, "CPUSLDO====================================================================\n");
ESP_LOGI(TAG, "CPUSLDO: %s Voltage:%u mV\n", power.isEnableCPUSLDO() ? "+" : "-", power.getCPUSLDOVoltage());
ESP_LOGI(TAG, "DLDO=======================================================================\n");
ESP_LOGI(TAG, "DLDO1: %s Voltage:%u mV\n", power.isEnableDLDO1() ? "+" : "-", power.getDLDO1Voltage());
ESP_LOGI(TAG, "DLDO2: %s Voltage:%u mV\n", power.isEnableDLDO2() ? "+" : "-", power.getDLDO2Voltage());
ESP_LOGI(TAG, "===========================================================================\n");
power.clearIrqStatus();
power.enableVbusVoltageMeasure();
power.enableBattVoltageMeasure();
power.enableSystemVoltageMeasure();
power.enableTemperatureMeasure();
// It is necessary to disable the detection function of the TS pin on the board
// without the battery temperature detection function, otherwise it will cause abnormal charging
power.disableTSPinMeasure();
// Disable all interrupts
power.disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
// Clear all interrupt flags
power.clearIrqStatus();
// Enable the required interrupt function
power.enableIRQ(
XPOWERS_AXP2101_BAT_INSERT_IRQ | XPOWERS_AXP2101_BAT_REMOVE_IRQ | //BATTERY
XPOWERS_AXP2101_VBUS_INSERT_IRQ | XPOWERS_AXP2101_VBUS_REMOVE_IRQ | //VBUS
XPOWERS_AXP2101_PKEY_SHORT_IRQ | XPOWERS_AXP2101_PKEY_LONG_IRQ | //POWER KEY
XPOWERS_AXP2101_BAT_CHG_DONE_IRQ | XPOWERS_AXP2101_BAT_CHG_START_IRQ //CHARGE
// XPOWERS_AXP2101_PKEY_NEGATIVE_IRQ | XPOWERS_AXP2101_PKEY_POSITIVE_IRQ | //POWER KEY
);
/*
The default setting is CHGLED is automatically controlled by the power.
- XPOWERS_CHG_LED_OFF,
- XPOWERS_CHG_LED_BLINK_1HZ,
- XPOWERS_CHG_LED_BLINK_4HZ,
- XPOWERS_CHG_LED_ON,
- XPOWERS_CHG_LED_CTRL_CHG,
* */
power.setChargingLedMode(XPOWERS_CHG_LED_BLINK_1HZ);
// Set the precharge charging current
power.setPrechargeCurr(XPOWERS_AXP2101_PRECHARGE_50MA);
// Set constant current charge current limit
power.setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_200MA);
// Set stop charging termination current
power.setChargerTerminationCurr(XPOWERS_AXP2101_CHG_ITERM_25MA);
// Set charge cut-off voltage
power.setChargeTargetVoltage(XPOWERS_AXP2101_CHG_VOL_4V1);
// Set the watchdog trigger event type
// power.setWatchdogConfig(XPOWERS_AXP2101_WDT_IRQ_TO_PIN);
// Set watchdog timeout
power.setWatchdogTimeout(XPOWERS_AXP2101_WDT_TIMEOUT_4S);
// Enable watchdog to trigger interrupt event
power.enableWatchdog();
return ESP_OK;
}
void pmu_isr_handler()
{
// Get PMU Interrupt Status Register
power.getIrqStatus();
if (power.isDropWarningLevel2Irq()) {
ESP_LOGI(TAG, "isDropWarningLevel2");
}
if (power.isDropWarningLevel1Irq()) {
ESP_LOGI(TAG, "isDropWarningLevel1");
}
if (power.isGaugeWdtTimeoutIrq()) {
ESP_LOGI(TAG, "isWdtTimeout");
}
if (power.isBatChargerOverTemperatureIrq()) {
ESP_LOGI(TAG, "isBatChargeOverTemperature");
}
if (power.isBatWorkOverTemperatureIrq()) {
ESP_LOGI(TAG, "isBatWorkOverTemperature");
}
if (power.isBatWorkUnderTemperatureIrq()) {
ESP_LOGI(TAG, "isBatWorkUnderTemperature");
}
if (power.isVbusInsertIrq()) {
ESP_LOGI(TAG, "isVbusInsert");
}
if (power.isVbusRemoveIrq()) {
ESP_LOGI(TAG, "isVbusRemove");
}
if (power.isBatInsertIrq()) {
ESP_LOGI(TAG, "isBatInsert");
}
if (power.isBatRemoveIrq()) {
ESP_LOGI(TAG, "isBatRemove");
}
if (power.isPekeyShortPressIrq()) {
ESP_LOGI(TAG, "isPekeyShortPress");
}
if (power.isPekeyLongPressIrq()) {
ESP_LOGI(TAG, "isPekeyLongPress");
}
if (power.isPekeyNegativeIrq()) {
ESP_LOGI(TAG, "isPekeyNegative");
}
if (power.isPekeyPositiveIrq()) {
ESP_LOGI(TAG, "isPekeyPositive");
}
if (power.isWdtExpireIrq()) {
ESP_LOGI(TAG, "isWdtExpire");
}
if (power.isLdoOverCurrentIrq()) {
ESP_LOGI(TAG, "isLdoOverCurrentIrq");
}
if (power.isBatfetOverCurrentIrq()) {
ESP_LOGI(TAG, "isBatfetOverCurrentIrq");
}
if (power.isBatChargeDoneIrq()) {
ESP_LOGI(TAG, "isBatChargeDone");
}
if (power.isBatChargeStartIrq()) {
ESP_LOGI(TAG, "isBatChargeStart");
}
if (power.isBatDieOverTemperatureIrq()) {
ESP_LOGI(TAG, "isBatDieOverTemperature");
}
if (power.isChargeOverTimeoutIrq()) {
ESP_LOGI(TAG, "isChargeOverTimeout");
}
if (power.isBatOverVoltageIrq()) {
ESP_LOGI(TAG, "isBatOverVoltage");
}
// Clear PMU Interrupt Status Register
power.clearIrqStatus();
}
#endif /*CONFIG_XPOWERS_AXP2101_CHIP_AXP2102*/

View File

@@ -0,0 +1,209 @@
#include <stdio.h>
#include <cstring>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "sdkconfig.h"
#include "esp_idf_version.h"
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_XPOWERS_ESP_IDF_NEW_API)
#include "driver/i2c_master.h"
#else
#include "driver/i2c.h"
#endif
static const char *TAG = "XPowersLib";
#define I2C_MASTER_NUM (i2c_port_t)CONFIG_I2C_MASTER_PORT_NUM
#define I2C_MASTER_SDA_IO (gpio_num_t)CONFIG_PMU_I2C_SDA
#define I2C_MASTER_SCL_IO (gpio_num_t)CONFIG_PMU_I2C_SCL
#define I2C_MASTER_FREQ_HZ CONFIG_I2C_MASTER_FREQUENCY /*!< I2C master clock frequency */
#if CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_TIMEOUT_MS 1000
#define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */
#define READ_BIT I2C_MASTER_READ /*!< I2C master read */
#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
#define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */
#define ACK_VAL (i2c_ack_type_t)0x0 /*!< I2C ack value */
#define NACK_VAL (i2c_ack_type_t)0x1 /*!< I2C nack value */
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_XPOWERS_ESP_IDF_NEW_API)
// The new API passes the device address before initialization,
// AXP2102, 1XP192 belong to the same address
#define PMU_SLAVE_ADDRESS 0X34
i2c_master_dev_handle_t i2c_device;
#endif
/**
* @brief Read a sequence of bytes from a pmu registers
*/
int pmu_register_read(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len)
{
esp_err_t ret;
if (len == 0) {
return ESP_OK;
}
if (data == NULL) {
return ESP_FAIL;
}
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_XPOWERS_ESP_IDF_NEW_API)
ret = i2c_master_transmit_receive(
i2c_device,
(const uint8_t *)&regAddr,
1,
data,
len,
-1);
#else
i2c_cmd_handle_t cmd;
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (devAddr << 1) | WRITE_BIT, ACK_CHECK_EN);
i2c_master_write_byte(cmd, regAddr, ACK_CHECK_EN);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdTICKS_TO_MS(1000));
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "PMU i2c_master_cmd_begin FAILED! > ");
return ESP_FAIL;
}
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (devAddr << 1) | READ_BIT, ACK_CHECK_EN);
if (len > 1) {
i2c_master_read(cmd, data, len - 1, ACK_VAL);
}
i2c_master_read_byte(cmd, &data[len - 1], NACK_VAL);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdTICKS_TO_MS(1000));
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "PMU READ FAILED! > ");
}
#endif
return ret == ESP_OK ? 0 : -1;
}
/**
* @brief Write a byte to a pmu register
*/
int pmu_register_write_byte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len)
{
esp_err_t ret;
if (data == NULL) {
return ESP_FAIL;
}
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_XPOWERS_ESP_IDF_NEW_API)
uint8_t *write_buffer = (uint8_t *)malloc(sizeof(uint8_t) * (len + 1));
if (!write_buffer) {
return -1;
}
write_buffer[0] = regAddr;
memcpy(write_buffer + 1, data, len);
ret = i2c_master_transmit(
i2c_device,
write_buffer,
len + 1,
-1);
free(write_buffer);
#else
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (devAddr << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
i2c_master_write_byte(cmd, regAddr, ACK_CHECK_EN);
i2c_master_write(cmd, data, len, ACK_CHECK_EN);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdTICKS_TO_MS(1000));
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "PMU WRITE FAILED! < ");
}
#endif
return ret == ESP_OK ? 0 : -1;
}
/**
* @brief i2c master initialization
*/
esp_err_t i2c_init(void)
{
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_XPOWERS_ESP_IDF_NEW_API)
ESP_LOGI(TAG, "Implemented using read and write callback methods (Use higher version >= 5.0 API)");
i2c_master_bus_handle_t bus_handle;
i2c_master_bus_config_t i2c_bus_config;
memset(&i2c_bus_config, 0, sizeof(i2c_bus_config));
i2c_bus_config.clk_source = I2C_CLK_SRC_DEFAULT;
i2c_bus_config.i2c_port = I2C_MASTER_NUM;
i2c_bus_config.scl_io_num = (gpio_num_t)I2C_MASTER_SCL_IO;
i2c_bus_config.sda_io_num = (gpio_num_t)I2C_MASTER_SDA_IO;
i2c_bus_config.glitch_ignore_cnt = 7;
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &bus_handle));
i2c_device_config_t i2c_dev_conf = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = PMU_SLAVE_ADDRESS,
.scl_speed_hz = I2C_MASTER_FREQ_HZ,
};
return i2c_master_bus_add_device(bus_handle, &i2c_dev_conf, &i2c_device);
#else
ESP_LOGI(TAG, "Implemented using read and write callback methods (Use lower version < 5.0 API)");
i2c_config_t i2c_conf ;
memset(&i2c_conf, 0, sizeof(i2c_conf));
i2c_conf.mode = I2C_MODE_MASTER;
i2c_conf.sda_io_num = I2C_MASTER_SDA_IO;
i2c_conf.scl_io_num = I2C_MASTER_SCL_IO;
i2c_conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
i2c_conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
i2c_conf.master.clk_speed = I2C_MASTER_FREQ_HZ;
i2c_param_config(I2C_MASTER_NUM, &i2c_conf);
return i2c_driver_install(I2C_MASTER_NUM, i2c_conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
#endif
}
#else
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)) && defined(CONFIG_XPOWERS_ESP_IDF_NEW_API)
#include "soc/clk_tree_defs.h"
i2c_master_bus_handle_t bus_handle;
// * Using the new API of esp-idf 5.x, you need to pass the I2C BUS handle,
// * which is useful when the bus shares multiple devices.
esp_err_t i2c_init(void)
{
i2c_master_bus_config_t i2c_bus_config;
memset(&i2c_bus_config, 0, sizeof(i2c_bus_config));
i2c_bus_config.clk_source = I2C_CLK_SRC_DEFAULT;
i2c_bus_config.i2c_port = I2C_MASTER_NUM;
i2c_bus_config.scl_io_num = I2C_MASTER_SCL_IO;
i2c_bus_config.sda_io_num = I2C_MASTER_SDA_IO;
i2c_bus_config.glitch_ignore_cnt = 7;
return i2c_new_master_bus(&i2c_bus_config, &bus_handle);
}
#endif //ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)
#endif //CONFIG_I2C_COMMUNICATION_METHOD_CALLBACK_RW

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
#

View File

@@ -0,0 +1,259 @@
/**
* @file FastCharging_BleUartDebug.ino
* @author Lewis He (lewishe@outlook.com)
* @license MIT
* @copyright Copyright (c) 2024 Shenzhen Xin Yuan Electronic Technology Co., Ltd
* @date 2024-07-30
*
*/
// Use SY6970
// #define XPOWERS_CHIP_SY6970
// Use BQ25896
#define XPOWERS_CHIP_BQ25896
#include <XPowersLib.h>
#ifdef ARDUINO_ARCH_NRF52
#include <bluefruit.h>
#include <Adafruit_LittleFS.h>
PowerDeliveryHUSB238 pd;
XPowersPPM ppm;
#ifndef CONFIG_PMU_SDA
#define CONFIG_PMU_SDA 0
#endif
#ifndef CONFIG_PMU_SCL
#define CONFIG_PMU_SCL 1
#endif
const uint8_t i2c_sda = CONFIG_PMU_SDA;
const uint8_t i2c_scl = CONFIG_PMU_SCL;
BLEUart bleuart; // uart over ble
bool find_ppm = false;
String buffer;
void disconnect_callback(uint16_t conn_handle, uint8_t reason)
{
Serial.println();
Serial.print("Disconnected, reason = 0x"); Serial.println(reason, HEX);
}
void connect_callback(uint16_t conn_handle)
{
BLEConnection *conn = Bluefruit.Connection(conn_handle);
Serial.println("Connected");
// request PHY changed to 2MB
Serial.println("Request to change PHY");
conn->requestPHY();
// request to update data length
Serial.println("Request to change Data Length");
conn->requestDataLengthUpdate();
// request mtu exchange
Serial.println("Request to change MTU");
conn->requestMtuExchange(247);
// request connection interval of 7.5 ms
//conn->requestConnectionParameter(6); // in unit of 1.25
// Print out the current connection info
Serial.printf("Connection Info: PHY = %d Mbps, Conn Interval = %.2f ms, Data Length = %d, MTU = %d\n",
conn->getPHY(), conn->getConnectionInterval() * 1.25f, conn->getDataLength(), conn->getMtu());
// delay a bit for all the request to complete
delay(1000);
}
void startAdv(void)
{
// Advertising packet
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
// Include bleuart 128-bit uuid
Bluefruit.Advertising.addService(bleuart);
// Secondary Scan Response packet (optional)
// Since there is no room for 'Name' in Advertising packet
Bluefruit.ScanResponse.addName();
/* Start Advertising
* - Enable auto advertising if disconnected
* - Interval: fast mode = 20 ms, slow mode = 152.5 ms
* - Timeout for fast mode is 30 seconds
* - Start(timeout) with timeout = 0 will advertise forever (until connected)
*
* For recommended advertising interval
* https://developer.apple.com/library/content/qa/qa1931/_index.html
*/
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
}
void setup()
{
Serial.begin(115200);
// while (!Serial);
bool result = pd.init(Wire, i2c_sda, i2c_scl, HUSB238_SLAVE_ADDRESS);
if (result == false) {
while (1) {
Serial.println("USB Power Delivery controller not online...");
delay(1000);
}
}
find_ppm = ppm.init(Wire);
if (!find_ppm) {
Serial.println("Can't find XPowers PPM Chip !");
} else {
Serial.println("Find XPowers ppm Chip .Reset PPM default config");
ppm.resetDefault();
ppm.disableWatchdog();
ppm.enableCharge();
ppm.disableOTG();
// SY6970 Range:0~5056 mA / step:64mA
// BQ25896 Range:0~3008 mA / step:64mA
ppm.setChargerConstantCurr(2048);
// Disable current limit pin
ppm.disableCurrentLimitPin();
// SY6970 : Range : 100 mA ~ 3250 mA
ppm.setInputCurrentLimit(3250);
// ppm.disableInputCurrentLimit();
// Set the charging target voltage, Range:3840 ~ 4608mV ,step:16 mV
ppm.setChargeTargetVoltage(4208);
ppm.enableMeasure();
// ppm.setHighVoltageRequestedRange(RequestRange::REQUEST_9V);
// ppm.setSysPowerDownVoltage(3500);
// ppm.setVinDpmThreshold(POWERS_SY6970_VINDPM_VOL_MAX);
}
// Config the peripheral connection with maximum bandwidth
// more SRAM required by SoftDevice
// Note: All config***() function must be called before begin()
Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
Bluefruit.begin();
Bluefruit.setName("PowerDelivery");
Bluefruit.setTxPower(4); // Check bluefruit.h for supported values
Bluefruit.Periph.setConnectCallback(connect_callback);
Bluefruit.Periph.setDisconnectCallback(disconnect_callback);
Bluefruit.Periph.setConnInterval(6, 12); // 7.5 - 15 ms
// Configure and Start BLE Uart Service
bleuart.begin();
startAdv();
Serial.println("Please use Adafruit's Bluefruit LE app to connect in UART mode");
}
void loop()
{
buffer = "PD Vol:";
buffer.concat(pd.getPdVoltage());
buffer.concat("V ");
buffer.concat("Cur:");
buffer.concat(pd.getPdCurrent());
buffer.concat("A\n");
buffer.concat("Status:");
PowerDeliveryHUSB238::PD_Status status = pd.status();
switch (status) {
case PowerDeliveryHUSB238::NO_RESPONSE:
buffer.concat("no response");
break;
case PowerDeliveryHUSB238::SUCCESS:
buffer.concat("success");
break;
case PowerDeliveryHUSB238::INVALID_CMD:
buffer.concat("invalid command");
break;
case PowerDeliveryHUSB238::NOT_SUPPORT:
buffer.concat("not support");
break;
case PowerDeliveryHUSB238::TRANSACTION_FAIL:
buffer.concat("transaction failed");
break;
default:
break;
}
if (Bluefruit.connected() && bleuart.notifyEnabled()) {
buffer.concat("\n");
if (find_ppm) {
ppm.getFaultStatus();
buffer.concat("NTC:"); buffer.concat(ppm.getNTCStatusString()); buffer.concat("\n");
buffer.concat("VBUS:"); buffer.concat(ppm.getVbusVoltage()); buffer.concat("\n");
buffer.concat("VBAT:"); buffer.concat(ppm.getBattVoltage()); buffer.concat("\n");
buffer.concat("VSYS:"); buffer.concat(ppm.getSystemVoltage()); buffer.concat("\n");
buffer.concat("BUS:"); buffer.concat(ppm.getBusStatusString()); buffer.concat("\n");
buffer.concat("CHG:"); buffer.concat(ppm.getChargeStatusString()); buffer.concat("\n");
buffer.concat("CUR:"); buffer.concat(ppm.getChargeCurrent()); buffer.concat("\n");
}
bleuart.write(buffer.c_str());
} else {
Serial.println(buffer);
if (find_ppm) {
ppm.getFaultStatus();
Serial.print("NTC STR:"); Serial.println(ppm.getNTCStatusString());
Serial.printf("CHG TARGET VOLTAGE :%04dmV CURRENT:%04dmA PER_CHARGE_CUR %04dmA\n",
ppm.getChargeTargetVoltage(), ppm.getChargerConstantCurr(), ppm.getPrechargeCurr());
Serial.printf("VBUS:%s %04dmV VBAT:%04dmV VSYS:%04dmV\n", ppm.isVbusIn() ? "Connected" : "Disconnect",
ppm.getVbusVoltage(),
ppm.getBattVoltage(),
ppm.getSystemVoltage());
Serial.printf("BUS STATE:%d -- STR:%s\n", ppm.getBusStatus(), ppm.getBusStatusString());
Serial.printf("CHG STATE:%d -- STR:%s CURRENT:%04dmA\n", ppm.chargeStatus(), ppm.getChargeStatusString(), ppm.getChargeCurrent());
Serial.printf("[%lu]", millis() / 1000);
Serial.println("----------------------------------------------------------------------------------");
}
}
delay(5000);
}
#else
void setup()
{
Serial.begin(115200);
}
void loop()
{
Serial.println("ble examples only support nrf platform"); delay(1000);
}
#endif

View File

@@ -0,0 +1,182 @@
/**
* @file PowerDeliveryHUSB238_BleUart.ino
* @author Lewis He (lewishe@outlook.com)
* @license MIT
* @copyright Copyright (c) 2024 Shenzhen Xin Yuan Electronic Technology Co., Ltd
* @date 2024-07-24
*
*/
#include <XPowersLib.h>
#ifdef ARDUINO_ARCH_NRF52
#include <bluefruit.h>
#include <Adafruit_LittleFS.h>
PowerDeliveryHUSB238 pd;
#ifndef CONFIG_PMU_SDA
#define CONFIG_PMU_SDA 0
#endif
#ifndef CONFIG_PMU_SCL
#define CONFIG_PMU_SCL 1
#endif
const uint8_t i2c_sda = CONFIG_PMU_SDA;
const uint8_t i2c_scl = CONFIG_PMU_SCL;
BLEUart bleuart; // uart over ble
void connect_callback(uint16_t conn_handle)
{
BLEConnection *conn = Bluefruit.Connection(conn_handle);
Serial.println("Connected");
// request PHY changed to 2MB
Serial.println("Request to change PHY");
conn->requestPHY();
// request to update data length
Serial.println("Request to change Data Length");
conn->requestDataLengthUpdate();
// request mtu exchange
Serial.println("Request to change MTU");
conn->requestMtuExchange(247);
// request connection interval of 7.5 ms
//conn->requestConnectionParameter(6); // in unit of 1.25
// delay a bit for all the request to complete
delay(1000);
}
void startAdv(void)
{
// Advertising packet
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
// Include bleuart 128-bit uuid
Bluefruit.Advertising.addService(bleuart);
// Secondary Scan Response packet (optional)
// Since there is no room for 'Name' in Advertising packet
Bluefruit.ScanResponse.addName();
/* Start Advertising
* - Enable auto advertising if disconnected
* - Interval: fast mode = 20 ms, slow mode = 152.5 ms
* - Timeout for fast mode is 30 seconds
* - Start(timeout) with timeout = 0 will advertise forever (until connected)
*
* For recommended advertising interval
* https://developer.apple.com/library/content/qa/qa1931/_index.html
*/
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
}
void setup()
{
Serial.begin(115200);
// while (!Serial);
bool result = pd.init(Wire, i2c_sda, i2c_scl, HUSB238_SLAVE_ADDRESS);
if (result == false) {
while (1) {
Serial.println("USB Power Delivery controller not online...");
delay(1000);
}
}
// Config the peripheral connection with maximum bandwidth
// more SRAM required by SoftDevice
// Note: All config***() function must be called before begin()
Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
Bluefruit.begin();
Bluefruit.setName("PowerDelivery");
Bluefruit.setTxPower(4); // Check bluefruit.h for supported values
Bluefruit.Periph.setConnectCallback(connect_callback);
Bluefruit.Periph.setConnInterval(6, 12); // 7.5 - 15 ms
// Configure and Start BLE Uart Service
bleuart.begin();
startAdv();
Serial.println("Please use Adafruit's Bluefruit LE app to connect in UART mode");
}
String buffer;
void loop()
{
Serial.print("PD Voltage:"); Serial.print(pd.getPdVoltage()); Serial.print(" V");
Serial.print(" Current: "); Serial.print(pd.getPdCurrent()); Serial.println(" A");
buffer = "Vol:";
buffer.concat(pd.getPdVoltage());
buffer.concat("V ");
buffer.concat("Cur:");
buffer.concat(pd.getPdCurrent());
buffer.concat("A");
buffer.concat("Status:");
PowerDeliveryHUSB238::PD_Status status = pd.status();
Serial.print("USB Power Delivery Status : ");
switch (status) {
case PowerDeliveryHUSB238::NO_RESPONSE:
Serial.println("no response");
buffer.concat("no response");
break;
case PowerDeliveryHUSB238::SUCCESS:
Serial.println("success");
buffer.concat("success");
break;
case PowerDeliveryHUSB238::INVALID_CMD:
Serial.println("invalid command");
buffer.concat("invalid command");
break;
case PowerDeliveryHUSB238::NOT_SUPPORT:
Serial.println("not support");
buffer.concat("not support");
break;
case PowerDeliveryHUSB238::TRANSACTION_FAIL:
Serial.println("transaction failed");
buffer.concat("transaction failed");
break;
default:
break;
}
bleuart.write(buffer.c_str());
delay(5000);
}
#else
void setup()
{
Serial.begin(115200);
}
void loop()
{
Serial.println("ble examples only support nrf platform"); delay(1000);
}
#endif

View File

@@ -0,0 +1,72 @@
/**
* @file PowerDeliveryHUSB238.ino
* @author Lewis He (lewishe@outlook.com)
* @license MIT
* @copyright Copyright (c) 2024 Shenzhen Xin Yuan Electronic Technology Co., Ltd
* @date 2024-07-24
*
*/
#include <XPowersLib.h>
PowerDeliveryHUSB238 pd;
#ifndef CONFIG_PMU_SDA
#define CONFIG_PMU_SDA 0
#endif
#ifndef CONFIG_PMU_SCL
#define CONFIG_PMU_SCL 1
#endif
const uint8_t i2c_sda = CONFIG_PMU_SDA;
const uint8_t i2c_scl = CONFIG_PMU_SCL;
void setup()
{
Serial.begin(115200);
while (!Serial);
bool result = pd.init(Wire, i2c_sda, i2c_scl, HUSB238_SLAVE_ADDRESS);
if (result == false) {
while (1) {
Serial.println("USB Power Delivery controller not online...");
delay(1000);
}
}
}
void loop()
{
Serial.print("PD Voltage:"); Serial.print(pd.getPdVoltage()); Serial.print(" V");
Serial.print(" Current: "); Serial.print(pd.getPdCurrent()); Serial.println(" A");
PowerDeliveryHUSB238::PD_Status status = pd.status();
Serial.print("USB Power Delivery Status : ");
switch (status) {
case PowerDeliveryHUSB238::NO_RESPONSE:
Serial.println("no response");
break;
case PowerDeliveryHUSB238::SUCCESS:
Serial.println("success");
break;
case PowerDeliveryHUSB238::INVALID_CMD:
Serial.println("invalid command");
break;
case PowerDeliveryHUSB238::NOT_SUPPORT:
Serial.println("not support");
break;
case PowerDeliveryHUSB238::TRANSACTION_FAIL:
Serial.println("transaction failed");
break;
default:
break;
}
delay(1000);
}

View File

@@ -0,0 +1,176 @@
/**
* @file SY6970_Example.ino
* @author Lewis He (lewishe@outlook.com)
* @license MIT
* @copyright Copyright (c) 2023 Shenzhen Xin Yuan Electronic Technology Co., Ltd
* @date 2023-08-05
* @note SY6970 If the power supply is a separate USB power supply, VSYS can only provide a maximum load current of 500mA.
* If it is connected to a battery, the discharge current depends on the maximum discharge current of the battery.
*
*/
#define XPOWERS_CHIP_SY6970
#include <XPowersLib.h>
XPowersPPM PPM;
#ifndef CONFIG_PMU_SDA
#define CONFIG_PMU_SDA 0
#endif
#ifndef CONFIG_PMU_SCL
#define CONFIG_PMU_SCL 1
#endif
#ifndef CONFIG_PMU_IRQ
#define CONFIG_PMU_IRQ 28
#endif
const uint8_t i2c_sda = CONFIG_PMU_SDA;
const uint8_t i2c_scl = CONFIG_PMU_SCL;
const uint8_t pmu_irq_pin = CONFIG_PMU_IRQ;
uint32_t cycleInterval;
bool pmu_irq = false;
void setup()
{
Serial.begin(115200);
while (!Serial);
bool result = PPM.init(Wire, i2c_sda, i2c_scl, SY6970_SLAVE_ADDRESS);
if (result == false) {
while (1) {
Serial.println("PPM is not online...");
delay(50);
}
}
// Set the minimum operating voltage. Below this voltage, the PPM will protect
PPM.setSysPowerDownVoltage(3300);
// Set input current limit, default is 500mA
PPM.setInputCurrentLimit(3250);
Serial.printf("getInputCurrentLimit: %d mA\n", PPM.getInputCurrentLimit());
// Disable current limit pin
PPM.disableCurrentLimitPin();
// Set the charging target voltage, Range:3840 ~ 4608mV ,step:16 mV
PPM.setChargeTargetVoltage(4208);
// Set the precharge current , Range: 64mA ~ 1024mA ,step:64mA
PPM.setPrechargeCurr(64);
// The premise is that Limit Pin is disabled, or it will only follow the maximum charging current set by Limi tPin.
// Set the charging current , Range:0~5056mA ,step:64mA
PPM.setChargerConstantCurr(1024);
// Get the set charging current
PPM.getChargerConstantCurr();
Serial.printf("getChargerConstantCurr: %d mA\n", PPM.getChargerConstantCurr());
// To obtain voltage data, the ADC must be enabled first
PPM.enableMeasure();
// Turn on charging function
// If there is no battery connected, do not turn on the charging function
PPM.enableCharge();
// Turn off charging function
// If USB is used as the only power input, it is best to turn off the charging function,
// otherwise the VSYS power supply will have a sawtooth wave, affecting the discharge output capability.
// PPM.disableCharge();
// The OTG function needs to enable OTG, and set the OTG control pin to HIGH
// After OTG is enabled, if an external power supply is plugged in, OTG will be turned off
// PPM.enableOTG();
// PPM.disableOTG();
// pinMode(OTG_ENABLE_PIN, OUTPUT);
// digitalWrite(OTG_ENABLE_PIN, HIGH);
pinMode(pmu_irq_pin, INPUT_PULLUP);
attachInterrupt(pmu_irq_pin, []() {
pmu_irq = true;
}, FALLING);
}
void loop()
{
if (pmu_irq) {
pmu_irq = false;
// Get PPM interrupt status
PPM.getFaultStatus();
Serial.print("-> [");
Serial.print(millis() / 1000);
Serial.print("] ");
if (PPM.isWatchdogFault()) {
Serial.println("Watchdog Fault");
} else if (PPM.isBoostFault()) {
Serial.println("Boost Fault");
} else if (PPM.isChargeFault()) {
Serial.println("Charge Fault");
} else if (PPM.isBatteryFault()) {
Serial.println("Batter Fault");
} else if (PPM.isNTCFault()) {
Serial.print("NTC Fault:");
Serial.print(PPM.getNTCStatusString());
Serial.print(" Percentage:");
Serial.print(PPM.getNTCPercentage()); Serial.println("%");
} else {
/*
* When the battery is removed, INT will send an interrupt every 100ms. If the battery is not connected,
* you can use PPM.disableCharge() to turn off the charging function.
* */
// PPM.disableCharge();
Serial.println("Battery remove");
}
}
/*
* Obtaining the battery voltage and battery charging status does not directly read the register,
* but determines whether the charging current register is normal.
* If read directly, the reading will be inaccurate.
* The premise for obtaining these two states is that the NTC temperature measurement circuit is normal.
* If the NTC detection is abnormal, it will return 0
* * */
if (millis() > cycleInterval) {
Serial.printf("CHG TARGET VOLTAGE :%04dmV CURRENT:%04dmA PER_CHARGE_CUR %04dmA\n",
PPM.getChargeTargetVoltage(), PPM.getChargerConstantCurr(), PPM.getPrechargeCurr());
Serial.printf("VBUS:%s %04dmV VBAT:%04dmV VSYS:%04dmV\n", PPM.isVbusIn() ? "Connected" : "Disconnect",
PPM.getVbusVoltage(),
PPM.getBattVoltage(),
PPM.getSystemVoltage());
Serial.printf("BUS STATE:%d STR:%s\n", PPM.getBusStatus(), PPM.getBusStatusString());
Serial.printf("CHG STATE:%d STR:%s CURRENT:%04dmA\n", PPM.chargeStatus(), PPM.getChargeStatusString(), PPM.getChargeCurrent());
Serial.printf("[%lu]", millis() / 1000);
Serial.println("----------------------------------------------------------------------------------");
cycleInterval = millis() + 1000;
}
}

View File

@@ -0,0 +1,71 @@
/**
* @file SY6970_Shutdown_Example.ino
* @author Lewis He (lewishe@outlook.com)
* @license MIT
* @copyright Copyright (c) 2024 Shenzhen Xin Yuan Electronic Technology Co., Ltd
* @date 2024-05-23
*
*/
#define XPOWERS_CHIP_SY6970
#include <XPowersLib.h>
XPowersPPM PPM;
#ifndef CONFIG_PMU_SDA
#define CONFIG_PMU_SDA 0
#endif
#ifndef CONFIG_PMU_SCL
#define CONFIG_PMU_SCL 1
#endif
#ifndef CONFIG_PMU_IRQ
#define CONFIG_PMU_IRQ 28
#endif
const uint8_t i2c_sda = CONFIG_PMU_SDA;
const uint8_t i2c_scl = CONFIG_PMU_SCL;
const uint8_t pmu_irq_pin = CONFIG_PMU_IRQ;
uint32_t cycleInterval;
uint32_t countdown = 10;
void setup()
{
Serial.begin(115200);
while (!Serial);
bool result = PPM.init(Wire, i2c_sda, i2c_scl, SY6970_SLAVE_ADDRESS);
if (result == false) {
while (1) {
Serial.println("PPM is not online...");
delay(50);
}
}
}
void loop()
{
if (millis() > cycleInterval) {
Serial.printf("%d\n", countdown);
if (!(countdown--)) {
Serial.println("Shutdown .....");
// The shutdown function can only be used when the battery is connected alone,
// and cannot be shut down when connected to USB.
// It can only be powered on in the following two ways:
// 1. Press the /QON button
// 2. Connect to USB
PPM.shutdown();
countdown = 10000;
}
cycleInterval = millis() + 1000;
}
}

View File

@@ -0,0 +1,78 @@
/**
* @file SY6970_Watchdog_Example.ino
* @author Lewis He (lewishe@outlook.com)
* @license MIT
* @copyright Copyright (c) 2023 Shenzhen Xin Yuan Electronic Technology Co., Ltd
* @date 2023-08-31
*
*/
#define XPOWERS_CHIP_SY6970
#include <XPowersLib.h>
XPowersPPM PPM;
#ifndef CONFIG_PMU_SDA
#define CONFIG_PMU_SDA 15
#endif
#ifndef CONFIG_PMU_SCL
#define CONFIG_PMU_SCL 10
#endif
#ifndef CONFIG_PMU_IRQ
#define CONFIG_PMU_IRQ 28
#endif
const uint8_t i2c_sda = CONFIG_PMU_SDA;
const uint8_t i2c_scl = CONFIG_PMU_SCL;
const uint8_t pmu_irq_pin = CONFIG_PMU_IRQ;
uint32_t cycleInterval;
void setup()
{
Serial.begin(115200);
while (!Serial);
// Begin SY6970 PPM , Default disable watchdog timer
bool result = PPM.init(Wire, i2c_sda, i2c_scl, SY6970_SLAVE_ADDRESS);
if (result == false) {
while (1) {
Serial.println("PPM is not online...");
delay(50);
}
}
// Disable battery charge function
PPM.disableCharge();
/*
* Example:
* PPM.enableWatchdog(PowersSY6970::TIMER_OUT_40SEC);
* Optional parameters:
* PowersSY6970::TIMER_OUT_40SEC, //40 Second
* PowersSY6970::TIMER_OUT_80SEC, //80 Second
* PowersSY6970::TIMER_OUT_160SEC, //160 Second
* * */
// Enable SY6970 PPM watchdog function
PPM.enableWatchdog(PowersSY6970::TIMER_OUT_40SEC);
}
void loop()
{
// Feed watchdog , If the dog is not fed, the PPM will restart after a timeout, and all PPM settings will be restored to their default values
Serial.print(millis() / 1000); Serial.println(" Second");
PPM.feedWatchdog();
delay(1000);
}

View File

@@ -0,0 +1,516 @@
/*
MIT License
Copyright (c) 2022 lewis he
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
! WARN:
Please do not run the example without knowing the external load voltage of the PMU,
it may burn your external load, please check the voltage setting before running the example,
if there is any loss, please bear it by yourself
*/
#ifndef XPOWERS_NO_ERROR
#error "Running this example is known to not damage the device! Please go and uncomment this!"
#endif
#include <Arduino.h>
#include <Wire.h>
#include "XPowersLib.h"
#ifndef CONFIG_PMU_SDA
#define CONFIG_PMU_SDA 21
#endif
#ifndef CONFIG_PMU_SCL
#define CONFIG_PMU_SCL 22
#endif
#ifndef CONFIG_PMU_IRQ
#define CONFIG_PMU_IRQ 35
#endif
// Use the XPowersLibInterface standard to use the xpowers API
XPowersLibInterface *power = NULL;
bool pmu_flag = 0;
const uint8_t i2c_sda = CONFIG_PMU_SDA;
const uint8_t i2c_scl = CONFIG_PMU_SCL;
const uint8_t pmu_irq_pin = CONFIG_PMU_IRQ;
void setFlag(void)
{
pmu_flag = true;
}
void setup()
{
Serial.begin(115200);
if (!power) {
power = new XPowersAXP2101(Wire, i2c_sda, i2c_scl);
if (!power->init()) {
Serial.printf("Warning: Failed to find AXP2101 power management\n");
delete power;
power = NULL;
} else {
Serial.printf("AXP2101 PMU init succeeded, using AXP2101 PMU\n");
}
}
if (!power) {
power = new XPowersAXP192(Wire, i2c_sda, i2c_scl);
if (!power->init()) {
Serial.printf("Warning: Failed to find AXP192 power management\n");
delete power;
power = NULL;
} else {
Serial.printf("AXP192 PMU init succeeded, using AXP192 PMU\n");
}
}
if (!power) {
power = new XPowersAXP202(Wire, i2c_sda, i2c_scl);
if (!power->init()) {
Serial.printf("Warning: Failed to find AXP202 power management\n");
delete power;
power = NULL;
} else {
Serial.printf("AXP202 PMU init succeeded, using AXP202 PMU\n");
}
}
if (!power) {
Serial.println("PMU not detected, please check.."); while (1)delay(50);
}
//The following AXP192 power supply setting voltage is based on esp32 T-beam
if (power->getChipModel() == XPOWERS_AXP192) {
// lora radio power channel
power->setPowerChannelVoltage(XPOWERS_LDO2, 3300);
power->enablePowerOutput(XPOWERS_LDO2);
// oled module power channel,
// disable it will cause abnormal communication between boot and AXP power supply,
// do not turn it off
power->setPowerChannelVoltage(XPOWERS_DCDC1, 3300);
// enable oled power
power->enablePowerOutput(XPOWERS_DCDC1);
// gnss module power channel
power->setPowerChannelVoltage(XPOWERS_LDO3, 3300);
// power->enablePowerOutput(XPOWERS_LDO3);
//protected oled power source
power->setProtectedChannel(XPOWERS_DCDC1);
//protected esp32 power source
power->setProtectedChannel(XPOWERS_DCDC3);
//disable not use channel
power->disablePowerOutput(XPOWERS_DCDC2);
//disable all axp chip interrupt
power->disableIRQ(XPOWERS_AXP192_ALL_IRQ);
//
/* Set the constant current charging current of AXP192
opt:
XPOWERS_AXP192_CHG_CUR_100MA,
XPOWERS_AXP192_CHG_CUR_190MA,
XPOWERS_AXP192_CHG_CUR_280MA,
XPOWERS_AXP192_CHG_CUR_360MA,
XPOWERS_AXP192_CHG_CUR_450MA,
XPOWERS_AXP192_CHG_CUR_550MA,
XPOWERS_AXP192_CHG_CUR_630MA,
XPOWERS_AXP192_CHG_CUR_700MA,
XPOWERS_AXP192_CHG_CUR_780MA,
XPOWERS_AXP192_CHG_CUR_880MA,
XPOWERS_AXP192_CHG_CUR_960MA,
XPOWERS_AXP192_CHG_CUR_1000MA,
XPOWERS_AXP192_CHG_CUR_1080MA,
XPOWERS_AXP192_CHG_CUR_1160MA,
XPOWERS_AXP192_CHG_CUR_1240MA,
XPOWERS_AXP192_CHG_CUR_1320MA,
*/
power->setChargerConstantCurr(XPOWERS_AXP192_CHG_CUR_550MA);
}
// The following AXP202 power supply voltage setting is based on esp32 T-Watch
else if (power->getChipModel() == XPOWERS_AXP202) {
power->disablePowerOutput(XPOWERS_DCDC2); //not elicited
//Display backlight
power->setPowerChannelVoltage(XPOWERS_LDO2, 3300);
power->enablePowerOutput(XPOWERS_LDO2);
// Shiled Vdd
power->setPowerChannelVoltage(XPOWERS_LDO3, 3300);
power->enablePowerOutput(XPOWERS_LDO3);
// S7xG GNSS Vdd
power->setPowerChannelVoltage(XPOWERS_LDO4, 1800);
power->enablePowerOutput(XPOWERS_LDO4);
//
/* Set the constant current charging current of AXP202
opt:
XPOWERS_AXP202_CHG_CUR_100MA,
XPOWERS_AXP202_CHG_CUR_190MA,
XPOWERS_AXP202_CHG_CUR_280MA,
XPOWERS_AXP202_CHG_CUR_360MA,
XPOWERS_AXP202_CHG_CUR_450MA,
XPOWERS_AXP202_CHG_CUR_550MA,
XPOWERS_AXP202_CHG_CUR_630MA,
XPOWERS_AXP202_CHG_CUR_700MA,
XPOWERS_AXP202_CHG_CUR_780MA,
XPOWERS_AXP202_CHG_CUR_880MA,
XPOWERS_AXP202_CHG_CUR_960MA,
XPOWERS_AXP202_CHG_CUR_1000MA,
XPOWERS_AXP202_CHG_CUR_1080MA,
XPOWERS_AXP202_CHG_CUR_1160MA,
XPOWERS_AXP202_CHG_CUR_1240MA,
XPOWERS_AXP202_CHG_CUR_1320MA,
*/
power->setChargerConstantCurr(XPOWERS_AXP202_CHG_CUR_550MA);
}
// The following AXP192 power supply voltage setting is based on esp32s3 T-beam
else if (power->getChipModel() == XPOWERS_AXP2101) {
// gnss module power channel
power->setPowerChannelVoltage(XPOWERS_ALDO4, 3300);
power->enablePowerOutput(XPOWERS_ALDO4);
// lora radio power channel
power->setPowerChannelVoltage(XPOWERS_ALDO3, 3300);
power->enablePowerOutput(XPOWERS_ALDO3);
// m.2 interface
power->setPowerChannelVoltage(XPOWERS_DCDC3, 3300);
power->enablePowerOutput(XPOWERS_DCDC3);
// power->setPowerChannelVoltage(XPOWERS_DCDC4, 3300);
// power->enablePowerOutput(XPOWERS_DCDC4);
//not use channel
power->disablePowerOutput(XPOWERS_DCDC2); //not elicited
power->disablePowerOutput(XPOWERS_DCDC5); //not elicited
power->disablePowerOutput(XPOWERS_DLDO1); //Invalid power channel, it does not exist
power->disablePowerOutput(XPOWERS_DLDO2); //Invalid power channel, it does not exist
power->disablePowerOutput(XPOWERS_VBACKUP);
//disable all axp chip interrupt
power->disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
/* Set the constant current charging current of AXP2101
opt:
XPOWERS_AXP2101_CHG_CUR_100MA,
XPOWERS_AXP2101_CHG_CUR_125MA,
XPOWERS_AXP2101_CHG_CUR_150MA,
XPOWERS_AXP2101_CHG_CUR_175MA,
XPOWERS_AXP2101_CHG_CUR_200MA,
XPOWERS_AXP2101_CHG_CUR_300MA,
XPOWERS_AXP2101_CHG_CUR_400MA,
XPOWERS_AXP2101_CHG_CUR_500MA,
XPOWERS_AXP2101_CHG_CUR_600MA,
XPOWERS_AXP2101_CHG_CUR_700MA,
XPOWERS_AXP2101_CHG_CUR_800MA,
XPOWERS_AXP2101_CHG_CUR_900MA,
XPOWERS_AXP2101_CHG_CUR_1000MA,
*/
power->setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_500MA);
}
Serial.println("=======================================================================\n");
if (power->isChannelAvailable(XPOWERS_DCDC1)) {
Serial.printf("DC1 : %s Voltage:%u mV \n", power->isPowerChannelEnable(XPOWERS_DCDC1) ? "+" : "-", power->getPowerChannelVoltage(XPOWERS_DCDC1));
}
if (power->isChannelAvailable(XPOWERS_DCDC2)) {
Serial.printf("DC2 : %s Voltage:%u mV \n", power->isPowerChannelEnable(XPOWERS_DCDC2) ? "+" : "-", power->getPowerChannelVoltage(XPOWERS_DCDC2));
}
if (power->isChannelAvailable(XPOWERS_DCDC3)) {
Serial.printf("DC3 : %s Voltage:%u mV \n", power->isPowerChannelEnable(XPOWERS_DCDC3) ? "+" : "-", power->getPowerChannelVoltage(XPOWERS_DCDC3));
}
if (power->isChannelAvailable(XPOWERS_DCDC4)) {
Serial.printf("DC4 : %s Voltage:%u mV \n", power->isPowerChannelEnable(XPOWERS_DCDC4) ? "+" : "-", power->getPowerChannelVoltage(XPOWERS_DCDC4));
}
if (power->isChannelAvailable(XPOWERS_LDO2)) {
Serial.printf("LDO2 : %s Voltage:%u mV \n", power->isPowerChannelEnable(XPOWERS_LDO2) ? "+" : "-", power->getPowerChannelVoltage(XPOWERS_LDO2));
}
if (power->isChannelAvailable(XPOWERS_LDO3)) {
Serial.printf("LDO3 : %s Voltage:%u mV \n", power->isPowerChannelEnable(XPOWERS_LDO3) ? "+" : "-", power->getPowerChannelVoltage(XPOWERS_LDO3));
}
if (power->isChannelAvailable(XPOWERS_LDO4)) {
Serial.printf("LDO4 : %s Voltage:%u mV \n", power->isPowerChannelEnable(XPOWERS_LDO4) ? "+" : "-", power->getPowerChannelVoltage(XPOWERS_LDO4));
}
if (power->isChannelAvailable(XPOWERS_LDO5)) {
Serial.printf("LDO5 : %s Voltage:%u mV \n", power->isPowerChannelEnable(XPOWERS_LDO5) ? "+" : "-", power->getPowerChannelVoltage(XPOWERS_LDO5));
}
if (power->isChannelAvailable(XPOWERS_ALDO1)) {
Serial.printf("ALDO1: %s Voltage:%u mV \n", power->isPowerChannelEnable(XPOWERS_ALDO1) ? "+" : "-", power->getPowerChannelVoltage(XPOWERS_ALDO1));
}
if (power->isChannelAvailable(XPOWERS_ALDO2)) {
Serial.printf("ALDO2: %s Voltage:%u mV \n", power->isPowerChannelEnable(XPOWERS_ALDO2) ? "+" : "-", power->getPowerChannelVoltage(XPOWERS_ALDO2));
}
if (power->isChannelAvailable(XPOWERS_ALDO3)) {
Serial.printf("ALDO3: %s Voltage:%u mV \n", power->isPowerChannelEnable(XPOWERS_ALDO3) ? "+" : "-", power->getPowerChannelVoltage(XPOWERS_ALDO3));
}
if (power->isChannelAvailable(XPOWERS_ALDO4)) {
Serial.printf("ALDO4: %s Voltage:%u mV \n", power->isPowerChannelEnable(XPOWERS_ALDO4) ? "+" : "-", power->getPowerChannelVoltage(XPOWERS_ALDO4));
}
if (power->isChannelAvailable(XPOWERS_BLDO1)) {
Serial.printf("BLDO1: %s Voltage:%u mV \n", power->isPowerChannelEnable(XPOWERS_BLDO1) ? "+" : "-", power->getPowerChannelVoltage(XPOWERS_BLDO1));
}
if (power->isChannelAvailable(XPOWERS_BLDO2)) {
Serial.printf("BLDO2: %s Voltage:%u mV \n", power->isPowerChannelEnable(XPOWERS_BLDO2) ? "+" : "-", power->getPowerChannelVoltage(XPOWERS_BLDO2));
}
Serial.println("=======================================================================\n");
//Set up the charging voltage, AXP2101/AXP192 4.2V gear is the same
// XPOWERS_AXP192_CHG_VOL_4V2 = XPOWERS_AXP2101_CHG_VOL_4V2
power->setChargeTargetVoltage(XPOWERS_AXP192_CHG_VOL_4V2);
// Set VSY off voltage as 2600mV , Adjustment range 2600mV ~ 3300mV
power->setSysPowerDownVoltage(2600);
// Get the VSYS shutdown voltage
uint16_t vol = power->getSysPowerDownVoltage();
Serial.printf("-> getSysPowerDownVoltage:%u\n", vol);
// Set the time of pressing the button to turn off
power->setPowerKeyPressOffTime(XPOWERS_POWEROFF_4S);
uint8_t opt = power->getPowerKeyPressOffTime();
Serial.print("PowerKeyPressOffTime:");
switch (opt) {
case XPOWERS_POWEROFF_4S: Serial.println("4 Second");
break;
case XPOWERS_POWEROFF_6S: Serial.println("6 Second");
break;
case XPOWERS_POWEROFF_8S: Serial.println("8 Second");
break;
case XPOWERS_POWEROFF_10S: Serial.println("10 Second");
break;
default:
break;
}
// Set the button power-on press time
power->setPowerKeyPressOnTime(XPOWERS_POWERON_128MS);
opt = power->getPowerKeyPressOnTime();
Serial.print("PowerKeyPressOnTime:");
switch (opt) {
case XPOWERS_POWERON_128MS: Serial.println("128 Ms");
break;
case XPOWERS_POWERON_512MS: Serial.println("512 Ms");
break;
case XPOWERS_POWERON_1S: Serial.println("1 Second");
break;
case XPOWERS_POWERON_2S: Serial.println("2 Second");
break;
default:
break;
}
Serial.println("===========================================================================");
// It is necessary to disable the detection function of the TS pin on the board
// without the battery temperature detection function, otherwise it will cause abnormal charging
power->disableTSPinMeasure();
// Enable internal ADC detection
power->enableBattDetection();
power->enableVbusVoltageMeasure();
power->enableBattVoltageMeasure();
power->enableSystemVoltageMeasure();
/*
The default setting is CHGLED is automatically controlled by the PMU.
- XPOWERS_CHG_LED_OFF,
- XPOWERS_CHG_LED_BLINK_1HZ,
- XPOWERS_CHG_LED_BLINK_4HZ,
- XPOWERS_CHG_LED_ON,
- XPOWERS_CHG_LED_CTRL_CHG,
* */
power->setChargingLedMode(XPOWERS_CHG_LED_OFF);
pinMode(pmu_irq_pin, INPUT);
attachInterrupt(pmu_irq_pin, setFlag, FALLING);
// Clear all interrupt flags
power->clearIrqStatus();
/*
// call specific interrupt request
uint64_t pmuIrqMask = 0;
if (power->getChipModel() == XPOWERS_AXP192) {
pmuIrqMask = XPOWERS_AXP192_VBUS_INSERT_IRQ | XPOWERS_AXP192_VBUS_REMOVE_IRQ | //BATTERY
XPOWERS_AXP192_BAT_INSERT_IRQ | XPOWERS_AXP192_BAT_REMOVE_IRQ | //VBUS
XPOWERS_AXP192_PKEY_SHORT_IRQ | XPOWERS_AXP192_PKEY_LONG_IRQ | //POWER KEY
XPOWERS_AXP192_BAT_CHG_START_IRQ | XPOWERS_AXP192_BAT_CHG_DONE_IRQ ; //CHARGE
} else if (power->getChipModel() == XPOWERS_AXP2101) {
pmuIrqMask = XPOWERS_AXP2101_BAT_INSERT_IRQ | XPOWERS_AXP2101_BAT_REMOVE_IRQ | //BATTERY
XPOWERS_AXP2101_VBUS_INSERT_IRQ | XPOWERS_AXP2101_VBUS_REMOVE_IRQ | //VBUS
XPOWERS_AXP2101_PKEY_SHORT_IRQ | XPOWERS_AXP2101_PKEY_LONG_IRQ | //POWER KEY
XPOWERS_AXP2101_BAT_CHG_DONE_IRQ | XPOWERS_AXP2101_BAT_CHG_START_IRQ; //CHARGE
}
// Enable the required interrupt function
power->enableIRQ(pmuIrqMask);
*/
// Call the interrupt request through the interface class
power->disableInterrupt(XPOWERS_ALL_INT);
power->enableInterrupt(XPOWERS_USB_INSERT_INT |
XPOWERS_USB_REMOVE_INT |
XPOWERS_BATTERY_INSERT_INT |
XPOWERS_BATTERY_REMOVE_INT |
XPOWERS_PWR_BTN_CLICK_INT |
XPOWERS_CHARGE_START_INT |
XPOWERS_CHARGE_DONE_INT);
// Access the subclass method by getting the model
uint8_t chipType = power->getChipModel();
switch (chipType) {
case XPOWERS_AXP192: {
XPowersAXP192 *axp192 = static_cast<XPowersAXP192 *>(power);
axp192->enableCoulomb();
uint32_t data = axp192->getBattChargeCoulomb();
float chargeCurrent = axp192->getBatteryChargeCurrent();
float dischargeCurrent = axp192->getBattDischargeCurrent();
Serial.printf("AXP192 GetBattChargeCoulomb : %X\n", data);
Serial.printf("AXP192 GetBatteryChargeCurrent:%.2f mA\n", chargeCurrent);
Serial.printf("AXP192 GetBattDischargeCurrent:%.2f mA\n", dischargeCurrent);
}
break;
case XPOWERS_AXP202: {
XPowersAXP202 *axp202 = static_cast<XPowersAXP202 *>(power);
axp202->enableCoulomb();
uint32_t data = axp202->getBattChargeCoulomb();
Serial.printf("AX202 GetBattChargeCoulomb : %X\n", data);
}
break;
case XPOWERS_AXP2101: {
XPowersAXP2101 *axp2101 = static_cast<XPowersAXP2101 *>(power);
axp2101->fuelGaugeControl(true, true);
axp2101->setPrechargeCurr(XPOWERS_AXP2101_PRECHARGE_50MA);
axp2101->setChargerTerminationCurr(XPOWERS_AXP2101_CHG_ITERM_25MA);
}
break;
default:
break;
}
}
void printPMU()
{
Serial.print("isCharging:"); Serial.println(power->isCharging() ? "YES" : "NO");
Serial.print("isDischarge:"); Serial.println(power->isDischarge() ? "YES" : "NO");
Serial.print("isVbusIn:"); Serial.println(power->isVbusIn() ? "YES" : "NO");
Serial.print("getBattVoltage:"); Serial.print(power->getBattVoltage()); Serial.println("mV");
Serial.print("getVbusVoltage:"); Serial.print(power->getVbusVoltage()); Serial.println("mV");
Serial.print("getSystemVoltage:"); Serial.print(power->getSystemVoltage()); Serial.println("mV");
// The battery percentage may be inaccurate at first use, the PMU will automatically
// learn the battery curve and will automatically calibrate the battery percentage
// after a charge and discharge cycle
if (power->isBatteryConnect()) {
Serial.print("getBatteryPercent:"); Serial.print(power->getBatteryPercent()); Serial.println("%");
}
Serial.println();
}
void loop()
{
if (pmu_flag) {
pmu_flag = false;
// Get PMU Interrupt Status Register
uint32_t status = power->getIrqStatus();
Serial.print("STATUS => HEX:");
Serial.print(status, HEX);
Serial.print(" BIN:");
Serial.println(status, BIN);
if (power->isVbusInsertIrq()) {
Serial.println("isVbusInsert");
}
if (power->isVbusRemoveIrq()) {
Serial.println("isVbusRemove");
}
if (power->isBatInsertIrq()) {
Serial.println("isBatInsert");
}
if (power->isBatRemoveIrq()) {
Serial.println("isBatRemove");
}
if (power->isPekeyShortPressIrq()) {
Serial.println("isPekeyShortPress");
}
if (power->isPekeyLongPressIrq()) {
Serial.println("isPekeyLongPress");
}
if (power->isBatChargeDoneIrq()) {
Serial.println("isBatChargeDone");
}
if (power->isBatChargeStartIrq()) {
Serial.println("isBatChargeStart");
}
// Clear PMU Interrupt Status Register
power->clearIrqStatus();
}
delay(10);
}

View File

@@ -0,0 +1,31 @@
EXAMPLE_DIR = .
SRC_DIR = ../../src
DIR_BIN = ./build
OBJ_C = $(wildcard ${SRC_DIR}/*.cpp ${EXAMPLE_DIR}/*.cpp)
OBJ_O = $(patsubst %.cpp,${DIR_BIN}/%.o,$(notdir ${OBJ_C}))
TARGET = main
DEBUG = -DXPOWERS_NO_ERROR
$(shell mkdir -p $(DIR_BIN))
# Change to the directory where the g++ compilation chain is located
SDK_PATH = /mnt/c/Users/lewis/Desktop/liunx/
CC = $(SDK_PATH)/luckfox-pico/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-g++
MSG = -g -O0 -Wall
CFLAGS += $(MSG) $(DEBUG)
${TARGET}:${OBJ_O}
$(CC) $(CFLAGS) $(OBJ_O) -o $@ $(LIB)
${DIR_BIN}/%.o:$(EXAMPLE_DIR)/%.cpp
$(CC) $(CFLAGS) -c $< -o $@ -I $(SRC_DIR)
${DIR_BIN}/%.o:$(SRC_DIR)/%.cpp
$(CC) $(CFLAGS) -c $< -o $@ $(LIB)
clean :
rm $(DIR_BIN)/*.*
rm $(TARGET)

View File

@@ -0,0 +1,159 @@
/**
* @file linux_gpio.cpp
* @author Lewis He (lewishe@outlook.com)
* @license MIT
* @copyright Copyright (c) 2023 Shenzhen Xinyuan Electronic Technology Co., Ltd
* @date 2023-11-20
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
int linux_gpio_export(int pin);
int linux_gpio_unexport(int pin);
int linux_gpio_direction(int pin, int dir);
int linux_gpio_write(int pin, int value);
int linux_gpio_read(int pin);
int linux_gpio_edge(int pin, int edge);
int linux_gpio_export(int pin)
{
char buffer[64];
int len;
int fd;
fd = open("/sys/class/gpio/export", O_WRONLY);
if (fd < 0) {
printf("Failed to open export for writing!\n");
return (-1);
}
len = snprintf(buffer, sizeof(buffer), "%d", pin);
printf("%s,%d,%d\n", buffer, sizeof(buffer), len);
if (write(fd, buffer, len) < 0) {
printf("Failed to export gpio!");
return -1;
}
close(fd);
return 0;
}
int linux_gpio_unexport(int pin)
{
char buffer[64];
int len;
int fd;
fd = open("/sys/class/gpio/unexport", O_WRONLY);
if (fd < 0) {
printf("Failed to open unexport for writing!\n");
return -1;
}
len = snprintf(buffer, sizeof(buffer), "%d", pin);
if (write(fd, buffer, len) < 0) {
printf("Failed to unexport gpio!");
return -1;
}
close(fd);
return 0;
}
// dir: 0-->IN, 1-->OUT
int linux_gpio_direction(int pin, int dir)
{
const char dir_str[] = "in\0out";
char path[64];
int fd;
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/direction", pin);
fd = open(path, O_WRONLY);
if (fd < 0) {
printf("Failed to open gpio direction for writing!\n");
return -1;
}
if (write(fd, &dir_str[dir == 0 ? 0 : 3], dir == 0 ? 2 : 3) < 0) {
printf("Failed to set direction!\n");
return -1;
}
close(fd);
return 0;
}
// value: 0-->LOW, 1-->HIGH
int linux_gpio_write(int pin, int value)
{
const char values_str[] = "01";
char path[64];
int fd;
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin);
fd = open(path, O_WRONLY);
if (fd < 0) {
printf("Failed to open gpio value for writing!\n");
return -1;
}
if (write(fd, &values_str[value == 0 ? 0 : 1], 1) < 0) {
printf("Failed to write value!\n");
return -1;
}
close(fd);
return 0;
}
int linux_gpio_read(int pin)
{
char path[64];
char value_str[3];
int fd;
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin);
fd = open(path, O_RDONLY);
if (fd < 0) {
printf("Failed to open gpio value for reading!\n");
return -1;
}
if (read(fd, value_str, 3) < 0) {
printf("Failed to read value!\n");
return -1;
}
close(fd);
return (atoi(value_str));
}
// 0-->none, 1-->rising, 2-->falling, 3-->both
int linux_gpio_edge(int pin, int edge)
{
const char dir_str[] = "none\0rising\0falling\0both";
unsigned char ptr = 0;
char path[64];
int fd;
switch (edge) {
case 0:
ptr = 0;
break;
case 1:
ptr = 5;
break;
case 2:
ptr = 12;
break;
case 3:
ptr = 20;
break;
default:
ptr = 0;
}
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/edge", pin);
fd = open(path, O_WRONLY);
if (fd < 0) {
printf("Failed to open gpio edge for writing!\n");
return -1;
}
if (write(fd, &dir_str[ptr], strlen(&dir_str[ptr])) < 0) {
printf("Failed to set edge!\n");
return -1;
}
close(fd);
return 0;
}

View File

@@ -0,0 +1,532 @@
/*
MIT License
Copyright (c) 2023 lewis he
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
! WARN:
Please do not run the example without knowing the external load voltage of the PMU,
it may burn your external load, please check the voltage setting before running the example,
if there is any loss, please bear it by yourself
*/
#ifndef XPOWERS_NO_ERROR
#error "Running this example is known to not damage the device! Please go and uncomment this!"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <stdint.h>
#include <fcntl.h> //define O_RDWR
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <sys/poll.h>
#include "XPowersLib.h"
#ifndef CONFIG_PMU_IRQ
#define CONFIG_PMU_IRQ 55
#endif
extern int linux_gpio_edge(int pin, int edge);
extern int linux_gpio_direction(int pin, int dir);
extern int linux_gpio_export(int pin);
extern int linux_gpio_unexport(int pin);
const uint8_t pmu_irq_pin = CONFIG_PMU_IRQ;
// Change to the hardware I2C device name you need to use
const char *i2c_device = "/dev/i2c-3";
int hardware_i2c_fd = -1;
int linux_i2c_read_callback(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len)
{
uint8_t tmp[1] = {regAddr};
// Write reg address
write(hardware_i2c_fd, tmp, 1);
// Read reg data
return read(hardware_i2c_fd, data, len);
}
int linux_i2c_write_callback(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint8_t len)
{
uint8_t tmp[1] = {regAddr};
// Write reg address
write(hardware_i2c_fd, tmp, 1);
// Write data buffer
return write(hardware_i2c_fd, data, len);
}
// Use the XPowersLibInterface standard to use the xpowers API
XPowersLibInterface *PMU = NULL;
void printPMU()
{
printf("isCharging:%s\n", PMU->isCharging() ? "YES" : "NO");
printf("isDischarge:%s\n", PMU->isDischarge() ? "YES" : "NO");
printf("isVbusIn:%s\n", PMU->isVbusIn() ? "YES" : "NO");
printf("getBattVoltage:%u mV\n", PMU->getBattVoltage());
printf("getVbusVoltage:%u mV\n", PMU->getVbusVoltage());
printf("getSystemVoltage:%u mV\n", PMU->getSystemVoltage());
// The battery percentage may be inaccurate at first use, the PMU will automatically
// learn the battery curve and will automatically calibrate the battery percentage
// after a charge and discharge cycle
if (PMU->isBatteryConnect()) {
printf("getBatteryPercent:%d%%", PMU->getBatteryPercent());
}
printf("\n");
}
int main()
{
// Open I2C device
if ((hardware_i2c_fd = open(i2c_device, O_RDWR)) < 0) {
perror("Failed to open i2c device.\n");
exit(1);
} else {
printf("open : %s\r\n", i2c_device);
}
if (!PMU) {
if (ioctl(hardware_i2c_fd, I2C_SLAVE, AXP2101_SLAVE_ADDRESS) < 0) {
printf("Failed to access bus.\n");
exit(1);
}
PMU = new XPowersAXP2101(AXP2101_SLAVE_ADDRESS, linux_i2c_read_callback, linux_i2c_write_callback);
if (!PMU->init()) {
printf("Warning: Failed to find AXP2101 power management\n");
delete PMU;
PMU = NULL;
} else {
printf("AXP2101 PMU init succeeded, using AXP2101 PMU\n");
}
}
if (!PMU) {
if (ioctl(hardware_i2c_fd, I2C_SLAVE, AXP192_SLAVE_ADDRESS) < 0) {
printf("Failed to access bus.\n");
exit(1);
}
PMU = new XPowersAXP192(AXP192_SLAVE_ADDRESS, linux_i2c_read_callback, linux_i2c_write_callback);
if (!PMU->init()) {
printf("Warning: Failed to find AXP192 power management\n");
delete PMU;
PMU = NULL;
} else {
printf("AXP192 PMU init succeeded, using AXP192 PMU\n");
}
}
if (!PMU) {
if (ioctl(hardware_i2c_fd, I2C_SLAVE, AXP202_SLAVE_ADDRESS) < 0) {
printf("Failed to access bus.\n");
exit(1);
}
PMU = new XPowersAXP202(AXP202_SLAVE_ADDRESS, linux_i2c_read_callback, linux_i2c_write_callback);
printf("Warning: Failed to find AXP202 power management\n");
delete PMU;
PMU = NULL;
} else {
printf("AXP202 PMU init succeeded, using AXP202 PMU\n");
}
if (!PMU) {
printf("PMU not detected, please check..\n");
exit(1);
}
//The following AXP192 power supply setting voltage is based on esp32 T-beam
if (PMU->getChipModel() == XPOWERS_AXP192) {
// lora radio power channel
PMU->setPowerChannelVoltage(XPOWERS_LDO2, 3300);
PMU->enablePowerOutput(XPOWERS_LDO2);
// oled module power channel,
// disable it will cause abnormal communication between boot and AXP power supply,
// do not turn it off
PMU->setPowerChannelVoltage(XPOWERS_DCDC1, 3300);
// enable oled power
PMU->enablePowerOutput(XPOWERS_DCDC1);
// gnss module power channel
PMU->setPowerChannelVoltage(XPOWERS_LDO3, 3300);
// PMU->enablePowerOutput(XPOWERS_LDO3);
//protected oled power source
PMU->setProtectedChannel(XPOWERS_DCDC1);
//protected esp32 power source
PMU->setProtectedChannel(XPOWERS_DCDC3);
//disable not use channel
PMU->disablePowerOutput(XPOWERS_DCDC2);
//disable all axp chip interrupt
PMU->disableIRQ(XPOWERS_AXP192_ALL_IRQ);
//
/* Set the constant current charging current of AXP192
opt:
XPOWERS_AXP192_CHG_CUR_100MA,
XPOWERS_AXP192_CHG_CUR_190MA,
XPOWERS_AXP192_CHG_CUR_280MA,
XPOWERS_AXP192_CHG_CUR_360MA,
XPOWERS_AXP192_CHG_CUR_450MA,
XPOWERS_AXP192_CHG_CUR_550MA,
XPOWERS_AXP192_CHG_CUR_630MA,
XPOWERS_AXP192_CHG_CUR_700MA,
XPOWERS_AXP192_CHG_CUR_780MA,
XPOWERS_AXP192_CHG_CUR_880MA,
XPOWERS_AXP192_CHG_CUR_960MA,
XPOWERS_AXP192_CHG_CUR_1000MA,
XPOWERS_AXP192_CHG_CUR_1080MA,
XPOWERS_AXP192_CHG_CUR_1160MA,
XPOWERS_AXP192_CHG_CUR_1240MA,
XPOWERS_AXP192_CHG_CUR_1320MA,
*/
PMU->setChargerConstantCurr(XPOWERS_AXP192_CHG_CUR_550MA);
}
// The following AXP202 power supply voltage setting is based on esp32 T-Watch
else if (PMU->getChipModel() == XPOWERS_AXP202) {
PMU->disablePowerOutput(XPOWERS_DCDC2); //not elicited
//Display backlight
PMU->setPowerChannelVoltage(XPOWERS_LDO2, 3300);
PMU->enablePowerOutput(XPOWERS_LDO2);
// Shiled Vdd
PMU->setPowerChannelVoltage(XPOWERS_LDO3, 3300);
PMU->enablePowerOutput(XPOWERS_LDO3);
// S7xG GNSS Vdd
PMU->setPowerChannelVoltage(XPOWERS_LDO4, 1800);
PMU->enablePowerOutput(XPOWERS_LDO4);
//
/* Set the constant current charging current of AXP202
opt:
XPOWERS_AXP202_CHG_CUR_100MA,
XPOWERS_AXP202_CHG_CUR_190MA,
XPOWERS_AXP202_CHG_CUR_280MA,
XPOWERS_AXP202_CHG_CUR_360MA,
XPOWERS_AXP202_CHG_CUR_450MA,
XPOWERS_AXP202_CHG_CUR_550MA,
XPOWERS_AXP202_CHG_CUR_630MA,
XPOWERS_AXP202_CHG_CUR_700MA,
XPOWERS_AXP202_CHG_CUR_780MA,
XPOWERS_AXP202_CHG_CUR_880MA,
XPOWERS_AXP202_CHG_CUR_960MA,
XPOWERS_AXP202_CHG_CUR_1000MA,
XPOWERS_AXP202_CHG_CUR_1080MA,
XPOWERS_AXP202_CHG_CUR_1160MA,
XPOWERS_AXP202_CHG_CUR_1240MA,
XPOWERS_AXP202_CHG_CUR_1320MA,
*/
PMU->setChargerConstantCurr(XPOWERS_AXP202_CHG_CUR_550MA);
}
// The following AXP192 power supply voltage setting is based on esp32s3 T-beam
else if (PMU->getChipModel() == XPOWERS_AXP2101) {
// gnss module power channel
PMU->setPowerChannelVoltage(XPOWERS_ALDO4, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO4);
// lora radio power channel
PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO3);
// m.2 interface
PMU->setPowerChannelVoltage(XPOWERS_DCDC3, 3300);
PMU->enablePowerOutput(XPOWERS_DCDC3);
// PMU->setPowerChannelVoltage(XPOWERS_DCDC4, 3300);
// PMU->enablePowerOutput(XPOWERS_DCDC4);
//not use channel
PMU->disablePowerOutput(XPOWERS_DCDC2); //not elicited
PMU->disablePowerOutput(XPOWERS_DCDC5); //not elicited
PMU->disablePowerOutput(XPOWERS_DLDO1); //Invalid power channel, it does not exist
PMU->disablePowerOutput(XPOWERS_DLDO2); //Invalid power channel, it does not exist
PMU->disablePowerOutput(XPOWERS_VBACKUP);
//disable all axp chip interrupt
PMU->disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
/* Set the constant current charging current of AXP2101
opt:
XPOWERS_AXP2101_CHG_CUR_100MA,
XPOWERS_AXP2101_CHG_CUR_125MA,
XPOWERS_AXP2101_CHG_CUR_150MA,
XPOWERS_AXP2101_CHG_CUR_175MA,
XPOWERS_AXP2101_CHG_CUR_200MA,
XPOWERS_AXP2101_CHG_CUR_300MA,
XPOWERS_AXP2101_CHG_CUR_400MA,
XPOWERS_AXP2101_CHG_CUR_500MA,
XPOWERS_AXP2101_CHG_CUR_600MA,
XPOWERS_AXP2101_CHG_CUR_700MA,
XPOWERS_AXP2101_CHG_CUR_800MA,
XPOWERS_AXP2101_CHG_CUR_900MA,
XPOWERS_AXP2101_CHG_CUR_1000MA,
*/
PMU->setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_500MA);
}
printf("=======================================================================\n");
if (PMU->isChannelAvailable(XPOWERS_DCDC1)) {
printf("DC1 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC1) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC1));
}
if (PMU->isChannelAvailable(XPOWERS_DCDC2)) {
printf("DC2 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC2));
}
if (PMU->isChannelAvailable(XPOWERS_DCDC3)) {
printf("DC3 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC3) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC3));
}
if (PMU->isChannelAvailable(XPOWERS_DCDC4)) {
printf("DC4 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC4) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC4));
}
if (PMU->isChannelAvailable(XPOWERS_LDO2)) {
printf("LDO2 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_LDO2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_LDO2));
}
if (PMU->isChannelAvailable(XPOWERS_LDO3)) {
printf("LDO3 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_LDO3) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_LDO3));
}
if (PMU->isChannelAvailable(XPOWERS_LDO4)) {
printf("LDO4 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_LDO4) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_LDO4));
}
if (PMU->isChannelAvailable(XPOWERS_LDO5)) {
printf("LDO5 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_LDO5) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_LDO5));
}
if (PMU->isChannelAvailable(XPOWERS_ALDO1)) {
printf("ALDO1: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO1) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO1));
}
if (PMU->isChannelAvailable(XPOWERS_ALDO2)) {
printf("ALDO2: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO2));
}
if (PMU->isChannelAvailable(XPOWERS_ALDO3)) {
printf("ALDO3: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO3) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO3));
}
if (PMU->isChannelAvailable(XPOWERS_ALDO4)) {
printf("ALDO4: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO4) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO4));
}
if (PMU->isChannelAvailable(XPOWERS_BLDO1)) {
printf("BLDO1: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_BLDO1) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_BLDO1));
}
if (PMU->isChannelAvailable(XPOWERS_BLDO2)) {
printf("BLDO2: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_BLDO2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_BLDO2));
}
printf("=======================================================================\n");
//Set up the charging voltage, AXP2101/AXP192 4.2V gear is the same
// XPOWERS_AXP192_CHG_VOL_4V2 = XPOWERS_AXP2101_CHG_VOL_4V2
PMU->setChargeTargetVoltage(XPOWERS_AXP192_CHG_VOL_4V2);
// Set VSY off voltage as 2600mV , Adjustment range 2600mV ~ 3300mV
PMU->setSysPowerDownVoltage(2600);
// Get the VSYS shutdown voltage
uint16_t vol = PMU->getSysPowerDownVoltage();
printf("-> getSysPowerDownVoltage:%u\n", vol);
// Set the time of pressing the button to turn off
PMU->setPowerKeyPressOffTime(XPOWERS_POWEROFF_4S);
uint8_t opt = PMU->getPowerKeyPressOffTime();
printf("PowerKeyPressOffTime:");
switch (opt) {
case XPOWERS_POWEROFF_4S: printf("4 Second\n");
break;
case XPOWERS_POWEROFF_6S: printf("6 Second\n");
break;
case XPOWERS_POWEROFF_8S: printf("8 Second\n");
break;
case XPOWERS_POWEROFF_10S: printf("10 Second\n");
break;
default:
break;
}
// Set the button power-on press time
PMU->setPowerKeyPressOnTime(XPOWERS_POWERON_128MS);
opt = PMU->getPowerKeyPressOnTime();
printf("PowerKeyPressOnTime:");
switch (opt) {
case XPOWERS_POWERON_128MS: printf("128 Ms\n");
break;
case XPOWERS_POWERON_512MS: printf("512 Ms\n");
break;
case XPOWERS_POWERON_1S: printf("1 Second\n");
break;
case XPOWERS_POWERON_2S: printf("2 Second\n");
break;
default:
break;
}
printf("===========================================================================");
// It is necessary to disable the detection function of the TS pin on the board
// without the battery temperature detection function, otherwise it will cause abnormal charging
PMU->disableTSPinMeasure();
// Enable internal ADC detection
PMU->enableBattDetection();
PMU->enableVbusVoltageMeasure();
PMU->enableBattVoltageMeasure();
PMU->enableSystemVoltageMeasure();
/*
The default setting is CHGLED is automatically controlled by the PMU.
- XPOWERS_CHG_LED_OFF,
- XPOWERS_CHG_LED_BLINK_1HZ,
- XPOWERS_CHG_LED_BLINK_4HZ,
- XPOWERS_CHG_LED_ON,
- XPOWERS_CHG_LED_CTRL_CHG,
* */
PMU->setChargingLedMode(XPOWERS_CHG_LED_OFF);
// Clear all interrupt flags
PMU->clearIrqStatus();
/*
// call specific interrupt request
uint64_t pmuIrqMask = 0;
if (PMU->getChipModel() == XPOWERS_AXP192) {
pmuIrqMask = XPOWERS_AXP192_VBUS_INSERT_IRQ | XPOWERS_AXP192_VBUS_REMOVE_IRQ | //BATTERY
XPOWERS_AXP192_BAT_INSERT_IRQ | XPOWERS_AXP192_BAT_REMOVE_IRQ | //VBUS
XPOWERS_AXP192_PKEY_SHORT_IRQ | XPOWERS_AXP192_PKEY_LONG_IRQ | //POWER KEY
XPOWERS_AXP192_BAT_CHG_START_IRQ | XPOWERS_AXP192_BAT_CHG_DONE_IRQ ; //CHARGE
} else if (PMU->getChipModel() == XPOWERS_AXP2101) {
pmuIrqMask = XPOWERS_AXP2101_BAT_INSERT_IRQ | XPOWERS_AXP2101_BAT_REMOVE_IRQ | //BATTERY
XPOWERS_AXP2101_VBUS_INSERT_IRQ | XPOWERS_AXP2101_VBUS_REMOVE_IRQ | //VBUS
XPOWERS_AXP2101_PKEY_SHORT_IRQ | XPOWERS_AXP2101_PKEY_LONG_IRQ | //POWER KEY
XPOWERS_AXP2101_BAT_CHG_DONE_IRQ | XPOWERS_AXP2101_BAT_CHG_START_IRQ; //CHARGE
}
// Enable the required interrupt function
PMU->enableIRQ(pmuIrqMask);
*/
// Call the interrupt request through the interface class
PMU->disableInterrupt(XPOWERS_ALL_INT);
PMU->enableInterrupt(XPOWERS_USB_INSERT_INT |
XPOWERS_USB_REMOVE_INT |
XPOWERS_BATTERY_INSERT_INT |
XPOWERS_BATTERY_REMOVE_INT |
XPOWERS_PWR_BTN_CLICK_INT |
XPOWERS_CHARGE_START_INT |
XPOWERS_CHARGE_DONE_INT);
// Attach PMU irq to gpio interrupt
linux_gpio_unexport(pmu_irq_pin);
linux_gpio_export(pmu_irq_pin);
linux_gpio_direction(pmu_irq_pin, INPUT);
linux_gpio_edge(pmu_irq_pin, FALLING);
struct pollfd fdset[1];
char buf[64];
int fd, ret;
snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", pmu_irq_pin);
fd = open(buf, O_RDONLY);
if (fd < 0) {
printf("Failed to open gpio value for reading!\n");
return -1;
}
fdset[0].fd = fd;
fdset[0].events = POLLPRI;
while (1) {
ret = read(fd, buf, 10);
if (ret == -1) {
printf("read failed\n");
}
ret = poll(fdset, 1, 0);
if (ret == -1) {
printf("poll failed\n");
}
if (fdset[0].revents & POLLPRI) {
ret = lseek(fd, 0, SEEK_SET);
if (ret == -1) {
printf("lseek failed\n");
}
// Get PMU Interrupt Status Register
uint32_t status = PMU->getIrqStatus();
printf("STATUS => HEX:0x%X\n", status);
if (PMU->isVbusInsertIrq()) {
printf("isVbusInsert\n");
}
if (PMU->isVbusRemoveIrq()) {
printf("isVbusRemove\n");
}
if (PMU->isBatInsertIrq()) {
printf("isBatInsert\n");
}
if (PMU->isBatRemoveIrq()) {
printf("isBatRemove\n");
}
if (PMU->isPekeyShortPressIrq()) {
printf("isPekeyShortPress\n");
}
if (PMU->isPekeyLongPressIrq()) {
printf("isPekeyLongPress\n");
}
if (PMU->isBatChargeDoneIrq()) {
printf("isBatChargeDone\n");
}
if (PMU->isBatChargeStartIrq()) {
printf("isBatChargeStart\n");
}
// Clear PMU Interrupt Status Register
PMU->clearIrqStatus();
}
}
return 0;
}