オールインワン太陽光発電ハブ: 充電コントローラー、インバーター、モバイルバッテリー、LEDライト
部品と材料
| Microchip Technology ATmega8 | ×1 |
| バックコンバーター | ×1 |
| SparkFun 3W アルミニウムPCB LED (5個パック、暖白色) | ×1 |
| Nokia 5110 ディスプレイ | ×1 |
| SparkFun ヒートシンク | ×1 |
| SparkFun Nチャネル MOSFET | ×4 |
| SparkFun Pチャネル MOSFET | ×1 |
| ソーラーパネル 40W以下 (12Vシステム用) | ×1 |
| SparkFun リチウムイオン電池 18650セル | ×1 |
| DC-DC 0.9V-5V to USB モジュール 5V DC ブーストステップアップ電源 | ×1 |
| 汎用NPNトランジスタ | ×1 |
| 12-0-12/220 センタータップトランス | ×1 |
| 1N4007 高耐圧・大電流ダイオード | ×1 |
| ピンヘッダー 36ピン 1列 ロング (0.1インチ) | ×1 |
| スライドスイッチ | ×1 |
| SparkFun プッシュボタンスイッチ 12mm | ×1 |
| Arduino Proto Shield | ×1 |
| ストリップ/ベロ/プロト基板 8×11cm | ×1 |
| Arduino UNO | ×1 |
| Arduino Nano R3 | ×1 |
| Arduino Mega 2560 | ×1 |
| 低順方向電圧ショットキーダイオード 5822 | ×1 |
| コンデンサ 10µF | ×1 |
| コンデンサ 100nF | ×1 |
必要な工具と機械
| はんだごて(汎用) |
| ドリルモーター |
| ホットグルーガン(汎用) |
アプリとオンラインサービス
| Arduino IDE |
| AutoDesk 123D |
このプロジェクトについて
このプロジェクトについて
いくつかのソーラーパネル、12Vバッテリー、トランスなどが手元にあり、それらを有効活用したくてこのデバイスを作りました。単一ボード上の完全な小型PVソリューションです。まず各機能の役割を確認しましょう:
- 充電コントローラー: 太陽光パネルからDC蓄電池/バッテリーへの充電と、負荷によるバッテリー放電を制御し、バッテリー寿命を延ばすデバイス
- インバーター: DC電力をAC電力に変換してAC負荷を動作させるデバイス
- モバイルバッテリー: USBポートから5V DCを供給し、ガジェット/モバイルデバイスを携帯充電やオフグリッド充電
- 非常用ライト: 停電時、キャンプ、日没後の屋外活動で使える超高輝度LED光源
このデバイスにはこれらすべての機能があり、最後の2機能(モバイルバッテリーと非常用ライト)はオンボードのリチウムイオン電池で独立して動作します。ソーラーパネル(最大100W)、12V鉛酸バッテリー、トランスがあればすべての機能を利用できます。
Uno上のプロトタイプ版
最初の版はUnoボード上で最小限のハードウェアと機能で開発しました。Nokiaディスプレイを直接取り付け、MOSFETシールドでバッテリーの充放電を制御。メニュー操作なし、インバーターなし、PWM充電なしとクールな機能はなし!単純な充電オン/オフとバッテリー/パネル電圧表示のみ。機能はするが魅力に欠けます。
プロト基板上のフル機能版
以下の機能を持つ新版を開発しました:
- 最大100Wパネル対応 PWMソーラー充電コントローラー
- 60W矩形波ミニインバーター
- 最大3系統の12V DC負荷制御
- プライマリDC負荷の自動オン/オフ機能対応
- 独立したUSBモバイルバッテリー
- バックレギュレーターモジュール
- 点滅と輝度調整付きオンボードLEDライト
2つのボタン/スイッチでスクロールと選択によるメニュー操作、Nokia 5110ディスプレイでオプションとステータス表示。裏面はホットグルーで絶縁し、金属物とのショートを防止!
ディスプレイバックライトのオン/オフスイッチ、バックコンバーターを内部バッテリーから切り離して独立動作可能にするスイッチなど、便利な機能も追加。
Nokia 5110ディスプレイでのメニュー操作:
技術的な仕組みを学ぼう!
充電コントローラーにはオン/オフ型、PWM型、MPPT型があります。オン/オフ型が最もシンプル(私のバージョン1)で、バッテリー電圧が満充電近くになっても充電電流を絞りません。
一方PWM型は、バッテリーが満充電に近づくにつれて充電電流を徐々に減らします。PWMコントローラーの利点:
- 失われたバッテリー容量の回復と脱硫酸化
- バッテリーの受け入れ容量向上
- 平均バッテリー容量を95%まで維持
- 内部セルの電位差を均等化
- バッテリー発熱とガス発生を抑制、電解液損失防止
- 劣化を遅らせシステム寿命を延長
しかしPWMはパネルをバッテリー電圧近くで動作させるため、PVパネルから最大電力を取り出せません。MPPTはこの問題の解決策で、基本的にDC-DC可変昇降圧コンバーターであり、PWMより多くの太陽光発電を変換できます。
インバーターには矩形波、修正正弦波、純正弦波があります。矩形波インバーターは設計が最もシンプルで、ACランプ、蛍光灯、卓上扇風機、はんだごてなど小型DC負荷には十分ですが、誘導モーターや精密機器/電源には高調波歪みのため推奨しません。
修正正弦波は矩形波から作られる擬似正弦波で、単純な矩形波より良好。純正弦波インバーターはあらゆる負荷に最適ですが、ハードウェア設計が複雑で、ソフトウェアアルゴリズムも難しく、コストも高いです。
バックレギュレーターは降圧DC-DCコンバーターで、ここではパネルから電力を取って4.2Vリチウムイオン電池(コントローラーArduino+ディスプレイ、独立モバイルバッテリー、オンボードLEDライトの電源)を充電するバックモジュールを使用しています。
USBモバイルバッテリーは基本的にDC-DCブーストで、リチウムイオン/リチウムポリマー電池の3.3〜4.2V範囲をUSBバス電圧の5Vに昇圧してモバイルデバイスを充電します。バッテリー充電用のバックコンバーターも内蔵。このプロジェクトではバックモジュールがパネルから少し電力を取ってオンボードバッテリーを充電します。
ハードウェアの動作原理
デバイス周りのすべての接続を示す画像:
システムには様々な目的のハードウェアがあります。もちろん頭脳はAVR ATmega8Aマイコン(ATmega328Pでも微修正で使用可能、後述)で、Arduinoでプログラミングされています。
新品のATmega8AにArduino Optiboot8ブートローダーを書き込み。ブートローダー書き込み済みのArduino Mini/ATmega328を購入すれば手間を省けます。
コントローラー、ディスプレイ、LEDライト、モバイルバッテリーはオンボードリチウムイオン電池で駆動。2つのモーメンタリタッチボタンでディスプレイのメニューにアクセスし、デバイスの各機能を操作。スイッチは平滑コンデンサを並列接続してハードウェアデバウンス。スライドスイッチでデバイスの電源オン/オフ。
ソーラー充電機能は、2N2222トランジスタ駆動回路で駆動されるP-MOSFETをマイコンからのPWMで制御して実現。PWMは外部バッテリー電圧レベルに基づいて制御。ソーラーパネルからの電流はP-MOSFETを通って鉛酸バッテリーへ。バッテリーが満充電になるとマイコンからMOSFETをオフ。充電停止後バッテリー電圧が徐々に下がり、13.6Vに達すると低デューティサイクルでフロート充電を再開。
12V DC負荷はN-MOSFETで制御し、そのゲートをマイコンから制御。
オンボードLEDライトもN-MOSFETで駆動、ゲートをPWM制御して輝度調整。
インバーターブロックは2つのN-MOSFETを交互にオン/オフしてACを模擬。外付けセンタータップトランスを追加して矩形波AC出力を実現。
インバーター動作の説明:
ステップアップトランスのセンタータップを通る電流をMOSFETで交互に上向き/下向きに流すことで、二次側にAC電圧を生成。トップMOSFETオン/ボトムMOSFETオフで電流は上向き、逆で下向きに流れます。
両MOSFETはAC周波数の2倍でトグルする必要があります。50Hz ACを作るには、12-0-12V/220Vセンタータップトランスの低圧側に交互の矩形波を印加。50Hzは1波形20ms。したがって20ms/2 = 10ms、つまり100回/秒でインバーター駆動MOSFETのゲート信号をトグル。
警告!!!: AC電圧は人体に致死的です。死傷の恐れあり!トランスの高圧側には決して素手で触れないでください!
インバーター機能を使わない場合、「2XDC負荷」オプションでインバーター端子をさらに2系統の12V DC負荷として使用可能。
ソフトウェアの魔法
コードは2セット提供:単一Arduinoタブにまとめたフルコード、機能別にタブ分けしたコード。
タスク群を単一関数に一般化しています。例:
Get_ADCVal(): パネル、内部バッテリー、外部バッテリー電圧を測定、20サンプル平均を取って電圧変数を更新Context_Control(): ユーザー操作、アクション制御、ディスプレイ情報更新などCharging_Control(),Discharging_Control(),Load_Control(): システムのクローズドループとしてバックグラウンド動作。バッテリー電圧監視、自動負荷制御、過充電/過放電保護など
ユーザー入力は割り込み駆動のモーメンタリプレススイッチで取得。スイッチ押下でINT0/INT1関連ISR実行。揮発性変数dp と dsが変化。第3変数levelとdp(ディスプレイポインタ)、ds(ディスプレイコンテンツセレクター)でメニュー/サブメニューを移動しアクション実行。
AVRの16ビットTimer1を設定し、インバーター機能オン時に10msごとにTimer Overflow割り込み発生、PIN_INVPとPIN_INVNをフリップ。
すべてのLcd_...()関数はディスプレイ制御関連。
ATmega8A vs ATmega328P (Uno)
以下の変更でATmega328P/Unoに容易に移植可能。検索置換:
TIMSK → TIMSK1
#define ADC_VREF 2.69 → #define ADC_VREF 1.11
#define ADCVDIV_R1 22 → #define ADCVDIV_R1 8.2
ハードウェアでは22kΩの代わりに8.2kΩ抵抗を使用してパネル/バッテリー電圧をADC測定範囲にスケーリング。
アクション動画
私はプロジェクトについて文字だけでなく動画で確認する派です。同類の方は動画をお楽しみください。
改善の余地
ATmega8Aのフラッシュ容量が尽きたため、以下の重要機能を追加できませんでした:
- ソフトウェア制御過負荷/短絡保護
- グラフィカルアイコンとロゴ
- エネルギー測定とログ記録
- バックアップ時間の推定とアラーム
- ノートPC充電オプション
- 6Vシステム対応
- Bluetooth負荷制御
- タイマーベース負荷制御
- 更なるクール機能のためのRTCクロック
- IoT接続ソリューション
- etc.
こうしたプロジェクトを作る予定なら、これらの機能追加を検討してください!ATmega328P(Uno)やArduino Megaなら全機能搭載に適しています。ともかく仕事はこなせますし、私は満足しています。
追加リソース
- ATmega8ボードサポート付きArduino 1.0.6をダウンロード
- Arduino.exeを開き、ツール > ボード > Optiboot8 を選択
- この方法でブートローダー書き込み
- コードをコンパイルしてアップロード
コード
単一タブコード Arduino
#define PIN_SCE 12
#define PIN_RESET 13
#define PIN_DC 8
#define PIN_SDIN 7
#define PIN_SCLK 6
#define PIN_INVP 4
#define PIN_INVN 5
#define PIN_LOAD 9 // 12v dc load
#define PIN_LAMP 10 // WHITE LED LIGHT
#define PIN_BATTPWM 11 // Drives PMOS for Ext BAtt Charging
#define PIN_BATTint_Sense A2
#define PIN_SOLAR_Sense A0
#define PIN_BATText_Sense A3
#define ADC_VREF 2.695 // internal ref voltage, around 1.11V for Arduino Uno aka Atmega328P, here my Atmega8A gives this !
#define ADCVDIV_R1 22 // 22 K voltage divider lower Resistor
#define ADCVDIV_R2 175 // 175 K voltage divider upper Resistor
//const uint8_t skulljoke[] PROGMEM ={2,} ; // PIN 2 & 3 USED AS INTERRUPT SWITCH
// PIN 0 & 1 AS PROGRAMMING
// PIN RESET AS
#define LCD_C LOW
#define LCD_D HIGH
#define LCD_X 84
#define LCD_Y 48
uint8_t x=0;
uint8_t level=0;
uint8_t blinker=0;
boolean Load_Auto_Enable=0;
float maxADC_Voltage=0.0;
float BattInt_Voltage=0.0;
float BattExt_Voltage=0.0;
float PV_Voltage=0.0;
volatile int y=0;
volatile uint8_t dp =0;
volatile uint8_t ds =0;
volatile boolean cycle=0;
volatile uint8_t cdc_level =0;
void setup(void) {
LcdInitialise();
LcdClear();
LcdString("*ARDUBOY PV*");
LcdString(" CONTROLLER,");
LcdString("AC INVERTER,");
LcdString("POWER BANK, ");
LcdString("LAMP THING!!");
delay(3000);
analogReference(INTERNAL);
maxADC_Voltage=(ADC_VREF/ADCVDIV_R1)*(ADCVDIV_R1+ADCVDIV_R2);
pinMode(PIN_LOAD,OUTPUT);
digitalWrite(PIN_LOAD,LOW);
pinMode(2, INPUT_PULLUP);
attachInterrupt(0, SW1, FALLING);// Interrupt for Switch 1
pinMode(3, INPUT_PULLUP);
attachInterrupt(1, SW2, FALLING);// Interrupt for Switch 2
}
void loop(void) {
Get_ADCVal();
Context_Control();
Charging_Control();
Discharging_Control();
Load_Control();
LcdClear();
}
///////////// ADC ///////////////
void Get_ADCVal(void) {
int I=0, J=0, K=0;
for(x=0;x<20;x++) {
I=I+analogRead(PIN_BATTint_Sense);
J=J+analogRead(PIN_BATText_Sense);
K=K+analogRead(PIN_SOLAR_Sense);
}
BattInt_Voltage=I/20.0;
BattExt_Voltage=J/20.0;
PV_Voltage=K/20.0;
BattInt_Voltage=maxADC_Voltage*BattInt_Voltage/1023.0;
BattExt_Voltage=maxADC_Voltage*BattExt_Voltage/1023.0;
PV_Voltage=maxADC_Voltage*PV_Voltage/1023.0;
}
//////////// Display and Control //////////////
void Context_Control(void) {
if(ds==0) {show_menu();}
if(ds==1 && dp == 0) {show_info(); delay(100);}
// 1st Sub Menu
if(ds==1 && dp == 1) {
level=1; dp=0;
while(level==1) {
int temp=ds;
LcdClear(); show_load_ctrl(); delay(250);
if (dp==0){ if(ds!=temp){Load_Auto_Enable=0;digitalWrite(PIN_LOAD,LOW);}}
if (dp==1){if(ds!=temp){Load_Auto_Enable=0; digitalWrite(PIN_LOAD,HIGH);}}
if (dp==2){ if(ds!=temp){Load_Auto_Enable=1;}}
if (dp==3){show_load_ctrl();delay(250);level=0;dp=0;ds=0;}
}
}
// 2nd Sub Menu
if(ds==1 && dp == 2) {
level=2; dp=0;
while(level==2) {
int temp=ds;
show_inv_ctrl();delay(250); LcdClear();
if (dp==0){ if(ds!=temp){Timer1_Init();}}
if (dp==1){ if(ds!=temp){Timer1_DeInit();}}
if (dp==2){ if(ds!=temp){Timer1_DeInit();digitalWrite(PIN_INVP,1);digitalWrite(PIN_INVN,1);}}
if (dp==3){show_inv_ctrl();delay(250);level=0;dp=0;ds=0;}
}
}
// 3rd Sub Menu
if(ds==1 && dp == 3) {
level=3; dp=0;
while(level==3) {
int temp=ds;
LcdClear(); show_led_ctrl();delay(250);
if (dp==0){blinker=0;if(ds!=temp) {if(y<=255){y=y+15;analogWrite(PIN_LAMP,y);}}}
if (dp==1){blinker=0;if(ds!=temp) {if(y>=0){y=y-15;analogWrite(PIN_LAMP,y);}}}
if (dp==2){if(ds!=temp) {blinker^=1;analogWrite(PIN_LAMP,127);delay(250);analogWrite(PIN_LAMP,0);}}
if (dp==3){show_led_ctrl();delay(250);level=0;dp=0;ds=0;}
}
}
if(blinker==1) {analogWrite(PIN_LAMP,0);}
delay(250);
if(blinker==1) {analogWrite(PIN_LAMP,127);}
}
// メニュー表示関数群
void show_menu(void) {
LcdXY(0,dp); LcdString("->");
LcdXY(15,0); LcdString("Sys Info");
LcdXY(15,1); LcdString("DC Load+");
LcdXY(15,2); LcdString("AC Load~");
LcdXY(15,3); LcdString("LED Lamp");
}
void show_info(void) {
LcdXY(0,0); LcdString("Bat_I="); LcdNumtoString(BattInt_Voltage); LcdString("v");
LcdXY(0,1); LcdString("Bat_E="); LcdNumtoString(BattExt_Voltage); LcdString("v");
LcdXY(0,2); LcdString("Sol_P="); LcdNumtoString(PV_Voltage); LcdString("v");
LcdXY(0,3);
if(BattExt_Voltage >8.0) {LcdString("Batt Conn OK");} else {LcdString("Connect Batt");}
if (PV_Voltage > 10.5 && cdc_level!=3 && cdc_level!=0) {LcdString("Charging:ON ");} else {LcdString("Charging:OFF");}
if (TCNT1 >=45535 ) {LcdString("Inverter:ON");} else {LcdString("Inverter:OFF");}
}
void show_load_ctrl(void) {
LcdXY(0,dp); LcdString("->");
LcdXY(15,0); LcdString("Load Off");
LcdXY(15,1); LcdString("Load On");
LcdXY(15,2); LcdString("Load Auto");
LcdXY(15,3); LcdString("Return");
LcdXY(0,4); LcdString("Must Connect");
LcdString("12V DC Load");
}
void show_inv_ctrl(void) {
LcdXY(0,dp); LcdString("->");
LcdXY(15,0); LcdString("AC Inv On");
LcdXY(15,1); LcdString("AC Inv Off");
LcdXY(15,2); LcdString("2XDC Load");
LcdXY(15,3); LcdString("Return");
LcdXY(0,4); LcdString("2XDC Load,NO");
LcdXY(0,5); LcdString("TRANSFORMER!");
}
void show_led_ctrl(void) {
LcdXY(0,dp); LcdString("->");
LcdXY(15,0); LcdString("LED ++");
LcdXY(15,1); LcdString("LED --");
LcdXY(15,2); LcdString("LED Blk");
LcdXY(15,3); LcdString("Return");
LcdXY(0,4); LcdString("LED DISABLEs");
LcdXY(0,5); LcdString("When INVR On");
}
// 割り込みISR
void SW1() { dp++; if(dp>3){dp=0;} }
void SW2() { ds^=1; }
ISR(TIMER1_OVF_vect) {
noInterrupts();
TCNT1 = 45535;
cycle^=1;
if(cycle==0) {
digitalWrite(PIN_INVP,HIGH);
delayMicroseconds(1);
digitalWrite(PIN_INVN,LOW);
delayMicroseconds(1);
}
if(cycle==1) {
digitalWrite(PIN_INVP,LOW);
delayMicroseconds(1);
digitalWrite(PIN_INVN,HIGH);
delayMicroseconds(1);
}
interrupts();
}
// Nokia 5110 関数群
static const byte ASCII[][5] = {
{0x00, 0x00, 0x00, 0x00, 0x00}, // 20
{0x00, 0x00, 0x5f, 0x00, 0x00}, // 21 !
// ... (省略)
{0x78, 0x46, 0x41, 0x46, 0x78} // 7f
};
void LcdCharacter(char character) {
LcdWrite(LCD_D, 0x00);
for (int index = 0; index < 5; index++) {
LcdWrite(LCD_D, ASCII[character - 0x20][index]);
}
LcdWrite(LCD_D, 0x00);
}
void LcdClear(void) {
for (int index = 0; index < LCD_X * LCD_Y / 8; index++) {
LcdWrite(LCD_D, 0x00);
}
}
void LcdInitialise(void) {
pinMode(PIN_SCE, OUTPUT);
pinMode(PIN_RESET, OUTPUT);
pinMode(PIN_DC, OUTPUT);
pinMode(PIN_SDIN, OUTPUT);
pinMode(PIN_SCLK, OUTPUT);
digitalWrite(PIN_RESET, LOW);
digitalWrite(PIN_RESET, HIGH);
LcdWrite(LCD_C, 0x21);
LcdWrite(LCD_C, 0xA0);
LcdWrite(LCD_C, 0x04);
LcdWrite(LCD_C, 0x14);
LcdWrite(LCD_C, 0x20);
LcdWrite(LCD_C, 0x0C);
}
void LcdString(char *characters) {
while (*characters) { LcdCharacter(*characters++); }
}
void LcdWrite(byte dc, byte data) {
digitalWrite(PIN_DC, dc);
digitalWrite(PIN_SCE, LOW);
shiftOut(PIN_SDIN, PIN_SCLK, MSBFIRST, data);
digitalWrite(PIN_SCE, HIGH);
}
void LcdXY(int x,int y) {
LcdWrite(LCD_C,0x80|x);
LcdWrite(LCD_C,0x40|y);
}
void LcdNumtoString(float number) {
char string[8];
LcdString(dtostrf(number,5,2, string));
}
// バックグラウンド制御関数
void Load_Control(void) {
if (Load_Auto_Enable == 1 && PV_Voltage < 4.5 && cdc_level > 0) {digitalWrite(PIN_LOAD,HIGH);}
if (Load_Auto_Enable == 1 && (PV_Voltage >10.5 || cdc_level==0)) {digitalWrite(PIN_LOAD,LOW);}
}
void Charging_Control (void) {
if (PV_Voltage > 10.5 && BattExt_Voltage >8.0) {
if (BattExt_Voltage <= 12.5) { analogWrite(PIN_BATTPWM,255); cdc_level = 0; }
else if (BattExt_Voltage <=12.9) { analogWrite(PIN_BATTPWM,200); cdc_level = 1; }
else if (BattExt_Voltage <=13.3) { analogWrite(PIN_BATTPWM,160); cdc_level = 1; }
else if (BattExt_Voltage <=13.6) { analogWrite(PIN_BATTPWM,120); cdc_level = 2; }
else if (BattExt_Voltage <=13.9 && cdc_level == 2) { analogWrite(PIN_BATTPWM,80); cdc_level = 2; }
else if (BattExt_Voltage <=14.3 && cdc_level == 2) { analogWrite(PIN_BATTPWM,40); cdc_level = 2; }
// 過電圧ロックアウト
if (BattExt_Voltage > 14.3) { analogWrite(PIN_BATTPWM,0); cdc_level = 3; }
} else { analogWrite(PIN_BATTPWM,0); cdc_level = 3; }
}
void Discharging_Control (void) {
if (BattExt_Voltage <= 10.8) {
cdc_level = 0;
digitalWrite(PIN_LOAD,LOW);
Timer1_DeInit();
}
}
// Timer1 関数
void Timer1_Init(void) {
noInterrupts();
pinMode(PIN_INVP,OUTPUT);
pinMode(PIN_INVN,OUTPUT);
TCCR1A = 0; TCCR1B = 0;
TCNT1 = 45535;
TCCR1B |= (1 << CS11); // 8分周
TIMSK |= (1 << TOIE1); // オーバーフロー割り込み有効
interrupts();
}
void Timer1_DeInit(void) {
noInterrupts();
TCCR1A = 0; TCCR1B = 0; TCNT1 = 0;
digitalWrite(PIN_INVP,LOW);
digitalWrite(PIN_INVN,LOW);
interrupts();
}
整理されたフルコード C/C++
コードは整理済みで可読性良好(ダウンロードのみプレビューなし)
ブートローダー C/C++
ダウンロードのみプレビューなし
回路図
製造プロセス
- ハロゲンランプ:技術、歴史、そして未来——専門家の視点
- ラバランプ:歴史、設計、製造の秘密
- ソーラー暖房システム:パッシブからアクティブまで、持続可能な住宅暖房ソリューション
- 集積回路(IC):現代エレクトロニクスを支える微小強力チップ
- 太陽電池:初期実験から現代フォトボルタイクスまで
- スマート信号機:IoTで実現する適応型街路灯
- DIY Arduino USBゲームコントローラー - 高性能ゲームパッドを自作
- DIYクラウドコスチューム: LEDストリップ、Arduino Nano & SparkFunパーツで光る雲に
- ソーラートラッカー V2.0 – 高度なDIYソーラーパネル追尾システム
- 太陽エネルギー活用ガイド:クリーンで信頼性の高い電力へ
- ソーラーインバーターとは?太陽光発電を利用可能な電力に変換する仕組み