@jjlmoya/utils-drones 1.20.0 → 1.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/category/index.ts +14 -6
- package/src/category/seo.astro +1 -1
- package/src/entries.ts +13 -1
- package/src/tests/locale_completeness.test.ts +2 -2
- package/src/tests/tool_validation.test.ts +2 -2
- package/src/tool/drone-battery-c-rating-calculator/bibliography.astro +17 -0
- package/src/tool/drone-battery-c-rating-calculator/bibliography.ts +16 -0
- package/src/tool/drone-battery-c-rating-calculator/component.astro +192 -0
- package/src/tool/drone-battery-c-rating-calculator/controller.ts +225 -0
- package/src/tool/drone-battery-c-rating-calculator/dom-views.ts +119 -0
- package/src/tool/drone-battery-c-rating-calculator/drone-battery-c-rating-calculator.css +300 -0
- package/src/tool/drone-battery-c-rating-calculator/entry.ts +27 -0
- package/src/tool/drone-battery-c-rating-calculator/evaluator.ts +37 -0
- package/src/tool/drone-battery-c-rating-calculator/i18n/de.ts +192 -0
- package/src/tool/drone-battery-c-rating-calculator/i18n/en.ts +192 -0
- package/src/tool/drone-battery-c-rating-calculator/i18n/es.ts +192 -0
- package/src/tool/drone-battery-c-rating-calculator/i18n/fr.ts +192 -0
- package/src/tool/drone-battery-c-rating-calculator/i18n/id.ts +192 -0
- package/src/tool/drone-battery-c-rating-calculator/i18n/it.ts +192 -0
- package/src/tool/drone-battery-c-rating-calculator/i18n/ja.ts +192 -0
- package/src/tool/drone-battery-c-rating-calculator/i18n/ko.ts +192 -0
- package/src/tool/drone-battery-c-rating-calculator/i18n/nl.ts +192 -0
- package/src/tool/drone-battery-c-rating-calculator/i18n/pl.ts +192 -0
- package/src/tool/drone-battery-c-rating-calculator/i18n/pt.ts +192 -0
- package/src/tool/drone-battery-c-rating-calculator/i18n/ru.ts +192 -0
- package/src/tool/drone-battery-c-rating-calculator/i18n/sv.ts +192 -0
- package/src/tool/drone-battery-c-rating-calculator/i18n/tr.ts +192 -0
- package/src/tool/drone-battery-c-rating-calculator/i18n/zh.ts +192 -0
- package/src/tool/drone-battery-c-rating-calculator/index.ts +10 -0
- package/src/tool/drone-battery-c-rating-calculator/logic.test.ts +84 -0
- package/src/tool/drone-battery-c-rating-calculator/logic.ts +112 -0
- package/src/tool/drone-battery-c-rating-calculator/seo.astro +16 -0
- package/src/tool/drone-battery-c-rating-calculator/storage.ts +19 -0
- package/src/tool/drone-battery-c-rating-calculator/ui.ts +43 -0
- package/src/tools.ts +3 -1
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import type { DroneBatteryCRatingCalculatorLocaleContent } from '../entry';
|
|
2
|
+
import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
|
|
3
|
+
import type { SEOSection } from '../../../types';
|
|
4
|
+
import { BIBLIOGRAPHY_ITEMS } from '../bibliography';
|
|
5
|
+
|
|
6
|
+
const slug = 'dron-lipo-pil-c-degeri-hesaplayici';
|
|
7
|
+
const title = 'Dron LiPo Pil C Değeri ve Sürekli Deşarj Hesaplayıcı';
|
|
8
|
+
const description = 'İç direnç ve motor akım tüketimine dayanarak dron LiPo pillerinin gerçekçi sürekli deşarj akımını, C değerini, voltaj düşüşünü ve uçuş güvenliğini hesaplayın.';
|
|
9
|
+
|
|
10
|
+
const ui = {
|
|
11
|
+
title: 'Dron LiPo Pil C Değeri Hesaplayıcı',
|
|
12
|
+
subtitle: 'Multirotorlar için gerçekçi sürekli deşarjı, anlık pik gereksinimlerini ve voltaj düşüşünü analiz edin',
|
|
13
|
+
lipoSpecsHeader: 'Pil Özellikleri',
|
|
14
|
+
capacityLabel: 'Kapasite (mAh)',
|
|
15
|
+
claimedCRatingLabel: 'Beyan Edilen C Değeri',
|
|
16
|
+
cellCountLabel: 'Hücre Sayısı (Seri S)',
|
|
17
|
+
chemistryLabel: 'Pil Kimyası',
|
|
18
|
+
internalResistanceLabel: 'Hücre Başına İç Direnç (mΩ)',
|
|
19
|
+
quadSpecsHeader: 'Dron Akım Tüketimi',
|
|
20
|
+
motorCountLabel: 'Motor Sayısı',
|
|
21
|
+
peakMotorCurrentLabel: 'Motor Başına Pik Akım (Amper)',
|
|
22
|
+
auxCurrentLabel: 'Yardımcı Donanım Tüketimi (VTX, FC, Kamera) (Amper)',
|
|
23
|
+
presetSelectLabel: 'Hızlı Ayarlar',
|
|
24
|
+
customPreset: 'Özel',
|
|
25
|
+
whoopPreset: '1S TinyWhoop',
|
|
26
|
+
freestyle5Preset: '6S 5 İnç Serbest Uçuş',
|
|
27
|
+
cinewhoopPreset: '4S 3 İnci CineWhoop',
|
|
28
|
+
longRange7Preset: '6S 7 İnç Uzun Menzil',
|
|
29
|
+
racing5Preset: '6S 5 İnç Yarış',
|
|
30
|
+
resultsHeader: 'Güç ve Performans Analizi',
|
|
31
|
+
claimedMaxCurrentLabel: 'Beyan Edilen Maksimum Akım',
|
|
32
|
+
realisticCRatingLabel: 'Gerçekçi Sürekli C Değeri',
|
|
33
|
+
realisticMaxCurrentLabel: 'Gerçekçi Sürekli Akım',
|
|
34
|
+
totalPeakDrawLabel: 'Toplam Pik Akım Tüketimi',
|
|
35
|
+
voltageSagLabel: 'Tahmini Voltaj Düşüşü',
|
|
36
|
+
sagNominalVoltageLabel: 'Yük Altındaki Nominal Voltaj',
|
|
37
|
+
flightTimeFullThrottleLabel: 'Tam Gaz Uçuş Süresi',
|
|
38
|
+
flightTimeHoverLabel: 'Tahmini Askıda Kalma Süresi',
|
|
39
|
+
safetyStatusLabel: 'Güvenlik Teşhisi',
|
|
40
|
+
statusOptimalTitle: 'Güvenli ve Optimal Pil Uyumu',
|
|
41
|
+
statusOptimalDesc: 'Pil, aşırı ısınma veya şiddetli voltaj düşüşü olmadan pik akımı kolayca sağlar. Uzun hücre ömrü garantilidir.',
|
|
42
|
+
statusWarningTitle: 'Orta Düzey Termal ve Voltaj Stresi',
|
|
43
|
+
statusWarningDesc: 'Pik akım tüketimi pilin gerçekçi sınırına yakındır. Ani gaz vermelerde hafif voltaj düşüşü beklenir.',
|
|
44
|
+
statusDangerTitle: 'Yüksek Aşırı Akım ve Voltaj Düşüşü Riski',
|
|
45
|
+
statusDangerDesc: 'Pik tüketim pilin gerçek kapasitesini aşıyor. Yüksek ısınma, şiddetli voltaj düşüşü ve erken yıpranma riski.',
|
|
46
|
+
lipoVisualizerTitle: 'Canlı LiPo Durum Görselleştirici',
|
|
47
|
+
cellVoltageLabel: 'Hücre Başına Voltaj',
|
|
48
|
+
batteryHealthLabel: 'Pil Stres Durumu',
|
|
49
|
+
burstRatingRequiredLabel: 'Gerekli Anlık Peak C Değeri',
|
|
50
|
+
currentRatioLabel: 'Güç Yük Oranı',
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const faqItems = [
|
|
54
|
+
{
|
|
55
|
+
question: 'Dron LiPo pillerinde C değeri nedir?',
|
|
56
|
+
answer: 'C değeri, pil kapasitesine oranla maksimum sürekli deşarj hızını temsil eder. Örneğin 1500mAh 100C bir pil teorik olarak 150 Amper akım sağlayabilir.',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
question: 'Beyan edilen C değeri neden gerçekte daha düşüktür?',
|
|
60
|
+
answer: 'Üreticiler genellikle pazarlama amaçlı anlık zirve değerlerini yansıtır. Gerçek sürekli deşarj doğrudan iç dirence bağlıdır.',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
question: 'İç direnç voltaj düşüşünü ve ısınmayı nasıl etkiler?',
|
|
64
|
+
answer: 'Yüksek iç direnç hücre içinde istenmeyen bir direnç gibi çalışır. Yüksek akım çekildiğinde voltaj aniden düşer ve enerji ısıya dönüşür.',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
question: 'Freestyle uçuşta voltaj düşüşünü nasıl önlerim?',
|
|
68
|
+
answer: 'Düşük iç dirençli piller kullanın, pik tüketime karşı en az yüzde 15 güvenlik marjı bırakın ve hücre başına 3.5V altına inmeyin.',
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
const howToSteps = [
|
|
73
|
+
{
|
|
74
|
+
name: 'Ayarı seçin veya verileri girin',
|
|
75
|
+
text: 'mAh kapasitesini, beyan edilen C değerini, hücre sayısını ve ortalama iç direnci girin.',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: 'Motor tüketimini yapılandırın',
|
|
79
|
+
text: 'Motor sayısını, tam gazdaki motor başına pik akımı ve yardımcı donanım tüketimini girin.',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: 'Güvenlik teşhisini inceleyin',
|
|
83
|
+
text: 'Güvenli uçuş için gerçekçi sürekli akım ile dronun pik tüketimini karşılaştırın.',
|
|
84
|
+
},
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
const seoSections: SEOSection[] = [
|
|
88
|
+
{
|
|
89
|
+
type: 'title',
|
|
90
|
+
text: 'Dron LiPo C Değeri ve Gerçek Güç Çıkışını Anlamak',
|
|
91
|
+
level: 2,
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
type: 'paragraph',
|
|
95
|
+
html: 'FPV dronlar için doğru LiPo pili seçmek kapasite, C değeri ve motor akım tüketimi arasındaki ilişkiyi anlamayı gerektirir. Üreticiler 100C veya üzeri değerler belirtse de gerçek sürekli deşarj iç direnç ve ısı dağılımı ile sınırlıdır. Bu hesaplayıcı gerçekçi güvenlik marjları sunar.',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
type: 'title',
|
|
99
|
+
text: 'RC Pil Kimyaları Karşılaştırma Tablosu',
|
|
100
|
+
level: 2,
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
type: 'table',
|
|
104
|
+
headers: ['Kimya', 'Nominal V', 'Maks V', 'Enerji Yoğunluğu', 'Pik Deşarj', 'Önerilen Kullanım'],
|
|
105
|
+
rows: [
|
|
106
|
+
['LiPo (Standart)', '3.7V', '4.20V', 'Yüksek', '100C - 150C', '5 İnç FPV Yarış ve Serbest Uçuş'],
|
|
107
|
+
['LiHV (Yüksek Voltaj)', '3.8V', '4.35V', 'Çok Yüksek', '80C - 120C', 'TinyWhoop ve Mikro Dronlar'],
|
|
108
|
+
['Li-Ion (18650/21700)', '3.6V', '4.20V', 'Maksimum', '15C - 35C', '7 İnç Uzun Menzil Dronlar'],
|
|
109
|
+
['LiFePO4', '3.3V', '3.65V', 'Orta', '30C - 50C', 'Saha Şarj İstasyonları'],
|
|
110
|
+
],
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
type: 'title',
|
|
114
|
+
text: 'Voltaj Düşüşü ve İç Direncin Performansa Etkisi',
|
|
115
|
+
level: 2,
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
type: 'paragraph',
|
|
119
|
+
html: 'Voltaj düşüşü (voltage sag), ani gaz vermelerde voltajın aniden düşmesidir. Akım yüksek iç dirençten geçerken enerji itme gücü yerine ısıya dönüşür. Yıpranmış bir pil OSD ekranında erken düşük voltaj uyarısına yol açar.',
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
type: 'list',
|
|
123
|
+
items: [
|
|
124
|
+
'Düşük İç Direnç (Hücre başı 1-4 mΩ): Harika tepki, minimum voltaj düşüşü ve serin çalışma.',
|
|
125
|
+
'Orta İç Direnç (Hücre başı 5-10 mΩ): Serbest uçuş için standart performans.',
|
|
126
|
+
'Yüksek İç Direnç (Hücre başı >12 mΩ): Belirgin güç kaybı, şiddetli düşüş ve hızlı ısınma.',
|
|
127
|
+
],
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
type: 'title',
|
|
131
|
+
text: 'Serbest Uçuş Yarış ve Uzun Menzil Pil Optimizasyonu',
|
|
132
|
+
level: 2,
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
type: 'paragraph',
|
|
136
|
+
html: 'Farklı uçuş tarzları farklı güç profilleri gerektirir. 5 inç serbest uçuş dronları 120 Amper üzeri ani akım sıçramaları oluştururken 7 inç uzun menzil dronları sabit verimlilik arar. Doğru pil eşleşmesi havadaki ani kapanmaları önler.',
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
type: 'tip',
|
|
140
|
+
title: 'LiPo Bakım İpucu',
|
|
141
|
+
html: 'Kullanılmadığında LiPo pillerinizi her zaman hücre başına 3.80V ile 3.85V depolama voltajında saklayın. Pilleri 48 saatten fazla tam dolu bırakmak iç direnci kalıcı olarak artırır.',
|
|
142
|
+
},
|
|
143
|
+
];
|
|
144
|
+
|
|
145
|
+
const schemas: DroneBatteryCRatingCalculatorLocaleContent['schemas'] = [
|
|
146
|
+
{
|
|
147
|
+
'@context': 'https://schema.org',
|
|
148
|
+
'@type': 'FAQPage',
|
|
149
|
+
mainEntity: faqItems.map((item) => ({
|
|
150
|
+
'@type': 'Question',
|
|
151
|
+
name: item.question,
|
|
152
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
153
|
+
})),
|
|
154
|
+
} as WithContext<FAQPage>,
|
|
155
|
+
{
|
|
156
|
+
'@context': 'https://schema.org',
|
|
157
|
+
'@type': 'HowTo',
|
|
158
|
+
name: title,
|
|
159
|
+
description,
|
|
160
|
+
step: howToSteps.map((s, index) => ({
|
|
161
|
+
'@type': 'HowToStep',
|
|
162
|
+
position: index + 1,
|
|
163
|
+
name: s.name,
|
|
164
|
+
text: s.text,
|
|
165
|
+
})),
|
|
166
|
+
} as WithContext<HowTo>,
|
|
167
|
+
{
|
|
168
|
+
'@context': 'https://schema.org',
|
|
169
|
+
'@type': 'SoftwareApplication',
|
|
170
|
+
name: title,
|
|
171
|
+
description,
|
|
172
|
+
applicationCategory: 'UtilityApplication',
|
|
173
|
+
operatingSystem: 'All',
|
|
174
|
+
offers: {
|
|
175
|
+
'@type': 'Offer',
|
|
176
|
+
price: '0',
|
|
177
|
+
priceCurrency: 'TRY',
|
|
178
|
+
},
|
|
179
|
+
} as WithContext<SoftwareApplication>,
|
|
180
|
+
];
|
|
181
|
+
|
|
182
|
+
export const content: DroneBatteryCRatingCalculatorLocaleContent = {
|
|
183
|
+
slug,
|
|
184
|
+
title,
|
|
185
|
+
description,
|
|
186
|
+
ui,
|
|
187
|
+
seo: seoSections,
|
|
188
|
+
faq: faqItems,
|
|
189
|
+
howTo: howToSteps,
|
|
190
|
+
bibliography: BIBLIOGRAPHY_ITEMS,
|
|
191
|
+
schemas,
|
|
192
|
+
};
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import type { DroneBatteryCRatingCalculatorLocaleContent } from '../entry';
|
|
2
|
+
import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
|
|
3
|
+
import type { SEOSection } from '../../../types';
|
|
4
|
+
import { BIBLIOGRAPHY_ITEMS } from '../bibliography';
|
|
5
|
+
|
|
6
|
+
const slug = 'drone-battery-c-rating-calculator';
|
|
7
|
+
const title = '无人机 LiPo 电池 C 数与持续放电电流计算器';
|
|
8
|
+
const description = '基于单体电池内阻和电机功耗,计算穿越机与无人机 LiPo 电池的真实持续放电电流、C 倍率、电压压降(Voltage Sag)及飞行安全诊断。';
|
|
9
|
+
|
|
10
|
+
const ui = {
|
|
11
|
+
title: '无人机 LiPo 电池 C 数计算器',
|
|
12
|
+
subtitle: '分析多轴无人机的真实持续放电、峰值负载需求及电压压降',
|
|
13
|
+
lipoSpecsHeader: '电池参数规格',
|
|
14
|
+
capacityLabel: '容量 (mAh)',
|
|
15
|
+
claimedCRatingLabel: '标称 C 数 (C-Rating)',
|
|
16
|
+
cellCountLabel: '电池串联 S 数 (Series)',
|
|
17
|
+
chemistryLabel: '电池化学类型',
|
|
18
|
+
internalResistanceLabel: '单体电池内阻 (mΩ)',
|
|
19
|
+
quadSpecsHeader: '无人机动力功耗',
|
|
20
|
+
motorCountLabel: '电机数量',
|
|
21
|
+
peakMotorCurrentLabel: '单电机峰值电流 (A)',
|
|
22
|
+
auxCurrentLabel: '辅助设备电流 (图传/飞控/相机) (A)',
|
|
23
|
+
presetSelectLabel: '快速预设',
|
|
24
|
+
customPreset: '自定义',
|
|
25
|
+
whoopPreset: '1S TinyWhoop 微型机',
|
|
26
|
+
freestyle5Preset: '6S 5英寸 花飞机',
|
|
27
|
+
cinewhoopPreset: '4S 3英寸 涵道机',
|
|
28
|
+
longRange7Preset: '6S 7英寸 远航机',
|
|
29
|
+
racing5Preset: '6S 5英寸 竞速机',
|
|
30
|
+
resultsHeader: '动力与性能分析',
|
|
31
|
+
claimedMaxCurrentLabel: '标称最大电流',
|
|
32
|
+
realisticCRatingLabel: '真实持续 C 数',
|
|
33
|
+
realisticMaxCurrentLabel: '真实持续放电电流',
|
|
34
|
+
totalPeakDrawLabel: '总峰值抽流',
|
|
35
|
+
voltageSagLabel: '预估电压压降',
|
|
36
|
+
sagNominalVoltageLabel: '负载下标称电压',
|
|
37
|
+
flightTimeFullThrottleLabel: '全油门续航时间',
|
|
38
|
+
flightTimeHoverLabel: '预估悬停续航时间',
|
|
39
|
+
safetyStatusLabel: '安全性诊断',
|
|
40
|
+
statusOptimalTitle: '安全且最佳的电池匹配',
|
|
41
|
+
statusOptimalDesc: '电池可以轻松提供峰值电流,不会产生过大发热或严重压降。能够显著延长电池循环寿命。',
|
|
42
|
+
statusWarningTitle: '中度发热与电压应力',
|
|
43
|
+
statusWarningDesc: '峰值抽流接近电池的真实放电极限。在大油门猛推时会出现轻微的电压压降。',
|
|
44
|
+
statusDangerTitle: '过流与严重压降风险高',
|
|
45
|
+
statusDangerDesc: '无人机峰值抽流超过电池真实放电能力。存在过热、严重压降和电池加速老化的风险。',
|
|
46
|
+
lipoVisualizerTitle: '实时 LiPo 电池状态可视化',
|
|
47
|
+
cellVoltageLabel: '单体电压',
|
|
48
|
+
batteryHealthLabel: '电池负载应力',
|
|
49
|
+
burstRatingRequiredLabel: '所需峰值 C 数',
|
|
50
|
+
currentRatioLabel: '动力负载比例',
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const faqItems = [
|
|
54
|
+
{
|
|
55
|
+
question: '穿越机 LiPo 电池的 C 数代表什么?',
|
|
56
|
+
answer: 'C 数表示相对于电池容量的最大持续放电速率。例如 1500mAh 标称 100C 的电池,理论上可提供最高 150A 电流。',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
question: '为什么标称 C 数通常高于实际放电能力?',
|
|
60
|
+
answer: '厂商通常标注的是短时间爆发极限或理想实验室条件下的虚高数值。真实持续放电直接取决于单体电池的内阻。',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
question: '内阻如何影响电压压降和电池发热?',
|
|
64
|
+
answer: '内阻相当于电池内部的寄生电阻。当大电流通过时,内阻会导致电压骤降,并将电能转化为热能发热。',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
question: '花飞飞行中如何避免电压压降 (Voltage Sag)?',
|
|
68
|
+
answer: '使用低内阻的高品质电池,保持比峰值抽流高出至少 15% 的安全余量,且静置电压不要低于单体 3.5V。',
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
const howToSteps = [
|
|
73
|
+
{
|
|
74
|
+
name: '选择预设或输入电池参数',
|
|
75
|
+
text: '输入容量 (mAh)、标称 C 数、串联 S 数以及单体平均内阻。',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: '配置无人机电机与电子设备功耗',
|
|
79
|
+
text: '设置电机数量、全油门下单电机峰值电流及图传等辅助设备电流。',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: '查看安全诊断与真实电流',
|
|
83
|
+
text: '对比计算出的真实持续电流与无人机峰值抽流,确保飞行安全。',
|
|
84
|
+
},
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
const seoSections: SEOSection[] = [
|
|
88
|
+
{
|
|
89
|
+
type: 'title',
|
|
90
|
+
text: '理解穿越机 LiPo 电池 C 数与真实动力输出',
|
|
91
|
+
level: 2,
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
type: 'paragraph',
|
|
95
|
+
html: '为 FPV 穿越机选择合适的 LiPo 电池需要建立电池容量、C 数与电机电流消耗之间的对应关系。虽然厂家常宣传 100C 甚至更高,但真实的持续放电受限于内阻与散热能力。本计算器可算出真实的持续电流保障安全。',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
type: 'title',
|
|
99
|
+
text: '航模 RC 电池化学类型对比表',
|
|
100
|
+
level: 2,
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
type: 'table',
|
|
104
|
+
headers: ['化学类型', '标称电压', '最高电压', '能量密度', '峰值放电', '推荐应用场景'],
|
|
105
|
+
rows: [
|
|
106
|
+
['LiPo (标准聚合物)', '3.7V', '4.20V', '高', '100C - 150C', '5英寸 FPV 竞速与花飞穿越机'],
|
|
107
|
+
['LiHV (高压聚合物)', '3.8V', '4.35V', '很高', '80C - 120C', 'TinyWhoop 与微型空圈机'],
|
|
108
|
+
['Li-Ion (18650/21700)', '3.6V', '4.20V', '极高', '15C - 35C', '7英寸 长航时远航穿越机'],
|
|
109
|
+
['LiFePO4 (磷酸铁锂)', '3.3V', '3.65V', '中等', '30C - 50C', '外场充电站与电源箱'],
|
|
110
|
+
],
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
type: 'title',
|
|
114
|
+
text: '电压压降与内阻对 FPV 穿越机性能的影响',
|
|
115
|
+
level: 2,
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
type: 'paragraph',
|
|
119
|
+
html: '电压压降 (Voltage Sag) 是指在急加油门时电池电压的瞬间骤降。内阻偏高的老旧电池在大电流下会把电能大量转化为热能,导致 FPV 眼镜 OSD 界面提前弹出低压报警。',
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
type: 'list',
|
|
123
|
+
items: [
|
|
124
|
+
'超低内阻 (单体 1-4 mΩ): 动力爆发极佳,压降极小,工作温度低。',
|
|
125
|
+
'中等内阻 (单体 5-10 mΩ): 标准花飞飞行性能,油门全开时有轻微压降。',
|
|
126
|
+
'高内阻 (单体 >12 mΩ): 动力明显衰减,严重压降,电池发热剧烈。',
|
|
127
|
+
],
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
type: 'title',
|
|
131
|
+
text: '花飞、竞速与远航无人机的电池匹配优化',
|
|
132
|
+
level: 2,
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
type: 'paragraph',
|
|
136
|
+
html: '不同的飞行风格对供电系统有截然不同的要求。5英寸花飞机在做动作时会产生超过 120A 的短时电流爆发,而 7英寸远航机则更看重平稳高效的持续巡航。合理的电池匹配能有效防止空中意外断电掉机。',
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
type: 'tip',
|
|
140
|
+
title: 'LiPo 电池保存维保建议',
|
|
141
|
+
html: '闲置电池时请务必保持在单体 3.80V 至 3.85V 的保存电压 (Storage Mode)。满电放置超过 48 小时会导致电池内阻永久性升高并损伤容量。',
|
|
142
|
+
},
|
|
143
|
+
];
|
|
144
|
+
|
|
145
|
+
const schemas: DroneBatteryCRatingCalculatorLocaleContent['schemas'] = [
|
|
146
|
+
{
|
|
147
|
+
'@context': 'https://schema.org',
|
|
148
|
+
'@type': 'FAQPage',
|
|
149
|
+
mainEntity: faqItems.map((item) => ({
|
|
150
|
+
'@type': 'Question',
|
|
151
|
+
name: item.question,
|
|
152
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
153
|
+
})),
|
|
154
|
+
} as WithContext<FAQPage>,
|
|
155
|
+
{
|
|
156
|
+
'@context': 'https://schema.org',
|
|
157
|
+
'@type': 'HowTo',
|
|
158
|
+
name: title,
|
|
159
|
+
description,
|
|
160
|
+
step: howToSteps.map((s, index) => ({
|
|
161
|
+
'@type': 'HowToStep',
|
|
162
|
+
position: index + 1,
|
|
163
|
+
name: s.name,
|
|
164
|
+
text: s.text,
|
|
165
|
+
})),
|
|
166
|
+
} as WithContext<HowTo>,
|
|
167
|
+
{
|
|
168
|
+
'@context': 'https://schema.org',
|
|
169
|
+
'@type': 'SoftwareApplication',
|
|
170
|
+
name: title,
|
|
171
|
+
description,
|
|
172
|
+
applicationCategory: 'UtilityApplication',
|
|
173
|
+
operatingSystem: 'All',
|
|
174
|
+
offers: {
|
|
175
|
+
'@type': 'Offer',
|
|
176
|
+
price: '0',
|
|
177
|
+
priceCurrency: 'CNY',
|
|
178
|
+
},
|
|
179
|
+
} as WithContext<SoftwareApplication>,
|
|
180
|
+
];
|
|
181
|
+
|
|
182
|
+
export const content: DroneBatteryCRatingCalculatorLocaleContent = {
|
|
183
|
+
slug,
|
|
184
|
+
title,
|
|
185
|
+
description,
|
|
186
|
+
ui,
|
|
187
|
+
seo: seoSections,
|
|
188
|
+
faq: faqItems,
|
|
189
|
+
howTo: howToSteps,
|
|
190
|
+
bibliography: BIBLIOGRAPHY_ITEMS,
|
|
191
|
+
schemas,
|
|
192
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { droneBatteryCRatingCalculator } from './entry';
|
|
2
|
+
import type { ToolDefinition } from '../../types';
|
|
3
|
+
export * from './entry';
|
|
4
|
+
|
|
5
|
+
export const DRONE_BATTERY_C_RATING_CALCULATOR_TOOL: ToolDefinition = {
|
|
6
|
+
entry: droneBatteryCRatingCalculator,
|
|
7
|
+
Component: () => import('./component.astro'),
|
|
8
|
+
SEOComponent: () => import('./seo.astro'),
|
|
9
|
+
BibliographyComponent: () => import('./bibliography.astro'),
|
|
10
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
getNominalCellVoltage,
|
|
4
|
+
getFullyChargedCellVoltage,
|
|
5
|
+
calculateClaimedCurrent,
|
|
6
|
+
calculateRealisticCRating,
|
|
7
|
+
calculateTotalPeakDraw,
|
|
8
|
+
calculateVoltageSag,
|
|
9
|
+
calculateFlightTimeSeconds,
|
|
10
|
+
evaluateSafetyStatus,
|
|
11
|
+
calculateBatteryMetrics,
|
|
12
|
+
type BatteryInputs,
|
|
13
|
+
} from './logic';
|
|
14
|
+
|
|
15
|
+
describe('Drone Battery C-Rating Logic', () => {
|
|
16
|
+
it('should return correct nominal cell voltages', () => {
|
|
17
|
+
expect(getNominalCellVoltage('lipo')).toBe(3.7);
|
|
18
|
+
expect(getNominalCellVoltage('lihv')).toBe(3.8);
|
|
19
|
+
expect(getNominalCellVoltage('liion')).toBe(3.6);
|
|
20
|
+
expect(getNominalCellVoltage('life')).toBe(3.3);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should return correct fully charged cell voltages', () => {
|
|
24
|
+
expect(getFullyChargedCellVoltage('lipo')).toBe(4.2);
|
|
25
|
+
expect(getFullyChargedCellVoltage('lihv')).toBe(4.35);
|
|
26
|
+
expect(getFullyChargedCellVoltage('liion')).toBe(4.2);
|
|
27
|
+
expect(getFullyChargedCellVoltage('life')).toBe(3.65);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should calculate claimed continuous current', () => {
|
|
31
|
+
expect(calculateClaimedCurrent(1300, 75)).toBe(97.5);
|
|
32
|
+
expect(calculateClaimedCurrent(0, 75)).toBe(0);
|
|
33
|
+
expect(calculateClaimedCurrent(1500, -10)).toBe(0);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should calculate realistic C-rating based on internal resistance', () => {
|
|
37
|
+
expect(calculateRealisticCRating(4, 100, 1300)).toBe(52);
|
|
38
|
+
expect(calculateRealisticCRating(15, 80, 300)).toBe(80);
|
|
39
|
+
expect(calculateRealisticCRating(0, 80, 1300)).toBe(80);
|
|
40
|
+
expect(calculateRealisticCRating(25, 100, 1300)).toBe(21);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should calculate total peak current draw', () => {
|
|
44
|
+
expect(calculateTotalPeakDraw(4, 30, 1.5)).toBe(121.5);
|
|
45
|
+
expect(calculateTotalPeakDraw(0, 30, 1.5)).toBe(1.5);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should calculate voltage sag', () => {
|
|
49
|
+
expect(calculateVoltageSag(100, 5, 4)).toBe(2);
|
|
50
|
+
expect(calculateVoltageSag(0, 5, 4)).toBe(0);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('should calculate flight time in seconds', () => {
|
|
54
|
+
expect(calculateFlightTimeSeconds(1000, 60)).toBeCloseTo(48);
|
|
55
|
+
expect(calculateFlightTimeSeconds(1000, 0)).toBe(0);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should evaluate safety status correctly', () => {
|
|
59
|
+
expect(evaluateSafetyStatus(100, 90)).toBe('optimal');
|
|
60
|
+
expect(evaluateSafetyStatus(100, 150)).toBe('warning');
|
|
61
|
+
expect(evaluateSafetyStatus(100, 250)).toBe('danger');
|
|
62
|
+
expect(evaluateSafetyStatus(100, 0)).toBe('optimal');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should calculate complete battery metrics', () => {
|
|
66
|
+
const inputs: BatteryInputs = {
|
|
67
|
+
capacitymAh: 1300,
|
|
68
|
+
claimedCRating: 100,
|
|
69
|
+
cellCount: 4,
|
|
70
|
+
chemistry: 'lipo',
|
|
71
|
+
internalResistanceMOm: 5,
|
|
72
|
+
motorCount: 4,
|
|
73
|
+
peakMotorCurrentA: 25,
|
|
74
|
+
auxCurrentA: 1.5,
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const res = calculateBatteryMetrics(inputs);
|
|
78
|
+
expect(res.claimedMaxCurrentA).toBe(130);
|
|
79
|
+
expect(res.totalPeakDrawA).toBe(101.5);
|
|
80
|
+
expect(res.voltageSagV).toBeCloseTo(2.03);
|
|
81
|
+
expect(res.sagNominalVoltageV).toBeGreaterThan(0);
|
|
82
|
+
expect(res.flightTimeFullThrottleSec).toBeGreaterThan(0);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
export type BatteryChemistry = 'lipo' | 'lihv' | 'liion' | 'life';
|
|
2
|
+
export type SafetyStatus = 'optimal' | 'warning' | 'danger';
|
|
3
|
+
|
|
4
|
+
export interface BatteryInputs {
|
|
5
|
+
capacitymAh: number;
|
|
6
|
+
claimedCRating: number;
|
|
7
|
+
cellCount: number;
|
|
8
|
+
chemistry: BatteryChemistry;
|
|
9
|
+
internalResistanceMOm: number;
|
|
10
|
+
motorCount: number;
|
|
11
|
+
peakMotorCurrentA: number;
|
|
12
|
+
auxCurrentA: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface BatteryCalculationResults {
|
|
16
|
+
claimedMaxCurrentA: number;
|
|
17
|
+
realisticCRating: number;
|
|
18
|
+
realisticMaxCurrentA: number;
|
|
19
|
+
totalPeakDrawA: number;
|
|
20
|
+
voltageSagV: number;
|
|
21
|
+
sagNominalVoltageV: number;
|
|
22
|
+
sagFullVoltageV: number;
|
|
23
|
+
flightTimeFullThrottleSec: number;
|
|
24
|
+
flightTimeHoverSec: number;
|
|
25
|
+
burstRatingRequired: number;
|
|
26
|
+
safetyStatus: SafetyStatus;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function getNominalCellVoltage(chemistry: BatteryChemistry): number {
|
|
30
|
+
if (chemistry === 'lihv') return 3.8;
|
|
31
|
+
if (chemistry === 'liion') return 3.6;
|
|
32
|
+
if (chemistry === 'life') return 3.3;
|
|
33
|
+
return 3.7;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function getFullyChargedCellVoltage(chemistry: BatteryChemistry): number {
|
|
37
|
+
if (chemistry === 'lihv') return 4.35;
|
|
38
|
+
if (chemistry === 'liion') return 4.2;
|
|
39
|
+
if (chemistry === 'life') return 3.65;
|
|
40
|
+
return 4.2;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function calculateClaimedCurrent(capacitymAh: number, claimedCRating: number): number {
|
|
44
|
+
if (capacitymAh <= 0 || claimedCRating <= 0) return 0;
|
|
45
|
+
return (capacitymAh / 1000) * claimedCRating;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function calculateRealisticCRating(internalResistanceMOm: number, claimedC: number, capacitymAh: number): number {
|
|
49
|
+
if (internalResistanceMOm <= 0 || capacitymAh <= 0) return claimedC;
|
|
50
|
+
const capacityAh = capacitymAh / 1000;
|
|
51
|
+
const maxThermalAmps = Math.sqrt(18 / (internalResistanceMOm / 1000));
|
|
52
|
+
const maxThermalC = Math.round(maxThermalAmps / capacityAh);
|
|
53
|
+
return Math.min(claimedC, Math.max(10, maxThermalC));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function calculateTotalPeakDraw(motorCount: number, peakMotorCurrentA: number, auxCurrentA: number): number {
|
|
57
|
+
const motors = Math.max(0, motorCount);
|
|
58
|
+
const perMotor = Math.max(0, peakMotorCurrentA);
|
|
59
|
+
const aux = Math.max(0, auxCurrentA);
|
|
60
|
+
return motors * perMotor + aux;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function calculateVoltageSag(totalPeakDrawA: number, internalResistanceMOm: number, cellCount: number): number {
|
|
64
|
+
if (totalPeakDrawA <= 0 || internalResistanceMOm <= 0 || cellCount <= 0) return 0;
|
|
65
|
+
const packResistanceOm = (internalResistanceMOm / 1000) * cellCount;
|
|
66
|
+
return totalPeakDrawA * packResistanceOm;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function calculateFlightTimeSeconds(capacitymAh: number, currentA: number): number {
|
|
70
|
+
if (capacitymAh <= 0 || currentA <= 0) return 0;
|
|
71
|
+
return (capacitymAh / 1000 / currentA) * 3600 * 0.8;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function evaluateSafetyStatus(realisticMaxCurrentA: number, totalPeakDrawA: number): SafetyStatus {
|
|
75
|
+
if (totalPeakDrawA <= 0) return 'optimal';
|
|
76
|
+
const burstCapacityA = realisticMaxCurrentA * 1.8;
|
|
77
|
+
if (totalPeakDrawA <= realisticMaxCurrentA * 1.1) return 'optimal';
|
|
78
|
+
if (totalPeakDrawA <= burstCapacityA) return 'warning';
|
|
79
|
+
return 'danger';
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function calculateVoltagesAndRuntimes(inputs: BatteryInputs, totalPeakDrawA: number, voltageSagV: number) {
|
|
83
|
+
const nominalTotalV = getNominalCellVoltage(inputs.chemistry) * inputs.cellCount;
|
|
84
|
+
const fullTotalV = getFullyChargedCellVoltage(inputs.chemistry) * inputs.cellCount;
|
|
85
|
+
const sagNominalVoltageV = Math.max(0, nominalTotalV - voltageSagV);
|
|
86
|
+
const sagFullVoltageV = Math.max(0, fullTotalV - voltageSagV);
|
|
87
|
+
const flightTimeFullThrottleSec = calculateFlightTimeSeconds(inputs.capacitymAh, totalPeakDrawA);
|
|
88
|
+
const flightTimeHoverSec = calculateFlightTimeSeconds(inputs.capacitymAh, Math.max(1, totalPeakDrawA * 0.25));
|
|
89
|
+
return { sagNominalVoltageV, sagFullVoltageV, flightTimeFullThrottleSec, flightTimeHoverSec };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function calculateBatteryMetrics(inputs: BatteryInputs): BatteryCalculationResults {
|
|
93
|
+
const claimedMaxCurrentA = calculateClaimedCurrent(inputs.capacitymAh, inputs.claimedCRating);
|
|
94
|
+
const realisticCRating = calculateRealisticCRating(inputs.internalResistanceMOm, inputs.claimedCRating, inputs.capacitymAh);
|
|
95
|
+
const realisticMaxCurrentA = (inputs.capacitymAh / 1000) * realisticCRating;
|
|
96
|
+
const totalPeakDrawA = calculateTotalPeakDraw(inputs.motorCount, inputs.peakMotorCurrentA, inputs.auxCurrentA);
|
|
97
|
+
const voltageSagV = calculateVoltageSag(totalPeakDrawA, inputs.internalResistanceMOm, inputs.cellCount);
|
|
98
|
+
const sub = calculateVoltagesAndRuntimes(inputs, totalPeakDrawA, voltageSagV);
|
|
99
|
+
const burstRatingRequired = inputs.capacitymAh > 0 ? (totalPeakDrawA / (inputs.capacitymAh / 1000)) : 0;
|
|
100
|
+
const safetyStatus = evaluateSafetyStatus(realisticMaxCurrentA, totalPeakDrawA);
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
claimedMaxCurrentA,
|
|
104
|
+
realisticCRating,
|
|
105
|
+
realisticMaxCurrentA,
|
|
106
|
+
totalPeakDrawA,
|
|
107
|
+
voltageSagV,
|
|
108
|
+
...sub,
|
|
109
|
+
burstRatingRequired,
|
|
110
|
+
safetyStatus,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { SEORenderer } from '@jjlmoya/utils-shared';
|
|
3
|
+
import { droneBatteryCRatingCalculator } from './entry';
|
|
4
|
+
import type { KnownLocale } from '../../types';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
locale?: KnownLocale;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const { locale = 'en' } = Astro.props;
|
|
11
|
+
const loader = droneBatteryCRatingCalculator.i18n[locale] || droneBatteryCRatingCalculator.i18n.en;
|
|
12
|
+
const content = await loader?.();
|
|
13
|
+
if (!content) return null;
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
{content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { BatteryInputs } from './logic';
|
|
2
|
+
|
|
3
|
+
const STORAGE_KEY = 'jjl_drone_lipo_c_rating_inputs';
|
|
4
|
+
|
|
5
|
+
export function loadSavedInputs(): Partial<BatteryInputs> {
|
|
6
|
+
try {
|
|
7
|
+
const raw = localStorage.getItem(STORAGE_KEY);
|
|
8
|
+
if (!raw) return {};
|
|
9
|
+
return JSON.parse(raw) as Partial<BatteryInputs>;
|
|
10
|
+
} catch {
|
|
11
|
+
return {};
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function saveInputs(inputs: BatteryInputs): void {
|
|
16
|
+
try {
|
|
17
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify(inputs));
|
|
18
|
+
} catch {}
|
|
19
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface DroneBatteryCRatingCalculatorUI {
|
|
2
|
+
[key: string]: string;
|
|
3
|
+
title: string;
|
|
4
|
+
subtitle: string;
|
|
5
|
+
lipoSpecsHeader: string;
|
|
6
|
+
capacityLabel: string;
|
|
7
|
+
claimedCRatingLabel: string;
|
|
8
|
+
cellCountLabel: string;
|
|
9
|
+
chemistryLabel: string;
|
|
10
|
+
internalResistanceLabel: string;
|
|
11
|
+
quadSpecsHeader: string;
|
|
12
|
+
motorCountLabel: string;
|
|
13
|
+
peakMotorCurrentLabel: string;
|
|
14
|
+
auxCurrentLabel: string;
|
|
15
|
+
presetSelectLabel: string;
|
|
16
|
+
customPreset: string;
|
|
17
|
+
whoopPreset: string;
|
|
18
|
+
freestyle5Preset: string;
|
|
19
|
+
cinewhoopPreset: string;
|
|
20
|
+
longRange7Preset: string;
|
|
21
|
+
racing5Preset: string;
|
|
22
|
+
resultsHeader: string;
|
|
23
|
+
claimedMaxCurrentLabel: string;
|
|
24
|
+
realisticCRatingLabel: string;
|
|
25
|
+
realisticMaxCurrentLabel: string;
|
|
26
|
+
totalPeakDrawLabel: string;
|
|
27
|
+
voltageSagLabel: string;
|
|
28
|
+
sagNominalVoltageLabel: string;
|
|
29
|
+
flightTimeFullThrottleLabel: string;
|
|
30
|
+
flightTimeHoverLabel: string;
|
|
31
|
+
safetyStatusLabel: string;
|
|
32
|
+
statusOptimalTitle: string;
|
|
33
|
+
statusOptimalDesc: string;
|
|
34
|
+
statusWarningTitle: string;
|
|
35
|
+
statusWarningDesc: string;
|
|
36
|
+
statusDangerTitle: string;
|
|
37
|
+
statusDangerDesc: string;
|
|
38
|
+
lipoVisualizerTitle: string;
|
|
39
|
+
cellVoltageLabel: string;
|
|
40
|
+
batteryHealthLabel: string;
|
|
41
|
+
burstRatingRequiredLabel: string;
|
|
42
|
+
currentRatioLabel: string;
|
|
43
|
+
}
|