/**
* 電池残量表示
* https://rikoubou.hatenablog.com/entry/2021/04/02/174338
* を一部改変
*/
#include <M5StickCPlus.h>
/**
* Batteryクラス
*
* 電池残量を表示する。
*/
class Battery
{
public:
Battery();
void setPosAndSize(int posX, int posY, int showSizeNum);
void setDeleteBgColor(uint16_t color);
void setTextColor(uint16_t color);
void batteryUpdate();
void setSprite(TFT_eSprite *sprite);
void setCheckRate(uint16_t rate);
private:
const float MAX_BATTERY_VOLTAGE = 4.0f;
const float MIN_BATTERY_VOLTAGE = 3.2f;
const int8_t BITS_PER_PIXEL = 1;
const int TRANS_PARENTS = 0;
const int MAX_SHOW_SIZE = 7;
const int MIN_SHOW_SIZE = 1;
TFT_eSprite *_sprite; // = TFT_eSprite(&M5.Lcd);
bool _showFlg;
int _x;
int _y;
int _showSize;
int _width;
int _height;
int _top_width;
uint16_t _bg_color;
uint16_t _line_color;
uint16_t _text_color;
uint16_t ratecount = 100;
uint16_t rateskip = 100;
int i_percent = -1;
uint16_t statusColor = 0;
void drawBatteryLines();
int calcBatteryPercent();
uint16_t getBatteryColor();
void showBatteryPercent();
bool isLowBattery();
bool isUsingBattery();
};
/**
* コンストラクタ
*/
Battery::Battery()
{
// 初期化
_showFlg = true;
_x = 0;
_y = 0;
_showSize = 1;
_width = 28 * _showSize;
_height = 10 * _showSize;
_top_width = 2 * _showSize;
_bg_color = TFT_BLACK;
_line_color = TFT_WHITE;
_text_color = TFT_WHITE;
}
void Battery::setSprite(TFT_eSprite *sprite)
{
_sprite = sprite;
}
/**
* 表示位置(x, y)と表示サイズを設定する関数
*/
void Battery::setPosAndSize(int posX, int posY, int showSizeNum)
{
_x = posX;
_y = posY;
if (MAX_SHOW_SIZE < showSizeNum)
{
_showSize = MAX_SHOW_SIZE;
}
else if (showSizeNum < MIN_SHOW_SIZE)
{
_showSize = MIN_SHOW_SIZE;
}
else
{
_showSize = showSizeNum;
}
_width = 28 * _showSize;
_height = 10 * _showSize;
_top_width = 2 * _showSize;
}
void Battery::setCheckRate(uint16_t _checkrate)
{
ratecount = _checkrate;
}
/**
* 削除時の背景色を設定する関数
*/
void Battery::setDeleteBgColor(uint16_t color)
{
_bg_color = color;
}
/**
* 電池図形と文字の色を設定する関数
*/
void Battery::setTextColor(uint16_t color)
{
_line_color = color;
_text_color = color;
}
/**
* バッテリー残量の表示を更新する関数(ここを定期的に呼び出す)
*/
void Battery::batteryUpdate()
{
if (rateskip % 5 == 0 || statusColor == 0)
{
statusColor = getBatteryColor();
}
if (rateskip == 1 || i_percent == -1)
{
i_percent = calcBatteryPercent();
rateskip = ratecount;
}
// 電池図形内部背景塗りつぶし
_sprite->fillRect(_x, _y, _width - 1, _height - 1, TFT_BLACK);
// 電池の外形
drawBatteryLines();
// バッテリー残量の割合を計算して背景色塗りつぶし
int b_width = int((_width - 2) * (i_percent / 100.0f));
_sprite->fillRect(_x + 2, _y + 2, b_width, _height - 3, statusColor);
showBatteryPercent(); // バッテリー数値を表示
// Serial.printf("batt %d", i_percent);
// _sprite->pushSprite(_x + 1, _y + 1); // ディスプレイに表示
rateskip--;
}
/**
* 電池の図形を作成する関数
*/
void Battery::drawBatteryLines()
{
// 電池図形を作成
_sprite->fillRect(_x, _y, _width + 1, _height + 1, _line_color);
_sprite->fillRect(_x + 1, _y + 1, _width - 1, _height - 1, TRANS_PARENTS);
_sprite->fillRect(_x + _width + 1, _y + _top_width, _top_width, _height - (_top_width * 2) + 1, _line_color);
// _sprite->setBitmapColor(_line_color, TRANS_PARENTS); // 色を設定
// _sprite->pushSprite(_x, _y, TRANS_PARENTS); // 表示
// _sprite->deleteSprite(); // メモリ開放
}
/**
* バッテリー残量を表示する関数
*/
void Battery::showBatteryPercent()
{
// バッテリー数値を表示
_sprite->setCursor(_x + _width + 7, _y + _showSize + 1);
_sprite->setTextFont(1);
_sprite->setTextColor(_text_color);
_sprite->setTextSize(_showSize);
_sprite->print(i_percent);
_sprite->print("%");
}
/**
* バッテリーの状態に応じて色を取得する関数
*/
uint16_t Battery::getBatteryColor()
{
// バッテリー稼働中は緑、電圧が低い時は赤色、充電中は青色
uint16_t color = TFT_BLUE;
if (isLowBattery())
{
color = TFT_RED;
}
else if (!isUsingBattery())
{
color = TFT_GREEN;
}
return color;
}
/**
* 低電圧状態かを判定する関数
*/
bool Battery::isLowBattery()
{
// 低電圧状態(3.4V以下)だと1それ以外は0
uint8_t _low_bat = M5.Axp.GetWarningLeve();
if (_low_bat == 0)
{
return false;
}
else
{
return true;
}
}
/**
* バッテリー稼働か充電中かを判定する関数
*/
bool Battery::isUsingBattery()
{
// プラスが充電、マイナスがバッテリー稼働
float _ibat = M5.Axp.GetBatCurrent();
if (_ibat < 0.0f)
{
return true;
}
else
{
return false;
}
}
/**
* バッテリー残量%を計算する関数(戻り値は0~100)
*/
int Battery::calcBatteryPercent()
{
float _vbat = M5.Axp.GetBatVoltage();
float percent = (_vbat - MIN_BATTERY_VOLTAGE) / (MAX_BATTERY_VOLTAGE - MIN_BATTERY_VOLTAGE);
if (percent > 1.0f)
percent = 1.0f;
if (percent < 0.0f)
percent = 0.0f;
return roundf(percent * 100.0f);
}