2024-10-11 16:39:38 +02:00
// Copyright (C) 2024, Mark Qvist
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
2025-11-10 16:39:09 +01:00
# define PMU_TEMP_MIN -30
# define PMU_TEMP_MAX 90
# define PMU_TEMP_OFFSET 120
bool pmu_temp_sensor_ready = false ;
float pmu_temperature = PMU_TEMP_MIN - 1 ;
2024-10-05 00:42:19 +02:00
# if BOARD_MODEL == BOARD_TBEAM || BOARD_MODEL == BOARD_TBEAM_S_V1
2023-12-18 19:23:08 -07:00
# include <XPowersLib.h>
XPowersLibInterface * PMU = NULL ;
# ifndef PMU_WIRE_PORT
2024-10-05 00:42:19 +02:00
# if BOARD_MODEL == BOARD_TBEAM_S_V1
# define PMU_WIRE_PORT Wire1
# else
# define PMU_WIRE_PORT Wire
# endif
2023-12-18 19:23:08 -07:00
# endif
2022-10-29 00:50:16 +02:00
2022-12-16 19:59:30 +01:00
# define BAT_V_MIN 3.15
# define BAT_V_MAX 4.14
2022-10-29 00:50:16 +02:00
void disablePeripherals ( ) {
2023-12-18 19:23:08 -07:00
if ( PMU ) {
// GNSS RTC PowerVDD
PMU - > enablePowerOutput ( XPOWERS_VBACKUP ) ;
// LoRa VDD
PMU - > disablePowerOutput ( XPOWERS_ALDO2 ) ;
// GNSS VDD
PMU - > disablePowerOutput ( XPOWERS_ALDO3 ) ;
}
}
bool pmuInterrupt ;
void setPmuFlag ( )
{
pmuInterrupt = true ;
2022-10-29 00:50:16 +02:00
}
# elif BOARD_MODEL == BOARD_RNODE_NG_21 || BOARD_MODEL == BOARD_LORA32_V2_1
2022-12-16 19:59:30 +01:00
# define BAT_V_MIN 3.15
# define BAT_V_MAX 4.3
# define BAT_V_CHG 4.48
# define BAT_V_FLOAT 4.33
# define BAT_SAMPLES 5
2022-10-29 00:50:16 +02:00
const uint8_t pin_vbat = 35 ;
2022-12-16 19:59:30 +01:00
float bat_p_samples [ BAT_SAMPLES ] ;
float bat_v_samples [ BAT_SAMPLES ] ;
uint8_t bat_samples_count = 0 ;
int bat_discharging_samples = 0 ;
int bat_charging_samples = 0 ;
int bat_charged_samples = 0 ;
bool bat_voltage_dropping = false ;
float bat_delay_v = 0 ;
2024-10-01 14:57:57 +02:00
float bat_state_change_v = 0 ;
2025-01-15 10:21:15 +01:00
# elif BOARD_MODEL == BOARD_T3S3
2025-01-05 12:03:27 +01:00
# define BAT_V_MIN 3.15
2025-01-05 14:53:28 +01:00
# define BAT_V_MAX 4.217
2025-01-05 12:03:27 +01:00
# define BAT_V_CHG 4.48
# define BAT_V_FLOAT 4.33
# define BAT_SAMPLES 5
const uint8_t pin_vbat = 1 ;
float bat_p_samples [ BAT_SAMPLES ] ;
float bat_v_samples [ BAT_SAMPLES ] ;
uint8_t bat_samples_count = 0 ;
int bat_discharging_samples = 0 ;
int bat_charging_samples = 0 ;
int bat_charged_samples = 0 ;
bool bat_voltage_dropping = false ;
float bat_delay_v = 0 ;
float bat_state_change_v = 0 ;
2024-10-03 00:38:49 +02:00
# elif BOARD_MODEL == BOARD_TDECK
# define BAT_V_MIN 3.15
# define BAT_V_MAX 4.3
# define BAT_V_CHG 4.48
# define BAT_V_FLOAT 4.33
# define BAT_SAMPLES 5
const uint8_t pin_vbat = 4 ;
float bat_p_samples [ BAT_SAMPLES ] ;
float bat_v_samples [ BAT_SAMPLES ] ;
uint8_t bat_samples_count = 0 ;
int bat_discharging_samples = 0 ;
int bat_charging_samples = 0 ;
int bat_charged_samples = 0 ;
bool bat_voltage_dropping = false ;
float bat_delay_v = 0 ;
float bat_state_change_v = 0 ;
2024-09-27 00:28:37 +02:00
# elif BOARD_MODEL == BOARD_HELTEC32_V3
2025-11-10 15:49:52 +01:00
// Unless we implement some real voodoo
// on these boards, we can't say with
// any certainty whether we are actually
// charging and have reached a charge
// complete state. The *only* data point
// we have to go from is the bus voltage.
// The BAT_V_CHG and BAT_V_FLOAT values
// are set high here to avoid the display
// indication confusingly flapping
// between charge completed, charging and
// discharging states.
2025-11-10 15:50:46 +01:00
// Update: Vodoo implemented. Hopefully
// it will work accross different boards.
2025-11-10 15:49:52 +01:00
# define BAT_V_MIN 3.05
# define BAT_V_MAX 4.0
2025-11-10 12:02:36 +01:00
# define BAT_V_CHG 4.48
# define BAT_V_FLOAT 4.33
2024-10-01 14:57:57 +02:00
# define BAT_SAMPLES 7
2024-09-27 00:28:37 +02:00
const uint8_t pin_vbat = 1 ;
const uint8_t pin_ctrl = 37 ;
float bat_p_samples [ BAT_SAMPLES ] ;
float bat_v_samples [ BAT_SAMPLES ] ;
uint8_t bat_samples_count = 0 ;
int bat_discharging_samples = 0 ;
int bat_charging_samples = 0 ;
int bat_charged_samples = 0 ;
bool bat_voltage_dropping = false ;
float bat_delay_v = 0 ;
2024-10-01 14:57:57 +02:00
float bat_state_change_v = 0 ;
2025-11-01 15:33:24 +01:00
# elif BOARD_MODEL == BOARD_HELTEC32_V4
2025-11-10 15:49:52 +01:00
# define BAT_V_MIN 3.05
# define BAT_V_MAX 4.0
2025-11-01 15:33:24 +01:00
# define BAT_V_CHG 4.48
# define BAT_V_FLOAT 4.33
# define BAT_SAMPLES 7
const uint8_t pin_vbat = 1 ;
const uint8_t pin_ctrl = 37 ;
float bat_p_samples [ BAT_SAMPLES ] ;
float bat_v_samples [ BAT_SAMPLES ] ;
uint8_t bat_samples_count = 0 ;
int bat_discharging_samples = 0 ;
int bat_charging_samples = 0 ;
int bat_charged_samples = 0 ;
bool bat_voltage_dropping = false ;
float bat_delay_v = 0 ;
float bat_state_change_v = 0 ;
2025-01-13 18:05:35 +01:00
# elif BOARD_MODEL == BOARD_HELTEC_T114
# define BAT_V_MIN 3.15
# define BAT_V_MAX 4.165
# define BAT_V_CHG 4.48
# define BAT_V_FLOAT 4.33
# define BAT_SAMPLES 7
const uint8_t pin_vbat = 4 ;
const uint8_t pin_ctrl = 6 ;
float bat_p_samples [ BAT_SAMPLES ] ;
float bat_v_samples [ BAT_SAMPLES ] ;
uint8_t bat_samples_count = 0 ;
int bat_discharging_samples = 0 ;
int bat_charging_samples = 0 ;
int bat_charged_samples = 0 ;
bool bat_voltage_dropping = false ;
float bat_delay_v = 0 ;
float bat_state_change_v = 0 ;
2025-01-15 18:38:14 +01:00
# elif BOARD_MODEL == BOARD_TECHO
# define BAT_V_MIN 3.15
2025-01-15 21:18:52 +01:00
# define BAT_V_MAX 4.16
2025-01-15 18:38:14 +01:00
# define BAT_V_CHG 4.48
# define BAT_V_FLOAT 4.33
# define BAT_SAMPLES 7
const uint8_t pin_vbat = 4 ;
float bat_p_samples [ BAT_SAMPLES ] ;
float bat_v_samples [ BAT_SAMPLES ] ;
uint8_t bat_samples_count = 0 ;
int bat_discharging_samples = 0 ;
int bat_charging_samples = 0 ;
int bat_charged_samples = 0 ;
bool bat_voltage_dropping = false ;
float bat_delay_v = 0 ;
float bat_state_change_v = 0 ;
2022-10-29 00:50:16 +02:00
# endif
uint32_t last_pmu_update = 0 ;
uint8_t pmu_target_pps = 1 ;
int pmu_update_interval = 1000 / pmu_target_pps ;
2025-11-10 15:49:52 +01:00
uint8_t pmu_charged_ascertain = 0 ;
2023-10-07 19:45:55 +02:00
uint8_t pmu_rc = 0 ;
2025-11-10 15:49:52 +01:00
uint8_t pmu_sc = 0 ;
float bat_delay_diff = 0 ;
bool bat_diff_positive = false ;
2023-10-07 19:45:55 +02:00
# define PMU_R_INTERVAL 5
2025-11-10 15:49:52 +01:00
# define PMU_SCV_RESET_INTERVAL 3
2023-10-07 19:45:55 +02:00
void kiss_indicate_battery ( ) ;
2025-11-10 16:39:09 +01:00
void kiss_indicate_temperature ( ) ;
void measure_temperature ( ) {
2025-11-14 01:16:38 +01:00
# if PLATFORM == PLATFORM_ESP32
if ( pmu_temp_sensor_ready ) { pmu_temperature = temperatureRead ( ) ; } else { pmu_temperature = PMU_TEMP_MIN - 1 ; }
# endif
2025-11-10 16:39:09 +01:00
}
2022-10-29 00:50:16 +02:00
void measure_battery ( ) {
2025-11-01 15:33:24 +01:00
# if BOARD_MODEL == BOARD_RNODE_NG_21 || BOARD_MODEL == BOARD_LORA32_V2_1 || BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_HELTEC32_V4 || BOARD_MODEL == BOARD_TDECK || BOARD_MODEL == BOARD_T3S3 || BOARD_MODEL == BOARD_HELTEC_T114 || BOARD_MODEL == BOARD_TECHO
2022-12-16 19:59:30 +01:00
battery_installed = true ;
2025-11-10 15:49:52 +01:00
# if BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_HELTEC32_V4
battery_indeterminate = false ;
# else
battery_indeterminate = true ;
# endif
2024-09-27 00:28:37 +02:00
# if BOARD_MODEL == BOARD_HELTEC32_V3
float battery_measurement = ( float ) ( analogRead ( pin_vbat ) ) * 0.0041 ;
2025-11-01 15:33:24 +01:00
# elif BOARD_MODEL == BOARD_HELTEC32_V4
2025-11-10 15:49:52 +01:00
float battery_measurement = ( float ) ( analogRead ( pin_vbat ) ) * 0.00418 ;
2025-01-15 10:21:15 +01:00
# elif BOARD_MODEL == BOARD_T3S3
2025-01-05 14:53:28 +01:00
float battery_measurement = ( float ) ( analogRead ( pin_vbat ) ) / 4095.0 * 6.7828 ;
2025-01-13 18:05:35 +01:00
# elif BOARD_MODEL == BOARD_HELTEC_T114
float battery_measurement = ( float ) ( analogRead ( pin_vbat ) ) * 0.017165 ;
2025-01-15 18:38:14 +01:00
# elif BOARD_MODEL == BOARD_TECHO
2025-01-15 21:18:52 +01:00
float battery_measurement = ( float ) ( analogRead ( pin_vbat ) ) * 0.007067 ;
2024-09-27 00:28:37 +02:00
# else
2025-01-05 14:53:28 +01:00
float battery_measurement = ( float ) ( analogRead ( pin_vbat ) ) / 4095.0 * 7.26 ;
2024-09-27 00:28:37 +02:00
# endif
bat_v_samples [ bat_samples_count % BAT_SAMPLES ] = battery_measurement ;
2022-12-16 19:59:30 +01:00
bat_p_samples [ bat_samples_count % BAT_SAMPLES ] = ( ( battery_voltage - BAT_V_MIN ) / ( BAT_V_MAX - BAT_V_MIN ) ) * 100.0 ;
bat_samples_count + + ;
if ( ! battery_ready & & bat_samples_count > = BAT_SAMPLES ) {
battery_ready = true ;
}
2022-10-30 22:27:30 +01:00
2022-12-16 19:59:30 +01:00
if ( battery_ready ) {
2022-10-29 00:50:16 +02:00
2022-12-16 19:59:30 +01:00
battery_percent = 0 ;
for ( uint8_t bi = 0 ; bi < BAT_SAMPLES ; bi + + ) {
battery_percent + = bat_p_samples [ bi ] ;
}
battery_percent = battery_percent / BAT_SAMPLES ;
battery_voltage = 0 ;
for ( uint8_t bi = 0 ; bi < BAT_SAMPLES ; bi + + ) {
battery_voltage + = bat_v_samples [ bi ] ;
}
battery_voltage = battery_voltage / BAT_SAMPLES ;
if ( bat_delay_v = = 0 ) bat_delay_v = battery_voltage ;
2024-10-01 14:57:57 +02:00
if ( bat_state_change_v = = 0 ) bat_state_change_v = battery_voltage ;
2022-12-16 19:59:30 +01:00
if ( battery_percent > 100.0 ) battery_percent = 100.0 ;
if ( battery_percent < 0.0 ) battery_percent = 0.0 ;
if ( bat_samples_count % BAT_SAMPLES = = 0 ) {
2025-11-10 15:49:52 +01:00
pmu_sc + + ;
bat_delay_diff = battery_voltage - bat_state_change_v ;
2024-10-01 14:57:57 +02:00
2022-12-16 19:59:30 +01:00
if ( battery_voltage < bat_delay_v & & battery_voltage < BAT_V_FLOAT ) {
2024-10-01 14:57:57 +02:00
if ( bat_voltage_dropping = = false ) {
2025-11-10 15:49:52 +01:00
if ( bat_delay_diff < - 0.008 ) {
2024-10-01 14:57:57 +02:00
bat_voltage_dropping = true ;
bat_state_change_v = battery_voltage ;
}
2025-11-10 15:49:52 +01:00
} else {
if ( pmu_sc % PMU_SCV_RESET_INTERVAL = = 0 ) { bat_state_change_v = battery_voltage ; }
2024-10-01 14:57:57 +02:00
}
2022-12-16 19:59:30 +01:00
} else {
2024-10-01 14:57:57 +02:00
if ( bat_voltage_dropping = = true ) {
2024-10-01 15:33:03 +02:00
if ( bat_delay_diff > 0.01 ) {
2024-10-01 14:57:57 +02:00
bat_voltage_dropping = false ;
bat_state_change_v = battery_voltage ;
}
}
2022-12-16 19:59:30 +01:00
}
bat_samples_count = 0 ;
2024-10-01 14:57:57 +02:00
bat_delay_v = battery_voltage ;
2022-12-16 19:59:30 +01:00
}
if ( bat_voltage_dropping & & battery_voltage < BAT_V_FLOAT ) {
2025-11-10 15:49:52 +01:00
// if (battery_state != BATTERY_STATE_DISCHARGING) { SerialBT.printf("STATE CHANGE to DISCHARGING at delta=%.3fv. State change v is now %.3fv.\n", bat_delay_diff, bat_state_change_v); }
2022-12-16 19:59:30 +01:00
battery_state = BATTERY_STATE_DISCHARGING ;
2025-11-10 15:49:52 +01:00
pmu_charged_ascertain = 0 ;
2022-12-16 19:59:30 +01:00
} else {
2025-11-10 15:49:52 +01:00
if ( pmu_charged_ascertain < 8 ) { pmu_charged_ascertain + + ; }
else {
if ( battery_percent < 100.0 ) {
// if (battery_state != BATTERY_STATE_CHARGING) { SerialBT.printf("STATE CHANGE to CHARGING at delta=%.3fv. State change v is now %.3fv.\n", bat_delay_diff, bat_state_change_v); }
battery_state = BATTERY_STATE_CHARGING ;
} else {
// if (battery_state != BATTERY_STATE_CHARGED) { SerialBT.printf("STATE CHANGE to CHARGED at delta=%.3fv. State change v is now %.3fv.\n", bat_delay_diff, bat_state_change_v); }
battery_state = BATTERY_STATE_CHARGED ;
}
2024-10-11 10:21:10 +02:00
}
2022-12-16 19:59:30 +01:00
}
2025-01-18 15:20:58 +01:00
# if MCU_VARIANT == MCU_NRF52
if ( bt_state ! = BT_STATE_OFF ) { blebas . write ( battery_percent ) ; }
# endif
2022-12-16 19:59:30 +01:00
// if (bt_state == BT_STATE_CONNECTED) {
2025-11-10 15:49:52 +01:00
// SerialBT.printf("\nBus voltage %.3fv. Unfiltered %.3fv. Diff %.3f", battery_voltage, bat_v_samples[BAT_SAMPLES-1], bat_delay_diff);
2025-11-10 12:02:36 +01:00
// if (bat_voltage_dropping) { SerialBT.printf("\n Voltage is dropping. Percentage %.1f%%.", battery_percent); }
// else { SerialBT.printf("\n Voltage is not dropping. Percentage %.1f%%.", battery_percent); }
2025-11-10 15:49:52 +01:00
// if (battery_state == BATTERY_STATE_DISCHARGING) { SerialBT.printf("\n Battery discharging. delay_v %.3fv\nState change at %.3fv", bat_delay_v, bat_state_change_v); }
// if (battery_state == BATTERY_STATE_CHARGING) { SerialBT.printf("\n Battery charging. delay_v %.3fv\nState change at %.3fv", bat_delay_v, bat_state_change_v); }
2025-11-10 12:02:36 +01:00
// if (battery_state == BATTERY_STATE_CHARGED) { SerialBT.print("\n Battery is charged."); }
2024-10-01 14:57:57 +02:00
// SerialBT.print("\n");
2022-12-16 19:59:30 +01:00
// }
2022-10-29 00:50:16 +02:00
}
2024-10-05 00:42:19 +02:00
# elif BOARD_MODEL == BOARD_TBEAM || BOARD_MODEL == BOARD_TBEAM_S_V1
2023-12-18 19:23:08 -07:00
if ( PMU ) {
float discharge_current = 0 ;
float charge_current = 0 ;
float ext_voltage = 0 ;
float ext_current = 0 ;
if ( PMU - > getChipModel ( ) = = XPOWERS_AXP192 ) {
discharge_current = ( ( XPowersAXP192 * ) PMU ) - > getBattDischargeCurrent ( ) ;
charge_current = ( ( XPowersAXP192 * ) PMU ) - > getBatteryChargeCurrent ( ) ;
battery_voltage = PMU - > getBattVoltage ( ) / 1000.0 ;
// battery_percent = PMU->getBattPercentage()*1.0;
battery_installed = PMU - > isBatteryConnect ( ) ;
external_power = PMU - > isVbusIn ( ) ;
ext_voltage = PMU - > getVbusVoltage ( ) / 1000.0 ;
ext_current = ( ( XPowersAXP192 * ) PMU ) - > getVbusCurrent ( ) ;
}
else if ( PMU - > getChipModel ( ) = = XPOWERS_AXP2101 ) {
battery_voltage = PMU - > getBattVoltage ( ) / 1000.0 ;
// battery_percent = PMU->getBattPercentage()*1.0;
battery_installed = PMU - > isBatteryConnect ( ) ;
external_power = PMU - > isVbusIn ( ) ;
ext_voltage = PMU - > getVbusVoltage ( ) / 1000.0 ;
}
if ( battery_installed ) {
if ( PMU - > isCharging ( ) ) {
battery_state = BATTERY_STATE_CHARGING ;
2022-12-16 19:59:30 +01:00
battery_percent = ( ( battery_voltage - BAT_V_MIN ) / ( BAT_V_MAX - BAT_V_MIN ) ) * 100.0 ;
2022-10-30 22:27:30 +01:00
} else {
2023-12-18 19:23:08 -07:00
if ( PMU - > isDischarge ( ) ) {
battery_state = BATTERY_STATE_DISCHARGING ;
battery_percent = ( ( battery_voltage - BAT_V_MIN ) / ( BAT_V_MAX - BAT_V_MIN ) ) * 100.0 ;
} else {
battery_state = BATTERY_STATE_CHARGED ;
battery_percent = 100.0 ;
}
2022-10-30 22:27:30 +01:00
}
2023-12-18 19:23:08 -07:00
} else {
2024-10-01 18:07:10 +02:00
battery_state = BATTERY_STATE_UNKNOWN ;
2023-12-18 19:23:08 -07:00
battery_percent = 0.0 ;
battery_voltage = 0.0 ;
2022-10-30 22:27:30 +01:00
}
2023-12-18 19:23:08 -07:00
if ( battery_percent > 100.0 ) battery_percent = 100.0 ;
if ( battery_percent < 0.0 ) battery_percent = 0.0 ;
float charge_watts = battery_voltage * ( charge_current / 1000.0 ) ;
float discharge_watts = battery_voltage * ( discharge_current / 1000.0 ) ;
float ext_watts = ext_voltage * ( ext_current / 1000.0 ) ;
battery_ready = true ;
// if (bt_state == BT_STATE_CONNECTED) {
// if (battery_installed) {
// if (external_power) {
// SerialBT.printf("External power connected, drawing %.2fw, %.1fmA at %.1fV\n", ext_watts, ext_current, ext_voltage);
// } else {
// SerialBT.println("Running on battery");
// }
// SerialBT.printf("Battery percentage %.1f%%\n", battery_percent);
// SerialBT.printf("Battery voltage %.2fv\n", battery_voltage);
// // SerialBT.printf("Temperature %.1f%\n", auxillary_temperature);
// if (battery_state == BATTERY_STATE_CHARGING) {
// SerialBT.printf("Charging with %.2fw, %.1fmA at %.1fV\n", charge_watts, charge_current, battery_voltage);
// } else if (battery_state == BATTERY_STATE_DISCHARGING) {
// SerialBT.printf("Discharging at %.2fw, %.1fmA at %.1fV\n", discharge_watts, discharge_current, battery_voltage);
// } else if (battery_state == BATTERY_STATE_CHARGED) {
// SerialBT.printf("Battery charged\n");
// }
// } else {
// SerialBT.println("No battery installed");
// }
// SerialBT.println("");
// }
}
else {
battery_ready = false ;
}
2022-10-29 00:50:16 +02:00
# endif
2023-10-07 19:45:55 +02:00
if ( battery_ready ) {
pmu_rc + + ;
if ( pmu_rc % PMU_R_INTERVAL = = 0 ) {
kiss_indicate_battery ( ) ;
2025-11-10 16:39:09 +01:00
if ( pmu_temp_sensor_ready ) { kiss_indicate_temperature ( ) ; }
2023-10-07 19:45:55 +02:00
}
}
2022-10-29 00:50:16 +02:00
}
void update_pmu ( ) {
if ( millis ( ) - last_pmu_update > = pmu_update_interval ) {
measure_battery ( ) ;
2025-11-10 16:39:09 +01:00
measure_temperature ( ) ;
2022-10-29 00:50:16 +02:00
last_pmu_update = millis ( ) ;
}
}
bool init_pmu ( ) {
2025-11-10 16:39:09 +01:00
# if IS_ESP32S3
pmu_temp_sensor_ready = true ;
# endif
2025-01-15 21:18:52 +01:00
# if BOARD_MODEL == BOARD_RNODE_NG_21 || BOARD_MODEL == BOARD_LORA32_V2_1 || BOARD_MODEL == BOARD_TDECK || BOARD_MODEL == BOARD_T3S3 || BOARD_MODEL == BOARD_TECHO
2022-10-29 00:50:16 +02:00
pinMode ( pin_vbat , INPUT ) ;
return true ;
2024-09-27 00:28:37 +02:00
# elif BOARD_MODEL == BOARD_HELTEC32_V3
2025-04-24 00:09:33 +00:00
// there are three version of V3: V3, V3.1, and V3.2
// V3 and V3.1 have a pull up on pin_ctrl and are active low
// V3.2 has a transistor and active high
// put the pin input mode and read it. if it's high, we have V3 or V3.1
// other wise, it's a V3.2
uint16_t pin_ctrl_value ;
uint8_t pin_ctrl_active = LOW ;
pinMode ( pin_ctrl , INPUT ) ;
pin_ctrl_value = digitalRead ( pin_ctrl ) ;
if ( pin_ctrl_value = = HIGH ) {
// We have either a V3 or V3.1
pin_ctrl_active = LOW ;
}
else {
// We have a V3.2
pin_ctrl_active = HIGH ;
}
2024-09-27 00:28:37 +02:00
pinMode ( pin_ctrl , OUTPUT ) ;
2025-04-24 00:09:33 +00:00
digitalWrite ( pin_ctrl , pin_ctrl_active ) ;
2024-09-27 00:28:37 +02:00
return true ;
2025-11-01 15:33:24 +01:00
# elif BOARD_MODEL == BOARD_HELTEC32_V4
pinMode ( pin_ctrl , OUTPUT ) ;
2025-11-10 15:49:52 +01:00
digitalWrite ( pin_ctrl , HIGH ) ;
2025-11-01 15:33:24 +01:00
return true ;
2025-01-13 18:05:35 +01:00
# elif BOARD_MODEL == BOARD_HELTEC_T114
pinMode ( pin_ctrl , OUTPUT ) ;
digitalWrite ( pin_ctrl , HIGH ) ;
return true ;
2022-10-29 00:50:16 +02:00
# elif BOARD_MODEL == BOARD_TBEAM
Wire . begin ( I2C_SDA , I2C_SCL ) ;
2023-12-18 19:23:08 -07:00
if ( ! PMU ) {
PMU = new XPowersAXP2101 ( PMU_WIRE_PORT ) ;
if ( ! PMU - > init ( ) ) {
delete PMU ;
PMU = NULL ;
}
}
if ( ! PMU ) {
PMU = new XPowersAXP192 ( PMU_WIRE_PORT ) ;
if ( ! PMU - > init ( ) ) {
delete PMU ;
PMU = NULL ;
}
}
if ( ! PMU ) {
return false ;
}
2022-10-29 00:50:16 +02:00
// Configure charging indicator
2023-12-18 19:23:08 -07:00
PMU - > setChargingLedMode ( XPOWERS_CHG_LED_OFF ) ;
2022-10-29 00:50:16 +02:00
2023-12-18 19:23:08 -07:00
pinMode ( PMU_IRQ , INPUT_PULLUP ) ;
attachInterrupt ( PMU_IRQ , setPmuFlag , FALLING ) ;
2022-10-29 00:50:16 +02:00
2023-12-18 19:23:08 -07:00
if ( PMU - > getChipModel ( ) = = XPOWERS_AXP192 ) {
2022-10-29 00:50:16 +02:00
2023-12-18 19:23:08 -07:00
// Turn off unused power sources to save power
PMU - > disablePowerOutput ( XPOWERS_DCDC1 ) ;
PMU - > disablePowerOutput ( XPOWERS_DCDC2 ) ;
PMU - > disablePowerOutput ( XPOWERS_LDO2 ) ;
PMU - > disablePowerOutput ( XPOWERS_LDO3 ) ;
2022-10-29 00:50:16 +02:00
2023-12-18 19:23:08 -07:00
// Set the power of LoRa and GPS module to 3.3V
// LoRa
PMU - > setPowerChannelVoltage ( XPOWERS_LDO2 , 3300 ) ;
// GPS
PMU - > setPowerChannelVoltage ( XPOWERS_LDO3 , 3300 ) ;
// OLED
PMU - > setPowerChannelVoltage ( XPOWERS_DCDC1 , 3300 ) ;
2022-10-29 00:50:16 +02:00
2023-12-18 19:23:08 -07:00
// Turn on LoRa
PMU - > enablePowerOutput ( XPOWERS_LDO2 ) ;
2022-10-29 00:50:16 +02:00
2023-12-18 19:23:08 -07:00
// Turn on GPS
//PMU->enablePowerOutput(XPOWERS_LDO3);
// protected oled power source
PMU - > setProtectedChannel ( XPOWERS_DCDC1 ) ;
// protected esp32 power source
PMU - > setProtectedChannel ( XPOWERS_DCDC3 ) ;
// enable oled power
PMU - > enablePowerOutput ( XPOWERS_DCDC1 ) ;
PMU - > disableIRQ ( XPOWERS_AXP192_ALL_IRQ ) ;
PMU - > enableIRQ ( XPOWERS_AXP192_VBUS_REMOVE_IRQ |
XPOWERS_AXP192_VBUS_INSERT_IRQ |
XPOWERS_AXP192_BAT_CHG_DONE_IRQ |
XPOWERS_AXP192_BAT_CHG_START_IRQ |
XPOWERS_AXP192_BAT_REMOVE_IRQ |
XPOWERS_AXP192_BAT_INSERT_IRQ |
XPOWERS_AXP192_PKEY_SHORT_IRQ
) ;
}
else if ( PMU - > getChipModel ( ) = = XPOWERS_AXP2101 ) {
// Turn off unused power sources to save power
PMU - > disablePowerOutput ( XPOWERS_DCDC2 ) ;
PMU - > disablePowerOutput ( XPOWERS_DCDC3 ) ;
PMU - > disablePowerOutput ( XPOWERS_DCDC4 ) ;
PMU - > disablePowerOutput ( XPOWERS_DCDC5 ) ;
PMU - > disablePowerOutput ( XPOWERS_ALDO1 ) ;
PMU - > disablePowerOutput ( XPOWERS_ALDO2 ) ;
PMU - > disablePowerOutput ( XPOWERS_ALDO3 ) ;
PMU - > disablePowerOutput ( XPOWERS_ALDO4 ) ;
PMU - > disablePowerOutput ( XPOWERS_BLDO1 ) ;
PMU - > disablePowerOutput ( XPOWERS_BLDO2 ) ;
PMU - > disablePowerOutput ( XPOWERS_DLDO1 ) ;
PMU - > disablePowerOutput ( XPOWERS_DLDO2 ) ;
PMU - > disablePowerOutput ( XPOWERS_VBACKUP ) ;
// Set the power of LoRa and GPS module to 3.3V
// LoRa
PMU - > setPowerChannelVoltage ( XPOWERS_ALDO2 , 3300 ) ;
// GPS
PMU - > setPowerChannelVoltage ( XPOWERS_ALDO3 , 3300 ) ;
PMU - > setPowerChannelVoltage ( XPOWERS_VBACKUP , 3300 ) ;
// ESP32 VDD
// ! No need to set, automatically open , Don't close it
// PMU->setPowerChannelVoltage(XPOWERS_DCDC1, 3300);
// PMU->setProtectedChannel(XPOWERS_DCDC1);
PMU - > setProtectedChannel ( XPOWERS_DCDC1 ) ;
// LoRa VDD
PMU - > enablePowerOutput ( XPOWERS_ALDO2 ) ;
// GNSS VDD
//PMU->enablePowerOutput(XPOWERS_ALDO3);
// GNSS RTC PowerVDD
//PMU->enablePowerOutput(XPOWERS_VBACKUP);
}
PMU - > enableSystemVoltageMeasure ( ) ;
PMU - > enableVbusVoltageMeasure ( ) ;
PMU - > enableBattVoltageMeasure ( ) ;
// 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 ( ) ;
// Set the time of pressing the button to turn off
PMU - > setPowerKeyPressOffTime ( XPOWERS_POWEROFF_4S ) ;
2022-10-29 00:50:16 +02:00
2024-10-05 00:42:19 +02:00
return true ;
# elif BOARD_MODEL == BOARD_TBEAM_S_V1
Wire1 . begin ( I2C_SDA , I2C_SCL ) ;
if ( ! PMU ) {
PMU = new XPowersAXP2101 ( PMU_WIRE_PORT ) ;
if ( ! PMU - > init ( ) ) {
delete PMU ;
PMU = NULL ;
}
}
if ( ! PMU ) {
return false ;
}
/**
* gnss module power channel
* The default ALDO4 is off , you need to turn on the GNSS power first , otherwise it will be invalid during
* initialization
*/
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 ) ;
/**
* ALDO2 cannot be turned off .
* It is a necessary condition for sensor communication .
* It must be turned on to properly access the sensor and screen
* It is also responsible for the power supply of PCF8563
*/
PMU - > setPowerChannelVoltage ( XPOWERS_ALDO2 , 3300 ) ;
PMU - > enablePowerOutput ( XPOWERS_ALDO2 ) ;
// 6-axis , magnetometer ,bme280 , oled screen power channel
PMU - > setPowerChannelVoltage ( XPOWERS_ALDO1 , 3300 ) ;
PMU - > enablePowerOutput ( XPOWERS_ALDO1 ) ;
// sdcard power channle
PMU - > setPowerChannelVoltage ( XPOWERS_BLDO1 , 3300 ) ;
PMU - > enablePowerOutput ( XPOWERS_BLDO1 ) ;
// 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 ) ;
// Configure charging
PMU - > setChargeTargetVoltage ( XPOWERS_AXP2101_CHG_VOL_4V2 ) ;
PMU - > setChargerConstantCurr ( XPOWERS_AXP2101_CHG_CUR_500MA ) ;
// TODO: Reset
PMU - > setChargingLedMode ( XPOWERS_CHG_LED_CTRL_CHG ) ;
// Set the time of pressing the button to turn off
PMU - > setPowerKeyPressOffTime ( XPOWERS_POWEROFF_4S ) ;
PMU - > setPowerKeyPressOnTime ( XPOWERS_POWERON_128MS ) ;
// disable all axp chip interrupt
PMU - > disableIRQ ( XPOWERS_AXP2101_ALL_IRQ ) ;
PMU - > clearIrqStatus ( ) ;
// 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 ( ) ;
PMU - > enableVbusVoltageMeasure ( ) ;
PMU - > enableBattVoltageMeasure ( ) ;
2022-10-29 00:50:16 +02:00
return true ;
# else
return false ;
# endif
}