From 0b710dab63f08f0289940970b42de7679e1d9c3c Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Tue, 7 May 2024 15:48:02 +0200 Subject: [PATCH 01/56] Fix compile error in deep sleep example --- .../DeepSleep_WakeFromRTC_H7.ino | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino b/examples/DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino index f4ed84f..774b277 100644 --- a/examples/DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino +++ b/examples/DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino @@ -1,14 +1,15 @@ #include "Arduino.h" #include "Arduino_PowerManagement.h" -PowerManagement manager; Board board; void setup() { - manager = PowerManagement(); - manager.begin(); - board = manager.getBoard(); + board = Board(); + if(!board.begin()){ + Serial.println("Board initialization failed."); + while (true); + } board.enableWakeupFromRTC(); board.sleepFor(0, 0, 1); From 9a87c652ffa16b3ce00d899082bffa191e740ffa Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Wed, 8 May 2024 11:07:36 +0200 Subject: [PATCH 02/56] Rename wire utils file --- src/{wireUtils.h => WireUtils.h} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{wireUtils.h => WireUtils.h} (100%) diff --git a/src/wireUtils.h b/src/WireUtils.h similarity index 100% rename from src/wireUtils.h rename to src/WireUtils.h From bdf5ba6e1505174ab759e1cab0addee5c2e3d74f Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Wed, 8 May 2024 14:17:58 +0200 Subject: [PATCH 03/56] Apply style guide to enums --- src/Charger.cpp | 22 ++++++++--------- src/Charger.h | 63 ++++++++++++++++++++++++++----------------------- 2 files changed, 45 insertions(+), 40 deletions(-) diff --git a/src/Charger.cpp b/src/Charger.cpp index 108fe4f..02e7c35 100644 --- a/src/Charger.cpp +++ b/src/Charger.cpp @@ -224,26 +224,26 @@ ChargingState Charger::getState(){ uint8_t reg_val = PMIC.readPMICreg(Register::CHARGER_CHG_SNS); switch (extractBits(reg_val, 0, 3)) { case 0: - return ChargingState::PreCharge; + return ChargingState::preCharge; case 1: - return ChargingState::FastChargeConstantCurrent; + return ChargingState::fastChargeConstantCurrent; case 2: - return ChargingState::FastChargeConstantVoltage; + return ChargingState::fastChargeConstantVoltage; case 3: - return ChargingState::EndOfCharge; + return ChargingState::endOfCharge; case 4: - return ChargingState::Done; + return ChargingState::done; case 6: - return ChargingState::TimerFaultError; + return ChargingState::timerFaultError; case 7: - return ChargingState::ThermistorSuspendError; + return ChargingState::thermistorSuspendError; case 8: - return ChargingState::ChargerDisabled; + return ChargingState::chargerDisabled; case 9: - return ChargingState::BatteryOvervoltageError; + return ChargingState::batteryOvervoltageError; case 12: - return ChargingState::ChargerBypassed; + return ChargingState::chargerBypassed; default: - return ChargingState::None; + return ChargingState::none; } } diff --git a/src/Charger.h b/src/Charger.h index feb2a68..b54675b 100644 --- a/src/Charger.h +++ b/src/Charger.h @@ -9,75 +9,64 @@ typedef IEndOfCharge EndOfChargeCurrent; typedef IInputCurrentLimit InputCurrentLimit; /** - * Enum representing different states of charging. - * @see #None - * @see #PreCharge - * @see #FastChargeConstantCurrent - * @see #FastChargeConstantVoltage - * @see #EndOfCharge - * @see #Done - * @see #TimerFaultError - * @see #ThermistorSuspendError - * @see #ChargerDisabled - * @see #BatteryOvervoltageError - * @see #ChargerBypassed + * Enum representing different states of charging. */ enum class ChargingState { /** * Provided by the registers, not used in this API. */ - None = -1, + none = -1, /** * First stage of the charging process, prepares battery for the charging process. */ - PreCharge = 0, + preCharge = 0, /** * Second phase of the charging process where the battery is charging in constant current mode until it reaches the voltage where the it's considered fully charged. (4.2V) */ - FastChargeConstantCurrent = 1, + fastChargeConstantCurrent = 1, /** * Third phase of the charging process where the battery is kept at the fully charged voltage and current is slowly decreased to the end of charge current. */ - FastChargeConstantVoltage = 2, + fastChargeConstantVoltage = 2, /** * If the battery is still connected, the charger will ensure it's kept at 4.2V by topping up the voltage to avoid self discharge. */ - EndOfCharge = 3, + endOfCharge = 3, /** * Battery is fully charged */ - Done = 4, + done = 4, /** * The timer that is monitoring the charge status has encountered an error. */ - TimerFaultError = 6, + timerFaultError = 6, /** * Charging was suspended due to overheating */ - ThermistorSuspendError = 7, + thermistorSuspendError = 7, /** * Charger is disabled */ - ChargerDisabled = 8, + chargerDisabled = 8, /** * Charging was suspended due to an overvoltage fault */ - BatteryOvervoltageError = 9, + batteryOvervoltageError = 9, /** * The charger is bypassed completely and the USB voltage is powering the board */ - ChargerBypassed = 12 + chargerBypassed = 12 }; /** @@ -131,9 +120,15 @@ class Charger { /** * @brief Set the end-of-charge current. - * The default end-of-charge current is set to 0.05A. + * The charger IC determines when to terminate the charge cycle based on the current going into the battery + * dropping below the given threshold during the constant voltage phase. At this point, the battery + * is considered fully charged and charging is completed. If charge termination is disabled, + * the charge current will naturally decay to 0mA, but this is rarely done in practice. + * This is because the amount of charge going into the battery exponentially decreases during CV charging, + * and it would take a significantly longer time to recharge the battery with a very little increase in capacity. * @param current End-of-charge current in milli amperes (mA). - * Supported values: 5, 10, 20, 30, 50 + * The default end-of-charge current is set to 5 mA. + * Supported values: 5, 10, 20, 30, 50 * @return True if successful, false if an invalid value was provided or if the PMIC communication failed. */ bool setEndOfChargeCurrent(uint16_t current); @@ -164,20 +159,30 @@ class Charger { * @brief Get the input current limit. It is a safeguard to prevent overcurrent when charging * respectively to the maximum current the power source can provide. * - * This function returns the current limit of the input power source. - * - * @return The input current limit in amps. + * @return The input current limit in milli amperes (mA). */ uint16_t getInputCurrentLimit(); /** * @brief Get the current charging status. * @return Charging status enum value (ChargingState). + * The possible states are: + * - none: Provided by the registers, not used in this API. + * - preCharge: First stage of the charging process, prepares battery for the charging process. + * - fastChargeConstantCurrent: Second phase of the charging process where the battery is charging in constant current mode until it reaches the voltage where the it's considered fully charged. (4.2V) + * - fastChargeConstantVoltage: Third phase of the charging process where the battery is kept at the fully charged voltage and current is slowly decreased to the end of charge current. + * - endOfCharge: If the battery is still connected, the charger will ensure it's kept at 4.2V by topping up the voltage to avoid self discharge. + * - done: Battery is fully charged + * - timerFaultError: The timer that is monitoring the charge status has encountered an error. + * - thermistorSuspendError: Charging was suspended due to overheating + * - chargerDisabled: Charger is disabled + * - batteryOvervoltageError: Charging was suspended due to an overvoltage fault + * - chargerBypassed: The charger is bypassed completely and the USB voltage is powering the board */ ChargingState getState(); /** - * @brief Checks if the charger is enabled. + * @brief Checks if the charger and thus charging is enabled. * By default, the charger is enabled. * @return true if the charger is enabled, false otherwise. */ From b366d884da20a4b42827880223530677667e7026 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Wed, 8 May 2024 14:18:06 +0200 Subject: [PATCH 04/56] Update docs in charger sketch --- examples/Charger/Charger.ino | 48 +++++++++++++++++------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/examples/Charger/Charger.ino b/examples/Charger/Charger.ino index 6c8b425..8620e95 100644 --- a/examples/Charger/Charger.ino +++ b/examples/Charger/Charger.ino @@ -1,9 +1,9 @@ /* -Charger Demo + Charger Demo -This sketch demonstrates how to write charging parameters,read charger state and monitor charging using the PowerManagement library: -* In the setup() function, it sets the charging parameters -* In the loop() functionit prints the battery's voltage, current, percentage and the charger's state allowing you to monitor charging. + This sketch demonstrates how to write charging parameters,read charger state and monitor charging using the PowerManagement library: + * In the setup() function, it sets the charging parameters + * In the loop() functionit prints the battery's voltage, current, percentage and the charger's state allowing you to monitor charging. Requirements: - Arduino Portenta C33, Arduino Portenta H7, Arduino Nicla Vision @@ -11,20 +11,18 @@ This sketch demonstrates how to write charging parameters,read charger state and - PowerManagement library (installable from the Arduino Library Manager) Usage: - 1. Install the required library: - - Open the Arduino IDE. - - Go to "Sketch" -> "Include Library" -> "Manage Libraries..." - - Search for "PowerManagement" and install it. + 1. Connect the Battery: + 2. Upload the Sketch: - - Open the provided sketch in the Arduino IDE. - - Select your board type and port from the "Tools" menu. - - Click the "Upload" button to upload the sketch to your board. + - Open the provided sketch in the Arduino IDE. + - Select your board type and port from the "Tools" menu. + - Click the "Upload" button to upload the sketch to your board. 3. Monitor Serial Output: - - Open the Serial Monitor in the Arduino IDE. - - Set the baud rate to 115200. - - You will see the sketch continuously printing battery status and charger state. + - Open the Serial Monitor in the Arduino IDE. + - Set the baud rate to 115200. + - You will see the sketch continuously printing charger state information. */ #include "Arduino_PowerManagement.h" @@ -75,34 +73,34 @@ String getChargerState(){ ChargingState status = charger.getState(); switch (status) { - case ChargingState::PreCharge: + case ChargingState::preCharge: return "precharge"; break; - case ChargingState::FastChargeConstantCurrent: + case ChargingState::fastChargeConstantCurrent: return "fast-charge constant current"; break; - case ChargingState::FastChargeConstantVoltage: + case ChargingState::fastChargeConstantVoltage: return "fast-charge constant voltage"; break; - case ChargingState::EndOfCharge: + case ChargingState::endOfCharge: return "end-of-charge"; break; - case ChargingState::Done: + case ChargingState::done: return "done"; break; - case ChargingState::TimerFaultError: + case ChargingState::timerFaultError: return "timer fault"; break; - case ChargingState::ThermistorSuspendError: + case ChargingState::thermistorSuspendError: return "thermistor suspend"; break; - case ChargingState::ChargerDisabled: + case ChargingState::chargerDisabled: return "off"; break; - case ChargingState::BatteryOvervoltageError: + case ChargingState::batteryOvervoltageError: return "overvoltage condition"; break; - case ChargingState::ChargerBypassed: + case ChargingState::chargerBypassed: return "disabled"; break; default: @@ -112,7 +110,7 @@ String getChargerState(){ } void loop(){ - static ChargingState status = ChargingState::None; + static ChargingState status = ChargingState::none; if (status != charger.getState()) { status = charger.getState(); From 0ade3a42b69e0972e85a686aff96cf5d257c46aa Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Wed, 8 May 2024 15:56:28 +0200 Subject: [PATCH 05/56] Refactorings --- .../DeepSleep_WakeFromPin.ino | 2 +- .../DeepSleep_WakeFromRTC_C33.ino | 2 +- .../DeepSleep_WakeFromRTC_H7.ino | 2 +- src/Board.cpp | 46 +++++++++---------- src/Board.h | 21 ++++----- 5 files changed, 36 insertions(+), 37 deletions(-) diff --git a/examples/DeepSleep_WakeFromPin/DeepSleep_WakeFromPin.ino b/examples/DeepSleep_WakeFromPin/DeepSleep_WakeFromPin.ino index be4fe85..15828c9 100644 --- a/examples/DeepSleep_WakeFromPin/DeepSleep_WakeFromPin.ino +++ b/examples/DeepSleep_WakeFromPin/DeepSleep_WakeFromPin.ino @@ -45,7 +45,7 @@ void loop() { sleepFlag = false; //board.setAllPeripheralsPower(false); - board.deepSleepUntilWakeupEvent(); + board.standByUntilWakeupEvent(); } else { digitalWrite(LEDB, HIGH); diff --git a/examples/DeepSleep_WakeFromRTC_C33/DeepSleep_WakeFromRTC_C33.ino b/examples/DeepSleep_WakeFromRTC_C33/DeepSleep_WakeFromRTC_C33.ino index 22469cb..865e7cd 100644 --- a/examples/DeepSleep_WakeFromRTC_C33/DeepSleep_WakeFromRTC_C33.ino +++ b/examples/DeepSleep_WakeFromRTC_C33/DeepSleep_WakeFromRTC_C33.ino @@ -37,6 +37,6 @@ void setup() { void loop(){ //board.setAllPeripheralsPower(false); - board.deepSleepUntilWakeupEvent(); + board.standByUntilWakeupEvent(); } diff --git a/examples/DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino b/examples/DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino index 774b277..1a8ccac 100644 --- a/examples/DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino +++ b/examples/DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino @@ -16,7 +16,7 @@ void setup() { pinMode(LEDB, OUTPUT); digitalWrite(LEDB, LOW); board.setAllPeripheralsPower(false); - board.deepSleepUntilWakeupEvent(); + board.standByUntilWakeupEvent(); } void loop() { diff --git a/src/Board.cpp b/src/Board.cpp index b8a54f9..6dde10f 100644 --- a/src/Board.cpp +++ b/src/Board.cpp @@ -1,6 +1,8 @@ #include "Board.h" #include +constexpr int UNKNOWN_VALUE = 0xFF; + std::map ldo2VoltageMap = { {1.80f, Ldo2Voltage::V_1_80}, {1.90f, Ldo2Voltage::V_1_90}, @@ -43,20 +45,20 @@ std::map sw2VoltageMap = { }; Board::Board() { - #if defined(ARDUINO_PORTENTA_C33) - this -> lowPower = new LowPower(); - #elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) - if (CM7_CPUID == HAL_GetCurrentCPUID()) - { + #if defined(ARDUINO_PORTENTA_C33) + this->lowPower = new LowPower(); + #endif +} + +bool Board::begin() { + #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) + if (CM7_CPUID == HAL_GetCurrentCPUID()){ if (LowPowerReturnCode::success != LowPower.checkOptionBytes()){ LowPower.prepareOptionBytes(); } bootM4(); } #endif -} - -bool Board::begin() { return PMIC.begin() == 0; } @@ -80,19 +82,19 @@ void Board::setExternalPowerEnabled(bool on) { bool Board::setExternalVoltage(float voltage) { this -> setExternalPowerEnabled(false); - uint8_t voltageRegisterValue = getRailVoltage(voltage, 4); + uint8_t targetVoltage = getRailVoltageEnum(voltage, CONTEXT_SW2); - if (voltageRegisterValue == EMPTY_REGISTER){ + if (targetVoltage == UNKNOWN_VALUE){ return false; } - PMIC.writePMICreg(Register::PMIC_SW2_VOLT, voltageRegisterValue); - if(PMIC.readPMICreg(Register::PMIC_SW2_VOLT) == voltageRegisterValue){ + PMIC.writePMICreg(Register::PMIC_SW2_VOLT, targetVoltage); + if(PMIC.readPMICreg(Register::PMIC_SW2_VOLT) == targetVoltage){ this -> setExternalPowerEnabled(true); return true; - } else { - return false; } + + return false; } void Board::setCameraPowerEnabled(bool on) { @@ -106,8 +108,6 @@ void Board::setCameraPowerEnabled(bool on) { PMIC.getControl()->turnLDO2Off(Ldo2Mode::Normal); PMIC.getControl()->turnLDO3Off(Ldo3Mode::Normal); } - #else - #warning "This feature is currently only supported on the Nicla Vision Board" #endif } @@ -192,7 +192,7 @@ void Board::sleepUntilWakeupEvent(){ } #endif -void Board::deepSleepUntilWakeupEvent(){ +void Board::standByUntilWakeupEvent(){ #if defined(ARDUINO_PORTENTA_C33) lowPower -> deepSleep(); #elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) @@ -263,6 +263,7 @@ void Board::setAnalogDigitalConverterPower(bool on){ #endif void Board::setCommunicationPeripheralsPower(bool on){ + // TODO: Why do we only use the normal mode here? if(on) PMIC.getControl()->turnSw1On(Sw1Mode::Normal); else @@ -271,11 +272,11 @@ void Board::setCommunicationPeripheralsPower(bool on){ bool Board::setReferenceVoltage(float voltage) { - uint8_t voltageRegisterValue = getRailVoltage(voltage, CONTEXT_LDO2); + uint8_t voltageRegisterValue = getRailVoltageEnum(voltage, CONTEXT_LDO2); // If voltageRegisterValue is not empty, write it to the PMIC register // and return the result of the comparison directly. - if (voltageRegisterValue != EMPTY_REGISTER) { + if (voltageRegisterValue != UNKNOWN_VALUE) { PMIC.writePMICreg(Register::PMIC_LDO2_VOLT, voltageRegisterValue); return (PMIC.readPMICreg(Register::PMIC_LDO2_VOLT) == voltageRegisterValue); } @@ -283,7 +284,7 @@ bool Board::setReferenceVoltage(float voltage) { return false; } - uint8_t Board::getRailVoltage(float voltage, int context) { + uint8_t Board::getRailVoltageEnum(float voltage, int context) { switch (context) { case CONTEXT_LDO2: if (ldo2VoltageMap.find(voltage) != ldo2VoltageMap.end()) { @@ -304,10 +305,9 @@ bool Board::setReferenceVoltage(float voltage) { break; default: - return EMPTY_REGISTER; - break; + return UNKNOWN_VALUE; } - return EMPTY_REGISTER; + return UNKNOWN_VALUE; } diff --git a/src/Board.h b/src/Board.h index 3a7b9b8..1187d7f 100644 --- a/src/Board.h +++ b/src/Board.h @@ -13,16 +13,15 @@ #include "Arduino_LowPowerPortentaH7.h" #endif -#define CONTEXT_LDO2 2 -#define CONTEXT_SW1 3 -#define CONTEXT_SW2 4 +#define CONTEXT_LDO2 2 // LDO regulator: 1.8 V to 3.3 V, 400 mA +#define CONTEXT_SW1 3 // Buck converter: 1.0 A; 0.6 V to 1.3875 V +#define CONTEXT_SW2 4 // Buck converter: 1.0 A; 0.6 V to 1.3875 V enum class StandbyType : uint8_t { none = 0, untilPinActivity = 1, untilTimeElapsed = 2, untilEither = 3 - }; inline constexpr StandbyType operator|(StandbyType x, StandbyType y){ @@ -33,8 +32,6 @@ inline constexpr StandbyType operator|=(StandbyType& x, StandbyType y){ return x = x | y; } -constexpr int EMPTY_REGISTER = 0xFF; - /** * @brief Represents a board with power management capabilities. * @@ -185,7 +182,7 @@ class Board { * A wakeup event can be an interrupt on a pin or the RTC, * depending on what you set with enableWakeupFromPin() and enableWakeupFromRTC(). */ - void sleepUntilWakeupEvent(); + void standByUntilWakeupEvent(); #endif // TODO Same as above @@ -197,7 +194,7 @@ class Board { * A wakeup event can be an interrupt on a pin or the RTC, depending on what * you set with enableWakeupFromPin() and enableWakeupFromRTC(). */ - void deepSleepUntilWakeupEvent(); + void standByUntilWakeupEvent(); /** * @brief Toggle the peripherals' power on Portenta C33 (ADC, RGB LED, Secure Element, Wifi and Bluetooth). @@ -205,7 +202,6 @@ class Board { */ void setAllPeripheralsPower(bool on); - /** * @brief Toggles the communication peripherials' power on Portenta C33 (Wifi, Bluetooth and Secure Element) * @param on True to turn on the power, false to turn it off. @@ -221,7 +217,7 @@ class Board { #endif /** - * @brief Set the reference voltage on Portenta C33. This value is used by the ADC to convert analog values to digital values. + * @brief Set the reference voltage. This value is used by the ADC to convert analog values to digital values. * This can be particularly useful to increase the accuracy of the ADC when working with low voltages * @param voltage Reference voltage value in volts. It can be anything between 1.80V and 3.30V in steps of 0.10V. * Any value outside this range or with different steps will not be accepted by the library. @@ -232,7 +228,10 @@ class Board { // TODO add function to shut down the fuel gauge / and hibernate mode private: - static uint8_t getRailVoltage(float voltage, int context); + /** + * Convert a numeric voltage value to the corresponding enum value for the PMIC library. + */ + static uint8_t getRailVoltageEnum(float voltage, int context); #if defined(ARDUINO_PORTENTA_C33) LowPower * lowPower; From 8505b4c3e6e71a917475672e5395d221504173f8 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Wed, 8 May 2024 17:09:33 +0200 Subject: [PATCH 06/56] Simplify API --- src/Board.cpp | 46 ++++++++++++---------------------- src/Board.h | 69 ++++++++++++++------------------------------------- 2 files changed, 34 insertions(+), 81 deletions(-) diff --git a/src/Board.cpp b/src/Board.cpp index 6dde10f..78775d6 100644 --- a/src/Board.cpp +++ b/src/Board.cpp @@ -128,16 +128,10 @@ void Board::enableSleepWhenIdle(){ #endif -void Board::enableWakeupFromRTC(){ - #if defined(ARDUINO_PORTENTA_C33) - lowPower->enableWakeupFromRTC(); - #elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) - standbyType |= StandbyType::untilTimeElapsed; - #endif -} - #if defined(ARDUINO_PORTENTA_C33) -bool Board::sleepFor(int hours, int minutes, int seconds, void (* const callbackFunction)(), RTClock * rtc){ +void Board::enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds, void (* const callbackFunction)() = nullptr, RTClock * rtc = &RTC){ + lowPower->enableWakeupFromRTC(); + RTCTime currentTime; if (!rtc -> getTime(currentTime)) { return false; @@ -162,30 +156,19 @@ bool Board::sleepFor(int hours, int minutes, int seconds, void (* const callback return false; // Failed to set the alarm } delay(1); - return true; -} - -bool Board::sleepFor(int hours, int minutes, int seconds, void (* const callbackFunction)()){ - return this -> sleepFor(hours, minutes, seconds, callbackFunction, &RTC); + return true; } #endif -bool Board::sleepFor(int hours, int minutes, int seconds){ - #if defined(ARDUINO_PORTENTA_C33) - return this -> sleepFor(hours, minutes, seconds, NULL, &RTC); - #elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) - this -> rtcWakeupDelay = RTCWakeupDelay(hours, minutes, seconds); - return true; - #endif -} - -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) -bool Board::sleepFor(RTCWakeupDelay delay){ - this -> rtcWakeupDelay = delay; - return true; +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) +void Board::enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds){ + standbyType |= StandbyType::untilTimeElapsed; + wakeupDelayHours = hours; + wakeupDelayMinutes = minutes; + wakeupDelaySeconds = seconds; } #endif - + #if defined(ARDUINO_PORTENTA_C33) void Board::sleepUntilWakeupEvent(){ lowPower -> sleep(); @@ -196,6 +179,7 @@ void Board::standByUntilWakeupEvent(){ #if defined(ARDUINO_PORTENTA_C33) lowPower -> deepSleep(); #elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) + RTCWakeupDelay rtcWakeupDelay = RTCWakeupDelay(wakeupDelayHours, wakeupDelayMinutes, wakeupDelaySeconds); if(standbyType == StandbyType::untilEither) LowPower.standbyM7(LowPowerStandbyType::untilPinActivity | LowPowerStandbyType::untilTimeElapsed, rtcWakeupDelay); else if (standbyType == StandbyType::untilPinActivity) @@ -214,6 +198,7 @@ void Board::setAllPeripheralsPower(bool on){ // to communicate with the MCU. Wire3.end(); #else if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) + // TODO Can we extract this into functions? if(on){ PMIC.getControl() -> turnLDO2On(Ldo2Mode::Normal); PMIC.getControl() -> turnLDO2On(Ldo2Mode::Sleep); @@ -248,8 +233,9 @@ void Board::setAllPeripheralsPower(bool on){ #endif } -#if defined(ARDUINO_PORTENTA_C33) void Board::setAnalogDigitalConverterPower(bool on){ +// TODO Not available on the Portenta H7? +#if defined(ARDUINO_PORTENTA_C33) if(on){ PMIC.getControl()->turnLDO1On(Ldo1Mode::Normal); PMIC.getControl()->turnLDO1On(Ldo1Mode::Sleep); @@ -259,8 +245,8 @@ void Board::setAnalogDigitalConverterPower(bool on){ PMIC.getControl()->turnLDO1Off(Ldo1Mode::Sleep); PMIC.getControl()->turnLDO1Off(Ldo1Mode::Standby); } -} #endif +} void Board::setCommunicationPeripheralsPower(bool on){ // TODO: Why do we only use the normal mode here? diff --git a/src/Board.h b/src/Board.h index 1187d7f..6eaf827 100644 --- a/src/Board.h +++ b/src/Board.h @@ -100,7 +100,6 @@ class Board { */ void enableWakeupFromPin(); - /** * Enables sleep mode when the board is idle. */ @@ -117,62 +116,29 @@ class Board { #endif - /** - * Enables wake-up of the device from the RTC. - */ - void enableWakeupFromRTC(); - #if defined(ARDUINO_PORTENTA_C33) - // TODO Do I needs to call enableWakeupFromRTC() before calling this function? /** - * @brief Put the device in sleep mode for a specified amount of time. Restarts after waking up. + * @brief Enables wake-up of the device from the RTC. * This function allows to use a custom RTC instance to put the device in sleep mode. * @param hours The number of hours to sleep. * @param minutes The number of minutes to sleep. * @param seconds The number of seconds to sleep. * @param callbackFunction The function to call when the device wakes up. + * If no callback function is provided, the device will wake up without calling any function. * @param rtc The RTC instance to use for the sleep function. + * If no RTC instance is provided, the default RTC instance is used. * @return True if successful, false otherwise. */ - bool sleepFor(int hours, int minutes, int seconds, void (* const callbackFunction)(), RTClock * rtc); - - /** - * @brief Put the device in sleep mode for a specified amount of time. - * This function uses the default RTC instance to put the device in sleep mode. - * @param hours The number of hours to sleep. - * @param minutes The number of minutes to sleep. - * @param seconds The number of seconds to sleep. - * @param callbackFunction The function to call when the device wakes up. - * @return True if successful, false otherwise. - */ - bool sleepFor(int hours, int minutes, int seconds, void (* const callbackFunction)()); + void enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds, void (* const callbackFunction)() = nullptr, RTClock * rtc = &RTC); #endif - /** - * @brief Put the device in sleep mode for a specified amount of time. It restarts after waking up. - * This function uses the default RTC instance to put the device in sleep mode and - * does not call a function when the device wakes up. - * @param hours The number of hours to sleep. - * @param minutes The number of minutes to sleep. - * @param seconds The number of seconds to sleep. - * @return True if successful, false otherwise. - */ - bool sleepFor(int hours, int minutes, int seconds); - - #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) - - /** - * Sleeps the board for a specified delay. - * - * @param delay The delay as an RTCWakeupDelay object. - * @return True if the board successfully sleeps, false otherwise. - */ - bool sleepFor(RTCWakeupDelay delay); + #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) + void enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds); #endif - + #if defined(ARDUINO_PORTENTA_C33) - // TODO How to use this with the RTC? enableWakeupFromRTC(), then sleepFor, then this? + // TODO Restarts after waking up.? /** * Put the device into sleep mode until a wakeup event occurs * This sleep mode is ideal for applications requiring periodic wake-ups or @@ -182,13 +148,13 @@ class Board { * A wakeup event can be an interrupt on a pin or the RTC, * depending on what you set with enableWakeupFromPin() and enableWakeupFromRTC(). */ - void standByUntilWakeupEvent(); + void sleepUntilWakeupEvent(); #endif - // TODO Same as above + // TODO measurements are board specific. Need adjustments for Portenta H7. /** - * Put the device into deep sleep mode until a wakeup event occurs. - * For scenarios demanding drastic power conservation, the Deep Sleep Mode significantly reduces + * Put the device into standby mode until a wakeup event occurs. + * For scenarios demanding drastic power conservation, the standby Mode significantly reduces * the board's power usage to range between 90uA and 11mA depending on the state of the peripherals. * This mode restarts the board on wake-up, effectively running the setup() function again. * A wakeup event can be an interrupt on a pin or the RTC, depending on what @@ -208,14 +174,13 @@ class Board { */ void setCommunicationPeripheralsPower(bool on); - #if defined(ARDUINO_PORTENTA_C33) /** * @brief Toggles the power of the analog digital converter on Portenta C33. + * This is not available on the Portenta H7. * @param on True to turn on the power, false to turn it off. */ void setAnalogDigitalConverterPower(bool on); - #endif /** * @brief Set the reference voltage. This value is used by the ADC to convert analog values to digital values. * This can be particularly useful to increase the accuracy of the ADC when working with low voltages @@ -235,10 +200,12 @@ class Board { #if defined(ARDUINO_PORTENTA_C33) LowPower * lowPower; - #elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) - StandbyType standbyType = StandbyType::none; - RTCWakeupDelay rtcWakeupDelay = RTCWakeupDelay(0, 0, 0); #endif + + StandbyType standbyType = StandbyType::none; + uint32_t wakeupDelayHours; + uint32_t wakeupDelayMinutes; + uint32_t wakeupDelaySeconds; }; #endif \ No newline at end of file From 7a61e9fec521bdadaa603f1bcf63941524cf4c72 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Wed, 8 May 2024 17:14:14 +0200 Subject: [PATCH 07/56] Refactor example --- .../DeepSleep_WakeFromPin.ino | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/examples/DeepSleep_WakeFromPin/DeepSleep_WakeFromPin.ino b/examples/DeepSleep_WakeFromPin/DeepSleep_WakeFromPin.ino index 15828c9..8187b78 100644 --- a/examples/DeepSleep_WakeFromPin/DeepSleep_WakeFromPin.ino +++ b/examples/DeepSleep_WakeFromPin/DeepSleep_WakeFromPin.ino @@ -4,50 +4,52 @@ #define WAKE_PIN A3 -#define SLEEP_PIN 0 +#define GOTO_SLEEP_PIN 0 -volatile bool sleepFlag = false; +volatile bool shouldGoToSleep = false; -PowerManagement manager; Board board; Charger charger; void setup() { + board = Board(); + charger = Charger(); + board.begin(); + charger.begin(); - - - manager = PowerManagement(); - manager.begin(); - board = manager.getBoard(); - charger = manager.getCharger(); - - attachInterrupt(digitalPinToInterrupt(SLEEP_PIN), goToSleep, RISING); + // Allows to use a button to put the device into sleep mode + attachInterrupt(digitalPinToInterrupt(GOTO_SLEEP_PIN), goToSleep, RISING); #if defined(ARDUINO_PORTENTA_C33) - board.enableWakeupFromPin(WAKE_PIN, RISING); + // On Portenta C33, you can specify which pin to use to wake up the device from sleep mode + // Please read the documentation to understand which pins can be used to wake up the device. + board.enableWakeupFromPin(WAKE_UP_PIN, RISING); #elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) + // On Portenta only pin GPIO0 can be used to wake up the device from sleep mode board.enableWakeupFromPin(); #endif - + // TODO why is this needed? Why true? board.setAllPeripheralsPower(true); - charger.disable(); + // TODO why is this needed? + charger.setEnabled(false); pinMode(LEDB, OUTPUT); } void goToSleep(){ - sleepFlag = true; + shouldGoToSleep = true; } void loop() { - if(sleepFlag){ - sleepFlag = false; + if(shouldGoToSleep){ + shouldGoToSleep = false; + // TODO why is this here? //board.setAllPeripheralsPower(false); board.standByUntilWakeupEvent(); } else { - + // Show that the board is awake by blinking the LED digitalWrite(LEDB, HIGH); delay(1000); digitalWrite(LEDB, LOW); From c36ad19a170d12c19533086620ffd13cdd9452a7 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Thu, 9 May 2024 00:50:01 +0200 Subject: [PATCH 08/56] Use new target identifier for M4 --- src/Battery.h | 2 +- src/Board.cpp | 10 ++++++---- src/Board.h | 7 ++++--- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Battery.h b/src/Battery.h index 109775f..6dc06ce 100644 --- a/src/Battery.h +++ b/src/Battery.h @@ -269,7 +269,7 @@ class Battery { #if defined(ARDUINO_PORTENTA_C33) TwoWire *wire = &Wire3; - #elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) + #elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_GENERIC_STM32H747_M4) TwoWire *wire = &Wire1; #elif defined(ARDUINO_NICLA_VISION) TwoWire *wire = &Wire1; diff --git a/src/Board.cpp b/src/Board.cpp index 78775d6..5213ae7 100644 --- a/src/Board.cpp +++ b/src/Board.cpp @@ -117,7 +117,7 @@ void Board::enableWakeupFromPin(uint8_t pin, PinStatus direction){ } #endif -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) +#if defined(ARDUINO_PORTENTA_H7) || defined(ARDUINO_NICLA_VISION) void Board::enableWakeupFromPin(){ standbyType |= StandbyType::untilPinActivity; } @@ -160,7 +160,7 @@ void Board::enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t secon } #endif -#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) +#if defined(ARDUINO_PORTENTA_H7) || defined(ARDUINO_NICLA_VISION) void Board::enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds){ standbyType |= StandbyType::untilTimeElapsed; wakeupDelayHours = hours; @@ -178,7 +178,9 @@ void Board::sleepUntilWakeupEvent(){ void Board::standByUntilWakeupEvent(){ #if defined(ARDUINO_PORTENTA_C33) lowPower -> deepSleep(); - #elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) + #elif defined(ARDUINO_GENERIC_STM32H747_M4) + LowPower.standbyM4(); + #elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) RTCWakeupDelay rtcWakeupDelay = RTCWakeupDelay(wakeupDelayHours, wakeupDelayMinutes, wakeupDelaySeconds); if(standbyType == StandbyType::untilEither) LowPower.standbyM7(LowPowerStandbyType::untilPinActivity | LowPowerStandbyType::untilTimeElapsed, rtcWakeupDelay); @@ -197,7 +199,7 @@ void Board::setAllPeripheralsPower(bool on){ // I2C needs to be shut down because the PMIC would still try // to communicate with the MCU. Wire3.end(); - #else if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) + #else if defined(ARDUINO_PORTENTA_H7) // TODO Can we extract this into functions? if(on){ PMIC.getControl() -> turnLDO2On(Ldo2Mode::Normal); diff --git a/src/Board.h b/src/Board.h index 6eaf827..4435bba 100644 --- a/src/Board.h +++ b/src/Board.h @@ -5,11 +5,12 @@ #include #include "WireUtils.h" +#define ARDUINO_PORTENTA_H7 defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_GENERIC_STM32H747_M4) #if defined(ARDUINO_PORTENTA_C33) #include "Arduino_Portenta_C33_LowPower.h" #include "RTC.h" -#elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) +#elif defined(ARDUINO_PORTENTA_H7) || defined(ARDUINO_NICLA_VISION) #include "Arduino_LowPowerPortentaH7.h" #endif @@ -92,7 +93,7 @@ class Board { void setCameraPowerEnabled(bool enabled); - #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) + #if defined(ARDUINO_PORTENTA_H7) /** * Enables wakeup from pin GPIO0 on Portenta H7. @@ -132,7 +133,7 @@ class Board { void enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds, void (* const callbackFunction)() = nullptr, RTClock * rtc = &RTC); #endif - #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) + #if defined(ARDUINO_PORTENTA_H7) void enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds); #endif From 68623a087beb5b3fd569da69d2815049e23fd855 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Thu, 9 May 2024 00:50:17 +0200 Subject: [PATCH 09/56] Revamp standby example --- .../DeepSleep_WakeFromRTC_H7.ino | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/examples/DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino b/examples/DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino index 1a8ccac..84be74d 100644 --- a/examples/DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino +++ b/examples/DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino @@ -1,20 +1,39 @@ -#include "Arduino.h" #include "Arduino_PowerManagement.h" Board board; - void setup() { board = Board(); + + // When uploading this sketch to the M4 core, it just goes to standby mode. + #if defined(ARDUINO_GENERIC_STM32H747_M4) + board.standByUntilWakeupEvent(); + return; + #endif + + // Turn off the built-in LED + pinMode(LED_BUILTIN, OUTPUT); + digitalWrite(LED_BUILTIN, HIGH); + + // Turn on the blue LED to show that the board is still awake + pinMode(LEDB, OUTPUT); + digitalWrite(LEDB, LOW); + if(!board.begin()){ - Serial.println("Board initialization failed."); - while (true); + // If the board fails to initialize, it will blink the red LED + pinMode(LEDR, OUTPUT); + while (true){ + digitalWrite(LEDR, LOW); + delay(1000); + digitalWrite(LEDR, HIGH); + delay(1000); + } } - board.enableWakeupFromRTC(); - board.sleepFor(0, 0, 1); - pinMode(LEDB, OUTPUT); - digitalWrite(LEDB, LOW); + + board.enableWakeupFromRTC(0, 0, 10); // Sleep for 10 seconds + + // The LED should go off when the board goes to sleep board.setAllPeripheralsPower(false); board.standByUntilWakeupEvent(); } From 9cbeed3052ba2dd0f1c8b5e3789f121caa6b29dd Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Thu, 9 May 2024 00:51:43 +0200 Subject: [PATCH 10/56] Rename sketches --- .../Standby_WakeFromPin.ino} | 2 +- .../Standby_WakeFromRTC_C33.ino} | 0 .../Standby_WakeFromRTC_H7.ino} | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename examples/{DeepSleep_WakeFromPin/DeepSleep_WakeFromPin.ino => Standby_WakeFromPin/Standby_WakeFromPin.ino} (92%) rename examples/{DeepSleep_WakeFromRTC_C33/DeepSleep_WakeFromRTC_C33.ino => Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino} (100%) rename examples/{DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino => Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino} (100%) diff --git a/examples/DeepSleep_WakeFromPin/DeepSleep_WakeFromPin.ino b/examples/Standby_WakeFromPin/Standby_WakeFromPin.ino similarity index 92% rename from examples/DeepSleep_WakeFromPin/DeepSleep_WakeFromPin.ino rename to examples/Standby_WakeFromPin/Standby_WakeFromPin.ino index 8187b78..2b25a06 100644 --- a/examples/DeepSleep_WakeFromPin/DeepSleep_WakeFromPin.ino +++ b/examples/Standby_WakeFromPin/Standby_WakeFromPin.ino @@ -24,7 +24,7 @@ void setup() { // On Portenta C33, you can specify which pin to use to wake up the device from sleep mode // Please read the documentation to understand which pins can be used to wake up the device. board.enableWakeupFromPin(WAKE_UP_PIN, RISING); - #elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_NICLA_VISION) + #elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_GENERIC_STM32H747_M4) || defined(ARDUINO_NICLA_VISION) // On Portenta only pin GPIO0 can be used to wake up the device from sleep mode board.enableWakeupFromPin(); #endif diff --git a/examples/DeepSleep_WakeFromRTC_C33/DeepSleep_WakeFromRTC_C33.ino b/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino similarity index 100% rename from examples/DeepSleep_WakeFromRTC_C33/DeepSleep_WakeFromRTC_C33.ino rename to examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino diff --git a/examples/DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino b/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino similarity index 100% rename from examples/DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino rename to examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino From ae3693e076fb7bf4ad5e28a6b8ad5004c519ec35 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Thu, 9 May 2024 00:51:53 +0200 Subject: [PATCH 11/56] Use new m4 define --- examples/Powershell/Powershell.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/Powershell/Powershell.ino b/examples/Powershell/Powershell.ino index b9075b9..5ed77cb 100644 --- a/examples/Powershell/Powershell.ino +++ b/examples/Powershell/Powershell.ino @@ -115,14 +115,14 @@ void setRailVoltage(std::vector args){ #endif } else if (rail == "H7_external"){ - #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) + #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_GENERIC_STM32H747_M4) board.setExternalVoltage(voltage); #else Serial.println("Current board is not an arduino portenta h7"); #endif } else if (rail == "nicla_external"){ - #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) + #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_GENERIC_STM32H747_M4) board.setExternalVoltage(voltage); #else Serial.println("Current board is not an arduino nicla vision"); @@ -150,7 +150,7 @@ void toggleRail(std::vector args){ #endif } else if (rail == "H7_external"){ - #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) + #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_GENERIC_STM32H747_M4) board.setExternalPowerEnabled(on); #else Serial.println("Current board is not an arduino portenta h7"); From 5dc466ac2d967a787a446c08c5251594286bee47 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Thu, 9 May 2024 00:52:02 +0200 Subject: [PATCH 12/56] Update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ae36c47..2e767a5 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ This library streamlines the interaction with complex hardware components such a ## āœ… Supported Boards - Arduino Portenta H7 -- Arduino Nicla Vision +- Arduino Nicla Vision (Low power features not supported yet) - Arduino Portenta C33 ## Core Components of the Library From 375d186a82c1f58ed34c054b98d2b547fc9271e9 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Fri, 10 May 2024 09:52:39 +0200 Subject: [PATCH 13/56] Add documentation to low power sketch --- .../Standby_WakeFromRTC_H7.ino | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino b/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino index 84be74d..9bebfca 100644 --- a/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino +++ b/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino @@ -1,3 +1,37 @@ +/* + Charger Demo + + This sketch demonstrates how to use the PowerManagement library enable low power modes on the Arduino Portenta H7. + * In the setup() function, it enters standby mode and waits for a wakeup event from the RTC. + * The loop() functionit is not used in this sketch. + + IMPORTANT: Please note that this sketch has to be uploaded to the M4 core too in order to achieve the lowest power consumption. + + Requirements: + - Arduino Arduino Portenta H7 + - Arduino IDE + - PowerManagement library (installable from the Arduino Library Manager) + + Usage: + + 1. Connect a battery to the board. + + 2. Upload the Sketch to the M4 core: + - Open the provided sketch in the Arduino IDE. + - Select your board type and port from the "Tools" menu. + - Select the M4 core from the "Tools" menu. + - Click the "Upload" button to upload the sketch to your board. + + 3. Upload the Sketch to the M7 core: + - Select the M7 core from the "Tools" menu. + - Click the "Upload" button to upload the sketch to your board. + + 4. Observer LED behavior: + - The blue LED will turn on when the board is awake. + - The blue LED will turn off when the board goes to sleep. + - The red LED will blink if the board fails to initialize. +*/ + #include "Arduino_PowerManagement.h" Board board; From c567771871dd82fbc4a7b9d635e7ccd8b88d8eb5 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Fri, 10 May 2024 11:30:45 +0200 Subject: [PATCH 14/56] Add fuel gauge driver --- src/MAX1726Driver.h | 49 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/MAX1726Driver.h diff --git a/src/MAX1726Driver.h b/src/MAX1726Driver.h new file mode 100644 index 0000000..9165860 --- /dev/null +++ b/src/MAX1726Driver.h @@ -0,0 +1,49 @@ +#include "WireUtils.h" +// TODO extract into a separate header file and check how PF1550Driver is implemented +#include "BatteryConstants.h" + +enum class FuelGaugeOperationMode +{ + hibernate, + shutdown, + active +}; + +// TODO Extract into a separate header file or use this file in Battery.h +constexpr uint8_t I2C_ADDRESS = 0x36; // I2C address of the fuel gauge + +class MAX1726Driver { +private: + TwoWire *wire; +public: + bool setOperationMode(FuelGaugeOperationMode mode); + MAX1726Driver(TwoWire *wire); + ~MAX1726Driver(); +}; + +MAX1726Driver::MAX1726Driver(TwoWire *wire) { + this->wire = wire; +} + +MAX1726Driver::~MAX1726Driver(){} + +bool MAX1726Driver::setOperationMode(FuelGaugeOperationMode mode) { + if(mode == FuelGaugeOperationMode::active){ + // See section "Soft-Wakeup" in user manual https://www.analog.com/media/en/technical-documentation/user-guides/max1726x-modelgauge-m5-ez-user-guide.pdf + writeRegister16Bits(this->wire, I2C_ADDRESS, HIB_CFG_REG, 0x0); // Exit Hibernate Mode + writeRegister16Bits(this->wire, I2C_ADDRESS, SOFT_WAKEUP_REG, 0x90); // Wakes up the fuel gauge from hibernate mode to reduce the response time of the IC to configuration changes + writeRegister16Bits(this->wire, I2C_ADDRESS, SOFT_WAKEUP_REG, 0x0); // This command must be manually cleared (0x0000) afterward to keep proper fuel gauge timing + } else if(mode == FuelGaugeOperationMode::hibernate){ + // Enters hibernate mode somewhere between 2.812s and 5.625s if the threshold conditions are met + replaceRegisterBit(this->wire, I2C_ADDRESS, HIB_CFG_REG, 1, EN_HIBERNATION_BIT); // Enter Hibernate Mode + } else if(mode == FuelGaugeOperationMode::shutdown){ + // Enter active mode + // TODO use function instead + replaceRegisterBit(this->wire, I2C_ADDRESS, HIB_CFG_REG, 0, EN_HIBERNATION_BIT); // Exit Hibernate Mode + // TODO check if we can enter shutdown quicker by setting CTR manually in ShdnTimer + // The default shutdown timeout is 45s + replaceRegisterBit(this->wire, I2C_ADDRESS, CONFIG_REG, 1, SHDN_BIT); // Command shutdown mode + } + + return false; +} \ No newline at end of file From 1a424813e104729d00c4aaacdc38de14316304e1 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Fri, 10 May 2024 11:31:03 +0200 Subject: [PATCH 15/56] Add comments --- examples/Charger/Charger.ino | 2 +- examples/Standby_WakeFromPin/Standby_WakeFromPin.ino | 3 ++- src/Battery.cpp | 2 ++ src/WireUtils.h | 2 ++ 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/examples/Charger/Charger.ino b/examples/Charger/Charger.ino index 8620e95..dd0495f 100644 --- a/examples/Charger/Charger.ino +++ b/examples/Charger/Charger.ino @@ -12,7 +12,7 @@ Usage: - 1. Connect the Battery: + 1. Connect a Battery to the board 2. Upload the Sketch: - Open the provided sketch in the Arduino IDE. diff --git a/examples/Standby_WakeFromPin/Standby_WakeFromPin.ino b/examples/Standby_WakeFromPin/Standby_WakeFromPin.ino index 2b25a06..9d35812 100644 --- a/examples/Standby_WakeFromPin/Standby_WakeFromPin.ino +++ b/examples/Standby_WakeFromPin/Standby_WakeFromPin.ino @@ -29,7 +29,8 @@ void setup() { board.enableWakeupFromPin(); #endif - // TODO why is this needed? Why true? + // TODO why is this needed? Why true? -> Peripherals still off after reset? + // only necessary for C33 board.setAllPeripheralsPower(true); // TODO why is this needed? charger.setEnabled(false); diff --git a/src/Battery.cpp b/src/Battery.cpp index 9661201..554a016 100644 --- a/src/Battery.cpp +++ b/src/Battery.cpp @@ -11,6 +11,7 @@ Battery::Battery(BatteryCharacteristics batteryCharacteristics) : characteristic } bool Battery::begin(bool enforceReload) { + // PMIC already initializes the I2C bus, so no need to call Wire.begin() for the fuel gauge if(PMIC.begin() != 0){ return false; } @@ -72,6 +73,7 @@ void Battery::configureBatteryCharacteristics(){ void Battery::releaseFromHibernation(){ // See section "Soft-Wakeup" in user manual https://www.analog.com/media/en/technical-documentation/user-guides/max1726x-modelgauge-m5-ez-user-guide.pdf + // TODO to preserve the hiberation config, probably better to only set bit 15 to 0 writeRegister16Bits(this->wire, FUEL_GAUGE_ADDRESS, HIB_CFG_REG, 0x0); // Exit Hibernate Mode writeRegister16Bits(this->wire, FUEL_GAUGE_ADDRESS, SOFT_WAKEUP_REG, 0x90); // Wakes up the fuel gauge from hibernate mode to reduce the response time of the IC to configuration changes writeRegister16Bits(this->wire, FUEL_GAUGE_ADDRESS, SOFT_WAKEUP_REG, 0x0); // This command must be manually cleared (0x0000) afterward to keep proper fuel gauge timing diff --git a/src/WireUtils.h b/src/WireUtils.h index 63d20ff..491057d 100644 --- a/src/WireUtils.h +++ b/src/WireUtils.h @@ -101,6 +101,7 @@ static inline uint8_t getBit(TwoWire *wire, uint8_t address, uint8_t reg, uint8_ * @param indexFrom The index of the first bit to replace starting from LSB (0) * @param indexTo The index of the last bit (included) to replace starting from LSB (0) */ +// TODO switch order of parameters to conform with bitWrite() static inline void replaceRegisterBits(TwoWire *wire, uint8_t address, uint8_t reg, uint16_t data, uint16_t indexFrom, uint8_t indexTo) { uint16_t registerValue = readRegister16Bits(wire, address, reg); @@ -126,6 +127,7 @@ static inline void replaceRegisterBits(TwoWire *wire, uint8_t address, uint8_t r * @param data The new data (1 bit) to write to the register. * @param index The index of the bit to replace. */ +// TODO switch order of parameters to conform with bitWrite() static inline void replaceRegisterBit(TwoWire *wire, uint8_t address, uint8_t reg, uint16_t data, uint16_t index) { replaceRegisterBits(wire, address, reg, data, index, index); } From 1c2a9578992f78edd799ae6c7051c49fad23d982 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Fri, 10 May 2024 11:31:35 +0200 Subject: [PATCH 16/56] Enable shutdown mode of fuel gauge --- .../Standby_WakeFromRTC_H7.ino | 24 ++++++++++++------- src/BatteryConstants.h | 3 ++- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino b/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino index 9bebfca..f1082c5 100644 --- a/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino +++ b/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino @@ -33,17 +33,20 @@ */ #include "Arduino_PowerManagement.h" +#include "MAX1726Driver.h" -Board board; +Board board; +Charger charger; +MAX1726Driver fuelgauge(&Wire1); void setup() { - board = Board(); - // When uploading this sketch to the M4 core, it just goes to standby mode. #if defined(ARDUINO_GENERIC_STM32H747_M4) board.standByUntilWakeupEvent(); return; #endif + + charger.begin(); // Turn off the built-in LED pinMode(LED_BUILTIN, OUTPUT); @@ -64,14 +67,17 @@ void setup() { } } + charger.setEnabled(false); // -> Please measure if it makes a difference + delay(10000); // -> Give time to take the measurement - board.enableWakeupFromRTC(0, 0, 10); // Sleep for 10 seconds - + // Takes 45s to get into shutdown mode + fuelgauge.setOperationMode(FuelGaugeOperationMode::shutdown); + // The LED should go off when the board goes to sleep - board.setAllPeripheralsPower(false); + board.setAllPeripheralsPower(false); + + board.enableWakeupFromRTC(0, 0, 60); // Go to standby for 60 seconds board.standByUntilWakeupEvent(); } -void loop() { - // put your main code here, to run repeatedly: -} \ No newline at end of file +void loop() {} \ No newline at end of file diff --git a/src/BatteryConstants.h b/src/BatteryConstants.h index 2fb6878..b830a03 100644 --- a/src/BatteryConstants.h +++ b/src/BatteryConstants.h @@ -104,7 +104,8 @@ #define E_DET_BIT 8 // FStat Register: Empty Detection. This bit is set to 1 when the IC detects that the cell empty point has been reached. This bit is reset to 0 when the cell voltage rises above the recovery threshold. #define FULL_DET_BIT 5 // Status2 Register: Full Detection. #define FQ_BIT 7 // FStat Register: Full Qualified. This bit is set when all charge termination conditions have been met. See the End-of-Charge Detection section for details. -#define EN_HIBERNATION_BIT 15 +#define EN_HIBERNATION_BIT 15 // HibCfg Register: Enable Hibernate Mode. When set to 1, the IC will enter hibernate mode if conditions are met. When set to 0, the IC always remains in the active mode of operation. +#define SHDN_BIT 7 // Config Register: Write this bit to logic 1 to force a shutdown of the device after timeout of the ShdnTimer register #define HIB_BIT 1 // Hibernate Status. This bit is set to a 1 when the device is in hibernate mode or 0 when the device is in active mode. Hib is set to 0 at power-up. #define R100_BIT 13 // The R100 bit needs to be set when using a 100k NTC resistor #define VCHG_BIT 10 // Set to 1 for charge voltage higher than 4.25V (4.3Vā€“4.4V). Set VChg to 0 for 4.2V charge voltage. From a444d963106b624fa34ee06903b705d150cb74aa Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Mon, 13 May 2024 11:03:40 +0200 Subject: [PATCH 17/56] Add destructor for Board --- src/Board.cpp | 12 ++++++++++-- src/Board.h | 5 +++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Board.cpp b/src/Board.cpp index 5213ae7..15eeaa5 100644 --- a/src/Board.cpp +++ b/src/Board.cpp @@ -50,6 +50,12 @@ Board::Board() { #endif } +Board::~Board() { + #if defined(ARDUINO_PORTENTA_C33) + delete lowPower; + #endif +} + bool Board::begin() { #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) if (CM7_CPUID == HAL_GetCurrentCPUID()){ @@ -64,13 +70,15 @@ bool Board::begin() { bool Board::isUSBPowered() { uint16_t registerValue = PMIC.readPMICreg(Register::CHARGER_VBUS_SNS); - return bitRead(registerValue, 2) == 0; + // TODO: Check which one works + // return bitRead(registerValue, 2) == 0; + return bitRead(registerValue, 5) == 1; // ā€” VBUS is valid -> USB powered } bool Board::isBatteryPowered() { uint8_t registerValue = PMIC.readPMICreg(Register::CHARGER_BATT_SNS); uint8_t batteryPower = extractBits(registerValue, 0, 2); - return batteryPower == 0; + return batteryPower == 0; // No valid VBUS input -> battery powered } void Board::setExternalPowerEnabled(bool on) { diff --git a/src/Board.h b/src/Board.h index 4435bba..deb10ec 100644 --- a/src/Board.h +++ b/src/Board.h @@ -49,6 +49,11 @@ class Board { */ Board(); + /** + * @brief Destroy the Board object. + */ + ~Board(); + /** * @brief Initializes the board by initiating the PMIC. * From 6a9cae5070d84819eab20129dd1bc6903439408c Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Mon, 13 May 2024 11:50:24 +0200 Subject: [PATCH 18/56] Fix compile errors --- src/Board.cpp | 5 +++-- src/Board.h | 8 +++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Board.cpp b/src/Board.cpp index 15eeaa5..eebea3f 100644 --- a/src/Board.cpp +++ b/src/Board.cpp @@ -137,7 +137,7 @@ void Board::enableSleepWhenIdle(){ #if defined(ARDUINO_PORTENTA_C33) -void Board::enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds, void (* const callbackFunction)() = nullptr, RTClock * rtc = &RTC){ +bool Board::enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds, void (* const callbackFunction)(), RTClock * rtc){ lowPower->enableWakeupFromRTC(); RTCTime currentTime; @@ -169,11 +169,12 @@ void Board::enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t secon #endif #if defined(ARDUINO_PORTENTA_H7) || defined(ARDUINO_NICLA_VISION) -void Board::enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds){ +bool Board::enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds){ standbyType |= StandbyType::untilTimeElapsed; wakeupDelayHours = hours; wakeupDelayMinutes = minutes; wakeupDelaySeconds = seconds; + return true; } #endif diff --git a/src/Board.h b/src/Board.h index deb10ec..155dfb1 100644 --- a/src/Board.h +++ b/src/Board.h @@ -5,7 +5,9 @@ #include #include "WireUtils.h" -#define ARDUINO_PORTENTA_H7 defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_GENERIC_STM32H747_M4) +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_GENERIC_STM32H747_M4) +#define ARDUINO_PORTENTA_H7 +#endif #if defined(ARDUINO_PORTENTA_C33) #include "Arduino_Portenta_C33_LowPower.h" @@ -135,11 +137,11 @@ class Board { * If no RTC instance is provided, the default RTC instance is used. * @return True if successful, false otherwise. */ - void enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds, void (* const callbackFunction)() = nullptr, RTClock * rtc = &RTC); + bool enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds, void (* const callbackFunction)() = nullptr, RTClock * rtc = &RTC); #endif #if defined(ARDUINO_PORTENTA_H7) - void enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds); + bool enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds); #endif From a38f4a376d228def68134c15ded8fa509f7b060c Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Mon, 13 May 2024 14:28:23 +0200 Subject: [PATCH 19/56] Remove double instantiation --- examples/Battery/Battery.ino | 1 - examples/Charger/Charger.ino | 1 - 2 files changed, 2 deletions(-) diff --git a/examples/Battery/Battery.ino b/examples/Battery/Battery.ino index 0858c21..77d20af 100644 --- a/examples/Battery/Battery.ino +++ b/examples/Battery/Battery.ino @@ -38,7 +38,6 @@ void setup() { while (!Serial); delay(1000); // Delay to give time to load the Serial Monitor - charger = Charger(); charger.begin(); auto chargeVoltage = charger.getChargeVoltage(); auto endOfChargeCurrent = charger.getEndOfChargeCurrent(); diff --git a/examples/Charger/Charger.ino b/examples/Charger/Charger.ino index dd0495f..4e5dadf 100644 --- a/examples/Charger/Charger.ino +++ b/examples/Charger/Charger.ino @@ -39,7 +39,6 @@ void setup() { for (auto start = millis(); !Serial && millis() - start < 5000;); delay(1000); // Delay to give time to load the Serial Monitor - charger = Charger(); if(!charger.begin()){ Serial.println("Charger initialization failed."); while (true); From 24de629f46fadd0e56807cc0c6da908e938b19c3 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Mon, 13 May 2024 14:29:57 +0200 Subject: [PATCH 20/56] Reorder print statements --- examples/Battery/Battery.ino | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/Battery/Battery.ino b/examples/Battery/Battery.ino index 77d20af..41038b9 100644 --- a/examples/Battery/Battery.ino +++ b/examples/Battery/Battery.ino @@ -39,11 +39,9 @@ void setup() { delay(1000); // Delay to give time to load the Serial Monitor charger.begin(); + Serial.println("* šŸ”Œ Charger initialized."); auto chargeVoltage = charger.getChargeVoltage(); auto endOfChargeCurrent = charger.getEndOfChargeCurrent(); - // charger.setChargeVoltage(4.2); // Set the charge voltage in V - // charger.setEndOfChargeCurrent(5); // Set the end of charge current in mA - Serial.println("* šŸ”Œ Charger initialized."); Serial.println("* āš”ļø Charge voltage: " + String(chargeVoltage) + " V"); Serial.println("* āš”ļø End of charge current: " + String(endOfChargeCurrent) + " mA"); From 539baaa1a48485f0082da59f36bf8f45f79cb54e Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Mon, 13 May 2024 14:47:02 +0200 Subject: [PATCH 21/56] Improve readability --- .../Standby_WakeFromRTC_H7.ino | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino b/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino index f1082c5..213d040 100644 --- a/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino +++ b/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino @@ -39,34 +39,44 @@ Board board; Charger charger; MAX1726Driver fuelgauge(&Wire1); +void blinkLed(int ledPin, int delayTime = 1000){ + digitalWrite(ledPin, LOW); + delay(delayTime); + digitalWrite(ledPin, HIGH); + delay(delayTime); +} + void setup() { // When uploading this sketch to the M4 core, it just goes to standby mode. #if defined(ARDUINO_GENERIC_STM32H747_M4) board.standByUntilWakeupEvent(); return; #endif - - charger.begin(); - // Turn off the built-in LED + pinMode(LEDR, OUTPUT); // Used to indicate errors + digitalWrite(LEDR, HIGH); // Turn off the red LED pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(LED_BUILTIN, HIGH); + digitalWrite(LED_BUILTIN, HIGH); // Turn off the built-in LED + pinMode(LEDB, OUTPUT); // Used to indicate that the board is awake // Turn on the blue LED to show that the board is still awake - pinMode(LEDB, OUTPUT); digitalWrite(LEDB, LOW); + if(!charger.begin()){ + // If the charger fails to initialize, it will blink the red LED + while (true){ + blinkLed(LEDR); + } + } + if(!board.begin()){ // If the board fails to initialize, it will blink the red LED - pinMode(LEDR, OUTPUT); while (true){ - digitalWrite(LEDR, LOW); - delay(1000); - digitalWrite(LEDR, HIGH); - delay(1000); + blinkLed(LEDR); } } + delay(10000); // -> Give time to take the measurement charger.setEnabled(false); // -> Please measure if it makes a difference delay(10000); // -> Give time to take the measurement From eb7cd60ed8306f1f9a35b864b6d3d9b6f6075563 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Mon, 13 May 2024 14:58:52 +0200 Subject: [PATCH 22/56] Refactor C33 RTC wakeup example --- .../Standby_WakeFromRTC_C33.ino | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino b/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino index 865e7cd..0174e7f 100644 --- a/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino +++ b/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino @@ -1,42 +1,44 @@ -#include "Arduino.h" #include "Arduino_PowerManagement.h" #include "RTC.h" -RTCTime initial_time(1, Month::JANUARY, 2000, 12, 10, 00, DayOfWeek::TUESDAY, SaveLight::SAVING_TIME_ACTIVE); +RTCTime initialTime(1, Month::JANUARY, 2000, 12, 10, 00, DayOfWeek::TUESDAY, SaveLight::SAVING_TIME_ACTIVE); -LowPower lowPower; -PowerManagement manager; Board board; -Charger charger; + +void blinkLed(int ledPin, int delayTime = 1000){ + digitalWrite(ledPin, LOW); + delay(delayTime); + digitalWrite(ledPin, HIGH); + delay(delayTime); +} void setup() { + pinMode(LEDR, OUTPUT); // Used to indicate errors + digitalWrite(LEDR, HIGH); // Turn off the red LED pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(LED_BUILTIN, LOW); + digitalWrite(LED_BUILTIN, HIGH); // Turn off the built-in LED + pinMode(LEDB, OUTPUT); // Used to indicate that the board is awake + + // Turn on the blue LED to show that the board is still awake + digitalWrite(LEDB, LOW); RTC.begin(); - manager = PowerManagement(); - manager.begin(); - board = manager.getBoard(); - - board.enableWakeupFromRTC(); - board.setAllPeripheralsPower(true); + if(!board.begin()){ + while (true){ + blinkLed(LEDR); + } + } + board.enableWakeupFromRTC(0, 0, 10); // Sleep for 60 seconds + board.setAllPeripheralsPower(true); // TODO: Check if this is necessary if (!RTC.isRunning()) { - RTC.setTime(initial_time); + RTC.setTime(initialTime); } - digitalWrite(LED_BUILTIN, HIGH); - board.sleepFor(0, 0, 10); - - // Turn LED on to indicate the board is awake - digitalWrite(LED_BUILTIN, LOW); -} - -void loop(){ - //board.setAllPeripheralsPower(false); board.standByUntilWakeupEvent(); } +void loop(){} From 7b9c6d78b75143f514f4c9e2bbfaf7f46dfe13ca Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Mon, 13 May 2024 15:02:11 +0200 Subject: [PATCH 23/56] Removed unused variable --- examples/Charger/Charger.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/Charger/Charger.ino b/examples/Charger/Charger.ino index 4e5dadf..45fcbde 100644 --- a/examples/Charger/Charger.ino +++ b/examples/Charger/Charger.ino @@ -26,7 +26,6 @@ */ #include "Arduino_PowerManagement.h" -Battery battery; Charger charger; // Charge current in mA, a safe value for most batteries is half the battery capacity From e4b375091c1f4574b5f23d906668300e8b89e248 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Mon, 13 May 2024 15:56:14 +0200 Subject: [PATCH 24/56] Replace references to old repo location --- .github/workflows/compile-examples.yml | 4 ++-- README.md | 2 +- docs/README.md | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index f573626..84a1311 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -62,8 +62,8 @@ jobs: # Install the library from the local path. - source-path: ./ # - name: Arduino_PF1550 - - source-url: https://github.com/cristidragomir97/Arduino_PF1550_old.git - - source-url: https://github.com/cristidragomir97/Arduino_Portenta_C33_LowPower.git + - source-url: https://github.com/arduino-libraries/Arduino_PF1550_old.git + - source-url: https://github.com/arduino-libraries/Arduino_Portenta_C33_LowPower.git sketch-paths: | ${{ env.UNIVERSAL_SKETCH_PATHS }} ${{ matrix.board.additional-sketch-paths }} diff --git a/README.md b/README.md index 2e767a5..53d2dfd 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # āš” Arduino PowerManagement -[![Check Arduino](https://github.com/cristidragomir97/Arduino_PowerManagement/actions/workflows/check-arduino.yml/badge.svg)](https://github.com/cristidragomir97/Arduino_PowerManagement/actions/workflows/check-arduino.yml) [![Compile Examples](https://github.com/cristidragomir97/Arduino_PowerManagement/actions/workflows/compile-examples.yml/badge.svg)](https://github.com/cristidragomir97/Arduino_PowerManagement/actions/workflows/compile-examples.yml) [![Spell Check](https://github.com/cristidragomir97/Arduino_PowerManagement/actions/workflows/spell-check.yml/badge.svg)](https://github.com/cristidragomir97/Arduino_PowerManagement/actions/workflows/spell-check.yml) [![Sync Labels](https://github.com/cristidragomir97/Arduino_PowerManagement/actions/workflows/sync-labels.yml/badge.svg)](https://github.com/cristidragomir97/Arduino_PowerManagement/actions/workflows/sync-labels.yml) +[![Check Arduino](https://github.com/arduino-libraries/Arduino_PowerManagement/actions/workflows/check-arduino.yml/badge.svg)](https://github.com/arduino-libraries/Arduino_PowerManagement/actions/workflows/check-arduino.yml) [![Compile Examples](https://github.com/arduino-libraries/Arduino_PowerManagement/actions/workflows/compile-examples.yml/badge.svg)](https://github.com/arduino-libraries/Arduino_PowerManagement/actions/workflows/compile-examples.yml) [![Spell Check](https://github.com/arduino-libraries/Arduino_PowerManagement/actions/workflows/spell-check.yml/badge.svg)](https://github.com/arduino-libraries/Arduino_PowerManagement/actions/workflows/spell-check.yml) [![Sync Labels](https://github.com/arduino-libraries/Arduino_PowerManagement/actions/workflows/sync-labels.yml/badge.svg)](https://github.com/arduino-libraries/Arduino_PowerManagement/actions/workflows/sync-labels.yml) The Arduino Pro Power Management Library serves as a comprehensive and sophisticated power management toolkit tailored for Arduino Pro boards, encompassing the Portenta H7, Portenta C33, and Nicla Vision. diff --git a/docs/README.md b/docs/README.md index 06a23aa..06f5ff7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -221,19 +221,19 @@ To simplify things, we have added a convenience function in `Board` called `slee Here's an overview of the reduction in power usage that you can expect from this library on the Portenta C33. The screenshots below are taken from the nRF Power Profiler application using a Nordic PPK2 while running the blink sketch on the same board. #### Without power optimisations -![](https://raw.githubusercontent.com/cristidragomir97/Arduino_Portenta_C33_LowPower/main/extras/results/normal_usage_blink.png) +![](https://raw.githubusercontent.com/arduino-libraries/Arduino_Portenta_C33_LowPower/main/extras/results/normal_usage_blink.png) #### Sleep (ADC, RGB LED, Secure Element, Wifi and Bluetooth off) -![](https://raw.githubusercontent.com/cristidragomir97/Arduino_Portenta_C33_LowPower/main/extras/results/sleep_no_peripherals.png) +![](https://raw.githubusercontent.com/arduino-libraries/Arduino_Portenta_C33_LowPower/main/extras/results/sleep_no_peripherals.png) #### Deep Sleep (ADC, RGB LED, Secure Element, Wifi and Bluetooth off) -![](https://raw.githubusercontent.com/cristidragomir97/Arduino_Portenta_C33_LowPower/main/extras/results/deep_sleep_no_peripherals.png) +![](https://raw.githubusercontent.com/arduino-libraries/Arduino_Portenta_C33_LowPower/main/extras/results/deep_sleep_no_peripherals.png) #### Sleep (ADC, RGB LED, Secure Element, Wifi and Bluetooth on) -![](https://raw.githubusercontent.com/cristidragomir97/Arduino_Portenta_C33_LowPower/main/extras/results/sleep_peripherals_on.png) +![](https://raw.githubusercontent.com/arduino-libraries/Arduino_Portenta_C33_LowPower/main/extras/results/sleep_peripherals_on.png) #### Deep Sleep (ADC, RGB LED, Secure Element, Wifi and Bluetooth on) -![](https://raw.githubusercontent.com/cristidragomir97/Arduino_Portenta_C33_LowPower/main/extras/results/deep_sleep_peripherals_on.png) +![](https://raw.githubusercontent.com/arduino-libraries/Arduino_Portenta_C33_LowPower/main/extras/results/deep_sleep_peripherals_on.png) From b2977929a0e44fbb96491d72d69c642ff0b58b90 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Mon, 13 May 2024 16:11:16 +0200 Subject: [PATCH 25/56] Fix CI workflow for compiling sketches --- .github/workflows/compile-examples.yml | 15 ++++++++++----- examples/Battery/Battery.ino | 1 - src/Battery.cpp | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 84a1311..e8fe54f 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -24,9 +24,7 @@ env: UNIVERSAL_SKETCH_PATHS: | - examples/Battery - examples/Charger - - examples/DeepSleep_WakeFromPin - - examples/DeepSleep_WakeFromRTC - - examples/Powershell + - examples/Standby_WakeFromPin SKETCHES_REPORTS_PATH: sketches-reports SKETCHES_REPORTS_ARTIFACT_NAME: sketches-reports @@ -46,6 +44,13 @@ jobs: - fqbn: arduino:renesas_portenta:portenta_c33 platforms: | - name: arduino:renesas_portenta + artifact-name-suffix: arduino-renesas_portenta-portenta_c33 + additional-sketch-paths: examples/ChargStandby_WakeFromRTC_C33er + - fqbn: arduino:mbed_portenta:envie_m7 + platforms: | + - name: arduino:mbed_portenta + artifact-name-suffix: arduino-mbed_portenta-envie_m7 + additional-sketch-paths: examples/Standby_WakeFromRTC_H7 steps: @@ -62,8 +67,8 @@ jobs: # Install the library from the local path. - source-path: ./ # - name: Arduino_PF1550 - - source-url: https://github.com/arduino-libraries/Arduino_PF1550_old.git - - source-url: https://github.com/arduino-libraries/Arduino_Portenta_C33_LowPower.git + - source-url: https://github.com/arduino-libraries/Arduino_PF1550.git + - source-url: https://github.com/arduino-libraries/Arduino_LowPowerPortentaC33.git sketch-paths: | ${{ env.UNIVERSAL_SKETCH_PATHS }} ${{ matrix.board.additional-sketch-paths }} diff --git a/examples/Battery/Battery.ino b/examples/Battery/Battery.ino index 41038b9..070b1a7 100644 --- a/examples/Battery/Battery.ino +++ b/examples/Battery/Battery.ino @@ -1,4 +1,3 @@ - /* Battery Information Display Demo diff --git a/src/Battery.cpp b/src/Battery.cpp index 554a016..98074b4 100644 --- a/src/Battery.cpp +++ b/src/Battery.cpp @@ -177,7 +177,7 @@ void Battery::setTemperatureMeasurementMode(bool externalTemperature){ configRegister = bitSet(configRegister, TSEL_BIT); configRegister = bitSet(configRegister, ETHRM_BIT); // FIXME: The external thermistor temperature measurement is not working as expected - // In oder to support this, probably more configuration is needed + // In order to support this, probably more configuration is needed // Currently after taking the first reading, the battery gets reported as disconnected // plus the register value is reset to the default value. } else { From a2a50927af5967566337de6fb25ecc135382febf Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 15 May 2024 06:32:30 +0200 Subject: [PATCH 26/56] Fix: include file for C33 low power library is called "Arduino_LowPowerPortentaC33.h". --- src/Board.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Board.h b/src/Board.h index 155dfb1..68e8016 100644 --- a/src/Board.h +++ b/src/Board.h @@ -10,7 +10,7 @@ #endif #if defined(ARDUINO_PORTENTA_C33) - #include "Arduino_Portenta_C33_LowPower.h" + #include "Arduino_LowPowerPortentaC33.h" #include "RTC.h" #elif defined(ARDUINO_PORTENTA_H7) || defined(ARDUINO_NICLA_VISION) #include "Arduino_LowPowerPortentaH7.h" From 3409f89cc90e7189e26841911c7c1fb6fd17ab04 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Wed, 15 May 2024 17:28:18 +0200 Subject: [PATCH 27/56] Reorganize RTC standby example --- .../Standby_WakeFromRTC_C33.ino | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino b/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino index 0174e7f..0bf8ca7 100644 --- a/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino +++ b/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino @@ -14,30 +14,36 @@ void blinkLed(int ledPin, int delayTime = 1000){ } void setup() { + board.setAllPeripheralsPower(true); // TODO: Check if this is necessary + pinMode(LEDR, OUTPUT); // Used to indicate errors digitalWrite(LEDR, HIGH); // Turn off the red LED pinMode(LED_BUILTIN, OUTPUT); + digitalWrite(LED_BUILTIN, LOW); // Turn on the built-in LED + delay(1000); digitalWrite(LED_BUILTIN, HIGH); // Turn off the built-in LED pinMode(LEDB, OUTPUT); // Used to indicate that the board is awake // Turn on the blue LED to show that the board is still awake digitalWrite(LEDB, LOW); - RTC.begin(); - if(!board.begin()){ while (true){ blinkLed(LEDR); } } - - board.enableWakeupFromRTC(0, 0, 10); // Sleep for 60 seconds - board.setAllPeripheralsPower(true); // TODO: Check if this is necessary - + + RTC.begin(); if (!RTC.isRunning()) { - RTC.setTime(initialTime); + if(!RTC.setTime(initialTime)){ + while (true){ + blinkLed(LEDR); + } + } } + board.enableWakeupFromRTC(0, 0, 10, [](){}, &RTC); // Sleep for 10 seconds + // board.setAllPeripheralsPower(false); board.standByUntilWakeupEvent(); } From d716bd044840cc0e291a3099fd5aa75175e9bd27 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Wed, 15 May 2024 17:28:40 +0200 Subject: [PATCH 28/56] Only end I2C when turning off power --- src/Board.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Board.cpp b/src/Board.cpp index eebea3f..683696f 100644 --- a/src/Board.cpp +++ b/src/Board.cpp @@ -205,9 +205,11 @@ void Board::setAllPeripheralsPower(bool on){ this -> setCommunicationPeripheralsPower(on); this -> setExternalPowerEnabled(on); this -> setAnalogDigitalConverterPower(on); - // I2C needs to be shut down because the PMIC would still try - // to communicate with the MCU. - Wire3.end(); + if(!on){ + // I2C needs to be shut down because the PMIC would still try + // to communicate with the MCU. + Wire3.end(); + } #else if defined(ARDUINO_PORTENTA_H7) // TODO Can we extract this into functions? if(on){ From 7de86c52cec6025fd5aa56c3883228009929fce1 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Wed, 15 May 2024 17:29:03 +0200 Subject: [PATCH 29/56] Add snippet to handle non-callback alarm --- src/Board.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Board.cpp b/src/Board.cpp index 683696f..56b2e2b 100644 --- a/src/Board.cpp +++ b/src/Board.cpp @@ -160,8 +160,13 @@ bool Board::enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t secon match.addMatchHour(); // Trigger the alarm when the hours match // Set the alarm callback (assuming you have a callback function named alarmCallback) - if (!rtc -> setAlarmCallback(callbackFunction, alarmTime, match)) { + if (callbackFunction && !rtc -> setAlarmCallback(callbackFunction, alarmTime, match)) { return false; // Failed to set the alarm + } else { + // Set the alarm without a callback + // if (!rtc -> setAlarm(alarmTime, match)) { + // return false; // Failed to set the alarm + // } } delay(1); return true; From 9fbd9b3738bf1e17ea2b12ddffff221b57d946c4 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Wed, 15 May 2024 17:29:30 +0200 Subject: [PATCH 30/56] Add commented out code that may be required --- src/Board.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Board.cpp b/src/Board.cpp index 56b2e2b..be35aa2 100644 --- a/src/Board.cpp +++ b/src/Board.cpp @@ -268,10 +268,15 @@ void Board::setAnalogDigitalConverterPower(bool on){ void Board::setCommunicationPeripheralsPower(bool on){ // TODO: Why do we only use the normal mode here? - if(on) + if(on){ PMIC.getControl()->turnSw1On(Sw1Mode::Normal); - else + // PMIC.getControl()->turnSw1On(Sw1Mode::Sleep); + // PMIC.getControl()->turnSw1On(Sw1Mode::Standby); + } else { PMIC.getControl()->turnSw1Off(Sw1Mode::Normal); + // PMIC.getControl()->turnSw1Off(Sw1Mode::Sleep); + // PMIC.getControl()->turnSw1Off(Sw1Mode::Standby); + } } From ded196a7f10b0c96a97aa88cd607a10e65ca0efa Mon Sep 17 00:00:00 2001 From: Cristian Paul Dragomir Date: Fri, 17 May 2024 10:42:51 +0300 Subject: [PATCH 31/56] fixed WakeFromRTC_C33 --- .../DeepSleep_WakeFromRTC_H7.ino | 83 +++++++++++++++++++ .../Standby_WakeFromRTC_C33.ino | 16 ++-- src/Board.cpp | 2 +- 3 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 examples/DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino diff --git a/examples/DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino b/examples/DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino new file mode 100644 index 0000000..f1082c5 --- /dev/null +++ b/examples/DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino @@ -0,0 +1,83 @@ +/* + Charger Demo + + This sketch demonstrates how to use the PowerManagement library enable low power modes on the Arduino Portenta H7. + * In the setup() function, it enters standby mode and waits for a wakeup event from the RTC. + * The loop() functionit is not used in this sketch. + + IMPORTANT: Please note that this sketch has to be uploaded to the M4 core too in order to achieve the lowest power consumption. + + Requirements: + - Arduino Arduino Portenta H7 + - Arduino IDE + - PowerManagement library (installable from the Arduino Library Manager) + + Usage: + + 1. Connect a battery to the board. + + 2. Upload the Sketch to the M4 core: + - Open the provided sketch in the Arduino IDE. + - Select your board type and port from the "Tools" menu. + - Select the M4 core from the "Tools" menu. + - Click the "Upload" button to upload the sketch to your board. + + 3. Upload the Sketch to the M7 core: + - Select the M7 core from the "Tools" menu. + - Click the "Upload" button to upload the sketch to your board. + + 4. Observer LED behavior: + - The blue LED will turn on when the board is awake. + - The blue LED will turn off when the board goes to sleep. + - The red LED will blink if the board fails to initialize. +*/ + +#include "Arduino_PowerManagement.h" +#include "MAX1726Driver.h" + +Board board; +Charger charger; +MAX1726Driver fuelgauge(&Wire1); + +void setup() { + // When uploading this sketch to the M4 core, it just goes to standby mode. + #if defined(ARDUINO_GENERIC_STM32H747_M4) + board.standByUntilWakeupEvent(); + return; + #endif + + charger.begin(); + + // Turn off the built-in LED + pinMode(LED_BUILTIN, OUTPUT); + digitalWrite(LED_BUILTIN, HIGH); + + // Turn on the blue LED to show that the board is still awake + pinMode(LEDB, OUTPUT); + digitalWrite(LEDB, LOW); + + if(!board.begin()){ + // If the board fails to initialize, it will blink the red LED + pinMode(LEDR, OUTPUT); + while (true){ + digitalWrite(LEDR, LOW); + delay(1000); + digitalWrite(LEDR, HIGH); + delay(1000); + } + } + + charger.setEnabled(false); // -> Please measure if it makes a difference + delay(10000); // -> Give time to take the measurement + + // Takes 45s to get into shutdown mode + fuelgauge.setOperationMode(FuelGaugeOperationMode::shutdown); + + // The LED should go off when the board goes to sleep + board.setAllPeripheralsPower(false); + + board.enableWakeupFromRTC(0, 0, 60); // Go to standby for 60 seconds + board.standByUntilWakeupEvent(); +} + +void loop() {} \ No newline at end of file diff --git a/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino b/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino index 0bf8ca7..a4663e9 100644 --- a/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino +++ b/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino @@ -14,7 +14,7 @@ void blinkLed(int ledPin, int delayTime = 1000){ } void setup() { - board.setAllPeripheralsPower(true); // TODO: Check if this is necessary + pinMode(LEDR, OUTPUT); // Used to indicate errors digitalWrite(LEDR, HIGH); // Turn off the red LED @@ -24,14 +24,17 @@ void setup() { digitalWrite(LED_BUILTIN, HIGH); // Turn off the built-in LED pinMode(LEDB, OUTPUT); // Used to indicate that the board is awake - // Turn on the blue LED to show that the board is still awake - digitalWrite(LEDB, LOW); + if(!board.begin()){ while (true){ blinkLed(LEDR); } } + + board.setAllPeripheralsPower(true); // TODO: Check if this is necessary + // Turn on the blue LED to show that the board is still awake + digitalWrite(LEDB, LOW); RTC.begin(); if (!RTC.isRunning()) { @@ -43,8 +46,11 @@ void setup() { } board.enableWakeupFromRTC(0, 0, 10, [](){}, &RTC); // Sleep for 10 seconds - // board.setAllPeripheralsPower(false); + + delay(1000); // Let the user see that the board is ready to sleep + + board.setAllPeripheralsPower(false); board.standByUntilWakeupEvent(); } -void loop(){} +void loop(){} \ No newline at end of file diff --git a/src/Board.cpp b/src/Board.cpp index be35aa2..297ff53 100644 --- a/src/Board.cpp +++ b/src/Board.cpp @@ -319,4 +319,4 @@ bool Board::setReferenceVoltage(float voltage) { return UNKNOWN_VALUE; -} +} \ No newline at end of file From bb6a43ee5771bca34724ca260965afcaba80f6bc Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Thu, 23 May 2024 14:52:34 +0200 Subject: [PATCH 32/56] Use RTC alarm without callback --- .../Standby_WakeFromRTC_C33.ino | 3 ++- src/Board.cpp | 11 ++++++++--- src/Board.h | 3 ++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino b/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino index a4663e9..20a96a4 100644 --- a/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino +++ b/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino @@ -45,7 +45,8 @@ void setup() { } } - board.enableWakeupFromRTC(0, 0, 10, [](){}, &RTC); // Sleep for 10 seconds + // board.enableWakeupFromRTC(0, 0, 10, [](){}); // Sleep for 10 seconds + board.enableWakeupFromRTC(0, 0, 10); // Sleep for 10 seconds delay(1000); // Let the user see that the board is ready to sleep diff --git a/src/Board.cpp b/src/Board.cpp index 297ff53..1a08e55 100644 --- a/src/Board.cpp +++ b/src/Board.cpp @@ -164,13 +164,18 @@ bool Board::enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t secon return false; // Failed to set the alarm } else { // Set the alarm without a callback - // if (!rtc -> setAlarm(alarmTime, match)) { - // return false; // Failed to set the alarm - // } + if (!rtc -> setAlarm(alarmTime, match)) { + return false; // Failed to set the alarm + } } delay(1); return true; } + +bool Board::enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds, RTClock * rtc){ + return enableWakeupFromRTC(hours, minutes, seconds, nullptr, rtc); +} + #endif #if defined(ARDUINO_PORTENTA_H7) || defined(ARDUINO_NICLA_VISION) diff --git a/src/Board.h b/src/Board.h index 68e8016..e1aef8d 100644 --- a/src/Board.h +++ b/src/Board.h @@ -137,7 +137,8 @@ class Board { * If no RTC instance is provided, the default RTC instance is used. * @return True if successful, false otherwise. */ - bool enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds, void (* const callbackFunction)() = nullptr, RTClock * rtc = &RTC); + bool enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds, void (* const callbackFunction)(), RTClock * rtc = &RTC); + bool enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds, RTClock * rtc = &RTC); #endif #if defined(ARDUINO_PORTENTA_H7) From 3bad6decefe9307201cb72d753d90affb1813fda Mon Sep 17 00:00:00 2001 From: Cristian Paul Dragomir Date: Mon, 3 Jun 2024 16:37:10 +0300 Subject: [PATCH 33/56] Apply adjustments from the library review --- .../DeepSleep_WakeFromRTC_H7.ino | 83 ------ examples/Powershell/Powershell.ino | 238 ------------------ examples/Powershell/README.md | 78 ------ .../Standby_WakeFromPin.ino | 28 +-- .../Standby_WakeFromRTC_C33.ino | 7 +- .../Standby_WakeFromRTC_H7.ino | 15 +- src/Battery.cpp | 2 - src/Battery.h | 2 +- src/Board.cpp | 75 ++---- src/Board.h | 10 +- src/MAX1726Driver.h | 1 - 11 files changed, 46 insertions(+), 493 deletions(-) delete mode 100644 examples/DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino delete mode 100644 examples/Powershell/Powershell.ino delete mode 100644 examples/Powershell/README.md diff --git a/examples/DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino b/examples/DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino deleted file mode 100644 index f1082c5..0000000 --- a/examples/DeepSleep_WakeFromRTC_H7/DeepSleep_WakeFromRTC_H7.ino +++ /dev/null @@ -1,83 +0,0 @@ -/* - Charger Demo - - This sketch demonstrates how to use the PowerManagement library enable low power modes on the Arduino Portenta H7. - * In the setup() function, it enters standby mode and waits for a wakeup event from the RTC. - * The loop() functionit is not used in this sketch. - - IMPORTANT: Please note that this sketch has to be uploaded to the M4 core too in order to achieve the lowest power consumption. - - Requirements: - - Arduino Arduino Portenta H7 - - Arduino IDE - - PowerManagement library (installable from the Arduino Library Manager) - - Usage: - - 1. Connect a battery to the board. - - 2. Upload the Sketch to the M4 core: - - Open the provided sketch in the Arduino IDE. - - Select your board type and port from the "Tools" menu. - - Select the M4 core from the "Tools" menu. - - Click the "Upload" button to upload the sketch to your board. - - 3. Upload the Sketch to the M7 core: - - Select the M7 core from the "Tools" menu. - - Click the "Upload" button to upload the sketch to your board. - - 4. Observer LED behavior: - - The blue LED will turn on when the board is awake. - - The blue LED will turn off when the board goes to sleep. - - The red LED will blink if the board fails to initialize. -*/ - -#include "Arduino_PowerManagement.h" -#include "MAX1726Driver.h" - -Board board; -Charger charger; -MAX1726Driver fuelgauge(&Wire1); - -void setup() { - // When uploading this sketch to the M4 core, it just goes to standby mode. - #if defined(ARDUINO_GENERIC_STM32H747_M4) - board.standByUntilWakeupEvent(); - return; - #endif - - charger.begin(); - - // Turn off the built-in LED - pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(LED_BUILTIN, HIGH); - - // Turn on the blue LED to show that the board is still awake - pinMode(LEDB, OUTPUT); - digitalWrite(LEDB, LOW); - - if(!board.begin()){ - // If the board fails to initialize, it will blink the red LED - pinMode(LEDR, OUTPUT); - while (true){ - digitalWrite(LEDR, LOW); - delay(1000); - digitalWrite(LEDR, HIGH); - delay(1000); - } - } - - charger.setEnabled(false); // -> Please measure if it makes a difference - delay(10000); // -> Give time to take the measurement - - // Takes 45s to get into shutdown mode - fuelgauge.setOperationMode(FuelGaugeOperationMode::shutdown); - - // The LED should go off when the board goes to sleep - board.setAllPeripheralsPower(false); - - board.enableWakeupFromRTC(0, 0, 60); // Go to standby for 60 seconds - board.standByUntilWakeupEvent(); -} - -void loop() {} \ No newline at end of file diff --git a/examples/Powershell/Powershell.ino b/examples/Powershell/Powershell.ino deleted file mode 100644 index 5ed77cb..0000000 --- a/examples/Powershell/Powershell.ino +++ /dev/null @@ -1,238 +0,0 @@ -#include "PowerManagement.h" -#include -#include - -PowerManagement manager; -Battery battery; -Board board; -Charger charger; - - -std::vector splitString(String input) { - std::vector args; - int start = 0; - int end = input.indexOf(' '); - while (end >= 0) { - args.push_back(input.substring(start, end)); - start = end + 1; - end = input.indexOf(' ', start); - } - args.push_back(input.substring(start)); - return args; -} - - -void printChargerStatus(){ - ChargingState status = charger.getState(); - - switch (status) { - case ChargingState::PreCharge: - Serial.println("precharge"); - // Additional code specific to precharge - break; - case ChargingState::FastChargeConstantCurrent: - Serial.println("fast-charge constant current"); - // Additional code specific to fast-charge CC - break; - case ChargingState::FastChargeConstantVoltage: - Serial.println("fast-charge constant voltage"); - // Additional code specific to fast-charge CV - break; - case ChargingState::EndOfCharge: - Serial.println("end-of-charge"); - // Additional code specific to end-of-charge - break; - case ChargingState::Done: - Serial.println("done"); - // Additional code specific to done - break; - case ChargingState::TimerFaultError: - Serial.println("timer fault"); - // Additional code specific to timer fault - break; - case ChargingState::ThermistorSuspendError: - Serial.println("thermistor suspend"); - // Additional code specific to thermistor suspend - break; - case ChargingState::ChargerDisabled: - Serial.println("off"); - // Additional code specific to off - break; - case ChargingState::BatteryOvervoltageError: - Serial.println("overvoltage condition"); - // Additional code specific to battery overvoltage condition - break; - case ChargingState::ChargerBypassed: - Serial.println("disabled"); - // Additional code specific to linear only - break; - default: - Serial.println("unknown"); - // Additional code for handling unknown status - break; - } -} - -void status(){ - - Serial.println("BOARD: \n--------------------------"); - Serial.print("* Powered by usb: "); Serial.println(board.isUSBPowered()); - Serial.print("* Powered by battery: "); Serial.println(board.isBatteryPowered()); - Serial.println(); - - Serial.println("CHARGER: \n--------------------------"); - Serial.print("* Charger status: "); printChargerStatus(); - Serial.println(); - - Serial.println("BATTERY: \n--------------------------"); - Serial.println( - "* Voltage: " + String(battery.voltage()) + "mV \n" + - "* Current: " + String(battery.current()) + "mA \n" + - "* Percentage: " + String(battery.percentage()) + "% \n" + - "* Remaining Capacity: " + String(battery.remainingCapacity()) + "mAh \n" + - "* Temperature: " + String(battery.temperature()) + "\n" + - "\n"); -} - - -void setRailVoltage(std::vector args){ - String rail = args[1]; - float voltage = atof(args[2].c_str()); - - if(rail == "C33_reference"){ - #if defined(ARDUINO_PORTENTA_C33) - if(board.setReferenceVoltage(voltage)) Serial.println("Successfully changed reference voltage"); - else Serial.println("Failed to set reference voltage"); - #else - Serial.println("Current board is not an arduino portenta c33"); - #endif - } else if (rail == "C33_external"){ - #if defined(ARDUINO_PORTENTA_C33) - if(board.setExternalVoltage(voltage)) Serial.println("Successfully set external voltage"); - else Serial.println("Failed to set external voltage"); - #else - Serial.println("Current board is not an arduino portenta c33"); - #endif - - } else if (rail == "H7_external"){ - #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_GENERIC_STM32H747_M4) - board.setExternalVoltage(voltage); - #else - Serial.println("Current board is not an arduino portenta h7"); - #endif - - } else if (rail == "nicla_external"){ - #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_GENERIC_STM32H747_M4) - board.setExternalVoltage(voltage); - #else - Serial.println("Current board is not an arduino nicla vision"); - #endif - - } -} - -void toggleRail(std::vector args){ - String rail = args[1]; - bool on = atoi(args[2].c_str()) == 1; - - if (rail == "C33_external"){ - #if defined(ARDUINO_PORTENTA_C33) - board.setExternalPowerEnabled(on); - #else - Serial.println("Current board is not an arduino portenta c33"); - #endif - - } else if (rail == "C33_communication"){ - #if defined(ARDUINO_PORTENTA_C33) - board.setCommunicationPeripheralsPower(on); - #else - Serial.println("Current board is not an arduino portenta c33"); - #endif - - } else if (rail == "H7_external"){ - #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_GENERIC_STM32H747_M4) - board.setExternalPowerEnabled(on); - #else - Serial.println("Current board is not an arduino portenta h7"); - #endif - - } else if (rail == "nicla_external"){ - #if defined(ARDUINO_NICLA_VISION) - board.setExternalPowerEnabled(on); - #else - Serial.println("Current board is not an arduino nicla vision"); - #endif - - } else if (rail == "nicla_camera"){ - #if defined(ARDUINO_NICLA_VISION) - board.setCameraPowerEnabled(on); - #else - Serial.println("Current board is not an arduino nicla vision"); - #endif - } -} - -void toggleCharger(std::vector args){ - bool on = atoi(args[1].c_str()) == 1; - Serial.println(on); - - - if(on){ - if(charger.enable()){ - Serial.println("> Charger enabled"); - } else { - Serial.println("> Error enabling charger"); - } - - } else { - charger.disable(); - Serial.println("> Charger disabled"); - } -} - - - -void setup() { - Serial.begin(115200); - while (!Serial); - - manager = PowerManagement(); - manager.begin(); - - battery = manager.getBattery(); - board = manager.getBoard(); - charger = manager.getCharger(); - - - #if !defined(ARDUINO_NICLA_VISION) - charger.setChargeCurrent(0.2); - charger.setChargeVoltage(4.2); - charger.setEndOfChargeCurrent(0.005); - #endif -} - -void loop() { - if (Serial.available() > 0) { - String input = Serial.readString(); - input.trim(); - std::vector args = splitString(input); - - if (args.size() > 0) { - String command = args[0]; - if (command == "toggle_rail") { - toggleRail(args); - } else if (command == "set_rail_voltage") { - setRailVoltage(args); - } else if (command == "toggle_charger") { - toggleCharger(args); - } else if (command == "status") { - status(); - - } else { - Serial.println("Unknown command: " + command); - } - - Serial.println(); - } - } -} \ No newline at end of file diff --git a/examples/Powershell/README.md b/examples/Powershell/README.md deleted file mode 100644 index 9a21dd2..0000000 --- a/examples/Powershell/README.md +++ /dev/null @@ -1,78 +0,0 @@ -# Power ManagemtnInteractive Shell - -This sketch demonstrates the usage of the Power Management library to control and monitor power-related features of different Arduino boards. The sketch allows you to interact with various power management functionalities such as battery monitoring, charging control, and voltage rail adjustments. - -## Instructions - -1. Upload the sketch to your Arduino board. -2. Open the serial monitor at a baud rate of 115200. -3. Use the provided commands to interact with power management features. - -## Commands and Parameters - -### Toggle Rail -Toggle the state of a specific power rail. - -Command: `toggle_rail ` - -- ``: Specify the name of the power rail to toggle. - - Options: `C33_external`, `C33_communication`, `H7_external`, `nicla_external`, `nicla_camera` -- ``: Specify whether to turn the rail on or off. - - Options: `1` (on) or `0` (off) - -### Set Rail Voltage -Set the voltage of a specific power rail. - -Command: `set_rail_voltage ` - -- ``: Specify the name of the power rail to set the voltage for. - - Options: `C33_reference`, `C33_analog`, `C33_external`, `H7_external`, `nicla_external` -- ``: Specify the voltage value to set for the rail. - - Note: Voltage values must be within the acceptable range for the specific rail. - -### Toggle Charger -Toggle the state of the battery charger. - -Command: `toggle_charger ` - -- ``: Specify whether to enable or disable the charger. - - Options: `1` (on) or `0` (off) - -### Status -Display the status of the board, charger, and battery metrics. - -Command: `status` - -## Notes - -- Make sure to follow the guidelines for voltage and rail names to avoid unexpected behavior. -- Be cautious when adjusting voltage values, as incorrect values may damage your board or battery. - -## Example Usage - -1. To turn on the external power rail on a Portenta C33: - ``` - toggle_rail C33_external 1 - ``` - -2. To set the reference voltage to 1.20V on a Portenta C33: - ``` - set_rail_voltage C33_reference 1.20 - ``` - -3. To enable the charger: - ``` - toggle_charger 1 - ``` - -4. To view the status of the board, charger, and battery metrics: - ``` - status - ``` - -## License - -This sketch and library are provided under the [MIT License](LICENSE). -``` - -Feel free to modify and expand upon this template to suit your specific project and requirements. \ No newline at end of file diff --git a/examples/Standby_WakeFromPin/Standby_WakeFromPin.ino b/examples/Standby_WakeFromPin/Standby_WakeFromPin.ino index 9d35812..74ecb82 100644 --- a/examples/Standby_WakeFromPin/Standby_WakeFromPin.ino +++ b/examples/Standby_WakeFromPin/Standby_WakeFromPin.ino @@ -3,37 +3,31 @@ #include "Arduino_PowerManagement.h" -#define WAKE_PIN A3 -#define GOTO_SLEEP_PIN 0 +#define PORTENTA_C33_WAKEUP_PIN A3 +#define GOTO_SLEEP_PIN D0 volatile bool shouldGoToSleep = false; Board board; -Charger charger; void setup() { board = Board(); - charger = Charger(); board.begin(); - charger.begin(); + board.setAllPeripheralsPower(true); // Allows to use a button to put the device into sleep mode attachInterrupt(digitalPinToInterrupt(GOTO_SLEEP_PIN), goToSleep, RISING); #if defined(ARDUINO_PORTENTA_C33) - // On Portenta C33, you can specify which pin to use to wake up the device from sleep mode - // Please read the documentation to understand which pins can be used to wake up the device. - board.enableWakeupFromPin(WAKE_UP_PIN, RISING); + // On Portenta C33, you can specify which pin to use to wake up the device from sleep mode + // Please read the documentation to understand which pins can be used to wake up the device. + board.enableWakeupFromPin(PORTENTA_C33_WAKEUP_PIN, RISING); #elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_GENERIC_STM32H747_M4) || defined(ARDUINO_NICLA_VISION) - // On Portenta only pin GPIO0 can be used to wake up the device from sleep mode - board.enableWakeupFromPin(); + // On Portenta only pin GPIO0 can be used to wake up the device from sleep mode + board.enableWakeupFromPin(); #endif + - // TODO why is this needed? Why true? -> Peripherals still off after reset? - // only necessary for C33 - board.setAllPeripheralsPower(true); - // TODO why is this needed? - charger.setEnabled(false); pinMode(LEDB, OUTPUT); } @@ -45,9 +39,7 @@ void goToSleep(){ void loop() { if(shouldGoToSleep){ shouldGoToSleep = false; - - // TODO why is this here? - //board.setAllPeripheralsPower(false); + board.setAllPeripheralsPower(false); // turn off peripherals before going to sleep board.standByUntilWakeupEvent(); } else { // Show that the board is awake by blinking the LED diff --git a/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino b/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino index 20a96a4..0d8a0ee 100644 --- a/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino +++ b/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino @@ -25,7 +25,6 @@ void setup() { pinMode(LEDB, OUTPUT); // Used to indicate that the board is awake - if(!board.begin()){ while (true){ blinkLed(LEDR); @@ -33,8 +32,8 @@ void setup() { } board.setAllPeripheralsPower(true); // TODO: Check if this is necessary - // Turn on the blue LED to show that the board is still awake - digitalWrite(LEDB, LOW); + + digitalWrite(LEDB, LOW); // Turn on the blue LED to show that the board is still awake RTC.begin(); if (!RTC.isRunning()) { @@ -48,7 +47,7 @@ void setup() { // board.enableWakeupFromRTC(0, 0, 10, [](){}); // Sleep for 10 seconds board.enableWakeupFromRTC(0, 0, 10); // Sleep for 10 seconds - delay(1000); // Let the user see that the board is ready to sleep + delay(1000); // Keep the board awake for 1 second, so we can se it working board.setAllPeripheralsPower(false); board.standByUntilWakeupEvent(); diff --git a/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino b/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino index 213d040..9a31a08 100644 --- a/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino +++ b/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino @@ -36,7 +36,6 @@ #include "MAX1726Driver.h" Board board; -Charger charger; MAX1726Driver fuelgauge(&Wire1); void blinkLed(int ledPin, int delayTime = 1000){ @@ -62,12 +61,6 @@ void setup() { // Turn on the blue LED to show that the board is still awake digitalWrite(LEDB, LOW); - if(!charger.begin()){ - // If the charger fails to initialize, it will blink the red LED - while (true){ - blinkLed(LEDR); - } - } if(!board.begin()){ // If the board fails to initialize, it will blink the red LED @@ -76,17 +69,15 @@ void setup() { } } - delay(10000); // -> Give time to take the measurement - charger.setEnabled(false); // -> Please measure if it makes a difference - delay(10000); // -> Give time to take the measurement // Takes 45s to get into shutdown mode fuelgauge.setOperationMode(FuelGaugeOperationMode::shutdown); - + delay(10000); // keep the board awake for 10 seconds, so we can se it working + // The LED should go off when the board goes to sleep board.setAllPeripheralsPower(false); - board.enableWakeupFromRTC(0, 0, 60); // Go to standby for 60 seconds + board.enableWakeupFromRTC(0, 0, 10); // Go to standby for 10 seconds board.standByUntilWakeupEvent(); } diff --git a/src/Battery.cpp b/src/Battery.cpp index 98074b4..45bc813 100644 --- a/src/Battery.cpp +++ b/src/Battery.cpp @@ -52,8 +52,6 @@ bool Battery::awaitDataReady(uint16_t timeout){ return false; } - // TODO Remove the print statement - Serial.println("Waiting for the battery gauge to be ready..."); delay(100); // Wait for the data to be ready. This takes 710ms from power-up } } diff --git a/src/Battery.h b/src/Battery.h index 6dc06ce..38a23c3 100644 --- a/src/Battery.h +++ b/src/Battery.h @@ -146,7 +146,7 @@ class Battery { int16_t averagePower(); /** - * @brief Reads the current temperature of the internal die. + * @brief Reads the current temperature of the internal die of the battery gauge chip. * @return The current temperature in degrees Celsius. */ uint8_t internalTemperature(); diff --git a/src/Board.cpp b/src/Board.cpp index 1a08e55..25d507a 100644 --- a/src/Board.cpp +++ b/src/Board.cpp @@ -70,15 +70,13 @@ bool Board::begin() { bool Board::isUSBPowered() { uint16_t registerValue = PMIC.readPMICreg(Register::CHARGER_VBUS_SNS); - // TODO: Check which one works - // return bitRead(registerValue, 2) == 0; return bitRead(registerValue, 5) == 1; // ā€” VBUS is valid -> USB powered } bool Board::isBatteryPowered() { uint8_t registerValue = PMIC.readPMICreg(Register::CHARGER_BATT_SNS); uint8_t batteryPower = extractBits(registerValue, 0, 2); - return batteryPower == 0; // No valid VBUS input -> battery powered + return batteryPower == 0; } void Board::setExternalPowerEnabled(bool on) { @@ -212,76 +210,49 @@ void Board::standByUntilWakeupEvent(){ void Board::setAllPeripheralsPower(bool on){ #if defined(ARDUINO_PORTENTA_C33) + // The power architecture on the C33 puts peripherals on sepparate power lanes which are independent, so we can turn off the peripherals separately. + // Turning these rails will not interfere with your sketch. this -> setCommunicationPeripheralsPower(on); this -> setExternalPowerEnabled(on); this -> setAnalogDigitalConverterPower(on); - if(!on){ - // I2C needs to be shut down because the PMIC would still try - // to communicate with the MCU. - Wire3.end(); - } #else if defined(ARDUINO_PORTENTA_H7) - // TODO Can we extract this into functions? + // On the H7 several chips need different voltages, so we cannot turn the lanes that are dependent on eachother separately. + // This should only be used when going into standby mode, as turning off the USB-C PHY, Ethernet or Video bridge might cause undefined behaviour. if(on){ PMIC.getControl() -> turnLDO2On(Ldo2Mode::Normal); - PMIC.getControl() -> turnLDO2On(Ldo2Mode::Sleep); - PMIC.getControl() -> turnLDO2On(Ldo2Mode::Standby); PMIC.getControl() -> turnLDO1On(Ldo1Mode::Normal); - PMIC.getControl() -> turnLDO1On(Ldo1Mode::Sleep); - PMIC.getControl() -> turnLDO1On(Ldo1Mode::Standby); PMIC.getControl() -> turnLDO3On(Ldo3Mode::Normal); - PMIC.getControl() -> turnLDO3On(Ldo3Mode::Sleep); - PMIC.getControl() -> turnLDO3On(Ldo3Mode::Standby); PMIC.getControl() -> turnSw1On(Sw1Mode::Normal); - PMIC.getControl() -> turnSw1On(Sw1Mode::Sleep); - PMIC.getControl() -> turnSw1On(Sw1Mode::Standby); } else { PMIC.getControl() -> turnLDO2Off(Ldo2Mode::Normal); - PMIC.getControl() -> turnLDO2Off(Ldo2Mode::Sleep); - PMIC.getControl() -> turnLDO2Off(Ldo2Mode::Standby); PMIC.getControl() -> turnLDO1Off(Ldo1Mode::Normal); - PMIC.getControl() -> turnLDO1Off(Ldo1Mode::Sleep); - PMIC.getControl() -> turnLDO1Off(Ldo1Mode::Standby); PMIC.getControl() -> turnLDO3Off(Ldo3Mode::Normal); - PMIC.getControl() -> turnLDO3Off(Ldo3Mode::Sleep); - PMIC.getControl() -> turnLDO3Off(Ldo3Mode::Standby); PMIC.getControl() -> turnSw1Off(Sw1Mode::Normal); - PMIC.getControl() -> turnSw1Off(Sw1Mode::Sleep); - PMIC.getControl() -> turnSw1Off(Sw1Mode::Standby); - // I2C needs to be shut down because the PMIC would still try - // to communicate with the MCU. - Wire1.end(); } - #endif } - +// void Board::setAnalogDigitalConverterPower(bool on){ -// TODO Not available on the Portenta H7? -#if defined(ARDUINO_PORTENTA_C33) - if(on){ - PMIC.getControl()->turnLDO1On(Ldo1Mode::Normal); - PMIC.getControl()->turnLDO1On(Ldo1Mode::Sleep); - PMIC.getControl()->turnLDO1On(Ldo1Mode::Standby); - } else { - PMIC.getControl()->turnLDO1Off(Ldo1Mode::Normal); - PMIC.getControl()->turnLDO1Off(Ldo1Mode::Sleep); - PMIC.getControl()->turnLDO1Off(Ldo1Mode::Standby); - } -#endif + #if defined(ARDUINO_PORTENTA_C33) + if(on){ + PMIC.getControl()->turnLDO1On(Ldo1Mode::Normal); + } else { + PMIC.getControl()->turnLDO1Off(Ldo1Mode::Normal); + } + #endif + // On the H7 the ADC is powered by the main MCU power lane, so we cannot turn it off independently. } void Board::setCommunicationPeripheralsPower(bool on){ - // TODO: Why do we only use the normal mode here? - if(on){ - PMIC.getControl()->turnSw1On(Sw1Mode::Normal); - // PMIC.getControl()->turnSw1On(Sw1Mode::Sleep); - // PMIC.getControl()->turnSw1On(Sw1Mode::Standby); - } else { - PMIC.getControl()->turnSw1Off(Sw1Mode::Normal); - // PMIC.getControl()->turnSw1Off(Sw1Mode::Sleep); - // PMIC.getControl()->turnSw1Off(Sw1Mode::Standby); - } + #if defined(ARDUINO_PORTENTA_C33) + if(on){ + PMIC.getControl()->turnSw1On(Sw1Mode::Normal); + } else { + PMIC.getControl()->turnSw1Off(Sw1Mode::Normal); + } + #endif + // On the H7 the communication peripherals are powered by the main MCU power lane, + // so we cannot turn them off independently. } diff --git a/src/Board.h b/src/Board.h index e1aef8d..d80b61a 100644 --- a/src/Board.h +++ b/src/Board.h @@ -13,6 +13,9 @@ #include "Arduino_LowPowerPortentaC33.h" #include "RTC.h" #elif defined(ARDUINO_PORTENTA_H7) || defined(ARDUINO_NICLA_VISION) + // When used standalone the LowPowerPortentaH7 library will turn off the Ethernet interface to avoid issues with the line termination resistors, + // but in this library we can turn of the Ethernet interface using the PMIC, so we set the NO_ETHERNET_TURN_OFF flag to avoid turning off the Ethernet interface from both sides. + #define NO_ETHERNET_TURN_OFF #include "Arduino_LowPowerPortentaH7.h" #endif @@ -147,24 +150,23 @@ class Board { #if defined(ARDUINO_PORTENTA_C33) - // TODO Restarts after waking up.? /** * Put the device into sleep mode until a wakeup event occurs * This sleep mode is ideal for applications requiring periodic wake-ups or * brief intervals of inactivity and reduces consumption to a range between * 6mA and 18mA depending on the state of the peripherals. - * This sleep mode resumes the operation from the last operation. + * This sleep mode resumes the operation from the last operation without resetting the board. * A wakeup event can be an interrupt on a pin or the RTC, * depending on what you set with enableWakeupFromPin() and enableWakeupFromRTC(). */ void sleepUntilWakeupEvent(); #endif - // TODO measurements are board specific. Need adjustments for Portenta H7. + /** * Put the device into standby mode until a wakeup event occurs. * For scenarios demanding drastic power conservation, the standby Mode significantly reduces - * the board's power usage to range between 90uA and 11mA depending on the state of the peripherals. + * the board's power usage to micro amperes range depending on the state of the peripherals. * This mode restarts the board on wake-up, effectively running the setup() function again. * A wakeup event can be an interrupt on a pin or the RTC, depending on what * you set with enableWakeupFromPin() and enableWakeupFromRTC(). diff --git a/src/MAX1726Driver.h b/src/MAX1726Driver.h index 9165860..4a65a41 100644 --- a/src/MAX1726Driver.h +++ b/src/MAX1726Driver.h @@ -1,5 +1,4 @@ #include "WireUtils.h" -// TODO extract into a separate header file and check how PF1550Driver is implemented #include "BatteryConstants.h" enum class FuelGaugeOperationMode From f6b6057e140da1f6d8991fbeebf14ceca55aabb2 Mon Sep 17 00:00:00 2001 From: Cristian Paul Dragomir Date: Mon, 3 Jun 2024 16:43:56 +0300 Subject: [PATCH 34/56] fixed compilation workflow --- .github/workflows/compile-examples.yml | 2 +- src/Board.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index e8fe54f..969aee9 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -45,7 +45,7 @@ jobs: platforms: | - name: arduino:renesas_portenta artifact-name-suffix: arduino-renesas_portenta-portenta_c33 - additional-sketch-paths: examples/ChargStandby_WakeFromRTC_C33er + additional-sketch-paths: examples/Standby_WakeFromRTC_C33 - fqbn: arduino:mbed_portenta:envie_m7 platforms: | - name: arduino:mbed_portenta diff --git a/src/Board.cpp b/src/Board.cpp index 25d507a..42f3e40 100644 --- a/src/Board.cpp +++ b/src/Board.cpp @@ -216,7 +216,7 @@ void Board::setAllPeripheralsPower(bool on){ this -> setExternalPowerEnabled(on); this -> setAnalogDigitalConverterPower(on); #else if defined(ARDUINO_PORTENTA_H7) - // On the H7 several chips need different voltages, so we cannot turn the lanes that are dependent on eachother separately. + // On the H7 several chips need different voltages, so we cannot turn the lanes that are dependent on each other separately. // This should only be used when going into standby mode, as turning off the USB-C PHY, Ethernet or Video bridge might cause undefined behaviour. if(on){ PMIC.getControl() -> turnLDO2On(Ldo2Mode::Normal); From cd4b7e6d603ecf6e92151037367b94393c497f09 Mon Sep 17 00:00:00 2001 From: Cristian Paul Dragomir Date: Mon, 3 Jun 2024 16:54:30 +0300 Subject: [PATCH 35/56] Fix compile-examples.yaml --- .github/workflows/compile-examples.yml | 41 +++++--------------------- 1 file changed, 8 insertions(+), 33 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 969aee9..eb95fa9 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -1,3 +1,4 @@ +# Source: https://github.com/per1234/.github/blob/main/workflow-templates/compile-examples-private.md name: Compile Examples # See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows @@ -41,18 +42,17 @@ jobs: matrix: board: - - fqbn: arduino:renesas_portenta:portenta_c33 - platforms: | - - name: arduino:renesas_portenta - artifact-name-suffix: arduino-renesas_portenta-portenta_c33 - additional-sketch-paths: examples/Standby_WakeFromRTC_C33 - fqbn: arduino:mbed_portenta:envie_m7 platforms: | - name: arduino:mbed_portenta artifact-name-suffix: arduino-mbed_portenta-envie_m7 + additional-sketch-paths: examples/Standby_WakeFromRTC_C33 + - fqbn: arduino:renesas_portenta:portenta_c33 + platforms: | + - name: arduino:renesas_portenta + artifact-name-suffix: arduino-renesas_portenta-portenta_c33 additional-sketch-paths: examples/Standby_WakeFromRTC_H7 - steps: - name: Checkout repository uses: actions/checkout@v4 @@ -66,8 +66,7 @@ jobs: libraries: | # Install the library from the local path. - source-path: ./ - # - name: Arduino_PF1550 - - source-url: https://github.com/arduino-libraries/Arduino_PF1550.git + - name: Arduino_PF1550 - source-url: https://github.com/arduino-libraries/Arduino_LowPowerPortentaC33.git sketch-paths: | ${{ env.UNIVERSAL_SKETCH_PATHS }} @@ -79,29 +78,5 @@ jobs: uses: actions/upload-artifact@v4 with: if-no-files-found: error + name: sketches-report-${{ matrix.board.artifact-name-suffix }} path: ${{ env.SKETCHES_REPORTS_PATH }} - name: ${{ env.SKETCHES_REPORTS_ARTIFACT_NAME }} - - report-size-deltas: - needs: build - # Run even if some compilations failed. - if: always() && github.event_name == 'pull_request' - runs-on: ubuntu-latest - permissions: - pull-requests: write - - steps: - - name: Download sketches reports artifact - id: download-artifact - continue-on-error: true # If compilation failed for all boards then there are no artifacts - uses: actions/download-artifact@v4 - with: - name: ${{ env.SKETCHES_REPORTS_ARTIFACT_NAME }} - path: ${{ env.SKETCHES_REPORTS_PATH }} - - - name: Comment size deltas report to PR - uses: arduino/report-size-deltas@v1 - # If actions/download-artifact failed, there are no artifacts to report from. - if: steps.download-artifact.outcome == 'success' - with: - sketches-reports-source: ${{ env.SKETCHES_REPORTS_PATH }} \ No newline at end of file From d4020b883b387fd56a20e5b91dbafb1deecf2221 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Mon, 3 Jun 2024 16:27:27 +0200 Subject: [PATCH 36/56] Adjust indentation --- .github/workflows/compile-examples.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index eb95fa9..2828d99 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -23,9 +23,9 @@ on: env: UNIVERSAL_SKETCH_PATHS: | - - examples/Battery - - examples/Charger - - examples/Standby_WakeFromPin + - examples/Battery + - examples/Charger + - examples/Standby_WakeFromPin SKETCHES_REPORTS_PATH: sketches-reports SKETCHES_REPORTS_ARTIFACT_NAME: sketches-reports @@ -64,7 +64,6 @@ jobs: fqbn: ${{ matrix.board.fqbn }} platforms: ${{ matrix.board.platforms }} libraries: | - # Install the library from the local path. - source-path: ./ - name: Arduino_PF1550 - source-url: https://github.com/arduino-libraries/Arduino_LowPowerPortentaC33.git From 71326dfbe6e21b9cdcaf4861cd821a2b9def55b5 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Tue, 4 Jun 2024 10:45:34 +0200 Subject: [PATCH 37/56] Make I2C address configurable --- src/MAX1726Driver.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/MAX1726Driver.h b/src/MAX1726Driver.h index 4a65a41..6bfc9b5 100644 --- a/src/MAX1726Driver.h +++ b/src/MAX1726Driver.h @@ -1,27 +1,27 @@ #include "WireUtils.h" #include "BatteryConstants.h" -enum class FuelGaugeOperationMode -{ +enum class FuelGaugeOperationMode { hibernate, shutdown, active }; -// TODO Extract into a separate header file or use this file in Battery.h -constexpr uint8_t I2C_ADDRESS = 0x36; // I2C address of the fuel gauge +constexpr uint8_t DEFAULT_I2C_ADDRESS = 0x36; class MAX1726Driver { private: TwoWire *wire; + uint8_t i2cAddress; public: bool setOperationMode(FuelGaugeOperationMode mode); - MAX1726Driver(TwoWire *wire); + MAX1726Driver(TwoWire *wire, uint8_t i2cAddress); ~MAX1726Driver(); }; -MAX1726Driver::MAX1726Driver(TwoWire *wire) { +MAX1726Driver::MAX1726Driver(TwoWire *wire, uint8_t i2cAddress = DEFAULT_I2C_ADDRESS) { this->wire = wire; + this->i2cAddress = i2cAddress; } MAX1726Driver::~MAX1726Driver(){} @@ -29,9 +29,9 @@ MAX1726Driver::~MAX1726Driver(){} bool MAX1726Driver::setOperationMode(FuelGaugeOperationMode mode) { if(mode == FuelGaugeOperationMode::active){ // See section "Soft-Wakeup" in user manual https://www.analog.com/media/en/technical-documentation/user-guides/max1726x-modelgauge-m5-ez-user-guide.pdf - writeRegister16Bits(this->wire, I2C_ADDRESS, HIB_CFG_REG, 0x0); // Exit Hibernate Mode - writeRegister16Bits(this->wire, I2C_ADDRESS, SOFT_WAKEUP_REG, 0x90); // Wakes up the fuel gauge from hibernate mode to reduce the response time of the IC to configuration changes - writeRegister16Bits(this->wire, I2C_ADDRESS, SOFT_WAKEUP_REG, 0x0); // This command must be manually cleared (0x0000) afterward to keep proper fuel gauge timing + writeRegister16Bits(this->wire, i2cAddress, HIB_CFG_REG, 0x0); // Exit Hibernate Mode + writeRegister16Bits(this->wire, i2cAddress, SOFT_WAKEUP_REG, 0x90); // Wakes up the fuel gauge from hibernate mode to reduce the response time of the IC to configuration changes + writeRegister16Bits(this->wire, i2cAddress, SOFT_WAKEUP_REG, 0x0); // This command must be manually cleared (0x0000) afterward to keep proper fuel gauge timing } else if(mode == FuelGaugeOperationMode::hibernate){ // Enters hibernate mode somewhere between 2.812s and 5.625s if the threshold conditions are met replaceRegisterBit(this->wire, I2C_ADDRESS, HIB_CFG_REG, 1, EN_HIBERNATION_BIT); // Enter Hibernate Mode From a61a6e5ccf163e146601590d99b5783b0cafc85a Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Tue, 4 Jun 2024 10:46:19 +0200 Subject: [PATCH 38/56] Extract hibernate features into function --- src/MAX1726Driver.h | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/MAX1726Driver.h b/src/MAX1726Driver.h index 6bfc9b5..727ff9f 100644 --- a/src/MAX1726Driver.h +++ b/src/MAX1726Driver.h @@ -26,6 +26,15 @@ MAX1726Driver::MAX1726Driver(TwoWire *wire, uint8_t i2cAddress = DEFAULT_I2C_ADD MAX1726Driver::~MAX1726Driver(){} +void MAX1726Driver::setHibernateModeEnabled(bool enabled){ + if(enabled){ + // Enters hibernate mode somewhere between 2.812s and 5.625s if the threshold conditions are met + replaceRegisterBit(this->wire, i2cAddress, HIB_CFG_REG, 1, EN_HIBERNATION_BIT); // Enter Hibernate Mode + } else { + replaceRegisterBit(this->wire, i2cAddress, HIB_CFG_REG, 0, EN_HIBERNATION_BIT); // Exit Hibernate Mode + } +} + bool MAX1726Driver::setOperationMode(FuelGaugeOperationMode mode) { if(mode == FuelGaugeOperationMode::active){ // See section "Soft-Wakeup" in user manual https://www.analog.com/media/en/technical-documentation/user-guides/max1726x-modelgauge-m5-ez-user-guide.pdf @@ -33,15 +42,11 @@ bool MAX1726Driver::setOperationMode(FuelGaugeOperationMode mode) { writeRegister16Bits(this->wire, i2cAddress, SOFT_WAKEUP_REG, 0x90); // Wakes up the fuel gauge from hibernate mode to reduce the response time of the IC to configuration changes writeRegister16Bits(this->wire, i2cAddress, SOFT_WAKEUP_REG, 0x0); // This command must be manually cleared (0x0000) afterward to keep proper fuel gauge timing } else if(mode == FuelGaugeOperationMode::hibernate){ - // Enters hibernate mode somewhere between 2.812s and 5.625s if the threshold conditions are met - replaceRegisterBit(this->wire, I2C_ADDRESS, HIB_CFG_REG, 1, EN_HIBERNATION_BIT); // Enter Hibernate Mode - } else if(mode == FuelGaugeOperationMode::shutdown){ - // Enter active mode - // TODO use function instead - replaceRegisterBit(this->wire, I2C_ADDRESS, HIB_CFG_REG, 0, EN_HIBERNATION_BIT); // Exit Hibernate Mode - // TODO check if we can enter shutdown quicker by setting CTR manually in ShdnTimer - // The default shutdown timeout is 45s - replaceRegisterBit(this->wire, I2C_ADDRESS, CONFIG_REG, 1, SHDN_BIT); // Command shutdown mode + this->setHibernateModeEnabled(true); + } else if(mode == FuelGaugeOperationMode::shutdown){ + this->setHibernateModeEnabled(false); // Enter active mode + // The default (minimum) shutdown timeout is 45s + replaceRegisterBit(this->wire, i2cAddress, CONFIG_REG, 1, SHDN_BIT); // Command shutdown mode } return false; From cc79c9ed257b3fca03a5f83855f9c95d868c5289 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Tue, 4 Jun 2024 10:57:34 +0200 Subject: [PATCH 39/56] Change parameter order --- src/Battery.cpp | 2 +- src/MAX1726Driver.h | 6 +++--- src/WireUtils.h | 11 +++++------ 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/Battery.cpp b/src/Battery.cpp index 45bc813..e24c3ca 100644 --- a/src/Battery.cpp +++ b/src/Battery.cpp @@ -35,7 +35,7 @@ bool Battery::begin(bool enforceReload) { // Restore the original Hibernate Config Register value writeRegister16Bits(this->wire, FUEL_GAUGE_ADDRESS, HIB_CFG_REG, tempHibernateConfigRegister); // Restore Original HibCFG value - replaceRegisterBit(this->wire, FUEL_GAUGE_ADDRESS, STATUS_REG, 0x0, POR_BIT); // Clear POR bit after reset + replaceRegisterBit(this->wire, FUEL_GAUGE_ADDRESS, STATUS_REG, POR_BIT, 0x0); // Clear POR bit after reset return true; } diff --git a/src/MAX1726Driver.h b/src/MAX1726Driver.h index 727ff9f..f043689 100644 --- a/src/MAX1726Driver.h +++ b/src/MAX1726Driver.h @@ -29,9 +29,9 @@ MAX1726Driver::~MAX1726Driver(){} void MAX1726Driver::setHibernateModeEnabled(bool enabled){ if(enabled){ // Enters hibernate mode somewhere between 2.812s and 5.625s if the threshold conditions are met - replaceRegisterBit(this->wire, i2cAddress, HIB_CFG_REG, 1, EN_HIBERNATION_BIT); // Enter Hibernate Mode + replaceRegisterBit(this->wire, i2cAddress, HIB_CFG_REG, EN_HIBERNATION_BIT, 1); // Enter Hibernate Mode } else { - replaceRegisterBit(this->wire, i2cAddress, HIB_CFG_REG, 0, EN_HIBERNATION_BIT); // Exit Hibernate Mode + replaceRegisterBit(this->wire, i2cAddress, HIB_CFG_REG, EN_HIBERNATION_BIT, 0); // Exit Hibernate Mode } } @@ -46,7 +46,7 @@ bool MAX1726Driver::setOperationMode(FuelGaugeOperationMode mode) { } else if(mode == FuelGaugeOperationMode::shutdown){ this->setHibernateModeEnabled(false); // Enter active mode // The default (minimum) shutdown timeout is 45s - replaceRegisterBit(this->wire, i2cAddress, CONFIG_REG, 1, SHDN_BIT); // Command shutdown mode + replaceRegisterBit(this->wire, i2cAddress, CONFIG_REG, SHDN_BIT, 1); // Command shutdown mode } return false; diff --git a/src/WireUtils.h b/src/WireUtils.h index 491057d..329d781 100644 --- a/src/WireUtils.h +++ b/src/WireUtils.h @@ -97,12 +97,11 @@ static inline uint8_t getBit(TwoWire *wire, uint8_t address, uint8_t reg, uint8_ * @param wire The I2C object representing the I2C bus. * @param address The address of the device on the I2C bus. * @param reg The register to modify. - * @param data The new data (bits) to write to the register. * @param indexFrom The index of the first bit to replace starting from LSB (0) * @param indexTo The index of the last bit (included) to replace starting from LSB (0) + * @param data The new data (bits) to write to the register. */ -// TODO switch order of parameters to conform with bitWrite() -static inline void replaceRegisterBits(TwoWire *wire, uint8_t address, uint8_t reg, uint16_t data, uint16_t indexFrom, uint8_t indexTo) { +static inline void replaceRegisterBits(TwoWire *wire, uint8_t address, uint8_t reg, uint16_t indexFrom, uint8_t indexTo, uint16_t data) { uint16_t registerValue = readRegister16Bits(wire, address, reg); // Create a mask to clear the bits to be replaced @@ -124,12 +123,12 @@ static inline void replaceRegisterBits(TwoWire *wire, uint8_t address, uint8_t r * @param wire The TwoWire object representing the I2C bus. * @param address The address of the I2C device. * @param reg The register to modify. - * @param data The new data (1 bit) to write to the register. * @param index The index of the bit to replace. + * @param data The new data (1 bit) to write to the register. */ // TODO switch order of parameters to conform with bitWrite() -static inline void replaceRegisterBit(TwoWire *wire, uint8_t address, uint8_t reg, uint16_t data, uint16_t index) { - replaceRegisterBits(wire, address, reg, data, index, index); +static inline void replaceRegisterBit(TwoWire *wire, uint8_t address, uint8_t reg, uint16_t index, uint16_t data) { + replaceRegisterBits(wire, address, reg, index, index, data); } #endif \ No newline at end of file From 0a8a7e236bad93509436d67528eec2dc041895ef Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Tue, 4 Jun 2024 10:57:46 +0200 Subject: [PATCH 40/56] Add charging complete function --- src/MAX1726Driver.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/MAX1726Driver.h b/src/MAX1726Driver.h index f043689..21028fe 100644 --- a/src/MAX1726Driver.h +++ b/src/MAX1726Driver.h @@ -50,4 +50,11 @@ bool MAX1726Driver::setOperationMode(FuelGaugeOperationMode mode) { } return false; +} + +bool MAX1726Driver::chargingComplete(){ + // TODO This needs to be tested, probably it's a value that only temporarily indicates the end-of-charge condition. + // There is also a FULL_DET_BIT in the STATUS2 register but the datasheet does not explain it: + // return getBit(this->wire, i2cAddress, STATUS2_REG, FULL_DET_BIT) == 1; + return getBit(this->wire, i2cAddress, F_STAT_REG, FQ_BIT) == 1; } \ No newline at end of file From 31c8bb1a8cdd8763c303094667dc1cebf39eb1f3 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Tue, 4 Jun 2024 11:16:05 +0200 Subject: [PATCH 41/56] Remove charging complete function from battery API --- examples/Battery/Battery.ino | 1 - src/Battery.cpp | 7 ------- src/Battery.h | 7 ------- src/MAX1726Driver.h | 5 +++++ 4 files changed, 5 insertions(+), 15 deletions(-) diff --git a/examples/Battery/Battery.ino b/examples/Battery/Battery.ino index 070b1a7..b0a00a9 100644 --- a/examples/Battery/Battery.ino +++ b/examples/Battery/Battery.ino @@ -95,7 +95,6 @@ void loop() { if(batteryConnected){ Serial.println("* šŸŖ« Battery is empty: " + ( battery.isEmpty() ? String("Yes") : String("No"))); - Serial.println("* šŸ’Æ Charging complete: " + ( battery.chargingComplete() ? String("Yes") : String("No"))); Serial.println("* āš”ļø Voltage: " + String(battery.voltage()) + " V"); Serial.println("* āš”ļø Average Voltage: " + String(battery.averageVoltage()) + " V"); diff --git a/src/Battery.cpp b/src/Battery.cpp index e24c3ca..58f6279 100644 --- a/src/Battery.cpp +++ b/src/Battery.cpp @@ -340,13 +340,6 @@ bool Battery::isEmpty(){ return getBit(this->wire, FUEL_GAUGE_ADDRESS, F_STAT_REG, E_DET_BIT) == 1; } -bool Battery::chargingComplete(){ - // TODO This needs to be tested, probably it's a valua that only temporarily indicates the end-of-charge condition. - // TODO there is also a FULL_DET_BIT in the STATUS2 register but the datasheet does not explain it - // return getBit(this->wire, FUEL_GAUGE_ADDRESS, STATUS2_REG, FULL_DET_BIT) == 1; - return getBit(this->wire, FUEL_GAUGE_ADDRESS, F_STAT_REG, FQ_BIT) == 1; -} - int32_t Battery::timeToEmpty(){ if(!isConnected()){ return -1; diff --git a/src/Battery.h b/src/Battery.h index 38a23c3..743c9f9 100644 --- a/src/Battery.h +++ b/src/Battery.h @@ -192,13 +192,6 @@ class Battery { */ bool isEmpty(); - /** - * @brief Checks if the battery charging is complete. - * - * @return true if the charging is complete, false otherwise. - */ - bool chargingComplete(); - /** * Calculates the estimated time until the battery is empty. * @return The estimated time until the battery is empty, in seconds. diff --git a/src/MAX1726Driver.h b/src/MAX1726Driver.h index 21028fe..c23d907 100644 --- a/src/MAX1726Driver.h +++ b/src/MAX1726Driver.h @@ -52,6 +52,11 @@ bool MAX1726Driver::setOperationMode(FuelGaugeOperationMode mode) { return false; } +/** + * @brief Checks if the battery charging is complete. + * + * @return true if the charging is complete, false otherwise. + */ bool MAX1726Driver::chargingComplete(){ // TODO This needs to be tested, probably it's a value that only temporarily indicates the end-of-charge condition. // There is also a FULL_DET_BIT in the STATUS2 register but the datasheet does not explain it: From 6f5d4e0fd187c17da7ff607b5ea08fc1d52f25be Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Tue, 4 Jun 2024 11:54:00 +0200 Subject: [PATCH 42/56] Remove obsolete comment --- src/WireUtils.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/WireUtils.h b/src/WireUtils.h index 329d781..707b0f8 100644 --- a/src/WireUtils.h +++ b/src/WireUtils.h @@ -126,7 +126,6 @@ static inline void replaceRegisterBits(TwoWire *wire, uint8_t address, uint8_t r * @param index The index of the bit to replace. * @param data The new data (1 bit) to write to the register. */ -// TODO switch order of parameters to conform with bitWrite() static inline void replaceRegisterBit(TwoWire *wire, uint8_t address, uint8_t reg, uint16_t index, uint16_t data) { replaceRegisterBits(wire, address, reg, index, index, data); } From f098ca8702b204706b3243f057a41149f83322c8 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Tue, 4 Jun 2024 11:54:16 +0200 Subject: [PATCH 43/56] Preserve hibernation config --- src/MAX1726Driver.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MAX1726Driver.h b/src/MAX1726Driver.h index c23d907..6fdd2df 100644 --- a/src/MAX1726Driver.h +++ b/src/MAX1726Driver.h @@ -38,7 +38,7 @@ void MAX1726Driver::setHibernateModeEnabled(bool enabled){ bool MAX1726Driver::setOperationMode(FuelGaugeOperationMode mode) { if(mode == FuelGaugeOperationMode::active){ // See section "Soft-Wakeup" in user manual https://www.analog.com/media/en/technical-documentation/user-guides/max1726x-modelgauge-m5-ez-user-guide.pdf - writeRegister16Bits(this->wire, i2cAddress, HIB_CFG_REG, 0x0); // Exit Hibernate Mode + replaceRegisterBit(this->wire, i2cAddress, HIB_CFG_REG, EN_HIBERNATION_BIT, 0); // Exit Hibernate Mode writeRegister16Bits(this->wire, i2cAddress, SOFT_WAKEUP_REG, 0x90); // Wakes up the fuel gauge from hibernate mode to reduce the response time of the IC to configuration changes writeRegister16Bits(this->wire, i2cAddress, SOFT_WAKEUP_REG, 0x0); // This command must be manually cleared (0x0000) afterward to keep proper fuel gauge timing } else if(mode == FuelGaugeOperationMode::hibernate){ From 195d4fe347040d9b55cc049fcb5564979b3a1bb3 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Tue, 4 Jun 2024 11:59:06 +0200 Subject: [PATCH 44/56] Add function to shut down fuel gauge --- src/Board.cpp | 8 +++++++- src/Board.h | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Board.cpp b/src/Board.cpp index 42f3e40..f840268 100644 --- a/src/Board.cpp +++ b/src/Board.cpp @@ -1,4 +1,5 @@ #include "Board.h" +#include "MAX1726Driver.h" #include constexpr int UNKNOWN_VALUE = 0xFF; @@ -295,4 +296,9 @@ bool Board::setReferenceVoltage(float voltage) { return UNKNOWN_VALUE; -} \ No newline at end of file +} + +void Board::shutDownFuelGauge() { + MAX1726Driver fuelGauge(&Wire); + fuelGauge.setOperationMode(FuelGaugeOperationMode::shutdown); +} diff --git a/src/Board.h b/src/Board.h index d80b61a..1e0f8ef 100644 --- a/src/Board.h +++ b/src/Board.h @@ -201,7 +201,13 @@ class Board { */ bool setReferenceVoltage(float voltage); - // TODO add function to shut down the fuel gauge / and hibernate mode + /** + * @brief Shuts down the fuel gauge to reduce power consumption. + * The IC returns to active mode on any edge of any communication line. + * If the IC is power-cycled or the software RESET command is sent the IC + * returns to active mode of operation. + */ + void shutDownFuelGauge(); private: /** From 2f2d900b1cbc74a6066ac60ee42e9e2b164af9ef Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Tue, 4 Jun 2024 12:04:33 +0200 Subject: [PATCH 45/56] Fix compile issue --- src/MAX1726Driver.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/MAX1726Driver.h b/src/MAX1726Driver.h index 6fdd2df..c1724e3 100644 --- a/src/MAX1726Driver.h +++ b/src/MAX1726Driver.h @@ -13,7 +13,9 @@ class MAX1726Driver { private: TwoWire *wire; uint8_t i2cAddress; + void setHibernateModeEnabled(bool enabled); public: + bool chargingComplete(); bool setOperationMode(FuelGaugeOperationMode mode); MAX1726Driver(TwoWire *wire, uint8_t i2cAddress); ~MAX1726Driver(); From 2747199254418e80dcecb2474e7d3f31fd64e61c Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Tue, 4 Jun 2024 12:04:46 +0200 Subject: [PATCH 46/56] Adjust comments --- src/Battery.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Battery.cpp b/src/Battery.cpp index 58f6279..ac68c7f 100644 --- a/src/Battery.cpp +++ b/src/Battery.cpp @@ -71,10 +71,9 @@ void Battery::configureBatteryCharacteristics(){ void Battery::releaseFromHibernation(){ // See section "Soft-Wakeup" in user manual https://www.analog.com/media/en/technical-documentation/user-guides/max1726x-modelgauge-m5-ez-user-guide.pdf - // TODO to preserve the hiberation config, probably better to only set bit 15 to 0 - writeRegister16Bits(this->wire, FUEL_GAUGE_ADDRESS, HIB_CFG_REG, 0x0); // Exit Hibernate Mode + replaceRegisterBit(this->wire, FUEL_GAUGE_ADDRESS, HIB_CFG_REG, EN_HIBERNATION_BIT, 0); // Exit Hibernate Mode writeRegister16Bits(this->wire, FUEL_GAUGE_ADDRESS, SOFT_WAKEUP_REG, 0x90); // Wakes up the fuel gauge from hibernate mode to reduce the response time of the IC to configuration changes - writeRegister16Bits(this->wire, FUEL_GAUGE_ADDRESS, SOFT_WAKEUP_REG, 0x0); // This command must be manually cleared (0x0000) afterward to keep proper fuel gauge timing + writeRegister16Bits(this->wire, FUEL_GAUGE_ADDRESS, SOFT_WAKEUP_REG, 0x0); // Soft wake-up must be manually cleared (0x0000) afterward to keep proper fuel gauge timing } bool Battery::refreshBatteryGaugeModel(){ @@ -207,7 +206,8 @@ uint8_t Battery::internalTemperature(){ } setTemperatureMeasurementMode(false); - // TODO also see DieTemp Register (034h) for the internal die temperature p. 24 in DS + // Also see DieTemp Register (034h) for the internal die temperature p. 24 in DS + // If Config.TSel = 0, DieTemp and Temp registers have the value of the die temperature. return readRegister16Bits(this->wire, FUEL_GAUGE_ADDRESS, TEMP_REG) * TEMPERATURE_MULTIPLIER_C; } @@ -226,7 +226,6 @@ uint8_t Battery::batteryTemperature(){ } setTemperatureMeasurementMode(true); - // TODO possibly await a couple of readings before getting a meaningful temperature return readRegister16Bits(this->wire, FUEL_GAUGE_ADDRESS, TEMP_REG) * TEMPERATURE_MULTIPLIER_C; } From 69115074ff60be18bc8b0f2ad6e34e354c3da10d Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Tue, 4 Jun 2024 12:11:58 +0200 Subject: [PATCH 47/56] Use correct Wire instance depending on board --- src/Board.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Board.cpp b/src/Board.cpp index f840268..dae153d 100644 --- a/src/Board.cpp +++ b/src/Board.cpp @@ -299,6 +299,14 @@ bool Board::setReferenceVoltage(float voltage) { } void Board::shutDownFuelGauge() { - MAX1726Driver fuelGauge(&Wire); + #if defined(ARDUINO_PORTENTA_C33) + MAX1726Driver fuelGauge(&Wire3); + #elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_GENERIC_STM32H747_M4) + MAX1726Driver fuelGauge(&Wire1); + #elif defined(ARDUINO_NICLA_VISION) + MAX1726Driver fuelGauge(&Wire1); + #else + #error "The selected board is not supported by the Battery class." + #endif fuelGauge.setOperationMode(FuelGaugeOperationMode::shutdown); } From 3e615f110ac0fad2a97e15dbacf727f260be960c Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Tue, 4 Jun 2024 12:12:55 +0200 Subject: [PATCH 48/56] Command fuel gauge shutdown --- examples/Standby_WakeFromPin/Standby_WakeFromPin.ino | 1 + .../Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino | 1 + examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino | 6 +----- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/examples/Standby_WakeFromPin/Standby_WakeFromPin.ino b/examples/Standby_WakeFromPin/Standby_WakeFromPin.ino index 74ecb82..3c8b0c3 100644 --- a/examples/Standby_WakeFromPin/Standby_WakeFromPin.ino +++ b/examples/Standby_WakeFromPin/Standby_WakeFromPin.ino @@ -39,6 +39,7 @@ void goToSleep(){ void loop() { if(shouldGoToSleep){ shouldGoToSleep = false; + board.shutDownFuelGauge(); board.setAllPeripheralsPower(false); // turn off peripherals before going to sleep board.standByUntilWakeupEvent(); } else { diff --git a/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino b/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino index 0d8a0ee..ab3155b 100644 --- a/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino +++ b/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino @@ -49,6 +49,7 @@ void setup() { delay(1000); // Keep the board awake for 1 second, so we can se it working + board.shutDownFuelGauge(); board.setAllPeripheralsPower(false); board.standByUntilWakeupEvent(); } diff --git a/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino b/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino index 9a31a08..0011daa 100644 --- a/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino +++ b/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino @@ -33,10 +33,8 @@ */ #include "Arduino_PowerManagement.h" -#include "MAX1726Driver.h" Board board; -MAX1726Driver fuelgauge(&Wire1); void blinkLed(int ledPin, int delayTime = 1000){ digitalWrite(ledPin, LOW); @@ -69,11 +67,9 @@ void setup() { } } - - // Takes 45s to get into shutdown mode - fuelgauge.setOperationMode(FuelGaugeOperationMode::shutdown); delay(10000); // keep the board awake for 10 seconds, so we can se it working + board.shutDownFuelGauge(); // The LED should go off when the board goes to sleep board.setAllPeripheralsPower(false); From 6631167962a3789de1d4321b4534baa1785d7039 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Tue, 4 Jun 2024 12:21:13 +0200 Subject: [PATCH 49/56] Convert keys to lists --- .github/workflows/compile-examples.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 2828d99..8094f5d 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -46,12 +46,14 @@ jobs: platforms: | - name: arduino:mbed_portenta artifact-name-suffix: arduino-mbed_portenta-envie_m7 - additional-sketch-paths: examples/Standby_WakeFromRTC_C33 + additional-sketch-paths: | + - examples/Standby_WakeFromRTC_C33 - fqbn: arduino:renesas_portenta:portenta_c33 platforms: | - name: arduino:renesas_portenta artifact-name-suffix: arduino-renesas_portenta-portenta_c33 - additional-sketch-paths: examples/Standby_WakeFromRTC_H7 + additional-sketch-paths: | + - examples/Standby_WakeFromRTC_H7 steps: - name: Checkout repository From 560d2659779ed3df0f4b153e17d1e63b81d95a31 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Tue, 4 Jun 2024 12:35:00 +0200 Subject: [PATCH 50/56] Add missing library to dependencies --- .github/workflows/compile-examples.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 8094f5d..26a3e1e 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -68,6 +68,7 @@ jobs: libraries: | - source-path: ./ - name: Arduino_PF1550 + - name: Arduino_LowPowerPortentaH7 - source-url: https://github.com/arduino-libraries/Arduino_LowPowerPortentaC33.git sketch-paths: | ${{ env.UNIVERSAL_SKETCH_PATHS }} From 598c6ced789a33fe55e2556703189e4d084c89dc Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Tue, 4 Jun 2024 12:35:10 +0200 Subject: [PATCH 51/56] Add missing info to properties file --- library.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library.properties b/library.properties index d1a844c..d0f62ae 100644 --- a/library.properties +++ b/library.properties @@ -2,9 +2,9 @@ name=Arduino_PowerManagement version=1.0.0 author=Arduino maintainer=Arduino -sentence=Abstracts the functionality of the PF1550 Power Management IC and MAX17162 LiPo Fuel Gauge found in the Portenta C33, Portenta H7 and Nicla Vision boards. -paragraph= -category=Other +sentence=A library to charge and monitor the battery and use low power modes on the Portenta C33, Portenta H7 and Nicla Vision boards. +paragraph=Abstracts the functionality of the PF1550 Power Management IC and MAX17162 LiPo Fuel Gauge found in the Portenta C33, Portenta H7 and Nicla Vision boards. +category=Device Control url=https://github.com/arduino-libraries/Arduino_PowerManagement architectures=renesas_portenta, mbed_portenta, mbed_nicla includes=Arduino_PowerManagement.h From 424e3fdc6d87ad47805a4a73fd052214ef59cb92 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Tue, 4 Jun 2024 12:42:49 +0200 Subject: [PATCH 52/56] Swap example sketches in workflow file --- .github/workflows/compile-examples.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 26a3e1e..7912e76 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -47,13 +47,13 @@ jobs: - name: arduino:mbed_portenta artifact-name-suffix: arduino-mbed_portenta-envie_m7 additional-sketch-paths: | - - examples/Standby_WakeFromRTC_C33 + - examples/Standby_WakeFromRTC_H7 - fqbn: arduino:renesas_portenta:portenta_c33 platforms: | - name: arduino:renesas_portenta artifact-name-suffix: arduino-renesas_portenta-portenta_c33 additional-sketch-paths: | - - examples/Standby_WakeFromRTC_H7 + - examples/Standby_WakeFromRTC_C33 steps: - name: Checkout repository From 5ca3c240be62ac4f11bafbe1876d1b4609a47e25 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Tue, 4 Jun 2024 12:50:08 +0200 Subject: [PATCH 53/56] Eliminate extra white space --- examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino | 3 --- examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino b/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino index ab3155b..aa6afd2 100644 --- a/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino +++ b/examples/Standby_WakeFromRTC_C33/Standby_WakeFromRTC_C33.ino @@ -14,8 +14,6 @@ void blinkLed(int ledPin, int delayTime = 1000){ } void setup() { - - pinMode(LEDR, OUTPUT); // Used to indicate errors digitalWrite(LEDR, HIGH); // Turn off the red LED pinMode(LED_BUILTIN, OUTPUT); @@ -23,7 +21,6 @@ void setup() { delay(1000); digitalWrite(LED_BUILTIN, HIGH); // Turn off the built-in LED pinMode(LEDB, OUTPUT); // Used to indicate that the board is awake - if(!board.begin()){ while (true){ diff --git a/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino b/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino index 0011daa..6b776da 100644 --- a/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino +++ b/examples/Standby_WakeFromRTC_H7/Standby_WakeFromRTC_H7.ino @@ -68,8 +68,8 @@ void setup() { } delay(10000); // keep the board awake for 10 seconds, so we can se it working - board.shutDownFuelGauge(); + // The LED should go off when the board goes to sleep board.setAllPeripheralsPower(false); From 4db9acd1fb0de514f094a1dd88962d104011d2a2 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Tue, 4 Jun 2024 13:06:57 +0200 Subject: [PATCH 54/56] Add documentation --- src/MAX1726Driver.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/MAX1726Driver.h b/src/MAX1726Driver.h index c1724e3..012ef4d 100644 --- a/src/MAX1726Driver.h +++ b/src/MAX1726Driver.h @@ -13,10 +13,33 @@ class MAX1726Driver { private: TwoWire *wire; uint8_t i2cAddress; + /** + * Enables or disables the hibernate mode. + * + * @param enabled - true to enable hibernate mode, false to disable it. + */ void setHibernateModeEnabled(bool enabled); public: + /** + * Checks if the charging process is complete. + * + * @return true if the charging process is complete, false otherwise. + */ bool chargingComplete(); + /** + * Sets the operation mode of the Fuel Gauge. + * + * @param mode The operation mode to set. Possible values are: hibernate, shutdown, active. + * @return True if the operation mode was set successfully, false otherwise. + */ bool setOperationMode(FuelGaugeOperationMode mode); + + /** + * @brief Constructs a new MAX1726Driver object. + * + * @param wire Pointer to the TwoWire object for I2C communication. + * @param i2cAddress The I2C address of the MAX1726 device. The default value is 0x36. + */ MAX1726Driver(TwoWire *wire, uint8_t i2cAddress); ~MAX1726Driver(); }; From a1e512f152456f6fcbacee427fd265e34f05a966 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Tue, 4 Jun 2024 13:40:38 +0200 Subject: [PATCH 55/56] Add documentation --- src/Battery.h | 8 ++++++++ src/Board.h | 16 ++++++++++++++++ src/MAX1726Driver.h | 3 +++ 3 files changed, 27 insertions(+) diff --git a/src/Battery.h b/src/Battery.h index 743c9f9..fc0379c 100644 --- a/src/Battery.h +++ b/src/Battery.h @@ -15,6 +15,9 @@ enum class NTCResistor { Resistor100K }; +/** + * @brief This struct contains the characteristics of the battery. +*/ struct BatteryCharacteristics { /// @brief The battery's capacity in milliampere-hours (mAh). int capacity = 0; @@ -33,6 +36,7 @@ struct BatteryCharacteristics { /// @brief The NTC resistor value used in the battery pack (10K or 100K Ohm). NTCResistor ntcResistor = NTCResistor::Resistor10K; + /// @brief Sets the voltage level for clearing empty detection. Once the cell voltage rises above this point, empty voltage detection is re-enabled. float recoveryVoltage = DEFAULT_RECOVERY_VOLTAGE; }; @@ -46,6 +50,10 @@ class Battery { */ Battery(); + /** + * @brief Initializes the battery object with the given battery characteristics. + * @param batteryCharacteristics The characteristics of the battery. + */ Battery(BatteryCharacteristics batteryCharacteristics); /** diff --git a/src/Board.h b/src/Board.h index 1e0f8ef..c0c9277 100644 --- a/src/Board.h +++ b/src/Board.h @@ -141,10 +141,26 @@ class Board { * @return True if successful, false otherwise. */ bool enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds, void (* const callbackFunction)(), RTClock * rtc = &RTC); + + /** + * @brief Enables wake-up of the device from the RTC. + * @param hours The number of hours to sleep. + * @param minutes The number of minutes to sleep. + * @param seconds The number of seconds to sleep. + * @param rtc The RTC instance to use for the sleep function. Default is the shared RTC instance. + * @return True if successful, false otherwise. + */ bool enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds, RTClock * rtc = &RTC); #endif #if defined(ARDUINO_PORTENTA_H7) + /** + * Enables wake-up of the device from the RTC. + * @param hours The number of hours to sleep. + * @param minutes The number of minutes to sleep. + * @param seconds The number of seconds to sleep. + * @return True if successful, false otherwise. + */ bool enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds); #endif diff --git a/src/MAX1726Driver.h b/src/MAX1726Driver.h index 012ef4d..b63a81e 100644 --- a/src/MAX1726Driver.h +++ b/src/MAX1726Driver.h @@ -9,6 +9,9 @@ enum class FuelGaugeOperationMode { constexpr uint8_t DEFAULT_I2C_ADDRESS = 0x36; +/** + * @brief Driver class for the MAX1726 Fuel Gauge IC. + */ class MAX1726Driver { private: TwoWire *wire; From 887a0613d59c59d554ca5bf76a52db934d055c0c Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Tue, 4 Jun 2024 11:41:32 +0000 Subject: [PATCH 56/56] Update documentation --- docs/api.md | 747 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 556 insertions(+), 191 deletions(-) diff --git a/docs/api.md b/docs/api.md index e9672e4..a7bb185 100644 --- a/docs/api.md +++ b/docs/api.md @@ -2,31 +2,44 @@ Members | Descriptions --------------------------------|--------------------------------------------- -`class ` [`Battery`](#class_battery) | [Battery](#class_battery) class definition and member function declarations. -`class ` [`Board`](#class_board) | -`class ` [`Charger`](#class_charger) | [Charger](#class_charger) class for controlling charging parameters and monitoring charging status. -`class ` [`PowerManagement`](#class_power_management) | +`class ` [`Battery`](#class_battery) | This class provides a detailed insight into the battery's health and usage. +`class ` [`Board`](#class_board) | Represents a board with power management capabilities. +`class ` [`Charger`](#class_charger) | Class for controlling charging parameters and monitoring charging status. +`class ` [`MAX1726Driver`](#class_m_a_x1726_driver) | Driver class for the MAX1726 Fuel Gauge IC. +`struct ` [`BatteryCharacteristics`](#struct_battery_characteristics) | This struct contains the characteristics of the battery. # class `Battery` -[Battery](#class_battery) class definition and member function declarations. +This class provides a detailed insight into the battery's health and usage. ## Summary Members | Descriptions --------------------------------|--------------------------------------------- -| [`Battery`](#class_battery_1a36a6234c583e3b3506f4a77e3eb49989) | Constructor for the [Battery](#class_battery) class. Initializes the battery with default values for capacity and empty voltage. The default values are 200mAh and 3000mV respectively. | -| [`Battery`](#class_battery_1a8c861b38bb868a17f980615c47180655) | Constructor for the [Battery](#class_battery) class. | -| [`begin`](#class_battery_1abe2e94712b9e846f38f63884f6f995ef) | Initializes the battery communication and configuration. | -| [`isConnected`](#class_battery_1a9473c4a4583abea991268d0818f19dbe) | Checks if a battery is connected to the system. | -| [`voltage`](#class_battery_1af6c186181316398ab86a73591adc7229) | Reads the current voltage of the battery. Voltage is usually between 3000mV and 4200mV. | -| [`averageVoltage`](#class_battery_1a8b343c8244e16caba082643c3d3e9e46) | Reads the average voltage of the battery. | -| [`current`](#class_battery_1acc60fb79f995897dbcad56535b4ddc7f) | Reads the current flowing from the battery at the moment. | -| [`averageCurrent`](#class_battery_1a60543d61d65d23745ffb0b11a7b52bb4) | Reads the average current of the battery. | -| [`temperature`](#class_battery_1a9769b18902c4576c3ed7405c7e58bbea) | Reads the current temperature of the battery. | -| [`averageTemperature`](#class_battery_1a89b2bbbda3ce367b2e855ce9b258abf0) | Reads the average temperature of the battery. | -| [`percentage`](#class_battery_1a4d34768c6d8740fad39ce25028a01ee6) | Reads the battery's state of charge (SOC). This value is based on both the voltage and the current of the battery as well as compensation for the battery's age and temperature and discharge rate. | -| [`remainingCapacity`](#class_battery_1a622eb39d57504e13beaac16003c04fd3) | Reads the remaining capacity of the battery. | +| [`Battery`](#class_battery_1a36a6234c583e3b3506f4a77e3eb49989) | Initializes the battery object with default values for capacity (0mAh) and empty voltage (3.3V). | +| [`Battery`](#class_battery_1a64cc106078933ec547418bb649936d0e) | Initializes the battery object with the given battery characteristics. | +| [`begin`](#class_battery_1ad1ef0c48a213f0ad607f08fca6b30d96) | Initializes the battery communication and configuration. | +| [`isConnected`](#class_battery_1af280ded5baecec455934785c317df299) | Checks if a battery is connected to the system. | +| [`voltage`](#class_battery_1add29e37e363157d436d60d2679e4893c) | Reads the current voltage of the battery. Voltage is usually between 3.0V and 4.2V. | +| [`averageVoltage`](#class_battery_1a90aedc34714a42b3ba38e34db6736cf4) | Reads an average of voltage readings of the battery. | +| [`minimumVoltage`](#class_battery_1abde4f669d71076bfc09e4004e3369664) | Returns the minimum voltage value measured since the last device reset. At power-up the minimum voltage value is set to FFh (the maximum). | +| [`maximumVoltage`](#class_battery_1a7baebfaf75aff02842a5eab7ce1629e7) | Returns the maximum voltage value measured since the last device reset. At power-up the maximum voltage value is set to 00h (the minimum). | +| [`resetMaximumMinimumVoltage`](#class_battery_1a2d4bde0fc0207f0a103f67be970cc412) | Resets the minimum and maximum voltage values. | +| [`current`](#class_battery_1addc7658b5425f6bfabb8e55c7f73fd33) | Reads the current flowing from the battery at the moment. Negative values indicate that the battery is charging, positive values indicate that the battery is discharging. When no battery is connected, the value is -1. | +| [`averageCurrent`](#class_battery_1ab74143421658d9aafb05535558a315dc) | Reads an average of current readings of the battery. | +| [`minimumCurrent`](#class_battery_1a04fb9f935964dc4cad7673d581a4e701) | Reads the minimum current values measured since the last device reset. Note: The resolution of the minimum current value is 160mA so the value is rounded to the nearest 160mA. | +| [`maximumCurrent`](#class_battery_1a06bbac275505bd55f54904dde086ea72) | Reads the maximum current values measured since the last device reset. Note: The resolution of the minimum current value is 160mA so the value is rounded to the nearest 160mA. | +| [`resetMaximumMinimumCurrent`](#class_battery_1a86b64cfdb23050cc77a66c1e03750b42) | Resets the minimum and maximum current values. | +| [`power`](#class_battery_1acc75ec11734cdc2f877e11a122ebf164) | Reads the current power of the battery in milliwatts (mW). This value is calculated based on the current and voltage of the battery. | +| [`averagePower`](#class_battery_1a41ff59184770622e77ba133818996793) | Reads an average of power readings of the battery in milliwatts (mW). This value is calculated based on the current and voltage of the battery. | +| [`internalTemperature`](#class_battery_1a3967e87e3ff5bdfbfb99681902d31464) | Reads the current temperature of the internal die of the battery gauge chip. | +| [`averageInternalTemperature`](#class_battery_1a658633cd49a8b594f6a8e75a126e6b5d) | Reads an average of internal temperature readings of the battery. Note: If the battery temperature was read before, this function will change the configuration to read the internal temperature. You will have to await a couple of temperature readings before getting a meaningful average temperature. | +| [`percentage`](#class_battery_1a2f7cd7878c7e3b8227ff38e18c8f65e2) | Reads the battery's state of charge (SOC). This value is based on both the voltage and the current of the battery as well as compensation for the battery's age and temperature and discharge rate. | +| [`remainingCapacity`](#class_battery_1a769e8dddd81779757b8399660b084734) | Reads the remaining capacity of the battery. In combination with [current()](#class_battery_1addc7658b5425f6bfabb8e55c7f73fd33), this value can be used to estimate the remaining time until the battery is empty. | +| [`fullCapacity`](#class_battery_1afb54a909c0fa3e5d7aed34026a441c49) | Returns the full capacity of the battery. For this to work, the capacity of the battery must be set when initializing the battery object. | +| [`isEmpty`](#class_battery_1a91fab7f1d3534f6f657e5868ee9af95a) | Checks if the battery is empty. Returns false once the cell voltage rises above the recovery threshold. | +| [`timeToEmpty`](#class_battery_1af7775216c6a4278af417f8ebdfd94dbe) | Calculates the estimated time until the battery is empty. | +| [`timeToFull`](#class_battery_1a6eaae4e71787908063ad64ee58ba09d2) | Calculates the estimated time until the battery is fully charged. The value is determined by learning from the experience of prior charge cycles. | ## Members @@ -36,40 +49,38 @@ Battery() ``` -Constructor for the [Battery](#class_battery) class. Initializes the battery with default values for capacity and empty voltage. The default values are 200mAh and 3000mV respectively. +Initializes the battery object with default values for capacity (0mAh) and empty voltage (3.3V). -**See also**: [Battery(int, int)](#class_battery_1a8c861b38bb868a17f980615c47180655) - -**See also**: #defaultBatteryCapacityInMiliampereHours - -**See also**: #defaultEmptyVoltage
-### `Battery` +### `Battery` ```cpp -Battery(int capacityInMilliAmpereHours, int emptyVoltageInMilliVolts) +Battery( BatteryCharacteristics batteryCharacteristics) ``` -Constructor for the [Battery](#class_battery) class. +Initializes the battery object with the given battery characteristics. #### Parameters -* `capacityInMilliAmpereHours` The capacity of the battery in milliampere-hours (mAh). - -* `emptyVoltageInMilliVolts` The voltage at which the battery is considered empty in millivolts (mV). +* `batteryCharacteristics` The characteristics of the battery.
-### `begin` +### `begin` ```cpp -bool begin() +bool begin(bool enforceReload) ``` Initializes the battery communication and configuration. +#### Parameters +* `enforceReload` If set to true, the battery gauge config will be reloaded. + +#### Returns +True if the initialization was successful, false otherwise.
-### `isConnected` +### `isConnected` ```cpp boolean isConnected() @@ -78,128 +89,279 @@ boolean isConnected() Checks if a battery is connected to the system. #### Returns -True if a battery has been connected, false otherwise +True if a battery is connected, false otherwise
-### `voltage` +### `voltage` ```cpp -int voltage() +float voltage() ``` -Reads the current voltage of the battery. Voltage is usually between 3000mV and 4200mV. +Reads the current voltage of the battery. Voltage is usually between 3.0V and 4.2V. #### Returns -The current voltage in millivolts (mV). +The current voltage in volts (V).
-### `averageVoltage` +### `averageVoltage` ```cpp -unsigned int averageVoltage() +float averageVoltage() ``` -Reads the average voltage of the battery. +Reads an average of voltage readings of the battery. #### Returns -The average voltage in millivolts (mV). +The average voltage in volts (V).
-### `current` +### `minimumVoltage` ```cpp -int current() +float minimumVoltage() ``` -Reads the current flowing from the battery at the moment. +Returns the minimum voltage value measured since the last device reset. At power-up the minimum voltage value is set to FFh (the maximum). #### Returns -The current flowing from the battery at the moment miliamperes (mA). +The minimum voltage value in volts (V).
-### `averageCurrent` +### `maximumVoltage` ```cpp -int averageCurrent() +float maximumVoltage() ``` -Reads the average current of the battery. +Returns the maximum voltage value measured since the last device reset. At power-up the maximum voltage value is set to 00h (the minimum). #### Returns -The average current in millivolts (mV). +The maximum voltage value in volts (V).
-### `temperature` +### `resetMaximumMinimumVoltage` ```cpp -int temperature() +bool resetMaximumMinimumVoltage() ``` -Reads the current temperature of the battery. +Resets the minimum and maximum voltage values. #### Returns -The current temperature in degrees Celsius. +True if the minimum and maximum voltage values were successfully reset, false otherwise. +
+ +### `current` + +```cpp +int16_t current() +``` + +Reads the current flowing from the battery at the moment. Negative values indicate that the battery is charging, positive values indicate that the battery is discharging. When no battery is connected, the value is -1. + +#### Returns +The current flowing from the battery in milli amperes (mA). +
+ +### `averageCurrent` + +```cpp +int16_t averageCurrent() +``` + +Reads an average of current readings of the battery. + +#### Returns +The average current in milli amperes (mA). +
+ +### `minimumCurrent` + +```cpp +int16_t minimumCurrent() +``` + +Reads the minimum current values measured since the last device reset. Note: The resolution of the minimum current value is 160mA so the value is rounded to the nearest 160mA. + +#### Returns +The minimum current values in milli amperes (mA). +
+ +### `maximumCurrent` + +```cpp +int16_t maximumCurrent() +``` + +Reads the maximum current values measured since the last device reset. Note: The resolution of the minimum current value is 160mA so the value is rounded to the nearest 160mA. + +#### Returns +The maximum current values in milli amperes (mA).
-### `averageTemperature` +### `resetMaximumMinimumCurrent` ```cpp -int averageTemperature() +bool resetMaximumMinimumCurrent() ``` -Reads the average temperature of the battery. +Resets the minimum and maximum current values. + +#### Returns +True if the minimum and maximum current values were successfully reset, false otherwise. +
+ +### `power` + +```cpp +int16_t power() +``` + +Reads the current power of the battery in milliwatts (mW). This value is calculated based on the current and voltage of the battery. + +#### Returns +The current power in milliwatts (mW). +
+ +### `averagePower` + +```cpp +int16_t averagePower() +``` + +Reads an average of power readings of the battery in milliwatts (mW). This value is calculated based on the current and voltage of the battery. + +#### Returns +The average power in milliwatts (mW). +
+ +### `internalTemperature` + +```cpp +uint8_t internalTemperature() +``` + +Reads the current temperature of the internal die of the battery gauge chip. #### Returns The current temperature in degrees Celsius.
-### `percentage` +### `averageInternalTemperature` + +```cpp +uint8_t averageInternalTemperature() +``` + +Reads an average of internal temperature readings of the battery. Note: If the battery temperature was read before, this function will change the configuration to read the internal temperature. You will have to await a couple of temperature readings before getting a meaningful average temperature. + +#### Returns +The average temperature in degrees Celsius. +
+ +### `percentage` ```cpp -int percentage() +uint8_t percentage() ``` Reads the battery's state of charge (SOC). This value is based on both the voltage and the current of the battery as well as compensation for the battery's age and temperature and discharge rate. #### Returns -The state of charge as a percentage. +The state of charge as a percentage (Range: 0% - 100%).
-### `remainingCapacity` +### `remainingCapacity` ```cpp -int remainingCapacity() +uint16_t remainingCapacity() ``` -Reads the remaining capacity of the battery. +Reads the remaining capacity of the battery. In combination with [current()](#class_battery_1addc7658b5425f6bfabb8e55c7f73fd33), this value can be used to estimate the remaining time until the battery is empty. #### Returns The remaining capacity in milliampere-hours (mAh).
+### `fullCapacity` + +```cpp +uint16_t fullCapacity() +``` + +Returns the full capacity of the battery. For this to work, the capacity of the battery must be set when initializing the battery object. +#### Returns +The full capacity of the battery. +
+ +### `isEmpty` + +```cpp +bool isEmpty() +``` + +Checks if the battery is empty. Returns false once the cell voltage rises above the recovery threshold. + +#### Returns +true if the battery is empty, false otherwise. +
+ +### `timeToEmpty` + +```cpp +int32_t timeToEmpty() +``` + +Calculates the estimated time until the battery is empty. +#### Returns +The estimated time until the battery is empty, in seconds. If the battery is charging, the function returns -1. +
+ +### `timeToFull` + +```cpp +int32_t timeToFull() +``` + +Calculates the estimated time until the battery is fully charged. The value is determined by learning from the experience of prior charge cycles. +#### Returns +The estimated time until the battery is fully charged in seconds. If the battery is discharging, the function returns -1. +
+ # class `Board` +Represents a board with power management capabilities. + +The [Board](#class_board) class provides methods to check the power source, enable/disable power rails, set voltage levels, enable/disable wakeup from pins or RTC, put the device into sleep mode for a specified duration, and control peripherals' power. + +Supported boards: Arduino Portenta H7, Arduino Portenta C33, Arduino Nicla Vision. + ## Summary Members | Descriptions --------------------------------|--------------------------------------------- -| [`Board`](#class_board_1a9ee491d4fea680cf69b033374a9fdfcb) | Default constructor for the [Board](#class_board) class. | -| [`Board`](#class_board_1a46e7c2305b38070b01a5714449021b5c) | Constructor for the [Board](#class_board) class with a PF1550 PMIC instance. | +| [`Board`](#class_board_1a9ee491d4fea680cf69b033374a9fdfcb) | Construct a new [Board](#class_board) object. | +| [`~Board`](#class_board_1af73f45730119a1fd8f6670f53f959e68) | Destroy the [Board](#class_board) object. | +| [`begin`](#class_board_1a7cd62c2a663226bb02c87675e947ade0) | Initializes the board by initiating the PMIC. | | [`isUSBPowered`](#class_board_1aa53bea8ac0404de8a7389484a61937ae) | Check if the board is powered through USB. | | [`isBatteryPowered`](#class_board_1a80a62c172bea4a16b6983f204380f92b) | Check if the board is powered by the battery. | -| [`setExternalPowerEnabled`](#class_board_1a336acc6fbe5c9d3544a14bc47afc0fc8) | Set the voltage for the external power rail. This lane powers the pin labeled 3V3 on the board. | +| [`setExternalPowerEnabled`](#class_board_1a336acc6fbe5c9d3544a14bc47afc0fc8) | Enables/disables the voltage on the external power rail. This lane powers the pin labeled 3V3 on the board. | | [`setExternalVoltage`](#class_board_1ad92e1939e565023016b210ce6aae68b6) | Set the voltage for the external power rail. This lane powers the pin labeled 3V3 on the board. | -| [`setCameraPowerEnabled`](#class_board_1ad02a62c1b376df7523751fa4b3207204) | Set the camera power rail switch direction on boards with a built-in camera. | -| [`enableWakeupFromPin`](#class_board_1a94ac54f76a7e8fff5b7c6523af64169a) | Enables wake-up of the device from a specified pin (A0, A1, A2, A3, A4, A5, D4, D7 ) | -| [`enableWakeupFromRTC`](#class_board_1ae158d0367a2851d1f1f560bcca784412) | Enables wake-up of the device from the RTC. | -| [`sleepFor`](#class_board_1a966bcfa00c60eaf3b0a1aa89d1deea9d) | Put the device in sleep mode for a specified amount of time. | -| [`sleepFor`](#class_board_1a31c46d510bbf14e372e019b8789afd3b) | Put the device in sleep mode for a specified amount of time. | -| [`sleepUntilWakeupEvent`](#class_board_1a1d23524e0bfeb7282fa465f3834027e1) | Put the device into sleep mode until a wakeup event occurs. This sleep mode is ideal for applications requiring periodic wake-ups or brief intervals of inactivity and reduces consumption to a range between 6mA and 18mA depending on the state of the peripherals. This sleep mode resumes the operation from the last operation. A wakeup event can be an interrupt on a pin or the RTC, depending on what you set with [enableWakeupFromPin()](#class_board_1a94ac54f76a7e8fff5b7c6523af64169a) and [enableWakeupFromRTC()](#class_board_1ae158d0367a2851d1f1f560bcca784412). | -| [`deepSleepUntilWakeupEvent`](#class_board_1aa0f7c55bf12f52374a2694aff110836b) | Put the device into deep sleep mode until a wakeup event occurs. For scenarios demanding drastic power conservation, the Deep Sleep Mode significantly reduces the board's power usage to range between 90uA and 11mA depending on the state of the peripherals. This mode restarts the board on wakeup, effectively running the setup() function again. A wakeup event can be an interrupt on a pin or the RTC, depending on what you set with [enableWakeupFromPin()](#class_board_1a94ac54f76a7e8fff5b7c6523af64169a) and [enableWakeupFromRTC()](#class_board_1ae158d0367a2851d1f1f560bcca784412). | -| [`setAllPeripheralsPower`](#class_board_1a27dcc0b9d69a8cce256494192f2efb3a) | Turn the peripherals on Portenta C33 (ADC, RGB LED, Secure Element, Wifi and Bluetooth) off. | -| [`setCommunicationPeripheralsPower`](#class_board_1ac91aa31be1ea833d7266dda45dd1c5f2) | Set the communication power rail switch direction on Portenta C33 (Wifi, Bluetooth and Secure Element) | -| [`setAnalogDigitalConverterPower`](#class_board_1a3d9fbb30b03c3a7f733f0c89dd9dc43d) | Set the analog digital converter power rail switch direction on Portenta C33. | -| [`setReferenceVoltage`](#class_board_1a8feb9efc5439c8fec5139f66484200b5) | Set the reference voltage on Portenta C33. This value is used by the ADC to convert analog values to digital values. This can be particularly useful to increase the accuracy of the ADC when working with low voltages. | +| [`setCameraPowerEnabled`](#class_board_1ad02a62c1b376df7523751fa4b3207204) | Enables/disables the camera's power rail on boards with a built-in camera. | +| [`enableWakeupFromPin`](#class_board_1ae04b853e945b07852a65fb4f0e7e7d2b) | Enables wakeup from pin GPIO0 on Portenta H7. The pin is only accessible via high-density connectors. | +| [`enableSleepWhenIdle`](#class_board_1ae4c9772a307f85306102cf4333ecf249) | Enables sleep mode when the board is idle. | +| [`enableWakeupFromPin`](#class_board_1a94ac54f76a7e8fff5b7c6523af64169a) | Enables wake-up of the device from a specified pin (A0, A1, A2, A3, A4, A5, D4, D7 ) on Arduino Portenta C33. | +| [`enableWakeupFromRTC`](#class_board_1a5fc9e67d4e42ce7943b9675c17fd77f6) | Enables wake-up of the device from the RTC. This function allows to use a custom RTC instance to put the device in sleep mode. | +| [`enableWakeupFromRTC`](#class_board_1a49925de689c2f73f49b09d7b190e5036) | Enables wake-up of the device from the RTC. | +| [`enableWakeupFromRTC`](#class_board_1a27a7db805596399daf0e89de755eca0c) | Enables wake-up of the device from the RTC. | +| [`sleepUntilWakeupEvent`](#class_board_1a1d23524e0bfeb7282fa465f3834027e1) | Put the device into sleep mode until a wakeup event occurs This sleep mode is ideal for applications requiring periodic wake-ups or brief intervals of inactivity and reduces consumption to a range between 6mA and 18mA depending on the state of the peripherals. This sleep mode resumes the operation from the last operation without resetting the board. A wakeup event can be an interrupt on a pin or the RTC, depending on what you set with [enableWakeupFromPin()](#class_board_1ae04b853e945b07852a65fb4f0e7e7d2b) and [enableWakeupFromRTC()](#class_board_1a5fc9e67d4e42ce7943b9675c17fd77f6). | +| [`standByUntilWakeupEvent`](#class_board_1a7dda3836bbe5a11628d4d8a122529ded) | Put the device into standby mode until a wakeup event occurs. For scenarios demanding drastic power conservation, the standby Mode significantly reduces the board's power usage to micro amperes range depending on the state of the peripherals. This mode restarts the board on wake-up, effectively running the setup() function again. A wakeup event can be an interrupt on a pin or the RTC, depending on what you set with [enableWakeupFromPin()](#class_board_1ae04b853e945b07852a65fb4f0e7e7d2b) and [enableWakeupFromRTC()](#class_board_1a5fc9e67d4e42ce7943b9675c17fd77f6). | +| [`setAllPeripheralsPower`](#class_board_1a27dcc0b9d69a8cce256494192f2efb3a) | Toggle the peripherals' power on Portenta C33 (ADC, RGB LED, Secure Element, Wifi and Bluetooth). | +| [`setCommunicationPeripheralsPower`](#class_board_1ac91aa31be1ea833d7266dda45dd1c5f2) | Toggles the communication peripherials' power on Portenta C33 (Wifi, Bluetooth and Secure Element) | +| [`setAnalogDigitalConverterPower`](#class_board_1a3d9fbb30b03c3a7f733f0c89dd9dc43d) | Toggles the power of the analog digital converter on Portenta C33. This is not available on the Portenta H7. | +| [`setReferenceVoltage`](#class_board_1a8feb9efc5439c8fec5139f66484200b5) | Set the reference voltage. This value is used by the ADC to convert analog values to digital values. This can be particularly useful to increase the accuracy of the ADC when working with low voltages. | +| [`shutDownFuelGauge`](#class_board_1ae4af8f64cc1389bc0b640124dbb0d9c8) | Shuts down the fuel gauge to reduce power consumption. The IC returns to active mode on any edge of any communication line. If the IC is power-cycled or the software RESET command is sent the IC returns to active mode of operation. | ## Members @@ -209,20 +371,30 @@ The remaining capacity in milliampere-hours (mAh). Board() ``` -Default constructor for the [Board](#class_board) class. +Construct a new [Board](#class_board) object.
-### `Board` +### `~Board` ```cpp -Board(PF1550 * pmic) +~Board() ``` -Constructor for the [Board](#class_board) class with a PF1550 PMIC instance. +Destroy the [Board](#class_board) object. -#### Parameters -* `pmic` Pointer to the PF1550 PMIC instance. +
+ +### `begin` + +```cpp +bool begin() +``` + +Initializes the board by initiating the PMIC. + +#### Returns +true if the board initialization is successful, false otherwise.
### `isUSBPowered` @@ -255,7 +427,7 @@ True if powered by the battery, false otherwise. void setExternalPowerEnabled(bool on) ``` -Set the voltage for the external power rail. This lane powers the pin labeled 3V3 on the board. +Enables/disables the voltage on the external power rail. This lane powers the pin labeled 3V3 on the board. #### Parameters * `on` True to enable this power rail, false to disable it.
@@ -268,10 +440,10 @@ bool setExternalVoltage(float voltage) Set the voltage for the external power rail. This lane powers the pin labeled 3V3 on the board. #### Parameters -* `voltage` float value of the voltage value to set. `voltage` has to be one of the following (1.10, 1.20, 1.35, 1.50, 1.80, 2.50, 3.00 and 3.30) +* `voltage` float value of the voltage value to set. Value has to be one of the following (1.10, 1.20, 1.35, 1.50, 1.80, 2.50, 3.00, 3.30) #### Returns -True if successful, false otherwise. +True the voltage was set successfully, false otherwise.
### `setCameraPowerEnabled` @@ -280,10 +452,28 @@ True if successful, false otherwise. void setCameraPowerEnabled(bool enabled) ``` -Set the camera power rail switch direction on boards with a built-in camera. +Enables/disables the camera's power rail on boards with a built-in camera. #### Parameters -* `enabled` True to turn on the switches, false to turn them off. +* `enabled` True to turn on the camera, false to turn it off. +
+ +### `enableWakeupFromPin` + +```cpp +void enableWakeupFromPin() +``` + +Enables wakeup from pin GPIO0 on Portenta H7. The pin is only accessible via high-density connectors. +
+ +### `enableSleepWhenIdle` + +```cpp +void enableSleepWhenIdle() +``` + +Enables sleep mode when the board is idle.
### `enableWakeupFromPin` @@ -292,29 +482,43 @@ Set the camera power rail switch direction on boards with a built-in camera. void enableWakeupFromPin(uint8_t pin, PinStatus direction) ``` -Enables wake-up of the device from a specified pin (A0, A1, A2, A3, A4, A5, D4, D7 ) +Enables wake-up of the device from a specified pin (A0, A1, A2, A3, A4, A5, D4, D7 ) on Arduino Portenta C33. #### Parameters * `pin` The pin number used for waking up the device. * `direction` The direction of the interrupt that will wake up the device. (RISING, FALLING)
-### `enableWakeupFromRTC` +### `enableWakeupFromRTC` ```cpp -void enableWakeupFromRTC() +bool enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds, void(*)() callbackFunction, RTClock * rtc) ``` -Enables wake-up of the device from the RTC. +Enables wake-up of the device from the RTC. This function allows to use a custom RTC instance to put the device in sleep mode. + +#### Parameters +* `hours` The number of hours to sleep. + +* `minutes` The number of minutes to sleep. + +* `seconds` The number of seconds to sleep. + +* `callbackFunction` The function to call when the device wakes up. If no callback function is provided, the device will wake up without calling any function. + +* `rtc` The RTC instance to use for the sleep function. If no RTC instance is provided, the default RTC instance is used. + +#### Returns +True if successful, false otherwise.
-### `sleepFor` +### `enableWakeupFromRTC` ```cpp -bool sleepFor(int hours, int minutes, int seconds, void(*)() callbackFunction, RTClock * rtc) +bool enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds, RTClock * rtc) ``` -Put the device in sleep mode for a specified amount of time. +Enables wake-up of the device from the RTC. #### Parameters * `hours` The number of hours to sleep. @@ -323,22 +527,19 @@ Put the device in sleep mode for a specified amount of time. * `seconds` The number of seconds to sleep. -* `callbackFunction` The function to call when the device wakes up. - -* `RTC` The RTC instance to use for the sleep function. +* `rtc` The RTC instance to use for the sleep function. Default is the shared RTC instance. #### Returns True if successful, false otherwise.
-### `sleepFor` +### `enableWakeupFromRTC` ```cpp -bool sleepFor(int hours, int minutes, int seconds, void(*)() callbackFunction) +bool enableWakeupFromRTC(uint32_t hours, uint32_t minutes, uint32_t seconds) ``` -Put the device in sleep mode for a specified amount of time. - +Enables wake-up of the device from the RTC. #### Parameters * `hours` The number of hours to sleep. @@ -346,8 +547,6 @@ Put the device in sleep mode for a specified amount of time. * `seconds` The number of seconds to sleep. -* `callbackFunction` The function to call when the device wakes up. - #### Returns True if successful, false otherwise.
@@ -358,16 +557,16 @@ True if successful, false otherwise. void sleepUntilWakeupEvent() ``` -Put the device into sleep mode until a wakeup event occurs. This sleep mode is ideal for applications requiring periodic wake-ups or brief intervals of inactivity and reduces consumption to a range between 6mA and 18mA depending on the state of the peripherals. This sleep mode resumes the operation from the last operation. A wakeup event can be an interrupt on a pin or the RTC, depending on what you set with [enableWakeupFromPin()](#class_board_1a94ac54f76a7e8fff5b7c6523af64169a) and [enableWakeupFromRTC()](#class_board_1ae158d0367a2851d1f1f560bcca784412). +Put the device into sleep mode until a wakeup event occurs This sleep mode is ideal for applications requiring periodic wake-ups or brief intervals of inactivity and reduces consumption to a range between 6mA and 18mA depending on the state of the peripherals. This sleep mode resumes the operation from the last operation without resetting the board. A wakeup event can be an interrupt on a pin or the RTC, depending on what you set with [enableWakeupFromPin()](#class_board_1ae04b853e945b07852a65fb4f0e7e7d2b) and [enableWakeupFromRTC()](#class_board_1a5fc9e67d4e42ce7943b9675c17fd77f6).
-### `deepSleepUntilWakeupEvent` +### `standByUntilWakeupEvent` ```cpp -void deepSleepUntilWakeupEvent() +void standByUntilWakeupEvent() ``` -Put the device into deep sleep mode until a wakeup event occurs. For scenarios demanding drastic power conservation, the Deep Sleep Mode significantly reduces the board's power usage to range between 90uA and 11mA depending on the state of the peripherals. This mode restarts the board on wakeup, effectively running the setup() function again. A wakeup event can be an interrupt on a pin or the RTC, depending on what you set with [enableWakeupFromPin()](#class_board_1a94ac54f76a7e8fff5b7c6523af64169a) and [enableWakeupFromRTC()](#class_board_1ae158d0367a2851d1f1f560bcca784412). +Put the device into standby mode until a wakeup event occurs. For scenarios demanding drastic power conservation, the standby Mode significantly reduces the board's power usage to micro amperes range depending on the state of the peripherals. This mode restarts the board on wake-up, effectively running the setup() function again. A wakeup event can be an interrupt on a pin or the RTC, depending on what you set with [enableWakeupFromPin()](#class_board_1ae04b853e945b07852a65fb4f0e7e7d2b) and [enableWakeupFromRTC()](#class_board_1a5fc9e67d4e42ce7943b9675c17fd77f6).
### `setAllPeripheralsPower` @@ -376,8 +575,10 @@ Put the device into deep sleep mode until a wakeup event occurs. For scenarios d void setAllPeripheralsPower(bool on) ``` -Turn the peripherals on Portenta C33 (ADC, RGB LED, Secure Element, Wifi and Bluetooth) off. +Toggle the peripherals' power on Portenta C33 (ADC, RGB LED, Secure Element, Wifi and Bluetooth). +#### Parameters +* `on` True to turn on the power, false to turn it off.
### `setCommunicationPeripheralsPower` @@ -386,10 +587,10 @@ Turn the peripherals on Portenta C33 (ADC, RGB LED, Secure Element, Wifi and Blu void setCommunicationPeripheralsPower(bool on) ``` -Set the communication power rail switch direction on Portenta C33 (Wifi, Bluetooth and Secure Element) +Toggles the communication peripherials' power on Portenta C33 (Wifi, Bluetooth and Secure Element) #### Parameters -* `on` True to turn on the switches, false to turn them off. +* `on` True to turn on the power, false to turn it off.
### `setAnalogDigitalConverterPower` @@ -398,10 +599,10 @@ Set the communication power rail switch direction on Portenta C33 (Wifi, Bluetoo void setAnalogDigitalConverterPower(bool on) ``` -Set the analog digital converter power rail switch direction on Portenta C33. +Toggles the power of the analog digital converter on Portenta C33. This is not available on the Portenta H7. #### Parameters -* `on` True to turn on the switches, false to turn them off. +* `on` True to turn on the power, false to turn it off.
### `setReferenceVoltage` @@ -410,32 +611,46 @@ Set the analog digital converter power rail switch direction on Portenta C33. bool setReferenceVoltage(float voltage) ``` -Set the reference voltage on Portenta C33. This value is used by the ADC to convert analog values to digital values. This can be particularly useful to increase the accuracy of the ADC when working with low voltages. +Set the reference voltage. This value is used by the ADC to convert analog values to digital values. This can be particularly useful to increase the accuracy of the ADC when working with low voltages. #### Parameters -* `voltage` float value of the voltage value to set. It can be any value between 1.80V and 3.30V in steps of 0.10V. Any value outside this range or with different steps will not be accepted by the library. +* `voltage` Reference voltage value in volts. It can be anything between 1.80V and 3.30V in steps of 0.10V. Any value outside this range or with different steps will not be accepted by the library. #### Returns -True if successful, false otherwise. +True if the voltage was set successfully, false otherwise. +
+ +### `shutDownFuelGauge` + +```cpp +void shutDownFuelGauge() +``` + +Shuts down the fuel gauge to reduce power consumption. The IC returns to active mode on any edge of any communication line. If the IC is power-cycled or the software RESET command is sent the IC returns to active mode of operation. +
# class `Charger` -[Charger](#class_charger) class for controlling charging parameters and monitoring charging status. +Class for controlling charging parameters and monitoring charging status. ## Summary Members | Descriptions --------------------------------|--------------------------------------------- -| [`Charger`](#class_charger_1a386eef9a5c151f3e5eb3ee67a0aeb0cb) | Default constructor. | -| [`Charger`](#class_charger_1a941c1c93e7cca4055cb1b85c19c43824) | Constructor with PMIC instance. | -| [`setChargeCurrent`](#class_charger_1a5e2414a885c3d48a4767c725c1f734bb) | Set the charging current. | -| [`setChargeVoltage`](#class_charger_1aa3c52bef06f8d1069cc10b1829e4e878) | Set the charging voltage. | -| [`setEndOfChargeCurrent`](#class_charger_1a9a68b14cc28c160ba366cfc4eda4d0a0) | Set the end-of-charge current. | -| [`setInputCurrentLimit`](#class_charger_1ab4475b311be03071cf05b3c4ecfa9203) | The input current limit (ILIM) safeguards the device by preventing overcurrent, ensuring the charging current is within safe levels for the battery, and adapting to the maximum current the power source can provide, allowing you to charge and use the system at the same time. | -| [`getChargeStatus`](#class_charger_1a0c1c368e7b7cef05f9491efc4a576cb8) | Get the current charging status. | -| [`enable`](#class_charger_1a6e7a92f5fb4ae1f016ff13d5c716a81f) | Enables the charging functionality with either the default settings or the last saved parameters, depending on what was set previously. | -| [`disable`](#class_charger_1aa87840314777bb23a58cbead63407707) | Disable the charging functionality. | +| [`Charger`](#class_charger_1a386eef9a5c151f3e5eb3ee67a0aeb0cb) | Constructs a new [Charger](#class_charger) object. | +| [`begin`](#class_charger_1af3ebf5b1bbd6c4909f47217b83fe57ab) | Initializes the charger by initiating the PMIC. | +| [`setChargeCurrent`](#class_charger_1a7092cf5385bf469d3b27204478fb1671) | Set the charging current. The default charging current is set to 100mA. | +| [`getChargeCurrent`](#class_charger_1a3ff22dda98f766f42a3a7fdfc46d7a41) | Get the charge current in milli amperes (mA). | +| [`setChargeVoltage`](#class_charger_1a46cee977438a93ef66ed3882d741efbc) | Set the charging voltage in volts (V). The current charging voltage is set to 4.2V by default. | +| [`getChargeVoltage`](#class_charger_1af478d3be4756b758238823696c1a00c8) | Get the charge voltage in volts (V). | +| [`setEndOfChargeCurrent`](#class_charger_1a9b54c1077cc45ed826b8269ff57a3ee2) | Set the end-of-charge current. The charger IC determines when to terminate the charge cycle based on the current going into the battery dropping below the given threshold during the constant voltage phase. At this point, the battery is considered fully charged and charging is completed. If charge termination is disabled, the charge current will naturally decay to 0mA, but this is rarely done in practice. This is because the amount of charge going into the battery exponentially decreases during CV charging, and it would take a significantly longer time to recharge the battery with a very little increase in capacity. | +| [`getEndOfChargeCurrent`](#class_charger_1ae74b5ab591bd666c47cd133d2855152c) | Get the end of charge current. | +| [`setInputCurrentLimit`](#class_charger_1a1c4b5f61bd84e067c2643a0da1ccd1a7) | The input current limit (ILIM) safeguards the device by preventing overcurrent, ensuring the charging current is within safe levels for the battery, and adapting to the maximum current the power source can provide, allowing you to charge and use the system at the same time. The default input current limit is set to 1.5A. | +| [`getInputCurrentLimit`](#class_charger_1a768963364778f838e4b44463c020b173) | Get the input current limit. It is a safeguard to prevent overcurrent when charging respectively to the maximum current the power source can provide. | +| [`getState`](#class_charger_1a4670cf2d22eb36216e7ef2b65077021a) | Get the current charging status. | +| [`isEnabled`](#class_charger_1a908179315a74d96f27fbb86858ae4892) | Checks if the charger and thus charging is enabled. By default, the charger is enabled. | +| [`setEnabled`](#class_charger_1a4db5462b2061801340f022f2cd35e6c0) | Sets the enabled state of the charger. When enabling it uses the default settings or the last saved parameters, depending on what was set previously. | ## Members @@ -445,186 +660,336 @@ True if successful, false otherwise. Charger() ``` -Default constructor. +Constructs a new [Charger](#class_charger) object.
-### `Charger` +### `begin` ```cpp -Charger(PF1550 * pmic) +bool begin() ``` -Constructor with PMIC instance. +Initializes the charger by initiating the PMIC. -#### Parameters -* `pmic` Pointer to the PF1550 PMIC instance. +#### Returns +true if the charger initialization is successful, false otherwise.
-### `setChargeCurrent` +### `setChargeCurrent` ```cpp -void setChargeCurrent(ChargeCurrent current) +bool setChargeCurrent(uint16_t current) ``` -Set the charging current. +Set the charging current. The default charging current is set to 100mA. #### Parameters -* `current` Charging current enum value (ChargeCurrent). +* `current` Charging current in milli amperes (mA). Supported values: 100, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800, 850, 900, 950, 1000 + +#### Returns +True if successful, false if an invalid value was provided or if the PMIC communication failed. +
+ +### `getChargeCurrent` + +```cpp +uint16_t getChargeCurrent() +``` + +Get the charge current in milli amperes (mA). + +#### Returns +The charge current in float.
-### `setChargeVoltage` +### `setChargeVoltage` ```cpp -void setChargeVoltage(ChargeVoltage voltage) +bool setChargeVoltage(float voltage) ``` -Set the charging voltage. +Set the charging voltage in volts (V). The current charging voltage is set to 4.2V by default. #### Parameters -* `voltage` Charging voltage enum value (ChargeVoltage). +* `voltage` Charging voltage in volts (V). Supported values: 3.50, 3.52, 3.54, 3.56, 3.58, 3.60, 3.62, 3.64, 3.66, 3.68, 3.70, 3.72, 3.74, 3.76, 3.78, 3.80, 3.82, 3.84, 3.86, 3.88, 3.90, 3.92, 3.94, 3.96, 3.98, 4.00, 4.02, 4.04, 4.06, 4.08, 4.10, 4.12, 4.14, 4.16, 4.18, 4.20, 4.22, 4.24, 4.26, 4.28, 4.30, 4.32, 4.34, 4.36, 4.38, 4.40, 4.42, 4.44 + +#### Returns +True if successful, false if an invalid value was provided or if the PMIC communication failed.
-### `setEndOfChargeCurrent` +### `getChargeVoltage` ```cpp -void setEndOfChargeCurrent(EndOfChargeCurrent current) +float getChargeVoltage() ``` -Set the end-of-charge current. +Get the charge voltage in volts (V). + +#### Returns +The charge voltage as a float value. +
+ +### `setEndOfChargeCurrent` + +```cpp +bool setEndOfChargeCurrent(uint16_t current) +``` + +Set the end-of-charge current. The charger IC determines when to terminate the charge cycle based on the current going into the battery dropping below the given threshold during the constant voltage phase. At this point, the battery is considered fully charged and charging is completed. If charge termination is disabled, the charge current will naturally decay to 0mA, but this is rarely done in practice. This is because the amount of charge going into the battery exponentially decreases during CV charging, and it would take a significantly longer time to recharge the battery with a very little increase in capacity. #### Parameters -* `current` End-of-charge current enum value (EndOfChargeCurrent). +* `current` End-of-charge current in milli amperes (mA). The default end-of-charge current is set to 5 mA. Supported values: 5, 10, 20, 30, 50 + +#### Returns +True if successful, false if an invalid value was provided or if the PMIC communication failed.
-### `setInputCurrentLimit` +### `getEndOfChargeCurrent` ```cpp -void setInputCurrentLimit(InputCurrentLimit current) +uint16_t getEndOfChargeCurrent() ``` -The input current limit (ILIM) safeguards the device by preventing overcurrent, ensuring the charging current is within safe levels for the battery, and adapting to the maximum current the power source can provide, allowing you to charge and use the system at the same time. +Get the end of charge current. + +This function returns the current value at which the charging process is considered complete. Charging is terminated when the supplied current drops below the pre-programmed end of charge level. + +#### Returns +The end of charge current. +
+ +### `setInputCurrentLimit` + +```cpp +bool setInputCurrentLimit(uint16_t current) +``` + +The input current limit (ILIM) safeguards the device by preventing overcurrent, ensuring the charging current is within safe levels for the battery, and adapting to the maximum current the power source can provide, allowing you to charge and use the system at the same time. The default input current limit is set to 1.5A. #### Parameters -* `current` Maximum input current enum value (InputCurrentLimit). +* `current` Maximum input current in milli amperes (mA). Supported values: 10, 15, 20, 25, 30, 35, 40, 45, 50, 100, 150, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1500 + +#### Returns +True if successful, false if an invalid value was provided or if the PMIC communication failed. +
+ +### `getInputCurrentLimit` + +```cpp +uint16_t getInputCurrentLimit() +``` + +Get the input current limit. It is a safeguard to prevent overcurrent when charging respectively to the maximum current the power source can provide. + +#### Returns +The input current limit in milli amperes (mA).
-### `getChargeStatus` +### `getState` ```cpp -ChargeStatus getChargeStatus() +ChargingState getState() ``` Get the current charging status. #### Returns -Charging status enum value (ChargeStatus). +Charging status enum value (ChargingState). The possible states are: + +* none: Provided by the registers, not used in this API. + +* preCharge: First stage of the charging process, prepares battery for the charging process. + +* fastChargeConstantCurrent: Second phase of the charging process where the battery is charging in constant current mode until it reaches the voltage where the it's considered fully charged. (4.2V) + +* fastChargeConstantVoltage: Third phase of the charging process where the battery is kept at the fully charged voltage and current is slowly decreased to the end of charge current. + +* endOfCharge: If the battery is still connected, the charger will ensure it's kept at 4.2V by topping up the voltage to avoid self discharge. + +* done: [Battery](#class_battery) is fully charged + +* timerFaultError: The timer that is monitoring the charge status has encountered an error. + +* thermistorSuspendError: Charging was suspended due to overheating + +* chargerDisabled: [Charger](#class_charger) is disabled + +* batteryOvervoltageError: Charging was suspended due to an overvoltage fault + +* chargerBypassed: The charger is bypassed completely and the USB voltage is powering the board
-### `enable` +### `isEnabled` ```cpp -bool enable() +bool isEnabled() ``` -Enables the charging functionality with either the default settings or the last saved parameters, depending on what was set previously. +Checks if the charger and thus charging is enabled. By default, the charger is enabled. #### Returns -True if successful, false otherwise. +true if the charger is enabled, false otherwise.
-### `disable` +### `setEnabled` ```cpp -bool disable() +bool setEnabled(bool enabled) ``` -Disable the charging functionality. +Sets the enabled state of the charger. When enabling it uses the default settings or the last saved parameters, depending on what was set previously. + +#### Parameters +* `enabled` The desired enabled state of the charger. #### Returns -True if successful, false otherwise. +true if the enabled state was successfully set, false otherwise.
-# class `PowerManagement` +# class `MAX1726Driver` + +Driver class for the MAX1726 Fuel Gauge IC. ## Summary Members | Descriptions --------------------------------|--------------------------------------------- -| [`PowerManagement`](#class_power_management_1acc41d5c24cf751f6924e62c4e602f5b3) | constructor for the [PowerManagement](#class_power_management) | -| [`~PowerManagement`](#class_power_management_1a3d8e868a9d3eb39a971f1cfe901119df) | destructor for the [PowerManagement](#class_power_management) | -| [`begin`](#class_power_management_1a65bcff4dceb0effedd04b20be2e6695e) | start communication with the PMIC chip and the power gauge. | -| [`getBoard`](#class_power_management_1ad732d749ad09d03eff4523b617ec7e7f) | This class centralizes control over the power distribution within the board. It allows users to enable or disable specific power rails, and send the board into low-power modes. | -| [`getBattery`](#class_power_management_1aec3b949e2c9904113a7c406ac7019e00) | Dedicated to battery management, this class enables real-time monitoring of battery usage and health. | -| [`getCharger`](#class_power_management_1ae77d117118b803ba4d35132ab4d5270e) | Focused on battery charging dynamics, this class provides a detailed insight into charging parameters. | +| [`chargingComplete`](#class_m_a_x1726_driver_1a9c7c3d11d9dddc7667eafba19c52e65f) | Checks if the battery charging is complete. | +| [`setOperationMode`](#class_m_a_x1726_driver_1a13aeedba15e50b2fd2dada0a8ab0e5cd) | Sets the operation mode of the Fuel Gauge. | +| [`MAX1726Driver`](#class_m_a_x1726_driver_1af68eee6cc8a3d2a9fbbb0097b55e7ec6) | Constructs a new [MAX1726Driver](#class_m_a_x1726_driver) object. | +| [`~MAX1726Driver`](#class_m_a_x1726_driver_1a29bb1df9c115d16da9e4ce3afc99a992) | | ## Members -### `PowerManagement` +### `chargingComplete` ```cpp -PowerManagement() +bool chargingComplete() ``` -constructor for the [PowerManagement](#class_power_management) +Checks if the battery charging is complete. + +Checks if the charging process is complete. +#### Returns +true if the charging process is complete, false otherwise. + +#### Returns +true if the charging is complete, false otherwise.
-### `~PowerManagement` +### `setOperationMode` ```cpp -~PowerManagement() +bool setOperationMode(FuelGaugeOperationMode mode) ``` -destructor for the [PowerManagement](#class_power_management) +Sets the operation mode of the Fuel Gauge. + +#### Parameters +* `mode` The operation mode to set. Possible values are: hibernate, shutdown, active. +#### Returns +True if the operation mode was set successfully, false otherwise.
-### `begin` +### `MAX1726Driver` ```cpp -bool begin() +MAX1726Driver(TwoWire * wire, uint8_t i2cAddress) ``` -start communication with the PMIC chip and the power gauge. +Constructs a new [MAX1726Driver](#class_m_a_x1726_driver) object. -#### Returns -true if the initialization was successful, false otherwise +#### Parameters +* `wire` Pointer to the TwoWire object for I2C communication. + +* `i2cAddress` The I2C address of the MAX1726 device. The default value is 0x36.
-### `getBoard` +### `~MAX1726Driver` ```cpp -Board getBoard() +~MAX1726Driver() ``` -This class centralizes control over the power distribution within the board. It allows users to enable or disable specific power rails, and send the board into low-power modes. +
+ +# struct `BatteryCharacteristics` + +This struct contains the characteristics of the battery. + +## Summary + + Members | Descriptions +--------------------------------|--------------------------------------------- +| [`capacity`](#struct_battery_characteristics_1a6bd20a3ca22801553596234c7d80014c) | The battery's capacity in milliampere-hours (mAh). | +| [`emptyVoltage`](#struct_battery_characteristics_1af8847c64e47bd1ee07a2234572658baf) | The voltage in volts (V) at which the battery is considered empty. If you don't know this value you can use the minimumVoltage() function to find out while you let the battery completely discharge. | +| [`chargeVoltage`](#struct_battery_characteristics_1a1278657cc6c246d6545a3770d213cf91) | The voltage in volts (V) at which the battery is being charged. | +| [`endOfChargeCurrent`](#struct_battery_characteristics_1a13c651b4da45ab04ec9935023257aec2) | The current in milli amperes (mA) that is used to keep the battery charged at the end of the charging process. | +| [`ntcResistor`](#struct_battery_characteristics_1ab5b19a09ad5e5d61c1ad72bdf4de4fb3) | The NTC resistor value used in the battery pack (10K or 100K Ohm). | +| [`recoveryVoltage`](#struct_battery_characteristics_1aff1e9cdf23f2a9ff9e23da138f1791b4) | Sets the voltage level for clearing empty detection. Once the cell voltage rises above this point, empty voltage detection is re-enabled. | + +## Members + +### `capacity` + +```cpp +int capacity +``` + +The battery's capacity in milliampere-hours (mAh). -#### Returns -the [Board](#class_board) object.
-### `getBattery` +### `emptyVoltage` ```cpp -Battery getBattery() +float emptyVoltage ``` -Dedicated to battery management, this class enables real-time monitoring of battery usage and health. +The voltage in volts (V) at which the battery is considered empty. If you don't know this value you can use the minimumVoltage() function to find out while you let the battery completely discharge. -#### Returns -the [Battery](#class_battery) object.
-### `getCharger` +### `chargeVoltage` ```cpp -Charger getCharger() +float chargeVoltage ``` -Focused on battery charging dynamics, this class provides a detailed insight into charging parameters. +The voltage in volts (V) at which the battery is being charged. + +
+ +### `endOfChargeCurrent` + +```cpp +int endOfChargeCurrent +``` + +The current in milli amperes (mA) that is used to keep the battery charged at the end of the charging process. + +
+ +### `ntcResistor` + +```cpp +NTCResistor ntcResistor +``` + +The NTC resistor value used in the battery pack (10K or 100K Ohm). + +
+ +### `recoveryVoltage` + +```cpp +float recoveryVoltage +``` + +Sets the voltage level for clearing empty detection. Once the cell voltage rises above this point, empty voltage detection is re-enabled. -#### Returns -the [Charger](#class_charger) object.