203 lines
6.4 KiB
C++
203 lines
6.4 KiB
C++
/**
|
|
* @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 <stdint.h>
|
|
#include <iostream>
|
|
#include <math.h>
|
|
#include <Arduino.h>
|
|
|
|
#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 divider, so that maximum voltage for the
|
|
* microcontroller is 3.3 Volt.
|
|
*/
|
|
class Battery : public Component
|
|
{
|
|
public:
|
|
/**
|
|
* @brief States when the calibration modes is active
|
|
*
|
|
* - None means that no calibration is running
|
|
* - Reading means that the adc takes multiple values to calculate an average
|
|
* - Waiting means that the user has to set the new wanted voltage
|
|
* - Finished means that all measurements was taken
|
|
*/
|
|
enum CalibrationState
|
|
{
|
|
None,
|
|
Reading,
|
|
Waiting,
|
|
Finished
|
|
};
|
|
|
|
/**
|
|
* @brief Construct a new Battery object
|
|
*
|
|
* The voltage divider 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 divider.
|
|
* @param secondResistor Second resistor of the voltage divider.
|
|
*/
|
|
Battery(uint8_t pin, uint32_t firstResistor, uint32_t secondResistor);
|
|
|
|
/**
|
|
* @brief Construct a new Battery object
|
|
*
|
|
* With this constructor the real voltage is not calculated with the
|
|
* voltage divider but with a table which contains the raw reading from
|
|
* the adc mapped to a specific voltage
|
|
*
|
|
* @param pin
|
|
*/
|
|
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;
|
|
|
|
/**
|
|
* @brief Check if a new voltage was been calculated
|
|
*
|
|
* @return true
|
|
* @return false
|
|
*/
|
|
bool isNewValue();
|
|
|
|
// Calibration
|
|
CalibrationState getCalibrationState() const { return this->calibrationState; }
|
|
|
|
/**
|
|
* @brief Get the current calibration voltage target
|
|
*
|
|
* The returned value stand for the index of the table for this reason
|
|
* the real value have to be calculated. After the returned voltage has been set
|
|
* you have to call nextVoltageIsReady().
|
|
*
|
|
* @return uint8_t voltage multiply with 0,1 and add 7
|
|
*/
|
|
uint8_t getCurrentCalibrationVoltage() const { return this->currentCalibrationVoltage; }
|
|
|
|
/**
|
|
* @brief Read next wanted voltage
|
|
*
|
|
* If this function is called, the calibration mode reads the new voltage
|
|
* and save the value in the table.
|
|
*/
|
|
void nextVoltageIsReady();
|
|
|
|
/**
|
|
* @brief Calibrate the battery readings
|
|
*
|
|
* This calibration has only an effect if the Component
|
|
* uses the table with the raw adc values. The calibration gives
|
|
* the user different voltages that have to be set with a
|
|
* laboratory power supply. The power supply have to be connected
|
|
* instead of the battery.
|
|
*/
|
|
void startCalibration();
|
|
|
|
/**
|
|
* @brief abort the calibration
|
|
*/
|
|
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 calculateDelayMultiplier = 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 calculatedNewValues = 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 adcCurveCoefficient[5] = {0.000000000000016,
|
|
0.000000000118171,
|
|
0.000000301211691,
|
|
0.001109019271794,
|
|
0.034143524634089};
|
|
};
|
|
|
|
#endif // BATTERY_H
|