[C#]Chartコントロールを使用して、タスクマネージャー風のグラフを作成する

VisualStudioの2010ではグラフを表示するために、Chartコントロールというものが追加されています。
このコントロールを使用すると、手軽にグラフを作成する事が出来るのですが、デフォルトのプロパティ値ではデザインがいまいちなグラフが出来上がってしまいます。

コントロールをフォームに貼った直後のデザインは、以下のような感じになっています。



今回は、Chartコントロールを使用して、主に見た目に関するプロパティを確認しつつ、
Windowsのタスクマネージャー風のグラフを作成してみました。


[今回作成したプログラムによるグラフの表示]

情報を見える形にする技術


今回のサンプルプログラムです。
まずは、チャートの初期化処理です。

private void initChart( Chart chart ) {         
 
    // チャート全体の背景色を設定
    chart.BackColor = Color.Black;
    chart.ChartAreas[0].BackColor = Color.Transparent;
 
    // チャート表示エリア周囲の余白をカットする
    chart.ChartAreas[0].InnerPlotPosition.Auto = false;
    chart.ChartAreas[0].InnerPlotPosition.Width  = 100; // 100%
    chart.ChartAreas[0].InnerPlotPosition.Height = 90;  // 90%(横軸のメモリラベル印字分の余裕を設ける)
    chart.ChartAreas[0].InnerPlotPosition.X      = 8;
    chart.ChartAreas[0].InnerPlotPosition.Y      = 0;
 
 
    // X,Y軸情報のセット関数を定義
    Action<Axis> setAxis = (axisInfo) => {
        // 軸のメモリラベルのフォントサイズ上限値を制限
        axisInfo.LabelAutoFitMaxFontSize = 8;
 
        // 軸のメモリラベルの文字色をセット
        axisInfo.LabelStyle.ForeColor = Color.White;
 
        // 軸タイトルの文字色をセット(今回はTitle未使用なので関係ないが...)
        axisInfo.TitleForeColor       = Color.White;
 
        // 軸の色をセット
        axisInfo.MajorGrid.Enabled    = true;
        axisInfo.MajorGrid.LineColor  = ColorTranslator.FromHtml("#008242");
        axisInfo.MinorGrid.Enabled    = false;
        axisInfo.MinorGrid.LineColor  = ColorTranslator.FromHtml("#008242");
    };
 
    // X,Y軸の表示方法を定義
    setAxis( chart.ChartAreas[0].AxisY );
    setAxis( chart.ChartAreas[0].AxisX );
    chart.ChartAreas[0].AxisX.MinorGrid.Enabled = true;
    chart.ChartAreas[0].AxisY.Maximum = 100;    // 縦軸の最大値を100にする
 
    chart.AntiAliasing = AntiAliasingStyles.None;
 
    // 折れ線グラフとして表示
    chart.Series[0].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastLine;
    // 線の色を指定
    chart.Series[0].Color = ColorTranslator.FromHtml( "#00FF00" );
 
    // 凡例を非表示,各値に数値を表示しない
    chart.Series[0].IsVisibleInLegend   = false;    
    chart.Series[0].IsValueShownAsLabel = false;
 
    // チャートに表示させる値の履歴を全て0クリア
    while ( countHistory.Count <= MAX_HISTORY ) {
        countHistory.Enqueue( 0 );
    }
}



上記の初期化処理は、実際にはGUIからプロパティの指定を行っても問題ありませんが、今回は説明のためにコードから設定しています。
それでは、メソッド内の処理を順に確認してきます。



// チャート全体の背景色を設定
chart.BackColor = Color.Black;
chart.ChartAreas[0].BackColor = Color.Transparent;


まずは、背景を黒にします。chart.BackColorで背景色が指定できますが、これを黒にするだけでは、下記のようにグラフ表示エリアの周囲だけが黒くなってしまいます。


グラフの表示エリア内も同じ色にする為にchart.ChartAreasの背景色を透明にすると、下記のように全体が黒くなります。




// チャート表示エリア周囲の余白をカットする
chart.ChartAreas[0].InnerPlotPosition.Auto = false;
chart.ChartAreas[0].InnerPlotPosition.Width  = 100; // 100%
chart.ChartAreas[0].InnerPlotPosition.Height = 90;  // 90%(横軸のメモリラベル印字分の余裕を設ける)
chart.ChartAreas[0].InnerPlotPosition.X      = 8;
chart.ChartAreas[0].InnerPlotPosition.Y      = 0;


次に、グラフを表示している周囲の余白を微調整します。
下記の赤枠の部分です。


今回の例では、縦横軸のメモリ数値を表示させるため、HeightとXに余白を残しました。これをもし、Width,Heightを100にして、X,Yを共に0にすると完全に余白が無くなり、以下のような表示となります。




// X,Y軸情報のセット関数を定義
Action<Axis> setAxis = (axisInfo) => {
    // 軸のメモリラベルのフォントサイズ上限値を制限
    axisInfo.LabelAutoFitMaxFontSize = 8;
 
    // 軸のメモリラベルの文字色をセット
    axisInfo.LabelStyle.ForeColor = Color.White;
 
    // 軸タイトルの文字色をセット(今回はTitle未使用なので関係ないが...)
    axisInfo.TitleForeColor       = Color.White;
 
    // 軸の色をセット
    axisInfo.MajorGrid.Enabled    = true;
    axisInfo.MajorGrid.LineColor  = ColorTranslator.FromHtml("#008242");
    axisInfo.MinorGrid.Enabled    = false;
    axisInfo.MinorGrid.LineColor  = ColorTranslator.FromHtml("#008242");
};
 
// X,Y軸の表示方法を定義
setAxis( chart.ChartAreas[0].AxisY );
setAxis( chart.ChartAreas[0].AxisX );



次に、縦横軸の表示を変更します。
縦軸と横軸で同じ処理をする箇所が多いので、共通部を無名関数のsetAxis()として定義してしまいます。

この処理を実行する事で、グリッドの線が緑色で、メモリ数値の文字が白色になりました。




chart.ChartAreas[0].AxisX.MinorGrid.Enabled = true;
chart.ChartAreas[0].AxisY.Maximum = 100;    // 縦軸の最大値を100にする


縦軸と横軸で個別の設定を行います。
見栄え向上のため、横軸側は補助メモリのグリッドを追加します。
また、縦軸はCPU負荷を想定して、メモリの最大値を100にしてみました。




chart.AntiAliasing = AntiAliasingStyles.None;


軸メモリの数値にアンチエイリアスを掛けないようにします。



// 折れ線グラフとして表示
chart.Series[0].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastLine;
// 線の色を指定
chart.Series[0].Color = ColorTranslator.FromHtml( "#00FF00" );


グラフを折れ線にし、緑色で表示させます。
だいぶタスクマネージャーのグラフっぽくなってきました。




// 凡例を非表示
chart.Series[0].IsVisibleInLegend   = false;


最後に、右上に表示されている凡例を非表示します。
これで、デザインの指定は完了です。





次は、グラフの描画処理です。

//***************************************************************************
/// <summary> チャートを描画する
/// </summary>
/// <param name="chart"></param>
//***************************************************************************
private void showChart( Chart chart ) {
 
    //-----------------------
    // チャートに値をセット
    //-----------------------
    chart.Series[0].Points.Clear();
    foreach( int value in countHistory ) {
 
        // データをチャートに追加
        chart.Series[0].Points.Add( new DataPoint( 0, value ) );   
    }
}


こちらは、コレクションに登録されている値を全部chartコントロールに追加しなおしているだけなので簡単です。
上記の例では、countHistoryコレクションに入っている変数を全てAdd()しなおしていますが、新規データを取得の都度Add()し、チャートに表示させる履歴件数を一定にしたい場合はAdd()した後RemoveAt()で最初の要素を削除させても、タスクマネージャ風の最新履歴をスクロールさせる様なグラフが作成できます。



最後に、上記2メソッドの呼び出し側を作ります。
今回はCPU負荷をタイマーで表示させています。

// 取得データの履歴
const int MAX_HISTORY  = 40;
Queue<int> countHistory = new Queue<int>();
 
// CPU使用率の取得用カウンタ
PerformanceCounter pc = new PerformanceCounter("Processor", "% Processor Time", "_Total", true);
 
public Form1() {
    InitializeComponent();
 
    // チャートの表示を初期化
    initChart( chart1 );
 
    // 1秒周期でチャートを再描画
    timer1.Interval = 1000;
    timer1.Enabled = true;
 
}
 
//***************************************************************************
/// <summary>   タイマー処理
///             CPU負荷を一定周期で取得する
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
//***************************************************************************
private void timer1_Tick( object sender, EventArgs e ) {
    //---------------------------------
    // CPUの使用率を取得し、履歴に登録
    //---------------------------------
    int value = (int)pc.NextValue();
    countHistory.Enqueue( value );
 
    //------------------------------------------------
    // 履歴の最大数を超えていたら、古いものを削除する
    //------------------------------------------------
    while ( countHistory.Count > MAX_HISTORY ) {
        countHistory.Dequeue();
    }
 
    //------------------------------------------------
    // グラフを再描画する
    //------------------------------------------------
    showChart( chart1 );
}





以上で、今回のプログラム作成は完了です。
プログラムを実行し、タスクマネージャの表示と並べてみました。(画像クリックで拡大します)




データビジュアライゼーションのデザインパターン20 混沌から意味を見つける可視化の理論と導入

[C#]パフォーマンスカウンタから取得した値の履歴を,一定件数覚えておく

Windowsに標準で搭載されているコントロールパネルやパフォーマンスモニタでは、PCの現在の状態を表示しつつ、グラフで一定時間(直近30sec分など)の履歴を表示しているものがあります。
このような表示方法だと、現在の状況を確認しつつデータが増加・減少傾向のどちらにあるのかの、トレンドも同時に把握する事ができるので便利です。


[コントロールパネルによるCPU負荷履歴の表示]


今回は、パフォーマンスカウンタから値を取得し、その履歴を一定件数覚えておく処理を作成します。

以下が、今回のサンプルコードです。

// 取得データの履歴
const int MAX_HISTORY  = 40;
Queue<int> countHistory = new Queue<int>();
 
// CPU使用率の取得用カウンタ
PerformanceCounter pc = new PerformanceCounter("Processor", "% Processor Time", "_Total", true);
 
 
//***************************************************************************
/// <summary>   タイマー処理
///             CPU負荷を一定周期で取得する
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
//***************************************************************************
private void timer1_Tick( object sender, EventArgs e ) {
 
    //---------------------------------
    // CPUの使用率を取得し、履歴に登録
    //---------------------------------
    int value = (int)pc.NextValue();
    countHistory.Enqueue( value );
 
    //------------------------------------------------
    // 履歴の最大数を超えていたら、古いものを削除する
    //------------------------------------------------
    while ( countHistory.Count > MAX_HISTORY ) {
        countHistory.Dequeue();
    }
 
    //------------------------------------------------
    // グラフを再描画する
    //------------------------------------------------
    showChart( chart2 );
}





それでは、サンプルのコードを順に確認していきます。


まずは、履歴を覚えておく領域の確保です。

const int MAX_HISTORY  = 40;
Queue<int> countHistory = new Queue<int>();



一定のデータを覚えておくために、System.CollectionsパッケージにあるQueueクラスを利用します。
Queueは、最新のデータをEnqueue()で登録しておき、一方で最も古いデータをDequeue()するだけで破棄出来るため、今回の目的には最適です。

また、Queueに何件分の履歴を覚えておくかを,MAX_HISTORYの定数に定義しておきます。



次は、パフォーマンスカウンタからの値取得です。

// CPU使用率の取得用カウンタ
PerformanceCounter pc = new PerformanceCounter("Processor", "% Processor Time", "_Total", true);



パフォーマンスカウンタからの値を取得には、System.DiagnosticsパッケージのPerformanceCounterクラスを利用します。
上記の例では、CPUの使用率を取得しています。PerformanceCounterのコンストラクタ引数に何を指定できるかは、perfmon.exeを実行し、カウンターの追加ダイアログを表示する事で簡単に確認できます。


また、今回の例では省略されていますが、PerformanceCounterをnewした際は、使用後にpc.Dispose()をコールして、リソースの開放を行う必要があります。



データの保存先と取得元が確保できたら、次はデータの取得処理です。

private void timer1_Tick( object sender, EventArgs e ) {
 
    //---------------------------------
    // CPUの使用率を取得し、履歴に登録
    //---------------------------------
    int value = (int)pc.NextValue();
    countHistory.Enqueue( value );
 
    //------------------------------------------------
    // 履歴の最大数を超えていたら、古いものを削除する
    //------------------------------------------------
    while ( countHistory.Count > MAX_HISTORY ) {
        countHistory.Dequeue();
    }
}



データの取得には、今回Timerコントロールを使用します。

PerformanceCounterからは短時間でデータ取得が可能なのでTimerで十分ですが、データ取得に時間が掛かる場合(外部デバイスから値を取る等)は、データ取得中に画面を操作する事ができなくなる為、操作性が悪くなってしまいます。このような場合は、BackgroundWorkerコントロールを利用を検討します。



int value = (int)pc.NextValue();


パフォーマンスカウンタからのデータ取得はNextValue()のメソッドをコールするだけです。
NextValue()メソッドの初回の呼び出しでは、必ず0を返す仕様となっているため、このオブジェクトをデータ計測の度にnewしてしまうと期待する値が取得できない事に注意してください。



countHistory.Enqueue( value );


取得した値は、Queue#Enqueue()を利用してキューに追加しておきます。



while ( countHistory.Count > MAX_HISTORY ) {
    countHistory.Dequeue();
}


Enqueueしただけでは、時間と共に履歴情報が膨大になってしまいメモリを消費するので、一定量を超えた分は破棄します。今回のサンプルコードだけを見ると、この処理はwhileではなくifでも十分なように見えますが、プログラムのバグにより、本処理以外で誤って値がEnqueueされてしまった場合でもキューの情報が肥大化しないようにしています。


データの取得をタイマー処理で行い一定件数の履歴を保存しているので、上記例の場合、タイマーを1秒おきに実行すれば直近40秒分の履歴が取れる事になります。

上海問屋で売っているDC12V対応な単三・単四の充電器(16本版)の仕様

ソーラー発電を自作したので、DC12Vで動くモノを探していたところ、以下の商品を発見しました。
大量のニッケル水素電池を一気に充電できる充電器です。


放電機能 USB充電ポート搭載 充電器 (16本用) :単三・単四 ニッケル水素充電池対応 DN-67992

上記のページを見ると、シガーソケットで充電できる事は分かるのですが、
消費電力等の詳細な仕様が載っていません。



仕様を販売元に問い合わせたのですが、上海問屋側でもいまいち把握出来てないようだったので、
調べてみたところ海外のmegabatteriesというサイトでOEM品っぽいものを見つけました。

画像を見比べる分かるのですが、色以外は全く同じ形ですし、specを見ても上海問屋のページに記載されている範囲の情報とも一致しているようです。

おそらく中身は同じだと思われるので、この商品の仕様を転記しておきます。
(http://www.megabatteries.com/item_details2.asp?id=17283&cat1=&uid=1305 より)

16 Slot Titanium AA/AAA Fast Battery Charger with LCD Display
 
Charger Specifications:
    Input: 100 - 240 VAC 50/60Hz
    Output: 12V DC 1.3 amp
 
 
Features:
    Charges 1 - 16 pieces of size AAA and AA NiMH or NiCD Rechargeable Batteries
    LCD Display - 16 Respective LCD Indicators Showing Charging Status for each Slot.
    Short Circuit Protection
    Discharge Function allows you to refresh batteries before charging
    Identifies Defective Cells
    Intelligent microprocessor controlled.
    Negative delta V (- delta V) cut-off function.
    Reverse Polarity Protection
    Fail Safe Timer & Thermal Protection Charge Termination
    Safety Timer - Prevents Batteries from Over Charging
    Integrated USB ports - Plug in your portable MP3 players, phones, 
                           iPods and iPhones into the charger's USB ports
    100 - 240 volt Universal AC Adapter
    CE & ETL certified. RoHs & FCC Compliant
    Brand: Titanium
    DC Car Charger included
 
 
Charge Times:
    AAA 800 - 1200mAh -> 4 to 6 hours
    AA 1500 - 2900mAh -> 4 to 7 hours



消費電力はDC12Vで1.3Aなので、15Wぐらいのようです。




でもって、さらに調べてみると製造元は台湾の企業、Samya Technology Co Ltd.が作っているらしく、
元品番はMD-1600っぽいです。


こちらの仕様は以下の通り。
(http://samya.appliances-china.com/Product_Look.php?ID=132585 より)

Offer Category: Audio & Video Appliances  -  Battery Charger
Model: MD-1600
 
Key Specifications/Special Features:
    Charges 1 to 16 AA/AAA size Ni-MH batteries
    16 independent charging channel
    Unique discharge function
    Input: AC 100-240V or DC 12-24V
    Output: 1.4V/500mA, USB model 5V/500mA
    LCD indicators:
        Icon light off: no battery
        Icon flashing up: charging
        Icon full: finish
        Icon full flashing: error
        Icon flashing down: discharging
        Safety protection: short circuit protection, over-current protection, 
        reverse polarity protection, alkaline dection, safety timer
    Available color: black, white, gray
    Weight: 357g
    Dimension: 280(L) x 108(W) x 30(H)mm
    Application: digital camera, remote car, wireless mouse/keyboard, wii controller, children toy


こちらを見ても、電池が1.4V * 0.5A * 16本で、 USBが 5V*0.5A*2口、合計で16.2Wとなり、やはり同程度の消費電力です。
電池だけだと、11Wぐらいでしょうか。








あと、上海問屋では、上記商品のほかに12本の同時充電が可能な商品も売っています。

単三・単四 充電池対応 放電機能付き充電器(12本用):液晶表示で充電状況がわかりやすい!


これはamazon.comでオリジナルが売っており、Tenergy社のTN160です。

こちらのスペックは以下の通り。

Tenergy TN160 12-Bay battery charger pushes the envelope & adds even more charging slots to 
allow better charging efficiency.
Not just any other standard Volume charger – 12 battery charging capabilities in addition to 
a full range of essential features and more!
 
Whether you have a family with abundant toys & devices, or a business with a higher quantity 
charging requirement we highly recommend this heavy duty Tenergy TN160 charger. 
With a full array of safety features it is safe for both home & industrial use.
 
 
Features and Benefits:
    12 channels PWM switching fast charger with MUC control; its accurate voltage detection 
    ensures no over-charging and under-charging.
 
    Built-in IC and advanced Delta-V charging control function.
 
    12 independent charging channels for individual charging and detection: AA & AAA, 
   NIMH/ NICD can be mixed when charging. The battery can be placed at any channel of the charger.
 
    Suitable only for1.2v AA/AAA NIMH/NICD batteries.
 
    Constant current charging mode with –ΔV detection, ensures fast charging.
 
    Easy to use: simply connect the adaptor to charger, plug charger into household electric 
  outlet and insert battery into the battery compartment. Charger will start charging automatically.
 
    Large LCDs indicate charging status.
 
    Charger comes with refresh function.
 
    DC adaptor with wide AC input voltage 100-240V, designed for worldwide usage.
 
 
Safety Features:
    8 hour safety timer
    over-heat
    over-current
    short-circuit
    reverse polarity protection
 
    *Note: Don't charge Alkaline Batteries. 
           Only compatible with AA & AAA NiMH/NiCD Batteries.
 
Includes:
    Tenergy TN160 12-Bay AA/AAA NiMH/NiCd Battery Charger
    Packaging: Blister card
 
Specifications:
    Input: AC 100V~240V 50HZ/60HZ
    Output: 12V DC 1500mA
    Weight: 17.9 oz
    Dimensions: 240x120x23mm
    Color: White & Black


pdfのマニュアルはこちら

この商品にはシガーソケットは付いてないのですが、pdfの仕様を見るとチャージャー側の入力仕様がDC9-15V,2Aになっているので、シガーソケットのコネクタだけ自作すればDC12Vでも充電できそうな感じです。



AC100V用の充電器は複数持っているのですがインバーター経由だとロスもあるし、充電電池を使う事が多いので、買ってしまおうか検討中です…




放電機能 USB充電ポート搭載 充電器 (16本用) :単三・単四 ニッケル水素充電池対応
DN-67992

[C#]Listから最初のn件のデータだけ処理する

Listに登録したデータから、最初のn個だけを残して他は削除したい場合は
RemoveRange()メソッドを利用します。

int n = 10;
 
List<string> dataList = new List<string>();
if ( lstTest.Count > n ) {
	dataList.RemoveRange( n, dataList.Count - n );
}





また、リストの中身を書き換えずにn件目までのデータだけをループで処理したい場合は
LINQで用意されているTake()メソッドを使用すると便利です。

using System.Linq;
 
foreach ( string data in dataList.Take( n ) ) {
	Console.WriteLine( data );
}



Take()を利用して、最初のn件ではなく最後のn件をとりたい場合は、シーケンスをひっくり返します。

dataList.Reverse<string>().Take( n );


CとC++の非互換性:文字リテラルのサイズ

最近知った豆知識です。


CとC++で、以下のコードを実行したときの結果は異なります。

printf( "%d", sizeof('A') );



実行してみると、Cでは4が表示され、C++だと1となります。

理由は、C言語の仕様上文字リテラルはintとみなされ、C++ではcharとみなされるから。


以下、仕様より

An integer character constant has type int. 
 
The value of an integer character constant containing a single character 
that maps to a single-byte execution character is the numerical value of 
the representation of the mapped character interpreted as an integer.


ANSI C section6.4.4.4



A character literal is one or more characters enclosed in single quotes, as in 'x'


Programming languages C++(ISO/IEC 14882) 2.13.2


ちなみに、C言語では”文字定数(character constant)、C++では文字リテラル(character literal)。

[Windows]メモリエリア関係の用語まとめ(System.Diagnostics.Processクラス)

System.Diagnostics.Processにあるメモリ関係のプロパティを見ていたら、よく分からなくなってきたので、整理を兼ねてメモしておく。

メモリ


プロセスが使用しているメモリには、OSが管理するメモリ領域と、プログラムが使用するメモリ領域の2つがある。


OSが使用するメモリ領域


OSが使用するメモリ領域には、ページング化なエリアと、不可なエリアが存在する。

Process.NonpagedSystemMemorySize: ページングされないシステム メモリの量
Process.PagedSystemMemorySize   : ページング可能なシステム メモリの量



作成したプログラムのリソースリークを監視する際、このメモリはアプリから管理不可能な領域なので、
一般的には見なくて良い(はず)。



プログラムが使用するメモリ領域


プログラムが使用するメモリ領域はページング可能
プログラムが使用するメモリ領域は、プログラム側からは仮想アドレス空間として認識できる。

ページングの観点からメモリを見ると、仮想アドレスサイズ(Process.VirtualMemorySize)には以下の2つが存在する。

1.ページングファイル    (Process.PagedMemorySize)
2.物理メモリ




ワーキングセット


物理 RAM メモリ内でプロセスが現在参照できるメモリページのセットのこと。
ワーキングセットは物理メモリ上に存在していて、このデータを参照するときにページ フォルトを起こすことはない。
ワーキング セットのメモリは、使用されているメモリとは限らない(直前まで使用可能だったが、GCされて無い領域も含む)

ワーキングセット(Process.WorkingSet)は、以下の2つで構成される

1.共有データ
2.プライベート データ (Process.PrivateMemorySize)




共有データには、プログラムのコード等が含まれている
プライベートデータは、変数の値などの複数のプロセスで共有できない情報が入っている。


※ちなみに、VirtualMemorySize = PagedMemorySize + WorkingSetではないので注意。
(実測して確認した結果では、2つの和よりVirtualMemorySizeの方が大きかった)


プログラムが使用したメモリ領域の最大値


以下のメモリサイズのhighwatermark値はシステム側で監視しているので、それぞれ取得する事が可能。

Process.PagedMemorySize   の最大値  -> Process.PeakPagedMemorySize
Process.VirtualMemorySize の最大値  -> Process.PeakVirtualMemorySize
Process.WorkingSet        の最大値  -> Process.PeakWorkingSet

[C#]自前でToString()メソッドを実装時に気をつけるべき9つの事

C#では、ObjectクラスがToString()メソッドを持っているため、全てのオブジェクトがこのメソッドを継承しています。.NetFrameworkで用意されているクラスでは、ToString()をコールする事で有用な情報が帰ってくるのですが、自作のクラスではクラス名が分かる程度で役に立つ情報は有りません。


自前でToString()メソッドをオーバーライドしておくと、開発・デバッグが非常に捗りますが、そのときに注意すべき点が幾つかあります。

ToString() メソッド内で例外を発生させない
また、オブジェクトの内部状態に情報がセットされていない場合でも、空文字列やnullを返さないようにする。
 
 
ToString()の出力結果に改行文字を含めない
出力された文字列はログファイルに吐き出される場合もあるので、改行が含まれると問題が出る場合がある
 
 
返される文字列は、オブジェクトの内部状態を表現したものにする
但し、内部状態の情報が膨大になる場合は要約する事も検討する
※要約したくない場合IFormattableクラスを利用し、結果を出し分けるのも良い
 
 
パスワード等の、セキュリティ上問題がある情報をオブジェクトが保持している場合、
生データをそのまま出力させない
 
 
デバッグ目的で使われる事が多いので、人が見て分かりやすい形式で出力する
 
 
ToString(string, format)メソッドのオーバーロード行う場合は、
実行環境の言語に応じた出力を行う(特に,日付の表記法などに注意)
 
 
ToString()でしか取得できない情報を作らないようにする
これは、クラスの利用者がToString()の戻り値を解析して情報をとろうとするのを防ぐ為
 
 
ToString()をコールする事でオブジェクトの内部状態に副作用が起きないようにする
 
 
各インスタンスごとに異なる値が返るにすることを検討する






C#でToStringをオーバーライドする場合は、以下の形式でメソッドの定義を行います

public override string ToString() {
	...
}






また、ReShaperというプラグインを使用すると、Alt-Insを押すだけでToString()メソッドを実装してくれます。
オープンソースのプログラム作成や教育目的なら、無償で利用可能です(商用利用は有償です)
ReShaper

[C#]Windowsで実行中のサービス一覧と、起動状態を取得する

.Net Frameworkを使用して、Windowsで稼働中のサービス一覧を取得するにはSystem.ServiceProcessパッケージのServiceControllerクラスを使用します。

下記のコードで、全サービス一覧の列挙と、サービスの起動状態を取得できます。

static void Main( string[] args ) {
    //---------------------
    // サービス一覧を取得
    //---------------------
    System.ServiceProcess.ServiceController[] controllerList;
    controllerList = ServiceController.GetServices();
 
    //-------------------------------
    // 取得した全サービスを列挙する
    //-------------------------------
    foreach( ServiceController controller in controllerList ) {
 
        // サービスの起動状況を取得
        string statusName;
        switch( controller.Status ) {
            case ServiceControllerStatus.ContinuePending:
                statusName = "保留中";
                break;
            case ServiceControllerStatus.Paused:
                statusName = "一時中断";
                break;
            case ServiceControllerStatus.PausePending:
                statusName = "一時中断の保留中";
                break;
            case ServiceControllerStatus.Running:
                statusName = "実行中";
                break;
            case ServiceControllerStatus.StartPending:
                statusName = "開始中";
                break;
            case ServiceControllerStatus.Stopped:
                statusName = "停止";
                break;
            case ServiceControllerStatus.StopPending:
                statusName = "停止中";
                break;
            default:
                statusName = "不明";
                break;
        }
 
        // サービス名と、起動状態を出力する
        System.Console.WriteLine( "------------------------------------------" );
        System.Console.WriteLine( controller.ServiceName );
        System.Console.WriteLine( "    名称: " + controller.DisplayName );
        System.Console.WriteLine( "    状態: " + statusName );
 
    }
}




このプログラムを実行すると、以下のようにサービス一覧が表示されます。

[PHP]htmlからxmlに変換する関数群 : html2xml

phpでスクレイピングしたい時、htmlからxmlへの変換方法をいつも調べるので、
備忘録代わりに変換関数を作成しました。

この手の変換は、作るプログラムによって元ネタがurlだったりhtml文字列だったりします。
また変換先もxmlテキストが欲しいときやDOMDocumentが欲しいなど様々です。
という訳で、冗長ですが全パターン用意しました。

変換パターンによっては、中身がPHPの関数1行だけというラッパーになっている場合も有りますが、網羅しておいたほうが一覧性が良いかと思い、あえて用意しています。


変換可能なパターンは以下通りです。

url        -> html文字列
url        -> DOMDocumentオブジェクト
url        -> xml文字列
 
html文字列 -> DOMDocumentオブジェクト
html文字列 -> xml文字列
 
DOMDocumentオブジェクト -> xml文字列




変換の関数群です。

#****************************************************************
# 指定されたurlの内容をhtml文字列として返す
#****************************************************************
function url2html( $url ) {
    return file_get_contents( $url );
}
 
#****************************************************************
# html文字列をDOMDocumentオブジェクトとして返す
#****************************************************************
function html2xmldoc( $html ) {
    $xmlDoc = new DOMDocument('1.0', 'UTF-8');
 
    $xmlDoc->preserveWhiteSpace = false;
    @$xmlDoc->loadHTML($html);
    return $xmlDoc;
}
 
#****************************************************************
# DOMDocumentオブジェクトをxml文字列として返す
#****************************************************************
function xmldoc2xml( $xmldoc ) {
    return $xmldoc->saveXML();
}
 
#****************************************************************
# 指定されたurlの内容をDOMDocumentオブジェクトとして返す
#****************************************************************
function url2xmldoc( $url ) {
    $html   = file_get_contents( $url );
 
    $xmlDoc = new DOMDocument('1.0', 'UTF-8');  
    $xmlDoc->preserveWhiteSpace = false;
    @$xmlDoc->loadHTML($html);
 
    return $xmlDoc;
}
 
#****************************************************************
# 指定されたurlの内容をxml文字列として返す
#****************************************************************
function url2xml( $url ) {
    $html   = url2html( $url );
    $xmlDoc = html2xmldoc( $html );
    $xml    = xmldoc2xml( $xmlDoc );
    return $xml;
}
 
#****************************************************************
# html文字列をxml文字列として返す
#****************************************************************
function html2xml( $html ) {
    $xmlDoc = html2xmldoc( $html );
    $xml    = xmldoc2xml( $xmlDoc );
    return $xml;
}




htmlをDOMDocumentオブジェクトに変換後、xpathでスクレイピング出来ます。
下記の例では、googleよりキーワード”scraping”で検索し、リンクの一覧(aタグに含まれるhref属性)を出力しています。

$url = "http://www.google.co.jp/#q=scraping";
 
$xml = simplexml_import_dom( url2xmldoc( $url ));
$nodeList = $xml->xpath( "//a" );
 
foreach ($nodeList as $node) {
    echo $node["href"] . "\n";
}




2012/5/31追記:
変換元のhtmlがS-JISだった場合は、DOMDocumentクラスのloadHTML()メソッドで、文字化けしてしまうため、変換がうまくいきません。このような場合は、以下のように2回に分けて変換します。

$html = mb_convert_encoding( url2html( $url ), "HTML-ENTITIES", "SJIS" );
$xml  = simplexml_import_dom( html2xmldoc( $html ));


[C#]WebBrowserコントロールを使用して、指定したサイト全体の画像を取得(DLL化しました)

WebBrowserコントロールを使用して、プログラムから指定したサイト全体の画像を取得します。

サンプルコードは、以下の通り。

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Runtime.InteropServices.ComTypes;
 
namespace SiteCaptureSharp {
    //*************************************************************************
    /// <summary> Webサイトの画像イメージキャプチャ処理を管理します
    /// </summary>
    //*************************************************************************
    public class CaptureManager {
        [DllImport("ole32.dll")]
        private static extern int OleDraw( IntPtr pUnk, int dwAspect, IntPtr hdcDraw, ref Rectangle lprcBounds );
 
        //*********************************************************************
        /// <summary> 指定されたWebサイトをbitmap画像として取得する
        /// </summary>
        /// <param name="url">キャプチャ対象のサイトURL</param>
        /// <returns>         ページの画像</returns>
        //*********************************************************************
        public static Bitmap getBitmapFromUrl(string url ) {
            bool   isCaptured = false;
            Bitmap bitmap = null;
 
            //------------------------------------------------
            // Webサイト情報取得用のブラウザコントロールを作成
            //------------------------------------------------
 
            WebBrowser browser = new WebBrowser();
            browser.ScrollBarsEnabled      = false;
            browser.ScriptErrorsSuppressed = true;
 
            //---------------------------------------------
            // 指定URLへNavigate()完了時のハンドラを登録
            //---------------------------------------------
            browser.DocumentCompleted += (sender, e) => {
                if ( e.Url.Equals( "about:blank" ) ) {
                    return;
                }
 
                try {
                    // キャプチャサイズを指定
                    browser.Width  = browser.Document.Body.ScrollRectangle.Width;
                    browser.Height = browser.Document.Body.ScrollRectangle.Height;
 
                    // キャプチャの保存先bitmapを生成
                    bitmap = new Bitmap( browser.Width, browser.Height );
 
                    // 生成したbitmapにWebページの画像を保存
                    Graphics graphic = null;
                    IntPtr   ptrObj  = IntPtr.Zero;
                    IntPtr   ptrHdc  = IntPtr.Zero;
                    try {
                        graphic = Graphics.FromImage( bitmap );
                        ptrHdc  = graphic.GetHdc();
                        ptrObj  = Marshal.GetIUnknownForObject( browser.ActiveXInstance );
                        Rectangle rect = new Rectangle(0, 0, browser.Width, browser.Height );
 
                        // ptrObj画像内のrectで指定した領域を,HDCのエリアに貼付
                        OleDraw( ptrObj, (int)DVASPECT.DVASPECT_CONTENT, ptrHdc, ref rect );
                    } finally {
                        if ( ptrObj != IntPtr.Zero ) {
                            Marshal.Release( ptrObj );
                        }
                        if ( ptrHdc != IntPtr.Zero ) {
                            graphic.ReleaseHdc( ptrHdc );
                        }
                        if ( graphic != null ) {
                            graphic.Dispose();
                        }
                    }
                } finally {
                    isCaptured = true;
                }
            };
 
            //------------------------------------------------
            // 指定されたページへ遷移       
            //------------------------------------------------
            browser.Navigate( url );
            while( !isCaptured ) {
                // 指定URLのロード&キャプチャが完了するのを待つ
                Application.DoEvents();
                System.Threading.Thread.Sleep( 20 );
            }
 
            // 取得したbmp情報を返す
            return bitmap;
        }
    }
}



通常、WinFormで指定したコントロールの画像が欲しい場合は、Control.DrawToBitmap()で取得可能なのですが、WebBrowserコントロールは、ページによってはこのメソッドで画像が取れない場合がある為、Win32APIのOleDraw()を使用しています。



また、呼び元側は以下のような感じです。
シンプルに、1行でbitmapオブジェクトが取得できます。

Bitmap bitmap = SiteCaptureSharp.CaptureManager.getBitmapFromUrl( "http://www.yahoo.co.jp/" );
if ( bitmap != null ) {
    bitmap.Save( "c:\\test.bmp" );
}





DLL版も作ったので、DLLだけ欲しい場合はこちらのページからダウンロードしてください。
CaptureManagerは、前述のメソッドがひとつだけ存在する、シンプルなクラスです。

コマンドラインから,指定したURLのページ全体の画像を保存する

特定のWebサイトの内容全体を、コマンドラインからjpgファイルとして取得したかったのですが、
やりたい事を実現できそうなソフトが無さそうだったので、自作してみました。


例えば、以下のコマンドを実行すると…

CaptureSiteToJpg.exe /url http://www.yahoo.co.jp/ /out yahoo.jpg



このように、ページ全体の画像をjpgファイルとして取得する事が出来ます。
縦に長いページでも、途中で切れる事はありません。



また、この機能を実装するに当たり、画像取得処理をDLLとして切り出しました。
自分のプログラムで同様のことを行いたい場合は、DLL版を使用してくださいませ。
(DLL版のサンプルコードはこちらを参照してください)

コマンドラインプログラム、DLL共にソースコードつきです。


ダウンロード:
CaptureSiteToJpg.exe
DLL(と,ソースコード一式)

[C#]WebBrowserコントロール使用時、”Webページへのナビゲーションは取り消されました”エラーが出る時は?

WebBrowserコントロールを使用してNavigate()でサイトにアクセスした時、
“Webページへのナビゲーションは取り消されました”エラーが出る時があります。


その原因は多分…、指定したURLが間違ってます。
(例えば、http://www.yahoo.co.jp/ではなく、http://wwww.yahoo.co.jp/を指定したとか…)


初歩的なミスですが、気づかずにしばらく悩んでしまったので、備忘録としてのメモです。

[C#]現在のスレッドはシングル スレッド アパートメントでないため… エラーが出たときの対処法

コンソールアプリで、WinFormのコントロールを使用すると以下の例外が発生します。

System.Threading.ThreadStateException はハンドルされませんでした。
  Message=現在のスレッドはシングル スレッド アパートメントでないため、ActiveX コントロール 'xxxx' をインスタンス化できません。
  Source=System.Windows.Forms
  StackTrace:
       場所 Program.Main(String[] args) 場所 Program.cs:行 33
       場所 System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       場所 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       場所 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       場所 System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       場所 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       場所 System.Threading.ThreadHelper.ThreadStart()
  InnerException:





この場合の対処法は、Mainメソッドの上に,[STAThread]を追加しシングルスレッドアパートメントである事を明示させます。

static void Main( string[] args ) {
    ...
}


    ↓

[STAThread]
static void Main( string[] args ) {
    ...
}

[C#]ファイルを削除した時に、ゴミ箱へ移動させる

C#(.Net Framework)のプログラムから、ファイルを削除したときゴミ箱に移動させる方法です。

C#では、System.IO.File.Delete()メソッドでファイルの削除を行う事が可能ですが、この方法ではファイルがゴミ箱に移動される事無く、いきなり削除されてしまいます。削除ではなくゴミ箱への移動を行いたい場合は、FileSystemクラスのDeleteFile()メソッドを使用します。


FileSystemクラスは、Microsoft.VisualBasic.FileIOパッケージに登録されているのですが、
標準では使用できないため、参照設定でSystem.Printing(Microsoft.VisualBasic.dll)を追加します。



パッケージの追加を行ったら、以下のコードでファイルをゴミ箱に移動させる事ができます。

string fileName = "c:\\temp\\test.txt";
 
try {
    // FileSystemクラスは Microsoft.VisualBasic.FileIOパッケージ
    FileSystem.DeleteFile( fileName,
                           Microsoft.VisualBasic.FileIO.UIOption.AllDialogs,
                           Microsoft.VisualBasic.FileIO.RecycleOption.SendToRecycleBin );
 
} catch ( System.IO.FileNotFoundException ex ) {
    System.Console.WriteLine( "削除対象ファイルが存在しません:" + ex.Message );
 
} catch ( OperationCanceledException ex ) {
    System.Console.WriteLine( "削除がキャンセルされました:" + ex.Message );




プログラムを実行すると、以下のように削除確認のダイアログが表示されます。


このダイアログを表示させたくない場合は、DeleteFile()の第二引数をOnlyErrorDialogsにします。

また、第三引数でSendToRecycleBinの替わりに、DeletePermanentlyを指定する事でゴミ箱に移動させずにファイルを削除する事も可能です。この場合は、File.Delete()メソッドと同じような振る舞いとなります。

[C#]プリンタ一覧と、デフォルトプリンタを取得するには

C#(.Net Framework)のプログラムから、プリンタ一覧とデフォルトプリンタを取得する方法です。


.Net Frameworkでプリンタの情報を取得するには、System.Printingパッケージを使用します。
System.Printingパッケージは標準では使用できないため、以下のように、参照設定でSystem.Printingを追加する必要があります。



パッケージの追加を行ったら、以下のコードでシステムに登録されているプリンタ情報が取得できます

private void button1_Click( object sender, EventArgs e ) {
    textBox1.Text = "";
 
    //-------------------------------
    // デフォルトプリンタを取得する
    //-------------------------------
    PrintQueue defaultPrinter = new LocalPrintServer().DefaultPrintQueue;
 
    //-------------------------------------------
    // PCに登録されているプリンタを全て列挙する
    //-------------------------------------------
    foreach (PrintQueue queue in ( new PrintServer() ).GetPrintQueues() ) {
 
        // プリンタ名を取得する
        string printerName = queue.FullName;
 
        // 処理しているプリンタがデフォルトの時は、その事を通知
        if ( printerName.Equals ( defaultPrinter.FullName ) ) {
            printerName += " [デフォルトプリンタ]";
        }
 
        // プリンタ名を出力
        textBox1.AppendText( printerName + Environment.NewLine );
    }
}




プログラムを実行してみた結果が、以下の画面になります。



プリンタのプロパティで確認したプリンタ一覧と見比べると、正しくプリンタの情報が取得できている事が分かります。



ソーラー発電システムの自作 その3(チャージコントローラ)

前回までの記事で、ソーラーパネル側、バッテリー側の準備がそれぞれ出来ました。
ソーラー発電の自作用に,パネルを購入しました
ソーラー発電システムの自作 その2(バッテリー側)

今回は、両者を接続する事にします。


ソーラーパネル接続の仕組み

ソーラーパネルとバッテリの接続ですが、仕組み上は、ソーラーパネルからの端子をバッテリーに直結することは一応可能です(実際に30分ほど直結してみましたが、ちゃんと充電してくれました)。

ですが、それだと電気を使わない日が続くとバッテリーが過充電状態になってしまいます。また、雨の日が続いて充電が出来ていないのに電気を消費し続けてしまうと、今度は逆に過放電の状態になります。
ですので、ソーラーパネルとバッテリを直結して利用する場合は、日々バッテリーの電圧を測って、過充電や過放電が発生しない、適正な蓄電量になっている事を確認しなければなりません。


チャージコントローラー

前述のような形で、常に電圧を監視するのは、運用が非常に面倒です。
なので、通常はチャージコントローラーという機器を使用します。

チャージコントローラーは上記の過充電、過放電の管理を行ってくれます。
バッテリが十分に充電されている時は、パネルから給電されているときでも電気的に回路をカットする事で過充電を防いでくれます。また、バッテリ容量が残り少なくなると、強制的に電気の供給をカットしてくれます(そうなると、もちろん電化製品を使用することは出来なくなります)。


また、高価格なチャージコントローラーだと、上記の機能に加え、MPPT(Maximum Power Point Tracking)という仕組みで充電効率をアップしてくれます。
ソーラーパネルは天気によって発電量が異なるため、バッテリ直結すると、発電した電気を常に効率よく充電できるわけではなく、ロスが発生します。MPPT機能に対応したコントローラは、その辺をうまいことやってくれる事で、発電した電気を最大の効率でバッテリに充電できるようコントロールしてくれます。
これによって、同じパネルを使用していてもより多くの電気を充電可能となります。

MPPT対応のコントローラは価格が高くなるのですが、パネルの設置には場所をとることもあり、物理的な制約がある場合が多いため、ここはコストを掛けてもMPPTに対応したコントローラを購入した方が、後々の事を考えると良いです。



で、今回購入したコントローラは、以下の商品です。

OEM品が、楽天オークションで安く売っていたので(8000円ぐらい)、オークションで手に入れました。
オークションに出ていない場合は、同じものが楽天より上記のショップでも販売しています。

このコントローラの仕様は以前調べた事があるので、詳しく知りたい人は下記のページを確認してください。チャージコントローラMPPT10シリーズ(MPPT30,MPPT60,WS-MPPT30,SE-MPPT30 etc…)の機能説明



このコントローラの接続端子は、被覆を向いた電線を直接はめ込んだ後、ドライバーでネジを締めこむタイプでした。バッテリとコントローラ間は追加で線が必要となる為、ホームセンターで4sqの太さの電線を買ってきて接続しました。40cmの切り売りで、数百円(200円ぐらい)で買えます。

接続時の注意点としては、バッテリーを先に接続してから、その後でソーラーパネルを接続することぐらいで、非常に簡単です。この辺もコントローラによって異なるので、違うコントローラを使う場合はマニュアルを熟読する必要があります。

コントローラは6本の電線をつなぐ必要があり、左からソーラーパネル、バッテリー、負荷(シガーソケット)をそれぞれ接続します。


接続し終わると、無事動作してくれました。


静止画だと分かりませんが、CHARGEのランプが点滅しMPPT機能を利用して充電が行われます。

また、シガーソケット(負荷側)から電気を使いすぎると、BATTERYのランプが赤くなり、電気の供給が遮断される事も確認しました。

ソーラー発電システムの自作 その2(バッテリー側)

前回、ソーラーパネル側の準備が終わったので、次は室内側の仕組みづくりです

ソーラーパネルで発電した電気はバッテリーに蓄電したいのですが、いきなり仕組みを全部作ると問題があったときに切り分けが面倒になります。
なので、まずは簡単なバッテリーとLEDのライトを用意し、バッテリーからライトを点灯出来るようにしておきます。



バッテリー

最初に用意するのはバッテリーです。
バッテリーは、12Vの自動車用鉛蓄電バッテリーを使用します。

今回は、不要なバッテリーを貰う事が出来たので、これを使用する事にしました。



シガーソケット


バッテリーにLEDライトを直結しても良いのですが、それだと拡張性が無いので5口のシガーソケットを経由させることにします。こうしておくと、車向けの電気製品をそのまま使えるので便利です。


このような感じで、途中にON/OFFの切り替えスイッチがあるものです。




5口ソケットを箱から出した状態です。
元々車内で使用することを想定している商品なので、先っちょがシガープラグになっています。
これだとバッテリーに直結できないので端子を加工します。



カーショップで売っている、加工用の端子を買ってきます。



プラグの先を、ニッパーで切って…


元側の被覆を5cmほど剥いていきます。



先っちょに端子をつけてペンチで圧着すれば完成です。





バッテリー側はターミナルをつけて接続します。





LEDライト

次に用意するのは、動作確認用のLEDライトです。
これはカー用品店で1300円でした。



スペックはLED22個で2Wです。
12V駆動なので 2/12≒170mA程度の電流が流れます。




先がシガーソケットになってます。



接続すると無事ライトが点きました。



これでソーラーパネル側とバッテリー側の準備ができたので、次はいよいよ両者を接続します。


電線の断面積sq(スケア)と、流せる許容アンペアの対応表

sq(スケア)と、許容電流の対応表です。

0.5 sq  -   7A
0.75sq  -  10A
1.25sq  -  15A
2.0 sq  -  20A
4.0 sq  -  30A
5.0 sq  -  45A
5.5 sq  -  50A
8.0 sq  -  70A
 14 sq  -  90A
 22 sq  - 110A



基礎から学ぶ電気回路計算


ぱいすら女子


ソーラー発電の自作用に,パネルを購入しました

ソーラーパネルについて以前検討した内容を元に、楽天でソーラーパネルを購入しました。
目的はソーラー発電システムの自作です。

検討の結果、購入する事にしたのは以下の商品です。

単結晶ソーラーパネル100W人気のサイズ(85x85cm)

単結晶ソーラーパネル100W人気のサイズ(85x85cm)
価格:15,900円(税込、送料込)


決定のポイントは価格が安かったのと、庭に設置する際のサイズがちょうど良かったからです。
他の商品はたいてい横長のパネルですが、これは正方形なので横幅が小さく設置場所への収まりが良いです。

商品の発送は速く、注文してから2日後に到着しました。
余談ですが、購入時に着圧ソックス(?)がおまけとしてもらえるキャンペーンが行われていたのですが、不要だったので送ってもらわないメールで依頼したら、代わとしてにおまけの送料(80円)を値引きしてもらいました。

到着したパネルです。重さは10kg弱で、実際に見ると思ってたより大きめの印象でした。プチプチ+ダンボールで厳重梱包されてます。
ソーラーパネル:JRM100M<br />

こちらは裏側。
梱包材越しにケーブルが見えてます。
ソーラーパネル:JRM100M<br />

梱包を解いた状態の裏面です。
ケーブルの端子は、MC4という規格のもので防水仕様です。
ソーラーパネル:JRM100M<br />

パネル仕様が記載されたラベルのアップ画像。
ソーラーパネル:JRM100M<br />
仕様

画像だと見づらいので、スペックを転記しておきます。

Model:JRM100M
 
Rated Maximum Power(Pmax)               100W
Tolerance                          -1% - +3%
Voltage at Pmax(Vmp)                   13.2V
Current at Pmax(Imp)                   7.69A
Open-Circuit Voltage(Voc)             15.84V
Short-Circuit Current(Isc)             9.23A
Normal Operation Cell Temp(NOCT)      45±2℃
Maximum Series Fuse Rating               10A
Operation Temprature           -45℃ to +80℃
Protection Class                           □
Cell Technology                      Mono-Si
Weight(kg)                              8.95
Dimension(mm)                     850x850x35
 
All technical data at standard test condition
AM=1.5 E=1000W/m2 TC=25℃ Made in China
Tel:+86-577-86586777



購入したショップに記載されていた仕様は下記で、当然ながら一致してました。

●種類:単結晶
●最大出力100W
●開放電圧15.84V
●短絡電流9.23A
●最大出力動作電流7.69A
●重量8.95kg
●サイズ 85X85X3.5cm
●ソーラーセルのサイズ156X156mm



これを見ると、どうやらモノはJR SOLARという中国企業製のようです。
メーカーのサイトを見てみましたが、製品一覧にはあったのはもっと大型の商品のみで、JRM100Mの情報は載っていませんでした。

JRM100M<br />


ケーブル接続元のボックスは防水加工されていますが、マイナスドライバーを引っ掛けるだけで簡単にはずせます。
開けてみると、逆流防止のダイオード(?)が一本接続されてました。


本体に付いているケーブルは短いので、5mの延長ケーブルも一緒に購入しました。
接続は、差し込むだけなので簡単です。

延長ケーブルは、amazonでの購入です。
B004GWZI2I
60W 80W 120W パネル用延長ケーブル 5m 4.0sqタイプ 片側専用コネクタ付き

延長ケーブルの片方は、先ほどのMC4の端子が付いています。
B004GWZI2I

もう一方は、未加工の状態です。
B004GWZI2I

延長ケーブルは太さが4sqなので30Aまでなら問題なく流せます。
負荷接続時の電圧が13V程度なので30A*13V=390Wとなり、余裕を見て300Wぐらいまでならパネルを並列接続して拡張できるように余裕を見ておきました。

パネルと延長ケーブルを接続した状態です。差し込みには特に力は要らないです。


パネルを一旦、庭に仮置きしてみました。
動作確認のために、とりあえずで窓のレールに引っ掛けていますが、そのうち設置する架台も自作する予定です。


ケーブルは、エアコン用の通し穴を流用します。


これで、室外側の準備は完了です。
室内側の作業はこちら

ソーラー発電システムの自作 その2(バッテリー側)

4827722927
手作り太陽光発電 家庭で楽しむ太陽電池工作―電気の元はお日様です

[電子回路]リレーの仕組みの基礎知識


確認に使用した部品
 G6E-134P-US DC12
 オムロン製
 (マルツで購入。1個325円)

仕様書

マイクロリレー 形G6E | オムロン電子部品情報サイト
G6E-134P-US DC12 :オムロン制御機器
カタログ


ピンアサイン

5本のピンが出ていて、各ピンの番号は1,6,7,10,12pinになる。
番号が連番じゃないのは、各ピンの位置が物理的に離れているため。1番ピンをブレッドボードの”1″のところに刺すと、次のピンが”6″の位置に刺さるようになっている。ちょっと見づらいけど下の写真を見ると分かるかも。

仕様書より、このパーツ内の回路図。
下記の図はリレーを下から見た場合になる。




ブレッドボードに指した状態だと逆になるので、マークの下がpin1で、そこから反時計回りに6,7,10,12ピンとなる。
G6E-134P-US



仕組み

通常は、pin7とpin10が接続状態になっている。

pin1がプラス・pin6がマイナスで、ここに電圧をかけると電磁石の仕組みによって、7-10の替わりに、7-12ピンが通電する。

リレーをスイッチさせる場合、G6E-134P-US DC12は、1-6に12Vかける必要がある。
この電圧をのことをコイル定格電圧と呼ぶ。
(シリーズ内の他部品、例えばG6E-134P-US DC6だったら6Vで駆動できる)

この部品は状態保持しないので、1-6ピンの通電を止めると、接続が元に戻る。
このような仕組みをシングルスステイブルリレーと呼ぶ。

1-6ピンを通電させている間は、電磁石を動作させ続けているので当然電力を消費する。
G6E-134P-US DC12の場合は、200mWの消費電力になっている。


仕組み的に、1-6ピンの通電をさせたまま長期間連続通電させる使い方はNG。
理由は、コイルが発熱したり、接点の劣化によって接触不安定につながってしまうため。

長期間連続通電させたい場合は、ラッチングリレーというものを使用する。
ラッチングリレーは、一旦通電させると、リセットコイルのピンにパルスを送らない限り状態を保持し続ける仕組みになっている。また、ラッチングリレーはコイルにずっと通電し続ける必要がないので、消費電力的にも有利。

スイッチ側に仕様値より大きな電圧をかけると、想定以上の負担が掛かり(火花が飛ぶ)接点の寿命が縮んでしまう。
また、リレーをモーターの動作制御に使う場合は、モーターを動かし始めるときに一瞬大電流が流れるので、モーターの規格値よりキャパの大きな(5~10倍)リレーを使用する必要がある。白熱電球の場合はさらに大きくて、10~15倍の突入電流が入る事を考慮する。

G6E-134P-US DC12のスペック

感動消費電力はわずか98mW(定格消費電力:200mW)と、高感度を実現。
耐衝撃電圧1,500V(10×160μs)を確保し、FCC規格に準拠した設計。
自動実装への対応を考え、スティック包装を採用。
プラスチック・シール形で、自動はんだづけが可能。
超音波洗浄対応形をシリーズ化。
標準形でUL 、CSA規格取得。


電子回路のキホン

参考資料

リレーについては、この本の2章が分かりやすいです。
4873114772
Make: Electronics ―作ってわかる電気と電子回路の基礎 (Make:PROJECTS)