Open kenjihiranabe opened 2 weeks ago
平鍋担当である、モーターの電流計算を作りました。 これを積分して、上記の放電容量(used_charge)、の計算をしてください。> @tmori
ありがとうございます! まずはバッテリモデルのクラス設計してみますね。
えいやで考えてみました。
お互いの考えがあってるか、補足してみました。
ここは、下図のようなモデルでVbatを求める認識ですね。
ここは、ローターの電流計算結果を積分するという認識ですね。
ここは、Vbat × duty_rateなのかな?と思いましたが、どうでしょうか。
あ、ですです、情報としての+で書きました、森さんの認識正しいです。
電圧カーブは、C/C++ の関数としてコールバックを登録(もしくは Dependency Injection)するのがいい感じ。 多分、 《interface》 がそういうことを言っている?
電圧カーブは、C/C++ の関数としてコールバックを登録(もしくは Dependency Injection)するのがいい感じ。 多分、 《interface》 がそういうことを言っている?
はい、その通りです。 電圧カーブの関数インタフェースだけ決めておいて、関数実装はローダブルモジュール化して動的にローディングするのかなーっと思っています。
英語の用語を統一したい。参考 https://web.mit.edu/evt/summary_battery_specifications.pdf https://www.pveducation.org/pvcdrom/battery-characteristics/battery-capacity | 英語 | 日本語 | 単位 | 意味 |
---|---|---|---|---|
Nominal Capacity | 公称容量 | Ah(アンペアアワー) | バッテリーが供給できる理論上の電気量 | |
Actual Capacity | 実容量 | Ah(アンペアアワー) | 実際に使用可能な電気容量 | |
Energy Capacity | エネルギー容量 | Wh(ワットアワー) | バッテリーが蓄えられる電力量 | |
Specific Energy | エネルギー密度(重量) | Wh/kg | 単位重量あたりのエネルギー容量 | |
Energy Density | エネルギー密度(体積) | Wh/L | 単位体積あたりのエネルギー容量 | |
State of Charge (SoC) | 充電状態 | % | バッテリーの現在の充電レベル | |
State of Health (SoH) | 劣化状態 | % | バッテリーの健全性を示す指標 | |
Depth of Discharge (DoD) | 放電深度 | % | 完全充電状態からの放電量 | |
C-Rate | C率 | C(時間の逆数) | バッテリーの充放電速度を示す比率 | |
Cycle Life | サイクル寿命 | サイクル数 | 充放電可能な回数 | |
Maximum Charge Current | 最大充電電流 | A(アンペア) | 安全に充電できる最大電流値 | |
Maximum Discharge Current | 最大放電電流 | A(アンペア) | 安全に放電できる最大電流値 | |
Rated Voltage | 定格電圧 | V(ボルト) | バッテリーの公称電圧 | |
Nominal Voltage | 公称電圧 | V(ボルト) | バッテリーの標準的な動作電圧 | |
Operating Voltage | 動作電圧 | V(ボルト) | 実際の使用時の電圧範囲 | |
Open Circuit Voltage | 開回路電圧 | V(ボルト) | 無負荷時のバッテリー電圧 | |
Cut-off Voltage | カットオフ電圧 | V(ボルト) | 放電を停止する最低電圧 | |
Float Voltage | フロート電圧 | V(ボルト) | 満充電状態を維持する電圧 | |
Internal Resistance | 内部抵抗 | Ω(オーム) | バッテリー内部の電気抵抗 | |
Power Density | 出力密度 | W/kg | 単位重量あたりの最大出力 | |
Available Capacity | 利用可能容量 | Ah(アンペアアワー) | 現在使用可能な容量 | |
Remaining Capacity | 残存容量 | Ah(アンペアアワー) | 使用後に残っている容量 | |
Design Capacity | 設計容量 | Ah(アンペアアワー) | バッテリー設計時の目標容量 | |
Usable Capacity | 使用可能容量 | Ah(アンペアアワー) | 実際に使える容量範囲 | |
Rated Capacity | 定格容量 | Ah(アンペアアワー) | メーカーが保証する容量 | |
Capacity Retention | 容量保持率 | % | 経時変化後の容量維持率 | |
Loss of Capacity | 容量低下 | %/時間 | 時間経過による容量減少率 | |
Discharge Rate | 放電レート | A or C | 単位時間当たりの放電量 | |
Self-Discharge Rate | 自己放電率 | %/月 | 未使用時の自然な放電率 | |
Discharge Efficiency | 放電効率 | % | 放電時のエネルギー変換効率 | |
Terminal Voltage | 端子電圧 | V(ボルト) | 負荷接続時の実際の電圧 | |
Voltage Drop | 電圧降下 | V(ボルト) | 負荷による電圧の低下量 | |
State of Function (SoF) | 機能状態 | % | バッテリーの性能状態指標 |
実スペック例:(書きで、Specs のタブ) https://genstattu.com/gens-ace-2200mah-3s-60c-11-1v-g-tech-lipo-battery-pack-with-deans-plug/
今回のパラメータ(11.1V に使ったスペック、仕様のプルダウン) https://jp.robotshop.com/products/111v-3000mah-40c-3s-lipo-battery
バッテリーのコンフィグパラメータ、ひとまず、以下で実装進めます。 まずは動くものを作ってみます。
"battery": {
"vendor": "None",
"NominalCapacity": 11.1,
"ActualCapacity": 11.1
},
インタフェースは一旦、こうしました。
#ifndef _IDISCHARGE_DYNAMICS_HPP_
#define _IDISCHARGE_DYNAMICS_HPP_
namespace hako::assets::drone {
class IDischargeDynamics {
public:
virtual ~IDischargeDynamics() {};
virtual double get_discharged() = 0;
};
}
#endif /* _IDISCHARGE_DYNAMICS_HPP_ */
ローターのダイナミクスで継承して計算します。
class RotorDynamics : public hako::assets::drone::IRotorDynamics, public hako::assets::drone::IDischargeDynamics, public ICsvLog {
private:
double param_rad_per_sec_max = 6000.0;
double param_tr = 1.0;
double param_kr = 1.0;
bool battery_dynamics = false;
RotorBatteryModelConstants constants;
DroneRotorSpeedType speed;
DroneRotorSpeedType next_speed;
double delta_time_sec;
double total_time_sec;
double discharged_value;
void run_discharge(double vbat, double omega, double duty_rate)
{
double current = drone_physics::rotor_current(
vbat, /* battery voltage in volt [V]*/
this->constants.R, /* resistance in ohm [V/A] */
this->constants.K, /* back electromotive force coeff in [N m/A] */
omega, /* angular velocity in [rad/sec] */
duty_rate /* 0.0-1.0 (ratio of PWM) */
);
this->discharged_value += current * this->delta_time_sec;
}
void run(double control, double vbat) override
{
this->run_discharge(vbat, this->speed.data, control);
this->next_speed.data = (
drone_physics::rotor_omega_acceleration(vbat, constants.R, constants.Cq, constants.J, constants.K, constants.D, speed.data, control)
) * this->delta_time_sec
+ this->speed.data;
// Cap the next speed at the maximum RPS if it exceeds it
if (this->next_speed.data > this->param_rad_per_sec_max) {
this->next_speed.data = this->param_rad_per_sec_max;
}
// Ensure the next speed does not fall below the minimum RPS (assuming 0 for this example)
else if (this->next_speed.data < 0) {
this->next_speed.data = 0;
}
this->speed.data = this->next_speed.data;
this->total_time_sec += this->delta_time_sec;
}
飛行させた時の、放電量をプロットしてみました。
次はバッテリのダイナミクスを作ります。
この図の放電電流をどう決めるかは悩みどころですね。 固定ではなくて、ドローンの負荷で変わるんですよね、きっと。 ひとまず、最初は固定の放電電流であるとして実装してみます。 あと、グラフは単純に、リニアに変化する形で。
バッテリーつけて動かしてみました。
多分、バッテリー電圧モデルがうまくいってないので、すぐに落ちちゃいますね。。 どうも9.5V以下になると、推力が重力に勝てなくなるみたい。
あってるように思います。 確か、新しいphysics にした時に、11.1V でホバーの電圧、ようやく確保だった。フルduty でも、回転数を2倍にできる電圧はなかったと記憶していて、14.8 V の方がいいか迷った。
でも、バッテリーの減りが早すぎない?フル電圧はもっと長時間続かないといけない。
@kenjihiranabe バッテリーの減りが早い原因を調べ始めてます。
確認ですけれど、電流値はプラス/マイナスになるんですよね。
実際にシミュレーションして、ドローン飛行を色々とやってみた時のローターの電流値をグラフ化してみました。
マイナスの電流の場合も放電している状態であるので、電流は絶対値で積分して放電量を求めるべきなのですよね?
"R": 0.12,
"Cq": 3.0e-8,
"K": 3.28e-3,
"D": 0.0,
"J": 8.12e-6
"HoveringRpm": 13827.38146
ホバリング時の Rad/Secは、約 1447
です。
バッテリ電圧は、以下の式で計算しています。
Vbat = 初期電圧 - { (初期電圧 - 終了電圧) / 容量 } * 現在の放電量[Ah]
return (Vbat * duty_rate - K * omega)/R;
確認ですが、 容量:3.0Ah は、1時間=3600秒間、3.0A 流せる量。
確認ですが、 容量:3.0Ah は、1時間=3600秒間、3.0A 流せる量。
ですよね。こちらの情報を参考にしました。
https://jp.robotshop.com/products/111v-3000mah-40c-3s-lipo-battery
なので、上のグラフ、40秒間、ずっと電圧が下がり続けるのはなぜだろう。電圧モデルですが、容量尽きるまでずっとフラットにしてみては?
以下の計算式で求めた結果とシミュレーション結果が一致するかどうか
return (Vbat * duty_rate - K * omega)/R;
シミュレーションが10秒時点でホバリングしており、安定しているので、この時点のデータをベースにして、机上計算結果とシミュレーション結果が一致しているかチェックする。
なので、電流値は、18.9 A となるので、机上で計算した値とほぼ一致している。
(10.8 0.65 - (3.28e-3 1448)) / 0.12
なので、上のグラフ、40秒間、ずっと電圧が下がり続けるのはなぜだろう。
バッテリの電圧モデルを単純化して、以下のようにリニアに減る形にしているためですね。
電圧モデルですが、容量尽きるまでずっとフラットにしてみては?
放電容量が 3Ah に達する時間がどうなるかだと思うのですが、 ホバリングしている場合、シミュレーション結果として、1個のローターの電流値は 20A でした。 4個で80Aになります。
そうすると1秒あたり 80Asで、容量は3Ahだから、3600x3As となり、2.25分(=3x45秒)で容量尽きると思うのですが。。
ドローンの連続飛行時間は30分程度とよく聞くので、 そうすると、3Ah の容量だと、ローター全部で 6Aで、 1ローターあたり、1.5A くらいなのかなと思えてきました...。
うーむ。
↑二つ上の計算だけど、
そうすると1秒あたり 80Asで、容量は3Ahだから、3600As となり、45秒で容量尽きると思うのですが。。
ちょっと違っていて、この3倍ですね。(容量の3 を掛ける) それでも、3分もたないか。
いま、3cellなので、4cell にして、14.8V, 容量を 4Ah にスペックアップしようか。 そうすると、パワーアップして電流が減り、かつ容量も増えて、10分くらいもたないかな。
↑二つ上の計算だけど、
そうすると1秒あたり 80Asで、容量は3Ahだから、3600As となり、45秒で容量尽きると思うのですが。。
ちょっと違っていて、この3倍ですね。(容量の3 を掛ける) それでも、3分もたないか。
いま、3cellなので、4cell にして、14.8V, 容量を 4Ah にスペックアップしようか。 そうすると、パワーアップして電流が減り、かつ容量も増えて、10分くらいもたないかな。
あ、セル数の考え方を入れてませんでした。 並列で接続しているんですかね。
セル数をパラメータで入れられるようにしてみます。
直列です。でも容量増えますよ。
なるほど、理解できてきました。1セル3.7 Vなんですね。
ここ見ると、直列もありですが、並列と直列を合わせたのもあるみたいですね。
https://drone-under500.com/drone/technology/drone-battery-lithium-polymer/
コンフィグのバリエーションが複雑になりそうなので、セル数はやめておきます。。
全体としての計算結果をパラメータに指定してもらうことにします。
いま、3cellなので、4cell にして、14.8V, 容量を 4Ah にスペックアップしようか。 そうすると、パワーアップして電流が減り、かつ容量も増えて、10分くらいもたないかな。
ちょっとわからなくなりました。
1cell 3.7Vを4個直列接続したら、14.8V になりますが、Vbatは値を大きする方向に作用するので、電流値は減らないような気がしました。
実際に計測してみると、PID制御のせいか、20Aのままですね。
ただ、寿命は伸びました。
(微妙に下降しているな。。
定義方法:BatteryModelCsvFilePathに、CSVファイルパスを指定する。
"battery": {
"vendor": "None",
"BatteryModelCsvFilePath": "./battery_model.csv",
"VoltageLevelGreen": 11.1,
"VoltageLevelYellow": 9.5,
"CapacityLevelYellow": 2.5,
"NominalVoltage": 14.8,
"NominalCapacity": 5.0,
"EODVoltage": 3.0
},
定義例:コメントつけれます。
# Discharge Capacity (Ah), Voltage Level (V)
0.0, 14.8
0.1, 13.5
0.2, 13.0
0.3, 12.8
0.4, 12.7
0.5, 12.6
0.6, 12.5
0.8, 12.3
1.0, 12.1
1.5, 11.8
2.0, 11.5
2.5, 11.2
3.0, 11.0
3.1, 10.0
3.2, 8.0
3.3, 6.0
3.4, 4.5
3.5, 3.5
3.6, 3.0
3.7, 3.0
5.0, 3.0
グラフ化すると:
実験結果:うまくいったぽいよ。
モデル策定案:
定数として、
$$ V_{bat} = voltage(full_charge, used_charge, i, temp); $$
さらに将来的には、放電回数による「劣化」も視野に入れる(最後のグラフ)。
マクニカの資料例 https://www.macnica.co.jp/business/semiconductor/articles/renesas/145231/