/** * @file battery.h * @author Alexander Klein (alex@kleiax.de) * @brief Contains a class for battery monitoring * @version 0.1 * @date 2022-02-05 * * @copyright Copyright (c) 2022 * */ #ifndef BATTERY_H #define BATTERY_H #include #include #include #include #include "component.h" /** * @brief A class for battery monitoring * * This class reads the voltage from an analog pin to calculate the * charge level of a 3 Cell Li-Poly battery pack. The battery pack have * to be after a voltage diveder, so that maximum voltage for the * microcontroller is 3.3 Volt. */ class Battery : public Component { public: enum CalibrationState { None, Reading, Waiting, Finished }; /** * @brief Construct a new Battery object * * The voltage devider have to be calculated, so that the input * voltage from 3.3 Volt is never exceeded. It is assumed that * the microcontroller is connected to the second resistor. * * @param pin The analog to read from. * @param firstResistor First resistor of the voltage devider. * @param secondResistor Second resistor of the voltage devider. */ Battery(uint8_t pin, uint32_t firstResistor, uint32_t secondResistor); Battery(uint8_t pin); /** * @brief Get the battery voltage * * @return double in Volt */ double getBatteryVoltage() const; /** * @brief Get the charge level of the battery * * @return uint8_t charge level in percent */ uint8_t getBatteryPercent() const { return this->batteryPercent; } /** * @brief Checks if the battery is low. * * The function will also return false if the battery voltage is * absurd low. This is for the case that the uController is powered * by usb and no battery is connected. * * @param voltage the limit the battery have to * @return true if the battery is low * @return false if the battery is high */ bool isBatteryLow(double voltage) const; bool isNewValue(); // Calibration CalibrationState getCalibrationState() const { return this->calibrationState; } uint8_t getCurrentCalibrationVoltage() const { return this->currentCalibrationVoltage; } void nextVoltageIsReady(); void startCalibration(); void finishCalibration(); private: void run() override; void runCalibration(); double calculateInputVoltage(); void calculateBatteryVoltage(); void calculateBatteryPercent(); void readAdcToBuf(); void initBuffer(); uint16_t getBufAvg() const; static constexpr uint8_t bufferSize = 30; static constexpr uint8_t loopDelay = 100; static constexpr uint16_t adcMaxValue = 4095; CalibrationState calibrationState = CalibrationState::None; uint8_t absurdLowVoltage = 5; uint8_t pin; uint8_t batteryPercent = 0; uint8_t batteryLowPercent = 10; uint8_t bufferPos = 0; uint8_t calulationDelayMultiplier = 5; uint8_t loopCounter = 0; uint8_t currentCalibrationVoltage = 0; // *0.1 + 7 uint16_t adcBuffer[bufferSize]; uint16_t *newRawAdcVoltages = nullptr; uint32_t firstResistor = 0; uint32_t secondResistor = 0; bool calculatetNewValues = false; double batteryVoltage = 0; double batteryVoltageFactor; const float capacityVoltages[21] = {9.82, 10.83, 11.06, 11.12, // 0 5 10 15 11.18, 11.24, 11.3, 11.36, // 20 25 30 35 11.39, 11.45, 11.51, 11.56, // 40 45 50 55 11.62, 11.74, 11.86, 11.95, // 60 65 70 75 12.07, 12.25, 12.33, 12.45, // 80 85 90 95 12.6}; static constexpr uint8_t rawAdcVoltagesCount = 60; const double startVoltage = 7; const double stepVoltage = 0.1; const uint16_t rawAdcVoltages[rawAdcVoltagesCount] = // from 7.0V to 12.9V in 0.1V steps {1992, 2021, 2056, 2090, 2118, 2145, 2177, 2208, 2241, 2272, 2298, 2331, 2362, 2387, 2420, 2453, 2482, 2514, 2543, 2577, 2607, 2640, 2670, 2703, 2736, 2763, 2794, 2826, 2858, 2890, 2920, 2956, 2983, 3019, 3054, 3088, 3121, 3158, 3189, 3226, 3264, 3300, 3339, 3379, 3414, 3453, 3500, 3544, 3598, 3636, 3682, 3730, 3781, 3837, 3887, 3943, 3997, 4054, 4093, 4095}; const double adcCurveCoeficient[5] = {0.000000000000016, 0.000000000118171, 0.000000301211691, 0.001109019271794, 0.034143524634089}; }; #endif // BATTERY_H