diff --git a/hal/ArduinoHAL.h b/hal/ArduinoHAL.h index 14137e0..a4da5fa 100644 --- a/hal/ArduinoHAL.h +++ b/hal/ArduinoHAL.h @@ -28,6 +28,7 @@ using String = std::string; #define INPUT 0 #define HIGH 1 #define LOW 0 +#define ADC_VOLTAGE 192 inline void pinMode(int pin, int mode) { //NOLINT // Do nothing @@ -37,6 +38,18 @@ inline void digitalWrite(int pin, int value) { //NOLINT // Do nothing } +inline void analogReadResolution(int bits) { + // Do nothing, we will just return a 12-bit value in analogRead +} + +inline uint32_t analogRead(int pin) { + // Return a dummy 12 bit value for the voltage pin, and 0 for other pins. + // This allows us to test the battery voltage reading functionality without needing a real ADC. + if (pin == ADC_VOLTAGE) { + return static_cast((1 << 12) - 1); // Return full-scale value for a 12-bit ADC + } + return 0; // Default dummy value for other pins +} // millis mock which still gives us the time since the program started in milliseconds static auto program_start = std::chrono::high_resolution_clock::now(); diff --git a/include/PowerManagement.h b/include/PowerManagement.h index 7b5a578..c79f2cf 100644 --- a/include/PowerManagement.h +++ b/include/PowerManagement.h @@ -1,50 +1,64 @@ #ifndef PowerManagement_H #define PowerManagement_H -#include "Arduino.h" -#include "pins.h" +#include "ArduinoHAL.h" /** * @brief Simple ADC-based battery voltage helper. - * @note When to use: quick health checks of the main battery using an analog - * pin and known divider scaling. + * This class provides a way to read the battery voltage using an ADC pin and a scaling factor. + * + * The correct pin can be found in the hardware scematics under "ADC_VOLTAGE" + * and the scaling factor can be calculated based on the voltage divider used in the hardware design. + * For MARTHA 1.4, the voltage divider is 200k and 1k5, so the factor is (200k + 1k5) / 1k5 = 134.33333. + * + * The voltage at the pin is calculated as: + * vPin = (rawValue / (2^numAdcBits - 1)) * vRef + * where rawValue is the ADC reading, numAdcBits is the resolution of the ADC, and vRef is the reference voltage for the ADC (3.3V for MARTHA 1.4). + * The battery voltage is then calculated as: + * vBat = vPin * factor */ class BatteryVoltage { public: - BatteryVoltage(uint8_t adcPin, float conversionFactor) - : pin(adcPin), factor(conversionFactor) {} + /** + * @param adcPin The ADC pin connected to the battery voltage divider. + * @param factor The scaling factor to convert the pin voltage to battery voltage. + * @param numAdcBits The resolution of the ADC (e.g., 12 for 12-bit ADC). + * @param voltageThreshold A threshold voltage for low battery checks (not used in current implementation but can be useful for future extensions). + */ + BatteryVoltage(uint8_t adcPin, float factor, int numAdcBits, float voltageThreshold) + : pin(adcPin), factor(factor), numAdcBits(numAdcBits), voltageThreshold(voltageThreshold) {analogReadResolution(numAdcBits);} /** * @brief Sample the ADC and convert to battery voltage. * @return Converted voltage reading. - * @note When to use: periodic health checks or brownout warnings. */ float readVoltage() { // Set the pin for reading pinMode(pin, INPUT); - uint32_t rawValue = 0; - rawValue = analogRead(pin); // Should give a value between 0 and 1023, not sure how to convert this to the true voltage. - // Conversion notes -> respect to Vref you would do Vref * analogRead()/2^12. - // After that you can use the voltage divider equation to get the battery voltage level - // Vref is 134.33? - // float voltage = pow((rawValue/2),12) * factor; - Serial.println(rawValue); - return rawValue; + uint32_t rawValue = analogRead(pin); // Should give a value between 0 and 2^numAdcBits - 1 + float vRef = 3.3f; // reference voltage for the ADC on MARTHA 1.4 + + // Convert raw ADC value to voltage at the pin, then apply the factor to get battery voltage + float vPin = (static_cast(rawValue) / (static_cast(1 << numAdcBits) - 1)) * vRef; + float vBat = vPin * factor; + + return vBat; } /** * @brief Check whether voltage exceeds a minimal threshold. * @return true if voltage is above the survival threshold. - * @note When to use: lightweight go/no-go checks before more detailed - * power analysis. + * @note Could be useful for future extension, like triggering a low power mode */ - bool isAlive(){ - return readVoltage() > .3; // Not sure what a good cutoff is + bool isLow(){ + return readVoltage() < voltageThreshold; } private: uint8_t pin; float factor; + int numAdcBits; + float voltageThreshold; }; #endif // PowerManagement_H \ No newline at end of file